By ihsumlee , 9 June 2026
content

Position in the full course

This is the tenth and final step of the course.

The full learning order is:

1. ROS 2 node/topic/launch review
2. TF2 frame concept
3. Static sensor frames
4. Dynamic odometry frame
5. URDF + robot_state_publisher
6. SLAM mapping
7. AMCL localization
8. Nav2 path planning
9. RViz goal navigation
10. TF2 debugging in Nav2

In Step 9, you used RViz2 to send a navigation goal.

In Step 10, you will learn how to debug the most common TF2 and Nav2 problems.

The main goal is:

When Nav2 does not work, you should know how to check TF, topics, frame names, timestamps, lifecycle states, and RViz displays step by step.

1. Learning objectives

After this module, you should be able to:

  1. Explain why TF2 errors are common in Nav2.
  2. Check the full Nav2 TF tree.
  3. Use tf2_echo to check frame connections.
  4. Use view_frames to generate a TF tree.
  5. Use tf2_monitor to inspect TF delay and update rate.
  6. Debug missing map β†’ odom.
  7. Debug missing odom β†’ base_link.
  8. Debug missing sensor transforms such as base_link β†’ base_laser.
  9. Debug wrong frame names.
  10. Debug duplicate TF publishers.
  11. Debug use_sim_time problems.
  12. Debug RViz2 β€œNo transform” problems.
  13. Debug Nav2 costmap TF problems.
  14. Create a practical Nav2 TF debugging checklist.

2. Suggested teaching duration

Suggested duration: 2 hours

| Time | Activity | | ----------- | ----------------------------------------------------- | | 0–15 min | Review complete Nav2 TF tree | | 15–30 min | Explain common TF2 failure types | | 30–50 min | Practice tf2_echo, view_frames, and tf2_monitor | | 50–75 min | Debug missing frames | | 75–95 min | Debug timestamp and use_sim_time problems | | 95–110 min | Debug costmap and RViz2 errors | | 110–120 min | Final checklist and homework |


3. The correct Nav2 TF tree

For a typical AMR using Nav2, the TF tree should look like this:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            └── imu_link

If you use URDF from Step 5, the tree may include wheels:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            β”œβ”€β”€ imu_link
            β”œβ”€β”€ left_wheel_link
            └── right_wheel_link

The most important transforms are:

| Transform | Usually published by | Static or dynamic | | ------------------------- | ------------------------------- | ----------------- | | map β†’ odom | SLAM or AMCL | Dynamic | | odom β†’ base_link | Odometry or robot_localization | Dynamic | | base_link β†’ base_laser | URDF or static transform | Static | | base_link β†’ camera_link | URDF or static transform | Static | | base_link β†’ imu_link | URDF or static transform | Static |

Important rule:

Each transform should usually have one clear publisher.
Do not publish the same transform from multiple nodes.

4. Why TF2 debugging is important in Nav2

Nav2 depends heavily on TF2.

Nav2 must know:

Where is the robot in the map?
Where is the robot in odom?
Where is the LiDAR relative to the robot?
Where is the camera relative to the robot?
Where is the robot footprint?

If TF is wrong, Nav2 may show problems such as:

RViz2 shows β€œNo transform”.
AMCL particles do not converge.
LiDAR scan does not align with the map.
Costmap does not update.
Planner cannot compute a path.
Controller does not move the robot.
Robot moves in the wrong direction.
Robot spins in place.

Many Nav2 problems are actually TF problems.


5. First debugging rule: check TF before tuning Nav2

When navigation fails, do not immediately tune planner or controller parameters.

First check:

1. Is the TF tree connected?
2. Are frame names correct?
3. Are timestamps correct?
4. Is use_sim_time correct?
5. Are there duplicate TF publishers?
6. Are map, odom, base_link, and sensor frames available?

Only after TF is correct should you tune:

costmap parameters
planner parameters
controller parameters
AMCL parameters
velocity limits
robot footprint

6. Main debugging tools

You will use these tools frequently:

| Tool | Purpose | | --------------------------- | ---------------------------------- | | ros2 topic list | Check available topics | | ros2 node list | Check running nodes | | ros2 topic echo | Check message contents | | ros2 topic hz | Check topic frequency | | tf2_echo | Check transform between two frames | | view_frames | Generate complete TF tree PDF | | tf2_monitor | Monitor TF delay and update rate | | ros2 lifecycle get | Check Nav2 lifecycle node state | | RViz2 TF display | Visualize frames | | RViz2 Map/LaserScan display | Check map and scan alignment |


