Skip to the lesson
FixTheRobot Explore Robotics / Localization & SLAM / M7 SLAM with ROS 2 / M7-T4

Localization & SLAM · Theory · M7

M7-T4 — SLAM Toolbox and Mapping Workflows

SLAM Toolbox turns the pose-graph theory of Module 4 into a ROS 2 node. Knowing what its parameters mean is the difference between a clean map and a smeared one.

  • Lesson 4 of 8
  • Module 7: SLAM with ROS 2
  • Theory
  • About 10 minutes to read

SLAM Toolbox (Macenski and Jambrecic, 2021) is the default 2D lidar SLAM package for ROS 2 and the one used by Nav2. Internally it is the pipeline of Modules 3 and 4: scan matching, a sparse pose graph with loop closure, and a nonlinear solver (derived from Karto and Konolige’s sparse pose adjustment). This lesson explains its modes and the parameters you will actually change, and what each trades off.

Learning objectives

After this lesson, you should be able to:

  • Describe the SLAM Toolbox pipeline and relate each stage to the algorithms of earlier modules.
  • Choose between online asynchronous, online synchronous, offline and lifelong operation.
  • Explain the parameters for frames, topics, keyframe spacing, resolution, loop closing and the solver.
  • Launch SLAM Toolbox with a parameter file and use its services to save and serialise a map.

The problem and the intuition

SLAM Toolbox does not process every scan. A robot rolling at 0.5 m/s with a 10 Hz lidar produces a scan every 5 cm, far too similar to be worth a graph node each. It therefore keeps a scan only when the robot has moved or turned enough (minimum_travel_distance, minimum_travel_heading) and enough time has passed (minimum_time_interval). Each kept scan is matched to the nearby recent scans to get a relative-pose constraint, added as a node, and checked against older scans for loop closures. The whole graph is re-optimised by a sparse solver when constraints arrive. The map is simply all kept scans drawn at their optimised poses.

Seen this way, most parameters have an obvious meaning: how often to keep a scan, how hard to search for a match, how sure to be before closing a loop, and how fine to draw the map. And most failures are traceable: a map that smears at corners means the scan matcher was fed a poor initial guess (odometry or timing), a map with doubled walls means a missed or late loop closure, a wall bent at the end means a bad loop closure.

SLAM Toolbox = keyframe filter + scan matcher + pose graph + loop closure + sparse solver. The parameters set how often, how far and how sure.

SLAM Toolbox pipelineScans are filtered by travel distance and time into keyframes, matched to recent scans with a correlation scan matcher, added to a pose graph, loop closures are searched among older scans, and a sparse pose-graph solver (Ceres) updates the poses; the map is rendered from the poses and scans.Scan/scan + TF Keyframe filterdistance / heading / time Scan matchercorrelation, response Pose graphnodes + edges Loop closuresearch + verify Ceres solversparse pose adjustment Map + TF/map, map→odom Online: runs while driving. Offline: same pipeline over a logged run, with the whole graph optimised.
The SLAM Toolbox pipeline.

Modes, workflow and parameters

Problem. Build a 2D occupancy-grid map and a consistent pose graph from a 2D lidar and odometry, in real time or from a recorded run, and serve the map and the map → odom transform to the rest of the system.

Assumptions. Planar motion; a 2D lidar with a stable frame; odometry good enough for a coarse initial guess for scan matching; a mostly static environment; correct TF and timestamps (M7-T2, M7-T3).

Modes of operation

SLAM Toolbox modes
ModeLaunch fileBehaviourUse when
Online asynchronousonline_async_launch.pyProcesses the most recent scan; may skip scans if the solver is busy; always up to dateDefault on robots: real-time, tolerant of load
Online synchronousonline_sync_launch.pyProcesses every scan in order; can fall behind and drop messages when overloadedSmall robots with spare CPU where every scan matters
Offlineoffline_launch.pyMaps from a recorded run (bag), as fast as possible, and can optimise the whole graphBuilding a high-quality map from logged data
Localisationsame launch, mode: localizationLoads a serialised pose graph and localises in it (M7-T5)Operating in a known map
Lifelongmapping mode with a loaded graphContinues to add and remove scans in an existing graph to adapt to changeChanging environments (advanced)

Launching

ros2 launch slam_toolbox online_async_launch.py \
  slam_params_file:=/path/to/mapper_params_online_async.yaml use_sim_time:=true

Parameters you will change

Names and defaults follow the shipped mapper_params_online_async.yaml; check the file in your installed version.

