Skip to content

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's vx_max, vx_min and vy_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 velocities vx, vy and wz are not independent from each other. Driving with vx_max is only possible when vy and wz are 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 |