7. Basic TF2 debugging commands

7.1 Check TF topics

ros2 topic list | grep tf

Expected topics:

/tf
/tf_static

Meaning:

/tf contains dynamic transforms.
/tf_static contains static transforms.

7.2 Check dynamic TF messages

ros2 topic echo /tf --once

You may see transforms such as:

map β†’ odom
odom β†’ base_link

7.3 Check static TF messages

ros2 topic echo /tf_static --once

You may see transforms such as:

base_link β†’ base_laser
base_link β†’ camera_link
base_link β†’ imu_link

7.4 Generate TF tree

ros2 run tf2_tools view_frames
xdg-open frames.pdf

Expected Nav2 tree:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            └── imu_link

7.5 Check important transforms

ros2 run tf2_ros tf2_echo map odom
ros2 run tf2_ros tf2_echo odom base_link
ros2 run tf2_ros tf2_echo base_link base_laser
ros2 run tf2_ros tf2_echo map base_link

If all of these work, your main TF chain is connected.


8. Recommended Nav2 debugging order

Use this order when Nav2 fails.

1. Check ROS 2 environment.
2. Check required nodes.
3. Check required topics.
4. Check TF tree.
5. Check frame names.
6. Check use_sim_time.
7. Check lifecycle states.
8. Check map and scan alignment.
9. Check costmaps.
10. Check actions.
11. Check /cmd_vel.
12. Check robot driver.

This order helps you avoid random debugging.


9. Step 1: Check ROS 2 environment

Open a terminal:

source /opt/ros/jazzy/setup.bash
source ~/ros2_ws/install/setup.bash

Check ROS distribution:

printenv | grep ROS

Expected:

ROS_VERSION=2
ROS_DISTRO=jazzy

If your package cannot be found, source your workspace again:

source ~/ros2_ws/install/setup.bash

10. Step 2: Check required nodes

Run:

ros2 node list

For Nav2 localization and navigation, you may need:

map_server
amcl
planner_server
controller_server
bt_navigator
behavior_server
lifecycle_manager_localization
lifecycle_manager_navigation
robot_state_publisher
odometry node
LiDAR driver node

If a required node is missing, the corresponding function will fail.

Example:

| Missing node | Likely problem | | ----------------------- | -------------------------------- | | amcl | No localization | | map_server | No /map | | planner_server | No path planning | | controller_server | No path following | | robot_state_publisher | Missing robot static frames | | LiDAR driver | No /scan | | odometry node | No /odom or odom β†’ base_link |


11. Step 3: Check required topics

Run:

ros2 topic list

Important topics:

/map
/scan
/odom
/tf
/tf_static
/particle_cloud
/global_costmap/costmap
/local_costmap/costmap
/cmd_vel

Check each important topic:

ros2 topic echo /map --once
ros2 topic echo /scan --once
ros2 topic echo /odom --once
ros2 topic echo /cmd_vel

If /cmd_vel has output but the robot does not move, the problem may be in the robot driver, motor controller, topic remapping, or emergency stop.


12. Step 4: Check TF tree

Generate the TF tree:

ros2 run tf2_tools view_frames
xdg-open frames.pdf

Ask these questions:

Is map connected to odom?
Is odom connected to base_link?
Is base_link connected to base_laser?
Are there disconnected subtrees?
Are frame names spelled correctly?
Are there unexpected frames?
Are there duplicate or conflicting frames?

A correct tree should not look like this:

map
 └── odom

base_link
 └── base_laser

This is bad because map/odom is disconnected from base_link.

A correct tree should be connected:

map
 └── odom
      └── base_link
            └── base_laser

13. Step 5: Check frame names

Frame names must match your Nav2 parameters.

Common Nav2 frame parameters:

global_frame: map
odom_frame: odom
robot_base_frame: base_link
base_frame_id: base_link
scan_topic: scan

Common frame name problems:

| Expected | Accidentally used | | ------------ | ------------------------------------- | | base_link | base footprint, base-link, base | | base_laser | laser, laser_link, lidar_link | | odom | odom_combined, wheel_odom | | map | world, world_map |