SLAM Toolbox parameters
GroupParameter (typical default)Meaning and trade-off
Frames and topicsodom_frame (odom), map_frame (map), base_frame (base_footprint), scan_topic (/scan)Must match the robot’s TF tree and topic; the most common source of “no map” (M7-T2)
Modemode (mapping | localization)Select mapping or localisation
Clockuse_sim_time (false)Must equal the system’s clock choice
Keyframesminimum_travel_distance (0.5 m), minimum_travel_heading (0.5 rad), minimum_time_interval (0.5 s)Larger = fewer nodes, faster, coarser; smaller = denser graph, slower
Mapresolution (0.05 m), map_update_interval (5 s), max_laser_range (20 m)Resolution sets memory and detail; max range should not exceed the sensor’s reliable range
Throughputthrottle_scans (1), transform_publish_period (0.02 s), transform_timeout (0.2 s), tf_buffer_duration (30 s)Process every n-th scan; TF publication rate; patience for late transforms
Scan matchinguse_scan_matching (true), link_match_minimum_response_fine (0.1), correlation_search_space_dimension (0.5 m)Search window and acceptance threshold for matches
Loop closuredo_loop_closing (true), loop_search_maximum_distance (3.0 m), loop_match_minimum_response_coarse (0.35), loop_match_minimum_response_fine (0.45)How far to look for loops and how good a match must be; lower thresholds = more loops, more false ones
Solversolver_plugin (Ceres), ceres_linear_solver (SPARSE_NORMAL_CHOLESKY), ceres_loss_function (None)Optimiser settings; a robust loss can reduce the effect of a bad loop

Services and saving

ros2 service call /slam_toolbox/save_map slam_toolbox/srv/SaveMap "{name: {data: 'my_map'}}"          # occupancy grid: my_map.pgm + my_map.yaml
ros2 service call /slam_toolbox/serialize_map slam_toolbox/srv/SerializePoseGraph "{filename: 'my_graph'}"  # pose graph: my_graph.posegraph + my_graph.data

The second form is what localisation and continued mapping need (M7-T6). SLAM Toolbox also provides an RViz plugin with buttons for these services, and an interactive mode for moving nodes by hand.

keyframe
a scan that passed the distance, heading and time filters and became a graph node.
response
the scan-matcher score of a candidate alignment (0 to 1); thresholds decide acceptance.
Ceres
the nonlinear least-squares solver used for the pose graph.
serialised pose graph
the saved graph of nodes, scans and edges (not just the picture of the map).

Strengths, limitations, failure modes

SLAM Toolbox strengths and limitations
StrengthLimitation / failure mode
Works out of the box with Nav2; real-time on small computers; full loop closure and pose graph2D only; assumes a planar floor and a lidar with a long enough range
Serialised graphs support relocalisation, merging and lifelong mappingLong corridors and symmetric rooms cause degeneracy and false loops (M5-T4, M5-T10)
Offline mode can produce a clean map from a messy runLarge environments increase graph size and solver time; async mode can lag
Interactive editing of the graphQuality depends on odometry and timing; bad parameters give smeared maps without errors

A worked example: keyframe spacing, map memory and a smeared corner

  1. Keyframe rate. The robot drives at 0.5 m/s with a 10 Hz lidar. With minimum_travel_distance: 0.5 a keyframe is added about every 1 s (0.5 m at 0.5 m/s), i.e. one in ten scans. A 100 m path produces about 200 graph nodes. With minimum_travel_distance: 0.2 the same path has 500 nodes; the solver and loop search cost grow accordingly. On a turn in place, minimum_travel_heading (0.5 rad ≈ 28.6°) applies: a full turn adds about 12 keyframes.
  2. Map memory. The map is a grid of cells, 1 byte each. A 50 m × 50 m area at 0.05 m resolution is 1 000 × 1 000 = 106 cells, or 1 MB. At 0.02 m it is 2 500 × 2 500 = 6.25 × 106 cells, 6.25 MB, and it is sent over DDS every map_update_interval. For a 200 m × 200 m site at 0.05 m: 4 000 × 4 000 = 16 MB per message, which is a reason to raise map_update_interval or the resolution on large maps (M7-T8).
  3. A smeared corner. After a turn, the map shows every wall at the corner twice, offset by about 10 cm. The scan matcher is working (the walls are straight) but the initial guess handed to it was poor. Two suspects: the odometry rotates less than the robot does (wheel slip), or the scan is stamped late (M7-T3). Checking ros2 topic delay /scan shows 0.1 s: at a turn rate of 1 rad/s, a wall 5 m away is displaced by 0.5 m, much more than the observed 10 cm, so the true stamp error is smaller, but the direction of the fix is clear.
  4. A loop closure threshold. The map has a long corridor loop that never closes: the end of the corridor is 0.4 m from where it started, with parallel walls. The coarse response threshold loop_match_minimum_response_coarse: 0.35 rejects the candidate because the match is ambiguous. Lowering it to 0.25 closes the loop here, but in a building with identical corridors it might close a wrong one. The right approach is to lower it slowly and inspect the loop closures in RViz (the graph visualisation shows the accepted edges).
  5. Async versus sync. In async mode, at 10 Hz scans and a solver that takes 150 ms on a large graph, the node processes the scans it can and skips the rest; the map stays current. In sync mode it processes all of them in order, the queue grows, and eventually messages are dropped with warnings. The mapping is the same; the behaviour under load differs.

