Hi Chenlu and Peter I can certify that there is no problem making the navigation work as specified in the course:
Let me go step by step to see if I can clarify some points. But first, I want to thank Peter very much for his help and comments trying to help Chenlu (even if some points were not 100% correct, check below):
- Peter mentioned that the line to specify the path to the
behavior.xml
inside the bt_navigator.yaml
file file should be this:
default_nav_to_pose_bt_xml: â/home/user/ros2_ws/src/path_planner/config/behavior.xmlâ
THAT IS NOT CORRECT
the correct line is:
default_nav_to_pose_bt_xml: "/home/user/ros2_ws/src/path_planner_server/config/behavior.xml"
The reason why Peter wrote it wrong is because it was wrong in the course material (we confused him). This error was corrected a couple of weeks ago. Sorry Peter!
- Peter mentioned that the order in the
lifecycle_manager
is very important (inside the pathplanner.launch.py
), and he is right. However, the order he specifies is not correct. The order should be:
{'node_names': ['planner_server',
'controller_server',
'bt_navigator',
'recoveries_server']}])
- Chenlu, why are you launching everything from a single launch file? That is not the way we are teaching that, and there is a reason: now it is a lot more difficult to find the errors. You should only attempt to put everything in a single launch file, WHEN EVERYTHING WORKS SEPARATELY (that is the final exercise of Unit 5).
So go and separate the files in different launch files for each system.
- Your separated files should look like the ones below.
I overviewed your files and they look correct to me, except that they donât have the parameters for local and global costmaps. I didnât check each file line by line.
So it is now your turn: compare your separated files with mine. If they are different, you will get where the error is. If they are not, then both should work.
Let me know what happens, and where was the error in your files.
planner_server.yaml
planner_server:
ros__parameters:
expected_planner_frequency: 10.0
use_sim_time: True
planner_plugins: ["GridBased"]
GridBased:
plugin: "nav2_navfn_planner/NavfnPlanner"
tolerance: 0.5
use_astar: false
allow_unknown: true
global_costmap:
global_costmap:
ros__parameters:
update_frequency: 1.0
publish_frequency: 1.0
global_frame: map
robot_base_frame: base_link
use_sim_time: True
robot_radius: 0.15
resolution: 0.05
track_unknown_space: true
plugins: ["static_layer", "obstacle_layer", "inflation_layer"]
static_layer:
plugin: "nav2_costmap_2d::StaticLayer"
map_subscribe_transient_local: True
obstacle_layer:
plugin: "nav2_costmap_2d::ObstacleLayer"
enabled: True
observation_sources: scan
scan:
topic: /scan
max_obstacle_height: 2.0
clearing: True
marking: True
data_type: "LaserScan"
raytrace_max_range: 3.0
raytrace_min_range: 0.0
obstacle_max_range: 2.5
obstacle_min_range: 0.0
inflation_layer:
plugin: "nav2_costmap_2d::InflationLayer"
cost_scaling_factor: 3.0
inflation_radius: 0.35
always_send_full_costmap: True
controller.yaml
planner_server:
ros__parameters:
expected_planner_frequency: 10.0
use_sim_time: True
planner_plugins: ["GridBased"]
GridBased:
plugin: "nav2_navfn_planner/NavfnPlanner"
tolerance: 0.5
use_astar: false
allow_unknown: true
global_costmap:
global_costmap:
ros__parameters:
update_frequency: 1.0
publish_frequency: 1.0
global_frame: map
robot_base_frame: base_link
use_sim_time: True
robot_radius: 0.15
resolution: 0.05
track_unknown_space: true
plugins: ["static_layer", "obstacle_layer", "inflation_layer"]
static_layer:
plugin: "nav2_costmap_2d::StaticLayer"
map_subscribe_transient_local: True
obstacle_layer:
plugin: "nav2_costmap_2d::ObstacleLayer"
enabled: True
observation_sources: scan
scan:
topic: /scan
max_obstacle_height: 2.0
clearing: True
marking: True
data_type: "LaserScan"
raytrace_max_range: 3.0
raytrace_min_range: 0.0
obstacle_max_range: 2.5
obstacle_min_range: 0.0
inflation_layer:
plugin: "nav2_costmap_2d::InflationLayer"
cost_scaling_factor: 3.0
inflation_radius: 0.35
always_send_full_costmap: True
recovery.yaml
behavior_server:
ros__parameters:
costmap_topic: local_costmap/costmap_raw
footprint_topic: local_costmap/published_footprint
cycle_frequency: 10.0
behavior_plugins: ["spin", "backup", "wait"]
spin:
plugin: "nav2_behaviors/Spin"
backup:
plugin: "nav2_behaviors/BackUp"
wait:
plugin: "nav2_behaviors/Wait"
global_frame: odom
robot_base_frame: base_link
transform_timeout: 0.1
use_sim_time: true
simulate_ahead_time: 2.0
max_rotational_vel: 1.0
min_rotational_vel: 0.4
rotational_acc_lim: 3.2
bt_navigator.yaml
bt_navigator:
ros__parameters:
use_sim_time: True
global_frame: map
robot_base_frame: base_link
odom_topic: /odom
bt_loop_duration: 10
default_server_timeout: 20
default_nav_to_pose_bt_xml: "/home/user/ros2_ws/src/path_planner_server/config/behavior.xml"
plugin_lib_names:
- nav2_compute_path_to_pose_action_bt_node
- nav2_compute_path_through_poses_action_bt_node
- nav2_smooth_path_action_bt_node
- nav2_follow_path_action_bt_node
- nav2_spin_action_bt_node
- nav2_wait_action_bt_node
- nav2_back_up_action_bt_node
- nav2_drive_on_heading_bt_node
- nav2_clear_costmap_service_bt_node
- nav2_is_stuck_condition_bt_node
- nav2_goal_reached_condition_bt_node
- nav2_goal_updated_condition_bt_node
- nav2_globally_updated_goal_condition_bt_node
- nav2_is_path_valid_condition_bt_node
- nav2_initial_pose_received_condition_bt_node
- nav2_reinitialize_global_localization_service_bt_node
- nav2_rate_controller_bt_node
- nav2_distance_controller_bt_node
- nav2_speed_controller_bt_node
- nav2_truncate_path_action_bt_node
- nav2_truncate_path_local_action_bt_node
- nav2_goal_updater_node_bt_node
- nav2_recovery_node_bt_node
- nav2_pipeline_sequence_bt_node
- nav2_round_robin_node_bt_node
- nav2_transform_available_condition_bt_node
- nav2_time_expired_condition_bt_node
- nav2_path_expiring_timer_condition
- nav2_distance_traveled_condition_bt_node
- nav2_single_trigger_bt_node
- nav2_goal_updated_controller_bt_node
- nav2_is_battery_low_condition_bt_node
- nav2_navigate_through_poses_action_bt_node
- nav2_navigate_to_pose_action_bt_node
- nav2_remove_passed_goals_action_bt_node
- nav2_planner_selector_bt_node
- nav2_controller_selector_bt_node
- nav2_goal_checker_selector_bt_node
- nav2_controller_cancel_bt_node
- nav2_path_longer_on_approach_bt_node
- nav2_wait_cancel_bt_node
- nav2_spin_cancel_bt_node
- nav2_back_up_cancel_bt_node
- nav2_drive_on_heading_cancel_bt_node
behavior.xml
<!--
This Behavior Tree replans the global path periodically at 1 Hz, and has
recovery actions. Obtained from the official Nav2 package
-->
<root main_tree_to_execute="MainTree">
<BehaviorTree ID="MainTree">
<RecoveryNode number_of_retries="6" name="NavigateRecovery">
<PipelineSequence name="NavigateWithReplanning">
<RateController hz="1.0">
<RecoveryNode number_of_retries="1" name="ComputePathToPose">
<ComputePathToPose goal="{goal}" path="{path}" planner_id="GridBased"/>
<ClearEntireCostmap service_name="global_costmap/clear_entirely_global_costmap"/>
</RecoveryNode>
</RateController>
<RecoveryNode number_of_retries="1" name="FollowPath">
<FollowPath path="{path}" controller_id="FollowPath"/>
<ClearEntireCostmap service_name="local_costmap/clear_entirely_local_costmap"/>
</RecoveryNode>
</PipelineSequence>
<SequenceStar name="RecoveryActions">
<ClearEntireCostmap service_name="local_costmap/clear_entirely_local_costmap"/>
<ClearEntireCostmap service_name="global_costmap/clear_entirely_global_costmap"/>
<Spin spin_dist="1.57"/>
<Wait wait_duration="5"/>
</SequenceStar>
</RecoveryNode>
</BehaviorTree>
</root>
pathplanner.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
import os
from ament_index_python.packages import get_package_share_directory
nav2_yaml = os.path.join(get_package_share_directory('path_planner_server'), 'config','planner_server.yaml')
controller_yaml = os.path.join(get_package_share_directory('path_planner_server'), 'config','controller.yaml')
bt_navigator_yaml = os.path.join(get_package_share_directory('path_planner_server'), 'config','bt_navigator.yaml')
recovery_yaml = os.path.join(get_package_share_directory('path_planner_server'), 'config','recovery.yaml')
def generate_launch_description():
return LaunchDescription([
Node(
package='nav2_planner',
executable='planner_server',
name='planner_server',
output='screen',
parameters=[nav2_yaml]),
Node(
package='nav2_controller',
executable='controller_server',
name='controller_server',
output='screen',
parameters=[controller_yaml]),
Node(
package='nav2_bt_navigator',
executable='bt_navigator',
name='bt_navigator',
output='screen',
parameters=[bt_navigator_yaml]),
Node(
package='nav2_behaviors',
executable='behavior_server',
name='recoveries_server',
output='screen',
parameters=[recovery_yaml]),
Node(
package='nav2_lifecycle_manager',
executable='lifecycle_manager',
name='lifecycle_manager_pathplanner',
output='screen',
parameters=[{'use_sim_time': True},
{'autostart': True},
{'node_names': ['planner_server',
'controller_server',
'bt_navigator',
'recoveries_server']}])
])