Check your TF frame names:

ros2 run tf2_tools view_frames

Check your parameters:

ros2 param get /amcl base_frame_id
ros2 param get /amcl odom_frame_id
ros2 param get /amcl global_frame_id

If your LiDAR frame is laser_link but your URDF expects base_laser, fix one side so the names match.


14. Problem case 1: RViz2 shows β€œNo transform”

Symptom

RViz2 shows messages like:

No transform from [base_laser] to [map]
No transform from [base_link] to [map]
Frame [map] does not exist

Possible reasons

Fixed Frame is wrong.
map β†’ odom is missing.
odom β†’ base_link is missing.
base_link β†’ base_laser is missing.
use_sim_time is wrong.
Frame name is wrong.

Debug commands

ros2 run tf2_tools view_frames
ros2 run tf2_ros tf2_echo map odom
ros2 run tf2_ros tf2_echo odom base_link
ros2 run tf2_ros tf2_echo base_link base_laser
ros2 param get /rviz2 use_sim_time

Fix

Set RViz2 Fixed Frame to map.
Start AMCL or SLAM to publish map β†’ odom.
Start odometry to publish odom β†’ base_link.
Start robot_state_publisher or static TF for base_link β†’ base_laser.
Make sure use_sim_time is consistent.

15. Problem case 2: Missing map β†’ odom

Symptom

This command fails:

ros2 run tf2_ros tf2_echo map odom

You may see:

Invalid frame ID "map" passed to canTransform
or
Could not transform map to odom

Meaning

The localization or mapping source is not providing map β†’ odom.

Possible reasons

AMCL is not running.
SLAM is not running.
Map is not loaded.
Initial pose has not been set.
AMCL is not active.
No /scan data.
Wrong frame names in AMCL parameters.

Debug commands

ros2 node list | grep amcl
ros2 lifecycle get /amcl
ros2 topic echo /map --once
ros2 topic echo /scan --once
ros2 topic echo /initialpose
ros2 param get /amcl global_frame_id
ros2 param get /amcl odom_frame_id
ros2 param get /amcl base_frame_id

Fix

Launch AMCL localization.
Make sure map_server publishes /map.
Make sure /scan is available.
Set the initial pose in RViz2.
Check AMCL frame parameters.
Do not run SLAM and AMCL together unless intentionally configured.

16. Problem case 3: Missing odom β†’ base_link

Symptom

This command fails:

ros2 run tf2_ros tf2_echo odom base_link

Meaning

Your odometry system is not publishing the robot body pose in the odometry frame.

Possible reasons

Odometry node is not running.
Robot driver publishes /odom but not TF.
robot_localization is not publishing TF.
Frame names are wrong.
Two odometry nodes conflict.

Debug commands

ros2 topic echo /odom --once
ros2 topic echo /tf --once
ros2 node list
ros2 topic hz /odom

Important distinction

This may happen:

/odom topic exists,
but odom β†’ base_link TF does not exist.

This means the odometry message is being published, but the TF transform is not.

Nav2 usually needs both.

Fix

Enable TF publishing in your odometry source.
Use robot_localization to publish odom β†’ base_link if appropriate.
Make sure only one node publishes odom β†’ base_link.
Check frame_id and child_frame_id in /odom.

In /odom, check:

header.frame_id should usually be odom.
child_frame_id should usually be base_link.

17. Problem case 4: Missing base_link β†’ base_laser

Symptom

AMCL, SLAM, or costmap reports transform errors related to laser frame.

Example:

No transform from [base_laser] to [base_link]
No transform from [base_laser] to [map]

Meaning

ROS 2 knows the LiDAR scan frame, but TF does not know where the LiDAR is mounted on the robot.

Debug commands

ros2 topic echo /scan --once
ros2 run tf2_ros tf2_echo base_link base_laser
ros2 run tf2_tools view_frames

In /scan, check:

header.frame_id

If /scan says:

frame_id: laser

but your TF tree uses:

base_laser

then the frame names do not match.

Fix

Add the LiDAR frame to URDF.
Or publish a static transform from base_link to the LiDAR frame.
Make sure the scan header.frame_id matches the TF child frame.

Example static transform:

