Setting up parameters for selective application of nav2 libraries
I want to use the tracking controllers from nav2
as part of my simulation environment, in real life there will be a 3rd party tracking controller to which I can supply paths, but for simulation I am trying to emulate it.
As such, I am in a weird situation because I have paths generated, contours and AB lines, and I have obstacle avoidance and localization handled elsewhere. I purely want nav2
to act as a path->cmd_vel
handler and nothing more. Setting this up has proven difficult as I don't have so much experience with nav2
.
I am under the impression that it requires a map, therefore I've made an empty map, filled with only pixels of 254 grayscale. This is because this part should not consider obstacles, as that will be handled elsewhere. I'm not sure then if I need to enable the local or only the global map parameter configurations? Furthermore I have disabled amcl
, in favor of using robot_localization
instead.
Upon startup I get many error messages of
[bt_navigator-5] [INFO] [1638782303.256835846] [bt_navigator]: Configuring
[bt_navigator-5] [ERROR] [1638782303.285669115] []: Caught exception in callback for transition 10
[bt_navigator-5] [ERROR] [1638782303.285699955] []: Original error: Could not load library: libnav2_compute_path_through_poses_action_bt_node.so: cannot open shared object file: No such file or directory
[bt_navigator-5] [WARN] [1638782303.285730258] []: Error occurred while doing error handling.
[bt_navigator-5] [FATAL] [1638782303.285741871] [bt_navigator]: Lifecycle node bt_navigator does not have error state implemented
[lifecycle_manager-7] [ERROR] [1638782303.286312696] [lifecycle_manager_navigation]: Failed to change state for node: bt_navigator
[lifecycle_manager-7] [ERROR] [1638782303.286358255] [lifecycle_manager_navigation]: Failed to bring up all requested nodes. Aborting bringup.
As I said I'm not very experienced with nav2, so I'm not entirely sure which of the 20+ plugins are necessary, or if what I am trying to do is even really feasible. Note, using this and this as inspiration. Does anyone know of any examples of something similar?
map.yaml
image: default.pgm
resolution: 0.1
origin: [-50.0, -50.0, 0.0] # [0.0, 0.0, 0.0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196
my navigation.launch.py
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions.execute_process import ExecuteProcess
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
def generate_launch_description():
# Get the launch directory
bringup_dir = get_package_share_directory("nav2_bringup")
tractor_gazebo_dir = get_package_share_directory("tractor_gazebo")
# Create the launch configuration variables
use_sim_time = LaunchConfiguration("use_sim_time")
autostart = LaunchConfiguration("autostart")
params_file = LaunchConfiguration("params_file")
map_file = LaunchConfiguration("map_file")
# declare launch arguments
declare_use_sim_time = DeclareLaunchArgument(
"use_sim_time",
default_value="True",
description="Flag to enable use_sim_time",
)
declare_autostart = DeclareLaunchArgument(
"autostart",
default_value="True",
description="Automatically startup the nav2 stack",
)
declare_params_file = DeclareLaunchArgument(
"params_file",
default_value=os.path.join(
tractor_gazebo_dir, "config", "nav2.yaml" # "nav2_pure_pursuit.yaml"
),
description="Full path to the ROS2 parameters file to use",
)
declare_map_file = DeclareLaunchArgument(
"map_file",
default_value=os.path.join(tractor_gazebo_dir, "map", "default.yaml"),
description="Full path to the nav2 map yaml file to use",
)
nav2_map_server = Node(
package="nav2_map_server",
executable="map_server",
name="map_server",
output="screen",
parameters=[params_file, {"yaml_filename": map_file}],
)
# Specify the actions
nav2_bringup = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(bringup_dir, "launch", "navigation_launch.py")
),
launch_arguments={
"use_sim_time": use_sim_time,
"autostart": autostart,
"params_file": params_file,
}.items(),
)
return LaunchDescription(
[
declare_use_sim_time,
declare_autostart,
declare_params_file,
declare_map_file,
nav2_map_server,
nav2_bringup,
]
)
nav2.yaml
bt_navigator:
ros__parameters:
use_sim_time: False
bt_xml_filename: "bt_navigator.xml"
dwb_controller:
ros__parameters:
use_sim_time: False
debug_trajectory_details: True
min_vel_x: 0.0
min_vel_y: 0.0
max_vel_x: 0.26
max_vel_y: 0.0
max_vel_theta: 1.0
min_speed_xy: 0.0
max_speed_xy: 0.26
min_speed_theta: 0.0
min_x_velocity_threshold: 0.001
# Add high threshold velocity for turtlebot 3 issue.
# https://github.com/ROBOTIS-GIT/turtlebot3_simulations/issues/75
min_y_velocity_threshold: 0.5
min_theta_velocity_threshold: 0.001
acc_lim_x: 2.5
acc_lim_y: 0.0
acc_lim_theta: 3.2
decel_lim_x: -2.5
decel_lim_y: 0.0
decel_lim_theta: -3.2
vx_samples: 20
vy_samples: 5
vtheta_samples: 20
sim_time: 1.7
linear_granularity: 0.05
xy_goal_tolerance: 0.25
transform_tolerance: 0.2
critics: ["RotateToGoal", "Oscillation", "BaseObstacle", "GoalAlign", "PathAlign", "PathDist", "GoalDist"]
BaseObstacle.scale: 0.02
PathAlign.scale: 0.0
GoalAlign.scale: 0.0
PathDist.scale: 32.0
GoalDist.scale: 24.0
RotateToGoal.scale: 32.0
local_costmap:
local_costmap:
ros__parameters:
use_sim_time: False
global_frame: odom
plugin_names: ["obstacle_layer", "inflation_layer"]
plugin_types: ["nav2_costmap_2d::ObstacleLayer", "nav2_costmap_2d::InflationLayer"]
rolling_window: true
width: 3
height: 3
resolution: 0.05
robot_radius: 0.22
inflation_layer.cost_scaling_factor: 3.0
obstacle_layer:
enabled: True
always_send_full_costmap: True
observation_sources: scan
scan:
topic: /scan
max_obstacle_height: 2.0
clearing: True
marking: True
local_costmap_client:
ros__parameters:
use_sim_time: False
local_costmap_rclcpp_node:
ros__parameters:
use_sim_time: False
global_costmap:
global_costmap:
ros__parameters:
use_sim_time: False
robot_radius: 0.22
obstacle_layer:
enabled: True
always_send_full_costmap: True
observation_sources: scan
scan:
topic: /scan
max_obstacle_height: 2.0
clearing: True
marking: True
global_costmap_client:
ros__parameters:
use_sim_time: False
global_costmap_rclcpp_node:
ros__parameters:
use_sim_time: False
map_server:
ros__parameters:
use_sim_time: False
yaml_filename: "map.yaml"
lifecycle_manager:
ros__parameters:
use_sim_time: False
autostart: True
node_names: ['map_server', 'amcl',
'world_model', 'dwb_controller',
'navfn_planner', 'bt_navigator']
lifecycle_manager_service_client:
ros__parameters:
use_sim_time: False
lifecycle_manager_client_service_client:
ros__parameters:
use_sim_time: False
navfn_planner:
ros__parameters:
use_sim_time: False
tolerance: 0.0
use_astar: false
navfn_planner_GetCostmap_client:
ros__parameters:
use_sim_time: False
robot_state_publisher:
ros__parameters:
use_sim_time: False
world_model:
ros__parameters:
use_sim_time: False
Asked by morten on 2021-12-06 04:21:42 UTC
Answers
Absolutely and pretty easily, Nav2 was specifically designed do you could BYOC (bring your own components) or rip out things you don't need. If you look at the main Nav2 diagram in the documentation https://navigation.ros.org/, you'll see a number of main "task" servers. You should simply remove the ones you don't want or need to reduce the requirements on your system. In particular, it sounds like you don't want the Planner server or the Waypoint Follower server. You probably don't need AMCL or map server either.
At that point, its about configuring the behavior tree to contain the business-specific logic that you would like to have happen (e.g. follow a path given to it from another source) or call the controller server directly.
There's no reason you should need to fake out a map, you could remove that.
Could not load library: libnav2_compute_path_through_poses_action_bt_node.so
That's from the BT navigator not about to find a particular library. You should make sure that your list in the configuration file represents the distribution that you're actually using. Older distributions might not have all of the BT nodes that more current ones do.
Asked by stevemacenski on 2021-12-06 13:35:27 UTC
Comments
So, if I understand you right. By changing the BT I can use, for example, the DWB controller without maps, planners, or localization? And then just send poses to it through the send_goal
/FollowPath
action, where these poses are calculated elsewhere?
Asked by morten on 2021-12-08 06:38:50 UTC
Yup! That is correct.
Asked by stevemacenski on 2021-12-08 15:46:53 UTC
Using the planner necessitates a map though, right? So the path I have generated needs to be appropriate for the controller if I side-step the planner, at least spacing between poses wise.
Asked by morten on 2021-12-09 04:49:05 UTC
Still unsure about the previous comment. I agree with you that I don't want to use the planner, but my path is 50-50 AB lines and interpolated turns. I don't want to ensure the robot is able to get onto the path from start nor interpolate the entire thing so it works for the controllers. For this I would like to use the smacplanner, is this something that is possible without maps?
Asked by morten on 2022-01-12 03:58:54 UTC
Comments