SLAM (Simultaneous Localization and Mapping) is one of those robotics concepts that sounds harder than it is to get working. With the right tools — specifically, a spinning LIDAR and slam_toolbox — you can get a navigatable 2D map of a room in under an hour. This is the exact setup we use in the Room-Nav and Mobile-Light kits.
Hardware you need
- RPLIDAR A1 or A2 — SLAMTEC's entry-level spinning LIDAR ($99-$129). A1 gives 5.5m range, A2 gives 8m range.
- A robot that moves (differential drive minimum) — SLAM needs the robot to explore the space.
- ROS2 Humble — any arm64 or x86 Linux platform (Jetson Orin Nano, Raspberry Pi 5, Ubuntu laptop for testing).
- Wheel odometry — slam_toolbox works without it but quality is significantly better with encoder feedback.
Install slam_toolbox
# On ROS2 Humble (arm64 or x86)
sudo apt install ros-humble-slam-toolbox ros-humble-rplidar-ros
# Verify both are installed
ros2 pkg list | grep -E "slam|rplidar"Launch the LIDAR
# RPLIDAR A1 on USB
ros2 run rplidar_ros rplidar_composition \
--ros-args \
-p serial_port:=/dev/ttyUSB0 \
-p frame_id:=laser \
-p angle_compensate:=true
# Verify scan data is publishing
ros2 topic echo /scan --onceThe RPLIDAR A1 uses /dev/ttyUSB0 by default. If you have multiple USB devices, the device number may shift on reboot. Create a udev rule to assign a persistent name: SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="rplidar"
Configure slam_toolbox for online mapping
slam_toolbox:
ros__parameters:
# Mode: online_async for real-time mapping
mode: mapping
map_file_name: ""
# LIDAR frame — match your URDF
odom_frame: odom
map_frame: map
base_frame: base_link
scan_topic: /scan
# Tuning for RPLIDAR A1
minimum_travel_distance: 0.1 # meters between scans
minimum_travel_heading: 0.1 # radians
scan_buffer_size: 10
scan_buffer_maximum_scan_distance: 5.0 # A1 reliable range
# Loop closure aggressiveness — lower = more conservative
link_match_minimum_response_fine: 0.35Launch SLAM
# Launch slam_toolbox in async online mode
ros2 launch slam_toolbox online_async_launch.py \
params_file:=./slam_toolbox_params.yaml \
use_sim_time:=false
# In another terminal — open RViz2 to see the map build
rviz2 -d /opt/ros/humble/share/slam_toolbox/rviz/mapper_visualization.rvizDrive and map
slam_toolbox builds the map as the robot moves. You need to drive slowly and cover the space — too fast and loop closure quality drops. In RViz2, you'll see the occupancy grid grow in real time. Gray cells are unmapped, black cells are obstacles, white cells are free space.
- Drive at ≤ 0.3 m/s for best loop closure. The A1 scans at 5.5Hz — too fast and you skip scan positions.
- Close loops deliberately: return to starting position so slam_toolbox can correct accumulated drift.
- Avoid glass walls and mirrors — they cause phantom obstacles or transparent walls in the map.
- The A1 has a 15cm minimum range — objects closer than 15cm show up as holes in the map.
Save the map
# Save while slam_toolbox is still running
ros2 service call /slam_toolbox/save_map slam_toolbox/srv/SaveMap \
"{name: {data: '/home/robot/maps/my_room'}}"
# This creates:
# my_room.yaml — map metadata (resolution, origin)
# my_room.pgm — occupancy grid image (black=obstacle, white=free)
# Load a saved map for nav2 localization (AMCL)
ros2 launch nav2_bringup localization_launch.py \
map:=/home/robot/maps/my_room.yamlFor the Room-Nav kit, save your map, then use nav2 with AMCL for localization. The full bringup is: slam_toolbox (map once) → save map → nav2 + AMCL (localize in saved map) → send nav2 goal poses via RViz2 or the action server.
Common issues and fixes
| ISSUE | CAUSE | FIX |
|---|---|---|
| Map drifts or splits | No loop closure, too-fast driving | Slow down, revisit start position |
| Large holes in map | Glass, mirrors, or min-range violations | Add ultrasonic for <15cm blind spots |
| No /scan topic | Wrong USB device path | Check ls /dev/ttyUSB* after plugging in |
| LIDAR not spinning | Insufficient USB current | Use powered USB hub or direct 5V supply |
| Noisy map near motors | EMI from PWM motor signals | Add ferrite bead on motor wires near USB |