ros2 run tf2_ros static_transform_publisher \
  --x 0.20 --y 0.00 --z 0.15 \
  --roll 0 --pitch 0 --yaw 0 \
  --frame-id base_link \
  --child-frame-id base_laser

18. Problem case 5: Wrong static transform

Symptom

The robot localizes poorly, or the LiDAR scan does not align with the map.

Possible reasons

LiDAR x/y/z position is wrong.
LiDAR yaw is wrong.
Units are wrong.
Parent and child frames are reversed.
LiDAR frame convention is wrong.

Common unit mistake

Wrong:

x = 20
z = 15

This means 20 meters and 15 meters.

Correct:

x = 0.20
z = 0.15

This means 20 cm and 15 cm.

Debug commands

ros2 run tf2_ros tf2_echo base_link base_laser
rviz2

In RViz2:

Set Fixed Frame to base_link.
Add TF.
Add LaserScan.
Check whether the scan direction makes sense.

Fix

Measure the sensor mounting position carefully.
Use meters.
Check yaw direction.
Make sure base_link is parent and sensor frame is child.

19. Problem case 6: Duplicate TF publishers

Symptom

TF tree looks unstable, or transforms jump unexpectedly.

You may also see warnings about repeated data or conflicting publishers.

Common duplicate cases

URDF publishes base_link β†’ base_laser.
static_transform_publisher also publishes base_link β†’ base_laser.

robot_localization publishes odom β†’ base_link.
wheel odometry node also publishes odom β†’ base_link.

SLAM publishes map β†’ odom.
AMCL also publishes map β†’ odom.

Debug commands

ros2 topic echo /tf
ros2 topic echo /tf_static
ros2 node list
ros2 run tf2_tools view_frames

Fix

Only one source should publish each parent-child transform.
Use URDF for robot structure.
Use odometry or robot_localization for odom β†’ base_link.
Use SLAM or AMCL for map β†’ odom, not both at the same time in normal localization mode.

20. Problem case 7: use_sim_time mismatch

Symptom

TF exists, but RViz2 or Nav2 still reports transform timeout or extrapolation errors.

You may see:

Lookup would require extrapolation into the future.
Lookup would require extrapolation into the past.
Timed out waiting for transform.

Meaning

Some nodes may use simulation time, while others use system time.

Check clock

ros2 topic echo /clock --once

If /clock exists and you are using simulation, nodes should usually use:

use_sim_time: true

If you are using a real robot, nodes should usually use:

use_sim_time: false

Check node parameters

ros2 param get /amcl use_sim_time
ros2 param get /planner_server use_sim_time
ros2 param get /controller_server use_sim_time
ros2 param get /bt_navigator use_sim_time
ros2 param get /rviz2 use_sim_time

Fix

For simulation:

Set use_sim_time:=True for Nav2, AMCL, RViz2, and robot nodes.

For real robot:

Set use_sim_time:=False for Nav2, AMCL, RViz2, and robot nodes.

Important:

Do not mix simulation time and system time in the same Nav2 system.

21. Problem case 8: TF timestamp problems

Symptom

You see errors like:

Extrapolation into the future
Extrapolation into the past
Transform timeout
Data too old

Possible reasons

Sensor messages have old timestamps.
Odometry messages have old timestamps.
Computer clocks are not synchronized.
use_sim_time is inconsistent.
TF broadcaster uses wrong timestamp.
The robot publishes too slowly.

Debug commands

ros2 topic echo /scan --once
ros2 topic echo /odom --once
ros2 run tf2_ros tf2_monitor map base_link
ros2 topic hz /tf
ros2 topic hz /odom
ros2 topic hz /scan

Fix

Make sure all nodes use the same time source.
Make sure message timestamps are current.
Synchronize clocks between computers if using multiple machines.
Increase TF publish rate if too slow.
Check sensor driver timestamps.

For multi-computer robot systems:

Use time synchronization between computers, such as chrony or NTP.

22. Problem case 9: LiDAR scan does not align with the map

Symptom

In RViz2:

The map is visible.
The robot is visible.
The LiDAR scan is shifted or rotated away from the walls.

Possible reasons

Initial pose is wrong.
AMCL has not converged.
base_link β†’ base_laser is wrong.
LiDAR frame direction is wrong.
Map does not match the real environment.
Odometry is poor.
use_sim_time is wrong.

Debug order

