Lyrical to M-Turtle
Migration Actions and Deprecations
Behavior Server plugin parameters are now namespaced
The behavior plugins' parameters are now declared under the plugin's name from behavior_plugins, in the same way the acceleration_limit, deceleration_limit and minimum_speed parameters of BackUp and DriveOnHeading already were. The old node-level names are no longer read, so existing configurations must be updated or the defaults will silently apply:
| Old (node-level) | New (per plugin) |
|---|---|
simulate_ahead_time |
spin.simulate_ahead_time, backup.simulate_ahead_time, drive_on_heading.simulate_ahead_time |
max_rotational_vel |
spin.max_rotational_vel |
min_rotational_vel |
spin.min_rotational_vel |
rotational_acc_lim |
spin.rotational_acc_lim |
projection_time |
assisted_teleop.projection_time |
simulation_time_step |
assisted_teleop.simulation_time_step |
cmd_vel_teleop |
assisted_teleop.cmd_vel_teleop |
Substitute your own plugin names if they differ from the defaults. Simply move the parameter under the plugin's declaration in your configuration.
Single Lifecycle Manager in Nav2 Bringup
PR #6410 combines the separate lifecycle managers for localization, navigation, SLAM, keepout zones, speed zones and the loopback simulator into a single lifecycle_manager_nav2, started by bringup_launch.py. Measured on the Turtlebot 4 simulation launch, which previously ran four lifecycle managers, this reduces Nav2's CPU use by around 25%. The nested launch files in nav2_bringup no longer start a lifecycle manager of their own. Each has a get_lifecycle_nodes(context) function that returns its lifecycle node names, which bringup_launch.py collects into the node_names of the single manager.
Launching a nested file by itself, such as ros2 launch nav2_bringup navigation_launch.py, now leaves the servers unconfigured. Launch bringup_launch.py instead and use its arguments to turn off what you do not need, for example use_localization:=False when SLAM or another source provides the map and the map to odom transform. Anything that used the old manager names, such as lifecycle_manager_navigation/manage_nodes, should use lifecycle_manager_nav2 instead; the Nav2 RViz panel is already updated.
Move your own nested launch files to the same pattern: remove the lifecycle manager from each one, add a get_lifecycle_nodes(context) function that returns its lifecycle node names, and build the node_names of your single manager from those functions plus your own nodes. The task server tutorial shows this.
If you would rather run a launch file on its own, start a lifecycle manager beside it.
Default BT Updates
Recovery retries reset after navigation progress
PR #6652 adds distance-based retry resets to RecoveryNode. When its new reset_distance input is positive, the retry count resets to zero once the robot's displacement during an attempt of the first (main) child reaches that distance in meters. This allows navigation to recover from later failures after making progress without exhausting retries used earlier.
If you maintain a custom copy of these trees, add the new inputs to its outer recovery node to adopt this behavior:
<RecoveryNode number_of_retries="6" reset_distance="3.0"
global_frame="odom" name="NavigateRecovery">
<!-- Existing navigation and recovery children -->
</RecoveryNode>
For existing custom trees, no change is required: reset_distance defaults to 0.0, and any non-positive value disables distance resets.
Backup recovery now waits for the robot to move
PR #6635 replaces BackUp with the BackupWithReset subtree in six bundled navigation behavior trees with recovery actions. After a successful backup, the subtree skips another backup near the same pose. It allows backup again once the robot has moved at least reset_distance from the last backup pose. The backup history resets when the behavior tree is reloaded.
The updated trees also set wrap_around="true" on their RecoveryActions RoundRobin node so the recovery sequence can cycle (and for example spin can be executed multiple times). If you maintain a copy of one of these trees and want the same behavior, replace its recovery BackUp node with the BackupWithReset subtree and set wrap_around="true" on the RoundRobin. Adjust the frame names and reset distance for your robot.
Changes in FollowObject Action
FollowObject.action error codes are changed as below. If you are using this action you will have to adapt to handle new error codes:
| Old | New |
|---|---|
TF_ERROR = 901 |
TF_ERROR = 801 |
FAILED_TO_DETECT_OBJECT = 902 |
FAILED_TO_DETECT_OBJECT = 802 |
FAILED_TO_CONTROL = 903 |
FAILED_TO_CONTROL = 803 |
TIMEOUT = 904 |
TIMEOUT = 804 |
UNKNOWN = 999 |
UNKNOWN = 899 |
New Features and Improvements
Static Layer Overlays Without Resizing the Master
PR #6488 adds the Static Layer parameter resize_master, which defaults to true. Existing configurations require no changes: a Static Layer still resizes a non-rolling master costmap to match its incoming map.
Set resize_master: false for additional Static Layers whose maps should not control the master's geometry. For example, a Vector Object Server can publish an obstacle map with a smaller or changing extent while the primary Static Layer continues to own the site map geometry.
Assisted Teleop Times Out on Stale Teleop Commands
The AssistedTeleop behavior now stops the robot and fails the action with the new TELEOP_INPUT_TIMEOUT error code (733) when no teleop command has been received within the new teleop_command_timeout parameter (default 0.25 s).
Include Specific rclcpp Headers
PR #6558 replaces the broad rclcpp/rclcpp.hpp includes throughout Nav2 with the specific headers each file needs to speed up compilation and reduce build memory usage. We now recommend including specific rclcpp headers instead of globally including rclcpp/rclcpp.hpp.
See the ROS 2 documentation note on the rclcpp convenience header for more details.
MPPI Critics for Omnidirectional Velocity Limits
PR #6498 adds two MPPI critics. The ConstraintCritic bounds vx and vy separately. This creates a rectangular velocity space, with maximum translational velocity being sqrt(vx_max² + vy_max²). Therefore, any critic rewarding speed on an omnidirectional platform will lead to the robot driving diagonally, as sqrt(vx_max² + vy_max²) is larger than vx_max and vy_max alone.
- The OmniConstraintCritic (
mppi::critics::OmniConstraintCritic) is intended to be used for omnidirectional models instead of the ConstraintCritic. Its velocity space is an ellipse spanned by the controller'svx_max,vx_minandvy_max, so it keeps the same functionality as the ConstraintCritic, while preventing speed rewarding critics from forcing the robot to drive diagonally. - The MecanumCritic (
mppi::critics::MecanumCritic) is intended to be used to constrain a mecanum robot's drivetrain to its reachable velocity. This, because a mecanum model's velocitiesvx,vyandwzare not independent from each other. Driving withvx_maxis only possible whenvyandwzare zero, as otherwise a wheel would saturate.
Neither critic is enabled by default; existing configurations are unaffected.
Filled Footprint Option for Costmap Cost Queries
PR #6739 adds the footprint_fill field to the nav2_msgs/srv/GetCosts request. With use_footprint set, the service returns the maximum cost along the footprint outline. With footprint_fill also set, it returns the maximum cost over every cell inside the footprint. The CheckPoseOccupancy and RemoveInCollisionGoals BT nodes expose it as the footprint_fill input port.
The option defaults to false, so existing callers are unaffected.
The filled check reads every cell inside the footprint rather than only its outline, so prefer the outline check for frequent checks along whole paths. Some benchmark metrics for comparison, measured per pose on a free costmap with 0.05 m resolution:
| Robot footprint | Outline time | Footprint fill time |
|---|---|---|
| 0.70 m x 0.70 m | 0.28 µs | 3.57 µs |
| 1.45 m x 1.10 m | 0.41 µs | 9.25 µs |
| 2.00 m x 2.00 m | 0.56 µs | 20.3 µs |
Keepout Filter Checks the Whole Robot Footprint
PR #6526 makes the Keepout Filter check the whole robot footprint, instead of only the robot's center, when deciding whether the robot is inside a keepout zone. This only affects filters with override_lethal_cost enabled.
Previously, the filter looked at the mask cell under the robot's center. A robot whose edge overlapped a keepout zone, but whose center was still outside of it, was not considered to be in the zone. The lethal cost was therefore not overridden, and the robot could be stuck on the border of the zone with part of its footprint in lethal space. Now the filter checks the cells along the footprint outline (the footprint of the local or global costmap it runs in) against the mask. As soon as any part of the footprint touches a lethal or inscribed keepout cell, the lethal cost is replaced by lethal_override_cost, so the robot can navigate out of the zone.
Existing configurations require no changes. The behavior is identical when override_lethal_cost is false, and for robots whose footprint is entirely inside or outside of the keepout zones.
OpenMP support for MPPI CostCritic
PR #6228 <https://github.com/ros-navigation/navigation2/pull/6228>_ added OpenMP support for parallel processing, significantly improving the processing time for CostCritic. When build with OpenMp available & -DENABLE_OPENMP=ON, OpenMP will be used. Otherwise, scoring remains is single-threaded.
Increasing the thread number reduces computation time with the cost of higher CPU. Rough estimates: | threads | speed-up | |---------|----------| | 1 | 1.0x | | 2 | 1.8x | | 4 | 3.3x | | 8 | 5.9x |