Localization & SLAM · SLAM with ROS 2 · M7-L1 · ROS 2 project · Intermediate
Debug a ROS 2 SLAM Pipeline
The simulator runs, the node runs, and /map never fills. Work along the data path until you find where it breaks.
Bring up a SLAM stack in simulation, find why no map appears and verify with the standard introspection tools.
The problem
A colleague hands you a launch file: TurtleBot 3 in the Gazebo world plus SLAM Toolbox. Everything starts without errors, the robot drives, RViz opens. And there is no map.
You have the introspection tools of M7-T1 and nothing else. There is more than one fault, and fixing the first one reveals the next.
Expected behaviour. After you drive the robot a metre or two, /map is published with the room taking shape, map → odom → base_footprint exists, and the SLAM node reports scans being processed.
Observable failure. /map is missing or empty, the node log repeats warnings (for example about not being able to compute the odometry pose or about dropped messages), and RViz shows a lidar scan but no map.
This is a real ROS 2 project, not a browser lab. You run it on your own machine with ROS 2, a simulator and the tools of Module 7. The website does not run ROS 2 and does not grade it; you grade yourself with the criteria below and the
check.shscript.
Time: about 60 to 90 minutes · Level: Intermediate · Theory: M7-T1 SLAM System Architecture in ROS 2, M7-T8 Real-Time Performance and Resource Constraints
Prerequisites and setup
You need a computer with ROS 2 Humble on Ubuntu 22.04 (a virtual machine or container with a display is fine). Jazzy works for the SLAM and Nav2 parts; the simulator launch differs, and the project notes say where. Install once:
sudo apt update sudo apt install ros-humble-turtlebot3-gazebo ros-humble-turtlebot3-teleop ros-humble-slam-toolbox \ ros-humble-navigation2 ros-humble-nav2-bringup ros-humble-tf2-tools ros-humble-tf2-ros ros-humble-rviz2 source /opt/ros/humble/setup.bash export TURTLEBOT3_MODEL=burger
Get the project files: ros2_labs/l1-debug-a-ros2-slam-pipeline in the site’s repository (clone it, or copy the files listed below from this page). The folder ros2_labs/common holds scripts shared by several labs.
- Terminal 1:
export TURTLEBOT3_MODEL=burger, then from the project folderros2 launch launch/lab1.launch.py. A Gazebo window with the TurtleBot 3 world opens. - Terminal 2:
ros2 run turtlebot3_teleop teleop_keyboardand drive forward and turn a little. Keep this terminal for driving. - Terminal 3: your debugging terminal (source ROS 2 and set
TURTLEBOT3_MODELhere too).
Verification status. The project files follow the documented Humble interfaces but have not been executed by the site’s automated tests (they cannot run ROS 2). If a command or parameter is rejected by your version, the error names it: treat that as part of the exercise and tell us.
The project files
Two files are involved. You will edit them; the lab is to decide what to change from evidence, not by guessing.
launch/lab1.launch.py
"""Lab M7-L1: TurtleBot 3 world in Gazebo plus SLAM Toolbox. Several things are wrong; no map appears.
Run: ros2 launch launch/lab1.launch.py
"""
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
def generate_launch_description():
here = os.path.dirname(os.path.realpath(__file__))
params = os.path.join(here, '..', 'config', 'slam_params.yaml')
tb3 = os.path.join(get_package_share_directory('turtlebot3_gazebo'), 'launch', 'turtlebot3_world.launch.py')
return LaunchDescription([
IncludeLaunchDescription(PythonLaunchDescriptionSource(tb3)),
Node(
package='slam_toolbox',
executable='async_slam_toolbox_node',
name='slam_toolbox',
output='screen',
parameters=[params, {'use_sim_time': False}],
),
])
config/slam_params.yaml
# SLAM Toolbox parameters for lab M7-L1. This file contains mistakes on purpose: find them.
slam_toolbox:
ros__parameters:
solver_plugin: solver_plugins::CeresSolver
ceres_linear_solver: SPARSE_NORMAL_CHOLESKY
ceres_preconditioner: SCHUR_JACOBI
ceres_trust_strategy: LEVENBERG_MARQUARDT
ceres_dogleg_type: TRADITIONAL_DOGLEG
ceres_loss_function: None
odom_frame: odometry
map_frame: map
base_frame: base_footprint
scan_topic: /lidar/scan
mode: mapping
use_map_saver: true
debug_logging: false
throttle_scans: 1
transform_publish_period: 0.02
map_update_interval: 5.0
resolution: 0.05
max_laser_range: 3.5
minimum_time_interval: 0.5
transform_timeout: 0.2
tf_buffer_duration: 30.
stack_size_to_use: 40000000
enable_interactive_mode: true
use_scan_matching: true
use_scan_barycenter: true
minimum_travel_distance: 0.5
minimum_travel_heading: 0.5
scan_buffer_size: 10
scan_buffer_maximum_scan_distance: 10.0
link_match_minimum_response_fine: 0.1
link_scan_maximum_distance: 1.5
loop_search_maximum_distance: 3.0
do_loop_closing: true
loop_match_minimum_chain_size: 10
loop_match_maximum_variance_coarse: 3.0
loop_match_minimum_response_coarse: 0.35
loop_match_minimum_response_fine: 0.45
What to do
Follow the loop of this track: Problem → Experiment → Diagnose → Fix → Evaluate → Understand.
- Problem and experiment. Start the launch file and drive a little. Open RViz (
rviz2) with the fixed frameodomand add the LaserScan and Map displays. Note what you see. - Diagnose along the data path. Run, in order:
ros2 node list;ros2 topic list -t;ros2 topic hz /scan;ros2 topic info /scan -v;ros2 param get /slam_toolbox use_sim_time;ros2 run tf2_tools view_frames. After each, write down one sentence: what does this rule in or out? - Use the tool below with the contents of
config/slam_params.yamland the facts you collected (the robot publishes/scan, the odometry frame is namedodom, the base framebase_footprint) to see which parameters disagree with the robot. - Fix. Make the smallest changes that restore the data path, one at a time, restarting the launch after each. Record which symptom each change removed.
- Evaluate. Drive a loop around the world so that the map closes, then run
./check.sh. - Understand. Write three sentences: the three faults, the command that exposed each, and what the log said. Compare with the worked explanation.
Pre-flight tool
SLAM Toolbox parameter linter
Paste the contents of config/slam_params.yaml and fill in what you learned about the robot. The tool compares the two and lists disagreements. It cannot see the launch file, so it will not find every fault.
This tool only reads the text you paste. It does not connect to your robot, run ROS 2 or send anything anywhere.
Expected output
Typical output when things are right. Exact numbers, timestamps and wording differ between machines and versions.
Healthy node list and topics
ros2 node list /slam_toolbox /robot_state_publisher /turtlebot3_diff_drive /turtlebot3_laserscan ... ros2 topic list -t | grep -E "scan|map|tf" /map [nav_msgs/msg/OccupancyGrid] /scan [sensor_msgs/msg/LaserScan] /tf [tf2_msgs/msg/TFMessage] /tf_static [tf2_msgs/msg/TFMessage]
The SLAM node is on simulated time
ros2 param get /slam_toolbox use_sim_time Boolean value is: True
A frame tree that connects
map -> odom -> base_footprint -> base_link -> base_scan (view_frames writes frames_<date>.gv and .pdf in the current folder)
A growing map
ros2 topic echo /map --once --field info resolution: 0.05 width: 80 (grows as you explore) height: 80 ...
check.sh when everything is fixed
PASS the /slam_toolbox node is running PASS the SLAM node uses simulated time PASS the SLAM node subscribes to the lidar topic PASS transform map -> base_footprint is available PASS /map is published and contains more than 1500 known cells 5 passed, 0 failed
Troubleshooting
| Symptom | Likely cause | What to try |
|---|---|---|
| Gazebo does not open or the robot does not appear | Missing TURTLEBOT3_MODEL, no graphics in a VM, or an old Gazebo process still running | export TURTLEBOT3_MODEL=burger; killall gzserver gzclient; check you have a display |
ros2 topic hz /scan shows nothing | Simulation paused or still loading; or /scan is on another name | ros2 topic list; wait for Gazebo’s clock to start |
| Warnings about extrapolation or “Failed to compute odom pose” | Clock mismatch (sim time) or a frame name the odometry does not publish | Check use_sim_time on the node and the frame names against view_frames |
/map appears but stays tiny | You have not moved the robot enough (keyframes need travel) | Drive 1 to 2 m and turn; see minimum_travel_distance |
| After fixing one fault the symptom does not change | There are several faults; the first no longer masks the next but you cannot see it yet | Keep going down the data path; read the node log after every change |
| The parameter file edit has no effect | The launch file overrides it (parameters later in the list win) | Read the parameters=[...] list in the launch file |
Evaluation criteria
You are done when every criterion passes. check.sh automates most of them (run it from the project folder, with the launch file running and ROS 2 sourced). The remaining ones you judge yourself.
| Criterion | How to check | Passes when |
|---|---|---|
| The SLAM node is on simulated time | ros2 param get /slam_toolbox use_sim_time | prints True (automated) |
| The SLAM node receives the lidar | ros2 topic info /scan -v | lists slam_toolbox as a subscription (automated) |
| The frame tree connects | view_frames or tf2_echo | map → base_footprint exists (automated) |
| A real map is built | check.sh; RViz | more than 1500 known cells; walls are straight (partly automated) |
| You can name each fault and its evidence | your notes from task 6 | three faults, each with the command that exposed it (self-assessed) |
cd ros2_labs/l1-debug-a-ros2-slam-pipeline ./check.sh
Worked explanation
Try the lab before opening this.
Show the diagnosis and the fix
There are three faults.
- Wrong clock. The launch file passes
{'use_sim_time': False}after the parameter file. Gazebo publishes/clock, so the SLAM node stamps its transforms with wall-clock time and every lookup fails. Evidence:ros2 param get /slam_toolbox use_sim_timereturns False; the log reports huge time differences or extrapolation. Fix:True(and alsouse_sim_time: truein the YAML). - Wrong scan topic.
scan_topic: /lidar/scan, but the robot publishes/scan. Evidence:ros2 topic info /scan -vshows no subscription from slam_toolbox. Fix:/scan. - Wrong odometry frame.
odom_frame: odometry; the TurtleBot publishesodom. Evidence:view_framesshowsodom, notodometry; the log says it cannot compute the odometry pose. Fix:odom.
The faults mask one another: with the topic wrong you never see the frame error, because no scan ever arrives to need the transform.
Why it happens
A SLAM node needs four things at once: messages arriving (topic, QoS), a transform from the scan frame to the odometry frame (frame names), consistent time (clock), and parameters that name these correctly (M7-T1 to M7-T4). Any one missing gives the same visible symptom, an empty map. The only reliable method is to check each link in order and to treat “it started without errors” as no information at all.
What this project does not cover
- The simulator gives a clean lidar, a perfect clock and well-behaved odometry. Real robots add driver start-up ordering, network delays and drifting clocks.
- The faults are in configuration. A defective sensor or a bad calibration looks different (M6-T8).
- The project is written for Humble and Gazebo Classic; it has not been run by the site’s tests.
What’s next
Other projects in this module
- M7-L1: Debug a ROS 2 SLAM Pipeline: this project.
- M7-L2: Fix a TF Configuration Error
- M7-L3: Diagnose Sensor Timestamp Problems
- M7-L4: Configure Mapping and Localization
- M7-L5: Debug SLAM-to-Nav2 Integration