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:
- Explain why TF2 errors are common in Nav2.
- Check the full Nav2 TF tree.
- Use
tf2_echoto check frame connections. - Use
view_framesto generate a TF tree. - Use
tf2_monitorto inspect TF delay and update rate. - Debug missing
map β odom. - Debug missing
odom β base_link. - Debug missing sensor transforms such as
base_link β base_laser. - Debug wrong frame names.
- Debug duplicate TF publishers.
- Debug
use_sim_timeproblems. - Debug RViz2 βNo transformβ problems.
- Debug Nav2 costmap TF problems.
- 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
- What is the expected Nav2 TF chain from map to robot body?
- Which transform is usually published by AMCL?
- Which transform is usually published by odometry?
- Which transform is usually published by URDF or static TF?
- What command generates a TF tree PDF?
- What command checks the transform from
maptobase_link? - What is the difference between
/tfand/tf_static? - Why is
use_sim_timeimportant? - Why should you avoid duplicate TF publishers?
- What should you check if RViz2 shows βNo transformβ?
- What should you check if the LiDAR scan does not align with the map?
- What should you check if
/cmd_velexists 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.