1. Set initial pose again.
2. Check base_link β†’ base_laser.
3. Check scan header.frame_id.
4. Check map and environment match.
5. Move slowly and let AMCL converge.
6. Check odometry drift.

Useful commands

ros2 topic echo /scan --once
ros2 run tf2_ros tf2_echo base_link base_laser
ros2 run tf2_ros tf2_echo map base_link
ros2 topic echo /particle_cloud --once

23. Problem case 10: Global costmap or local costmap has TF errors

Symptom

Nav2 terminal may show messages like:

Timed out waiting for transform from base_link to map
Could not transform from base_laser to map
Robot is out of bounds of the costmap

Meaning

The costmap cannot transform robot or sensor data into the required frame.

Check costmap frames

Global costmap usually uses:

global_frame: map
robot_base_frame: base_link

Local costmap usually uses:

global_frame: odom
robot_base_frame: base_link

Debug commands

ros2 param get /global_costmap/global_costmap global_frame
ros2 param get /global_costmap/global_costmap robot_base_frame
ros2 param get /local_costmap/local_costmap global_frame
ros2 param get /local_costmap/local_costmap robot_base_frame
ros2 run tf2_ros tf2_echo map base_link
ros2 run tf2_ros tf2_echo odom base_link
ros2 run tf2_ros tf2_echo base_link base_laser

Fix

Make sure map β†’ odom exists.
Make sure odom β†’ base_link exists.
Make sure sensor frame exists.
Make sure costmap frame parameters match your TF tree.
Make sure scan topic frame_id matches your TF tree.

24. Problem case 11: Nav2 cannot plan a path

Symptom

You send a goal, but Nav2 reports failure.

Possible reasons

Robot is not localized.
map β†’ base_link is missing.
Goal is outside the map.
Goal is inside an obstacle.
Global costmap is blocked.
Planner Server is not active.

Debug commands

ros2 lifecycle get /planner_server
ros2 action list | grep compute
ros2 run tf2_ros tf2_echo map base_link
ros2 topic echo /global_costmap/costmap --once

Fix

Set initial pose again.
Choose a reachable goal in free space.
Check global costmap in RViz2.
Check robot_radius and inflation_radius.
Check planner_server lifecycle state.

25. Problem case 12: Nav2 plans but robot does not move

Symptom

RViz2 shows a path, but the robot stays still.

Possible reasons

Controller Server is not active.
No /cmd_vel is published.
Robot driver subscribes to a different velocity topic.
Emergency stop is active.
Motor driver is disabled.
Simulation is paused.
Controller parameters are invalid.

Debug commands

ros2 lifecycle get /controller_server
ros2 topic echo /cmd_vel
ros2 topic info /cmd_vel
ros2 node list

Fix

Activate controller_server.
Check /cmd_vel output.
Check which topic the robot driver subscribes to.
Check emergency stop.
Check robot motor enable state.
Check simulation pause state.

26. Problem case 13: Robot moves in the wrong direction

Symptom

The robot receives /cmd_vel, but moves backward, sideways, or rotates incorrectly.

Possible reasons

base_link x-axis is not forward.
Wheel encoder signs are wrong.
Motor driver interprets velocity incorrectly.
URDF wheel orientation is wrong.
Odometry yaw sign is wrong.

Debug commands

ros2 topic echo /cmd_vel
ros2 topic echo /odom
ros2 run tf2_ros tf2_echo odom base_link

Expected convention

For a mobile robot:

base_link x-axis points forward.
base_link y-axis points left.
base_link z-axis points upward.

Fix

Correct the base_link convention.
Correct wheel encoder sign.
Correct motor driver velocity mapping.
Correct URDF wheel orientation.
Check odometry direction.

27. Problem case 14: Robot spins in place

Symptom

The robot keeps rotating and does not go to the goal.

Possible reasons

Initial orientation is wrong.
AMCL localization is wrong.
Goal orientation is difficult.
Controller parameters are not tuned.
Odometry yaw is noisy.
IMU yaw is noisy or incorrectly fused.

Debug commands

ros2 run tf2_ros tf2_echo map base_link
ros2 topic echo /odom
ros2 topic echo /particle_cloud --once
ros2 topic echo /cmd_vel

Fix

