Quickstart

This guide walks through building Cartographer and running a basic SLAM example.

Prerequisites

  • C++14 compatible compiler (GCC 5.4+, Clang 3.9+)

  • CMake 3.5+

  • Dependencies:

    • Eigen 3.3+

    • Google Test (for tests)

    • Lua 5.3+

    • Protocol Buffers 3.0+

    • Ceres Solver 2.0+

    • Abseil

    • glog

    • gflags

On Ubuntu 20.04+:

sudo apt-get update
sudo apt-get install -y cmake libeigen3-dev liblua5.3-dev \
    libprotobuf-dev protobuf-compiler libceres-dev \
    libabsl-dev libgoogle-glog-dev libgflags-dev \
    ninja-build

Building

cd /path/to/cartographer
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

To run tests:

make test

Running SLAM

Cartographer is a library — you typically use it via the ROS integration (cartographer_ros) or by writing a custom application. For a minimal example, see the cartographer_ros package which provides launch files for common sensor configurations.

Using Configuration Files

Cartographer is configured via Lua files. A typical 2D SLAM setup:

-- my_2d_slam.lua
include "trajectory_builder_2d.lua"

TRAJECTORY_BUILDER_2D = {
  -- Tune these for your sensor
  min_range = 0.1,
  max_range = 30.0,
  voxel_filter_size = 0.025,
}

MAP_BUILDER = {
  use_trajectory_builder_2d = true,
  num_background_threads = 4,
}

Basic C++ Usage

#include "cartographer/mapping/map_builder.h"
#include "cartographer/common/configuration_file_resolver.h"
#include "cartographer/mapping/proto/map_builder_options.pb.h"

// Load configuration
cartographer::common::ConfigurationFileResolver resolver(
    {"/path/to/config_dir"});
auto code = resolver.GetFileContentOrDie("my_2d_slam.lua");
auto options = cartographer::mapping::CreateMapBuilderOptions(
    cartographer::common::MakeLuaParameterDictionary(code).get());

// Create MapBuilder
auto map_builder = cartographer::mapping::CreateMapBuilder(options);

// Add a trajectory
std::set<cartographer::mapping::TrajectoryBuilderInterface::SensorId> sensor_ids;
sensor_ids.insert({"rangefinder", "laser"});
int trajectory_id = map_builder->AddTrajectoryBuilder(
    sensor_ids, options.trajectory_builder_options(),
    [](const cartographer::mapping::TrajectoryBuilderInterface::LocalSlamResultData& data) {
      // Handle local SLAM results (submap updates, pose estimates)
    });

// Feed sensor data
// (Typically done via cartographer_ros or custom sensor bridges)

Sensor Data Format

Sensor data must be wrapped in Cartographer’s data types:

#include "cartographer/sensor/range_data.h"
#include "cartographer/sensor/point_cloud.h"
#include "cartographer/common/time.h"
#include "cartographer/transform/rigid_transform.h"

cartographer::sensor::RangeData range_data;
range_data.origin = Eigen::Vector3f(0, 0, 0);
range_data.returns = cartographer::sensor::PointCloud{
    // Points where laser hit obstacles
};
range_data.misses = cartographer::sensor::PointCloud{
    // Points along rays with no return (free space)
};

auto sensor_data = cartographer::sensor::MakeDispatchable(
    "laser", cartographer::common::FromUniversal(timestamp), range_data);

Serialization

Save/load map state:

// Save
map_builder->SerializeStateToFile(true, "map.pbstream");

// Load
std::map<int, int> trajectory_remapping =
    map_builder->LoadStateFromFile("map.pbstream", true);

Next Steps

  • Explore cartographer_ros for ROS integration with launch files and sensor bridges

  • Review configuration files in configuration_files/ for tuning parameters

  • Read the mapping, sensor, and common API documentation for custom integrations