I use slam_toolbox (source code) in ROS2 to run 2D SLAM on my robots. It combines LiDAR scan information alongside odometry to generate a map (.pgm + .yaml output).

I’ve used slam_toolbox to generate maps on:


Installing is as easy as running the following command:

sudo apt install ros-$ROS_DISTRO-slam-toolbox 

Using slam_toolbox

Launch Teleop on one window, and start SLAM using the following command:

ros2 launch slam_toolbox online_async_launch.py 

This will start the SLAM node, and start publishing the generated map to the /map topic.

If you want to launch with custom parameter files, run

ros2 launch slam_toolbox online_async_launch.py slam_params_file:=/f1tenth_ws/src/f1tenth_system/f1tenth_stack/config/f1tenth_online_async.yaml

On another terminal, open rviz by running



  • Add /map by topic (slam_toolbox publishes the latest map to this)
  • Add /graph_visualization by topic (optional, I personally do like this)
  • On top left corner of rviz, panels add new panel add SlamToolBoxPlugin panel
  • Once you’re done mapping, save the map using the plugin.
  • You can give it a name in the text box next to Save Map. Map will be saved in whichever directory you ran slam_toolbox.

The other way to save a map is through the terminal, by running

ros2 run nav2_map_server map_saver_cli -f map_name

Generated Map Explained

this would be the .yaml file generated. It’s actually quite straightforward.

image: Spielberg_map.png
resolution: 0.05796
origin: [-84.85359914210505,-36.30299725862132, 0.000000]
negate: 0
occupied_thresh: 0.45
free_thresh: 0.196

The resolution tells you the correspondence of pixels to meters.

The origin tells you where the (0,0) in the pixel space corresponds to.


The main reason why your map generated is terrible is because of BAD Odometry.

  • When I tried running F1TENTH SLAM for the first time, my odometry was inverted. As soon as I fixed that, the map generated was pretty clean
  • When I tried it on the Create3


I’ve had so many problems with slam_toolbox not working. Every single time, it had to do with inverted odometry.

The recommendation is to just look at the odom and base_link. They should correspond with each other as you move them in real life.

In my case, for some reason, as I was moving in one direction, the interpretation was going in the exact opposite direction. I just flipped the LiDAR around by 180 degrees, and that fixed the issue.


I learned to use this by consulting the F1TENTH lecture slides, which can be found here.

  • I’m pretty sure it’s slam_params_file instead of params_file everywhere?? I checked with ros2 param get slam_toolbox max_laser_range, the other one actually works. I figured it out from this source code
  • It’s slam_params_file on the newer ROS2 distributions