Google Cartographer ROS 2 Tutorial: High-Performance Graph SLAM Guide
Google Cartographer with ROS 2: The Ultimate Guide to Real-Time Graph SLAM
If you’ve ever tried to map a large warehouse or a sprawling outdoor campus, you know the "Drift Demon." Over time, small errors in odometry accumulate until your map looks more like a modern art piece than a floor plan.
Enter Google Cartographer.
Originally developed to map Google’s offices, Cartographer is a sophisticated, graph-based SLAM system that provides real-time simultaneous localization and mapping across 2D and 3D configurations. Today, we’re going to walk through how to deploy this beast in a ROS 2 environment.
1. Fundamentals: Why Cartographer is Different
Most SLAM algorithms fall into one of two traps: they are either too computationally expensive for real-time use or too simple to handle large-scale loop closures. Cartographer solves this using a two-tier optimization strategy.
Submaps: Local Consistency
Cartographer doesn’t try to optimize the whole world at once. Instead, it builds a series of Submaps. Each submap is a small, locally consistent piece of the world. As the robot moves, it inserts new LiDAR scans into the current submap using scan matching.
Global Optimization: The Graph
While submaps are being built, a background process—the Global SLAM—is constantly looking for "Loop Closures." When the robot recognizes a previously visited area, Cartographer runs a sparse pose-graph optimization. This "snaps" the submaps together, eliminating the accumulated drift.
The optimization objective function can be simplified as:
Where $\Xi$ represents the poses, $T$ is the transformation, and $\Delta_{i,j}$ is the constraint between scans.
2. Step-by-Step Implementation in ROS 2
We will be using ROS 2 Humble for this guide, as it is the most stable and widely supported distribution for robotics production in 2026.
Step 1: Installation
You don't need to build Cartographer from source unless you are doing heavy custom development. The binary packages are well-maintained.
sudo apt update
sudo apt install ros-humble-cartographer ros-humble-cartographer-ros
Step 2: Understanding the Lua Configuration
The most common point of failure in Cartographer is the Lua configuration file. Unlike many ROS packages that use YAML, Cartographer uses Lua scripts to allow for dynamic, complex logic within the config.
Create a file named my_robot.lua in your package's config folder:
include "map_builder.lua"
include "trajectory_builder.lua"
options = {
map_builder = MAP_BUILDER,
trajectory_builder = TRAJECTORY_BUILDER,
map_frame = "map",
tracking_frame = "base_link",
published_frame = "base_link",
odom_frame = "odom",
provide_odom_frame = true,
use_odometry = true,
use_nav_sat = false,
use_landmarks = false,
num_laser_scans = 1,
num_multi_echo_laser_scans = 0,
num_subdivisions_per_laser_scan = 1,
num_point_clouds = 0,
lookup_transform_timeout_sec = 0.2,
submap_publish_period_sec = 0.3,
pose_publish_period_sec = 5e-3,
trajectory_publish_period_sec = 30e-3,
}
MAP_BUILDER.use_trajectory_builder_2d = true
TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching = true
TRAJECTORY_BUILDER_2D.min_range = 0.1
TRAJECTORY_BUILDER_2D.max_range = 30.0
return options
Step 3: Create the Launch File
You need to tell ROS 2 where to find your configuration and which sensor topics to listen to.
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='cartographer_ros',
executable='cartographer_node',
name='cartographer_node',
output='screen',
parameters=[{'use_sim_time': True}],
arguments=['-configuration_directory', 'path/to/config',
'-configuration_basename', 'my_robot.lua'],
remappings=[('scan', '/your_robot/scan')]
),
Node(
package='cartographer_ros',
executable='cartographer_occupancy_grid_node',
name='occupancy_grid_node',
parameters=[{'resolution': 0.05}]
),
])
Step 4: Running and Visualization
Launch your robot’s state publisher, your LiDAR driver, and then your Cartographer launch file. Open RViz2 and add the Map and TF displays.
Pro Tip: If your map is "jumping" or spinning wildly, your
use_online_correlative_scan_matchingmight be fighting with a poor-quality IMU. Try disabling one or the other to isolate the noise.
3. Saving and Using Your Map
Once you are satisfied with your map, you need to serialize it. Cartographer saves maps in a .pbstream format, which includes the full pose-graph.
# Call the service to finish the trajectory
ros2 service call /finish_trajectory cartographer_ros_msgs/srv/FinishTrajectory "{trajectory_id: 0}"
# Serialize the map to a file
ros2 service call /write_state cartographer_ros_msgs/srv/WriteState "{filename: 'my_map.pbstream'}"
To use this map for future localization (Pure Localization mode), you simply change your Lua config to TRAJECTORY_BUILDER.pure_localization = true and point it to this .pbstream file.
Conclusion: Mastering the Graph
Google Cartographer is a professional-grade tool that rewards deep configuration. By moving from a simple "Filter-based" SLAM to this "Graph-based" architecture, you are giving your robot the ability to truly understand its history and environment.
What's next? Now that your robot has a map, it needs to move through it. Join us in our next post where we cover
Comments
Post a Comment