Set initial pose again.
Choose a simple nearby goal.
Reduce max angular velocity.
Check odometry yaw.
Check IMU frame and orientation.
Tune controller parameters later.

28. TF debugging checklist for Nav2

Use this checklist whenever Nav2 fails.

28.1 Required topics

ros2 topic echo /map --once
ros2 topic echo /scan --once
ros2 topic echo /odom --once
ros2 topic echo /tf --once
ros2 topic echo /tf_static --once

28.2 Required transforms

ros2 run tf2_ros tf2_echo map odom
ros2 run tf2_ros tf2_echo odom base_link
ros2 run tf2_ros tf2_echo base_link base_laser
ros2 run tf2_ros tf2_echo map base_link

28.3 TF tree

ros2 run tf2_tools view_frames
xdg-open frames.pdf

28.4 Lifecycle states

ros2 lifecycle get /amcl
ros2 lifecycle get /map_server
ros2 lifecycle get /planner_server
ros2 lifecycle get /controller_server
ros2 lifecycle get /bt_navigator

Expected:

active

28.5 Time setting

ros2 param get /amcl use_sim_time
ros2 param get /planner_server use_sim_time
ros2 param get /controller_server use_sim_time
ros2 param get /bt_navigator use_sim_time
ros2 param get /rviz2 use_sim_time

For simulation:

use_sim_time should usually be true.

For real robot:

use_sim_time should usually be false.

29. Create a simple debugging script

You can create a helper script to check common Nav2 items.

Create a file:

nano ~/ros2_ws/nav2_tf_debug_check.sh

Paste:

#!/bin/bash

echo "=============================="
echo "ROS Environment"
echo "=============================="
printenv | grep ROS

echo ""
echo "=============================="
echo "Nodes"
echo "=============================="
ros2 node list

echo ""
echo "=============================="
echo "Important Topics"
echo "=============================="
ros2 topic list | grep -E "map|scan|odom|tf|cmd_vel|costmap|particle"

echo ""
echo "=============================="
echo "TF Tree"
echo "=============================="
ros2 run tf2_tools view_frames

echo ""
echo "=============================="
echo "Check Key Transforms"
echo "=============================="

echo ""
echo "Checking map -> odom"
timeout 5 ros2 run tf2_ros tf2_echo map odom

echo ""
echo "Checking odom -> base_link"
timeout 5 ros2 run tf2_ros tf2_echo odom base_link

echo ""
echo "Checking base_link -> base_laser"
timeout 5 ros2 run tf2_ros tf2_echo base_link base_laser

echo ""
echo "Checking map -> base_link"
timeout 5 ros2 run tf2_ros tf2_echo map base_link

echo ""
echo "=============================="
echo "Lifecycle States"
echo "=============================="
ros2 lifecycle get /amcl
ros2 lifecycle get /map_server
ros2 lifecycle get /planner_server
ros2 lifecycle get /controller_server
ros2 lifecycle get /bt_navigator

echo ""
echo "=============================="
echo "Done"
echo "=============================="

Make it executable:

chmod +x ~/ros2_ws/nav2_tf_debug_check.sh

Run it:

~/ros2_ws/nav2_tf_debug_check.sh

This script does not fix problems automatically.

It helps you quickly collect debugging information.


30. Classroom practice: intentionally create and fix TF problems

Practice A: Wrong RViz Fixed Frame

Set RViz2 Fixed Frame to:

wrong_map

Observe the error.

Then fix it:

Set Fixed Frame to map.

Practice B: Missing LiDAR static transform

Stop the node that publishes:

base_link β†’ base_laser

Then run:

ros2 run tf2_ros tf2_echo base_link base_laser

Observe the error.

Then fix it by restarting:

robot_state_publisher
or
static_transform_publisher

Practice C: Missing AMCL initial pose

Launch AMCL but do not set the initial pose.

Check:

ros2 run tf2_ros tf2_echo map odom

Then set the initial pose in RViz2 and check again.


Practice D: Wrong scan frame name

Change the expected LiDAR frame name in your URDF or parameter file so it does not match /scan.header.frame_id.

Observe the costmap or AMCL error.

Then fix the frame name.


Practice E: use_sim_time mismatch

In simulation, set one node to:

use_sim_time: false

while others use:

use_sim_time: true

Observe TF timeout or extrapolation problems.