Engineering implications and limitations

Engineering implications

  • Start from the shipped parameter file and change only what you understand; keep your file in version control next to the launch file.
  • Set the frames first. Confirm that base_frame, odom_frame and scan_topic match your robot before tuning anything else.
  • Map slowly at first. Drive at walking speed with gentle turns until the map is clean; loop closure only helps if the local maps are good.
  • Close loops deliberately. Revisit places along the same route and from the same direction; save both the occupancy map and the serialised graph at the end.
  • Watch the logs. Warnings about dropped messages, extrapolation, or failure to compute odom pose name the problem directly.
  • Use offline mode for production maps. Record a bag, run offline, inspect and edit the graph, then save.

Limits

SLAM Toolbox is a 2D system. It assumes a planar, mostly static environment and a lidar with enough structure. It inherits the degeneracy of lidar scan matching in long featureless corridors and the aliasing of repetitive layouts, and it does not use an IMU or vision. For 3D or multi-sensor SLAM use the systems of Modules 5 and 6; for large-scale deployment add monitoring of the loop-closure quality and the graph size.

Common misconceptions

“More keyframes always mean a better map.”

Beyond a point they only add compute; scans taken a few centimetres apart carry almost the same information.

“Lowering the loop-closure threshold fixes missed loops.”

It also admits false ones; a false loop damages the map more than a missed one.

“The saved .pgm map contains everything needed to localise.”

Localisation in SLAM Toolbox needs the serialised pose graph; the .pgm is only the picture.

“If the map looks good, the timing and TF must be right.”

A static room hides timing errors; they show in turns, as smeared corners.

Engineering takeaways

  1. SLAM Toolbox is a keyframe filter, correlation scan matcher, pose graph with loop closure and a sparse Ceres solver, publishing /map and map → odom.
  2. Online async is the default for robots; offline mode builds the best maps from logged runs.
  3. The parameters that matter: frames and topics, keyframe spacing, resolution, loop-closure thresholds and throttling.
  4. Save both the occupancy map (for Nav2) and the serialised pose graph (for localisation and continued mapping).
  5. Most failures are inputs (frames, timing, odometry); inspect them before tuning the algorithm.

References and further reading

Primary papers and authoritative documentation.

Knowledge check

Three conceptual questions. Write an answer, then reveal the explanation. Your answers stay in your browser.

Question 1

A robot moves at 0.4 m/s with minimum_travel_distance: 0.5 and a 10 Hz lidar. Roughly how many scans become keyframes per minute, ignoring turns?

Explanation

The robot travels 0.4 × 60 = 24 m in a minute; one keyframe per 0.5 m gives about 48 keyframes out of 600 scans, i.e. one in about 12 scans.

Question 2

The map shows doubled walls at the end of a loop but straight local walls. Which mechanism is missing or failing?

Explanation

A loop closure: the local scan matching is fine (walls are straight), but the accumulated drift was not corrected because the loop was not detected or accepted. Check the loop-closure thresholds and search distance, and whether the route revisits the same place.

Question 3

Why must you serialise the pose graph if you want to continue mapping or localise later with SLAM Toolbox?

Explanation

The occupancy-grid image does not contain the scans and the graph of constraints that the algorithm needs; the serialised pose graph (.posegraph and .data) does, so SLAM Toolbox can load it and match new scans against the stored ones.

What’s next

A saved map can be used in two ways: to keep mapping, or to localise only. The next lesson compares mapping and localisation modes and shows how to give the robot its starting pose.

Practice this lesson

Configure Mapping and Localization

Build a map, save it and serialised graph, then relaunch in localization mode with a correct initial pose.

Next lesson

M7-T5 — Mapping vs Localization Mode

Choose between mapping, localization and lifelong modes and set the initial pose properly.

Nothing below is required to finish this lesson.