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.
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.
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
| Mode | Launch file | Behaviour | Use when |
|---|---|---|---|
| Online asynchronous | online_async_launch.py | Processes the most recent scan; may skip scans if the solver is busy; always up to date | Default on robots: real-time, tolerant of load |
| Online synchronous | online_sync_launch.py | Processes every scan in order; can fall behind and drop messages when overloaded | Small robots with spare CPU where every scan matters |
| Offline | offline_launch.py | Maps from a recorded run (bag), as fast as possible, and can optimise the whole graph | Building a high-quality map from logged data |
| Localisation | same launch, mode: localization | Loads a serialised pose graph and localises in it (M7-T5) | Operating in a known map |
| Lifelong | mapping mode with a loaded graph | Continues to add and remove scans in an existing graph to adapt to change | Changing 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.
| Group | Parameter (typical default) | Meaning and trade-off |
|---|---|---|
| Frames and topics | odom_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) |
| Mode | mode (mapping | localization) | Select mapping or localisation |
| Clock | use_sim_time (false) | Must equal the system’s clock choice |
| Keyframes | minimum_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 |
| Map | resolution (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 |
| Throughput | throttle_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 matching | use_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 closure | do_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 |
| Solver | solver_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
| Strength | Limitation / failure mode |
|---|---|
| Works out of the box with Nav2; real-time on small computers; full loop closure and pose graph | 2D only; assumes a planar floor and a lidar with a long enough range |
| Serialised graphs support relocalisation, merging and lifelong mapping | Long corridors and symmetric rooms cause degeneracy and false loops (M5-T4, M5-T10) |
| Offline mode can produce a clean map from a messy run | Large environments increase graph size and solver time; async mode can lag |
| Interactive editing of the graph | Quality depends on odometry and timing; bad parameters give smeared maps without errors |
A worked example: keyframe spacing, map memory and a smeared corner
- Keyframe rate. The robot drives at 0.5 m/s with a 10 Hz lidar. With
minimum_travel_distance: 0.5a 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. Withminimum_travel_distance: 0.2the 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. - 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 raisemap_update_intervalor the resolution on large maps (M7-T8). - 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 /scanshows 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. - 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.35rejects 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). - 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_frameandscan_topicmatch 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
- SLAM Toolbox is a keyframe filter, correlation scan matcher, pose graph with loop closure and a sparse Ceres solver, publishing /map and map → odom.
- Online async is the default for robots; offline mode builds the best maps from logged runs.
- The parameters that matter: frames and topics, keyframe spacing, resolution, loop-closure thresholds and throttling.
- Save both the occupancy map (for Nav2) and the serialised pose graph (for localisation and continued mapping).
- Most failures are inputs (frames, timing, odometry); inspect them before tuning the algorithm.
References and further reading
Primary papers and authoritative documentation.
- Macenski, S. and Jambrecic, I. (2021). SLAM Toolbox: SLAM for the dynamic world. Journal of Open Source Software 6(61), 2783.
- Konolige, K., Grisetti, G., Kümmerle, R., Burgard, W., Limketkai, B. and Vincent, R. (2010). Efficient sparse pose adjustment for 2D mapping. IEEE/RSJ IROS.
- Agarwal, S., Mierle, K. et al. Ceres Solver. ceres-solver.org.
- Macenski, S., Martín, F., White, R. and Ginés Clavero, J. (2020). The Marathon 2: A navigation system. IEEE/RSJ IROS.
- Grisetti, G., Kümmerle, R., Stachniss, C. and Burgard, W. (2010). A tutorial on graph-based SLAM. IEEE Intelligent Transportation Systems Magazine 2(4).
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.
Related content
Nothing below is required to finish this lesson.
- BeforeM7-T3: Sensor Topics and Message Timing
Explain stamps, QoS, message filters and the extrapolation errors caused by bad timestamps.
- LabM7-L4: Configure Mapping and Localization
Build a map, save it and serialised graph, then relaunch in localization mode with a correct initial pose.
Get notified when the next lesson and new labs are released.
One email per new lesson or lab.