Skip to the project
FixTheRobot Explore Robotics / Localization & SLAM / M7 / M7-L1

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.sh script.

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.

  1. Terminal 1: export TURTLEBOT3_MODEL=burger, then from the project folder ros2 launch launch/lab1.launch.py. A Gazebo window with the TurtleBot 3 world opens.
  2. Terminal 2: ros2 run turtlebot3_teleop teleop_keyboard and drive forward and turn a little. Keep this terminal for driving.
  3. Terminal 3: your debugging terminal (source ROS 2 and set TURTLEBOT3_MODEL here 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.

  1. Problem and experiment. Start the launch file and drive a little. Open RViz (rviz2) with the fixed frame odom and add the LaserScan and Map displays. Note what you see.
  2. 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?
  3. Use the tool below with the contents of config/slam_params.yaml and the facts you collected (the robot publishes /scan, the odometry frame is named odom, the base frame base_footprint) to see which parameters disagree with the robot.
  4. 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.
  5. Evaluate. Drive a loop around the world so that the map closes, then run ./check.sh.
  6. 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

    Troubleshooting guide
    SymptomLikely causeWhat to try
    Gazebo does not open or the robot does not appearMissing TURTLEBOT3_MODEL, no graphics in a VM, or an old Gazebo process still runningexport TURTLEBOT3_MODEL=burger; killall gzserver gzclient; check you have a display
    ros2 topic hz /scan shows nothingSimulation paused or still loading; or /scan is on another nameros2 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 publishCheck use_sim_time on the node and the frame names against view_frames
    /map appears but stays tinyYou 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 changeThere are several faults; the first no longer masks the next but you cannot see it yetKeep going down the data path; read the node log after every change
    The parameter file edit has no effectThe 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.

    Evaluation criteria
    CriterionHow to checkPasses when
    The SLAM node is on simulated timeros2 param get /slam_toolbox use_sim_timeprints True (automated)
    The SLAM node receives the lidarros2 topic info /scan -vlists slam_toolbox as a subscription (automated)
    The frame tree connectsview_frames or tf2_echomap → base_footprint exists (automated)
    A real map is builtcheck.sh; RVizmore than 1500 known cells; walls are straight (partly automated)
    You can name each fault and its evidenceyour notes from task 6three 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.

    1. 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_time returns False; the log reports huge time differences or extrapolation. Fix: True (and also use_sim_time: true in the YAML).
    2. Wrong scan topic. scan_topic: /lidar/scan, but the robot publishes /scan. Evidence: ros2 topic info /scan -v shows no subscription from slam_toolbox. Fix: /scan.
    3. Wrong odometry frame. odom_frame: odometry; the TurtleBot publishes odom. Evidence: view_frames shows odom, not odometry; 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

    Next

    M7-L2: Fix a TF Configuration Error

    Repair a broken TF tree (duplicate parents, wrong frame names, missing static transform).