FixTheRobot Explore Robotics / Systems Engineering / Engineering Guides / Module 13

Engineering Guides · Module 13

Configuring Nav2

Defaults are a demo robot’s values. Check each against your robot: speeds, tolerances, rates and frames.

  • Intermediate
  • Module 13: Navigation Stack & Autonomous Motion Planning
  • Written for ROS 2 Jazzy where ROS 2 is used
  • Sources checked 2026-11-06

Assumptions: Numbers in the examples are illustrative and the code is executed by the site’s tests. Facts taken from a cited source are marked; other statements are general engineering knowledge and must be confirmed on the datasheet of the part you use.

1. Engineering problem

Nav2 starts with the parameters of the default robot (a small differential-drive demo platform). Most early failures come from defaults that contradict the real robot: speed limits, goal tolerances finer than the localisation, a progress checker that expects more motion than the robot makes.

2. When is this needed?

  • Bringing up Nav2 on a new robot.
  • When navigation aborts with progress or goal errors.
  • Before field trials.

3. Selection and design decisions

From the Jazzy default parameter file (read 2026-11-06): the controller_server runs at controller_frequency: 20.0 with failure_tolerance: 0.3; the SimpleProgressChecker uses required_movement_radius: 0.5 and movement_time_allowance: 10.0; the SimpleGoalChecker uses xy_goal_tolerance: 0.25 and yaw_goal_tolerance: 0.25; the planner_server has expected_planner_frequency: 20.0 and NavFn; the behavior_server lists spin, backup, drive_on_heading, assisted_teleop and wait; the MPPI defaults include vx_max: 0.5, vx_min: -0.35 and wz_max: 1.9.

Overview
ServerWhat to set from the robotCheck
controller_serverFrequency, speed limits, goal and progress checkersSpeeds ≤ robot limits; tolerances ≥ 2× localisation error
planner_serverPlanner plugin and tolerancePlanning time below the period
behavior_serverRecovery behaviours and framesFrames match tf
bt_navigatorBehaviour tree and framesTree matches your needs
costmapsFootprint, inflation, sensorsSee the costmap guide
velocity_smoother, collision_monitor (if used)Limits and zonesConsistent with the controller

4. Advantages and disadvantages

  • Tight goal tolerances give accuracy and can make goals unreachable.
  • A strict progress checker detects stuck robots and aborts slow but legitimate moves.
  • Higher controller frequency needs compute and fresh costmaps.

5. Requirements and constraints

  • Frames in all servers match the tf tree.
  • Velocity and acceleration limits match what the robot can do.
  • Goal tolerances are consistent with the localisation accuracy.

6. Architecture

bt_navigator ─▶ planner_server ─▶ smoother ─▶ controller_server ─▶ cmd_vel ; behavior_server for recoveries ; costmaps for both

7. Implementation

  1. Copy the default parameter file for your Nav2 version.
  2. Set frames, footprint and speed limits for your robot.
  3. Check consistency (below).
  4. Run in simulation, then at low speed on the robot.
  5. Tune the rest (costmaps, controller, recoveries) one at a time.
cfg = {"controller_frequency": 20.0, "expected_planner_frequency": 20.0, "required_movement_radius": 0.5, "movement_time_allowance": 10.0,
       "xy_goal_tolerance": 0.25, "vx_max": 0.5, "failure_tolerance": 0.3, "transform_tolerance": 0.1}
robot = {"max_speed": 0.8, "lidar_rate_hz": 10.0, "position_accuracy": 0.05}
msgs = []
min_speed = cfg["required_movement_radius"] / cfg["movement_time_allowance"]
msgs.append(f"progress checker needs an average of {min_speed:.2f} m/s over {cfg['movement_time_allowance']:.0f} s")
if robot["max_speed"] > cfg["vx_max"]:
    msgs.append(f"robot can do {robot['max_speed']} m/s but the controller is limited to {cfg['vx_max']} m/s")
if cfg["xy_goal_tolerance"] < 2 * robot["position_accuracy"]:
    msgs.append("goal tolerance is below twice the localisation accuracy: goals may never be 'reached'")
if cfg["controller_frequency"] > 2 * robot["lidar_rate_hz"]:
    msgs.append("controller runs faster than twice the LiDAR rate: the local costmap changes less often than the controller")
print("\n".join(msgs))

Printed (checked by the site’s tests):

progress checker needs an average of 0.05 m/s over 10 s
robot can do 0.8 m/s but the controller is limited to 0.5 m/s

Reading it: with the default progress checker, the robot must move at least 0.5 m in 10 s, an average of 0.05 m/s; the robot can reach 0.8 m/s but the controller caps it at 0.5 m/s. The goal tolerance of 0.25 m is above twice the assumed 0.05 m localisation accuracy, so it passes. The robot values are illustrative.

8. Real examples

  • Commands (Jazzy): ros2 launch nav2_bringup navigation_launch.py params_file:=my_params.yaml (not executed by the site’s tests).

9. Failure scenarios

  • The robot never reaches the goal because the tolerance is below the localisation error.
  • Aborts with “failed to make progress” in a slow section.
  • Speed limits that exceed what the robot can brake from.

10. Troubleshooting

  1. Check each server’s log for the error code.
  2. Compare frames with view_frames.
  3. Reduce speed to test whether the problem is dynamics or configuration.

11. Validation

  • The consistency check prints the lines shown (executed by the site tests).
  • Ten navigation runs complete with the expected tolerance.

12. Engineering checklist

13. Further references

Related on FixTheRobot