Nav2 overview
If you have gotten to this point of the ROS guide this is the end to the Nav2 section.
Here is a brief overview of what is needed to set up the Nav2 stack
- create URDF
- create custom joint_state_pub node to publish
odom=>base_link
tf and/cmd_vel
- set up sim environment
- add lidar Node
- add Slam Node for
map=>odom
tf - run nav2 bringup
There is still one last part of this guide which is in the next page about setup.py
. For the sake of making the whole guide easier to follow I have changed the way setup.py
was created. The next guide goes into detail on how to fix this.
Further guides
Some extra features you could add to Nav2 are listed here. These are just some extra things I found useful for Robomasters specifically
- Robot footprint is the 2D representation of the robot nav2 uses for collision avoidance. It can be tuned to better fit the robot
- obstacles that wont be picked up by the lidar can still be avoided by specifying “keep out” zones.
- Bumps to avoid in the Robomasters 2025 field:
- If your robot blocks off certain parts of the Lidar’s scan it can show up in your map. To avoid this ROS has a
laser_filters
package where you can ignore parts of the Lidar scan.
example setup for ROS2 (the yaml config file stays the same from the guide):
lidar_filter_yaml = os.path.join(pkg_share, 'config', 'lidar_filter.yaml') ... lidar_filter = Node( package='laser_filters', executable='scan_to_scan_filter_chain', # name='laser_filters', output='screen', emulate_tty=True, # remappings=[ # # Remap the default '/chatter' topic to '/conversation' # ('/scan', '/scan_raw'), # ('/scan_filtered', '/scan'), # ], parameters=[lidar_filter_yaml])
- If your robot blocks off certain parts of the Lidar’s scan it can show up in your map. To avoid this ROS has a
- Nav2 has a custom system to describe “robot behavior” such as what to do if suck or when to go to which goal. It can be though of as an advanced state machine.
- It is recommend in Robomasters to use the behavior trees for sentry decision making
- It is common to have real sense nodes in Robomasters. If you do use one there is a ROS2 node for it where you can specify all the parameters.
Configuring for holinomic drive
For our team’s Nav2 setup specifically we set our robot to be omnidirectional or a holinomic drive instead of diff drive. This requires lots of changes in the nav2 params so I will do my best to list them here. These are just the params that I found worked for jazzy.
Here is another guide that goes over some of the nav2 parameters if lost
- amcl
robot_model_type
set to"nav2_amcl::OmniMotionModel”
- controller_server
- ros__parameters
min_y_velocity_threshold
set to0.001
- general_goal_checker
yaw_goal_tolerance
set to0.50
- FollowPath
ay_min
set to-3.0
vy_min
set to-0.35
wz_max
set to1.9
motion_model
set to"Omni”
critics
add"TwirlingCritic"
to the arrayGoalAngleCritic
enabled
set tofalse
Add this under
PathAngleCritic
with the same number of tabsTwirlingCritic: enabled: true twirling_cost_power: 1 twirling_cost_weight: 10.0
- ros__parameters
- behavior_server
- ros__parameters
max_rotational_vel
set to0.0
min_rotational_vel
set to0.0
- ros__parameters
- velocity_smoother
- ros__parameters
max_velocity
set to[0.5, 0.5, 2.0]
min_velocity
set to[-0.5, -0.5, -2.0]
max_accel
set to[2.5, 2.5, 3.2]
max_decel
set to[-2.5, -2.5, -3.2]
- ros__parameters
behavior tree replacement:
There is a spin critic in the default behavior tree so to get rid of it you have to provide your own behavior tree:
in the config folder make this file my_nav_to_pose_bt.xml
note this is just a template to just get holinomic drive to work it is recommend you make your own.
<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 name="ClearGlobalCostmap-Context" service_name="global_costmap/clear_entirely_global_costmap"/>
</RecoveryNode>
</RateController>
<RecoveryNode number_of_retries="1" name="FollowPath">
<FollowPath path="{path}" controller_id="FollowPath"/>
<ClearEntireCostmap name="ClearLocalCostmap-Context" service_name="local_costmap/clear_entirely_local_costmap"/>
</RecoveryNode>
</PipelineSequence>
<ReactiveFallback name="RecoveryFallback">
<GoalUpdated/>
<SequenceStar name="RecoveryActions">
<ClearEntireCostmap name="ClearLocalCostmap-Subtree" service_name="local_costmap/clear_entirely_local_costmap"/>
<ClearEntireCostmap name="ClearGlobalCostmap-Subtree" service_name="global_costmap/clear_entirely_global_costmap"/>
<Wait wait_duration="5"/>
</SequenceStar>
</ReactiveFallback>
</RecoveryNode>
</BehaviorTree>
</root>
Then in the launch file add this
bt_xml = os.path.join(pkg_share, 'config', 'my_nav_to_pose_bt.xml')
...
nav2_bringup_node = IncludeLaunchDescription(
PythonLaunchDescriptionSource([
FindPackageShare("nav2_bringup"), '/launch', '/navigation_launch.py']),
launch_arguments={
'params_file': nav2_yaml,
'use_sim_time': LaunchConfiguration('use_sim_time')
'default_bt_xml_filename': bt_xml
}.items()
)
architectural decisions
Why all in one node?
ideally you are suppose to represent the hardware/resources better by having be physical nodes however for Robomasters many things are latency sensitive and having message pass though the ROS middleware had too much latency. Granted this was just though our limited testing was without fine tuning ROS for our specific application. However for the Robomaster’s robotics completion teams just need a dead simple working framework that works well enough for competition. Genraly robomasters clubs don’t have lots of time to fine tune and configure ROS perfectly so arcitecthing the whole robot under the my_node
is jank but works for our specific situation. This guide is ment to give teams a bare bones working Nav2 stack where teams can later on extend and re architect the whole design.
Further Nav2 stuff to look at
- https://docs.nav2.org/concepts/index.html
- https://docs.nav2.org/configuration/index.html
- https://docs.nav2.org/plugin_tutorials/index.html
- https://docs.nav2.org/tuning/index.html
- https://docs.nav2.org/plugins/index.html
- making custom gazebo worlds
common bugs:
[bt_navigator-11] [ERROR] [1752642430.128585554] [transformPoseInTargetFrame]: Extrapolation Error looking up target frame: Lookup would require extrapolation into the future. Requested time 1752642429.927490 but the latest data is at time 3.800000, when looking up transform from frame [base_link] to frame [map]
not using sim time
for got to set map frame
idk talk about this (mention how this is a cleaner version):