Then fix all nodes to use the same time source.


31. Final debugging flowchart

Use this flowchart when Nav2 does not work:

Nav2 does not work
        |
        v
Can you see /map, /scan, /odom?
        |
        |-- No β†’ Start map server, LiDAR, or odometry source
        |
        v
Does view_frames show map β†’ odom β†’ base_link β†’ sensor?
        |
        |-- No β†’ Fix missing TF publisher or frame name
        |
        v
Is use_sim_time consistent?
        |
        |-- No β†’ Fix use_sim_time for all nodes
        |
        v
Are Nav2 lifecycle nodes active?
        |
        |-- No β†’ Check parameters and launch errors
        |
        v
Does RViz scan align with map?
        |
        |-- No β†’ Reset initial pose, check sensor TF, check map
        |
        v
Can Nav2 plan a path?
        |
        |-- No β†’ Check goal, global costmap, planner_server
        |
        v
Does /cmd_vel publish?
        |
        |-- No β†’ Check controller_server and behavior tree
        |
        v
Does robot move?
        |
        |-- No β†’ Check motor driver, topic remap, emergency stop
        |
        v
Navigation works

32. Practice assignment

Assignment title

Debug a Nav2 TF Tree

Task 1: Generate the TF tree

Run:

ros2 run tf2_tools view_frames

Submit:

frames.pdf screenshot

Explain whether your TF tree is connected.


Task 2: Check key transforms

Submit screenshots of:

ros2 run tf2_ros tf2_echo map odom
ros2 run tf2_ros tf2_echo odom base_link
ros2 run tf2_ros tf2_echo base_link base_laser
ros2 run tf2_ros tf2_echo map base_link

Task 3: Check important topics

Submit screenshots of:

ros2 topic echo /map --once
ros2 topic echo /scan --once
ros2 topic echo /odom --once
ros2 topic echo /tf_static --once

Task 4: Check lifecycle states

Submit screenshots of:

ros2 lifecycle get /amcl
ros2 lifecycle get /planner_server
ros2 lifecycle get /controller_server
ros2 lifecycle get /bt_navigator

Task 5: Diagnose one problem

Choose one problem:

RViz2 No transform
Missing map β†’ odom
Missing odom β†’ base_link
Missing base_link β†’ base_laser
Scan not aligned with map
Robot does not move
Robot spins in place
Costmap blocks the path

Write:

Problem:
Observed symptom:
Commands used:
Root cause:
Solution:
Result after fixing:

33. Mini quiz

  1. What is the expected Nav2 TF chain from map to robot body?
  2. Which transform is usually published by AMCL?
  3. Which transform is usually published by odometry?
  4. Which transform is usually published by URDF or static TF?
  5. What command generates a TF tree PDF?
  6. What command checks the transform from map to base_link?
  7. What is the difference between /tf and /tf_static?
  8. Why is use_sim_time important?
  9. Why should you avoid duplicate TF publishers?
  10. What should you check if RViz2 shows β€œNo transform”?
  11. What should you check if the LiDAR scan does not align with the map?
  12. What should you check if /cmd_vel exists but the robot does not move?

34. Key summary

In this module, you learned how to debug TF2 problems in Nav2.

The most important TF tree is:

map
 └── odom
      └── base_link
            β”œβ”€β”€ base_laser
            β”œβ”€β”€ camera_link
            └── imu_link

You learned how to check:

TF tree
frame names
map topic
scan topic
odom topic
static transforms
dynamic transforms
use_sim_time
lifecycle states
costmaps
/cmd_vel

You used:

tf2_echo
view_frames
tf2_monitor
ros2 topic echo
ros2 topic hz
ros2 lifecycle get
RViz2

The most important debugging rule is:

When Nav2 fails, check TF first before tuning planner or controller parameters.

This completes the 10-step ROS 2 Jazzy TF2 and Nav2 course.

The complete learning path is:

1. Understand ROS 2 node/topic/launch basics.
2. Understand TF2 frames and TF tree.
3. Publish static sensor frames.
4. Publish dynamic odometry frame.
5. Use URDF and robot_state_publisher.
6. Build a map using SLAM.
7. Localize using AMCL.
8. Understand Nav2 path planning.
9. Send navigation goals using RViz2.
10. Debug TF2 and Nav2 problems systematically.

Tags