cartographer/configuration_files/trajectory_builder_3d.lua

Overview

Configuration for 3D local SLAM (LocalTrajectoryBuilder3D). Controls 3D point cloud processing, scan matching, hybrid grid submaps, and pose extrapolation.

Configuration

MAX_3D_RANGE = 60.
INTENSITY_THRESHOLD = 40

TRAJECTORY_BUILDER_3D = {
  min_range = 1.,
  max_range = MAX_3D_RANGE,
  num_accumulated_range_data = 1,
  voxel_filter_size = 0.15,

  high_resolution_adaptive_voxel_filter = {
    max_length = 2.,
    min_num_points = 150,
    max_range = 15.,
  },

  low_resolution_adaptive_voxel_filter = {
    max_length = 4.,
    min_num_points = 200,
    max_range = MAX_3D_RANGE,
  },

  use_online_correlative_scan_matching = false,
  real_time_correlative_scan_matcher = {
    linear_search_window = 0.15,
    angular_search_window = math.rad(1.),
    translation_delta_cost_weight = 1e-1,
    rotation_delta_cost_weight = 1e-1,
  },

  ceres_scan_matcher = {
    occupied_space_weight_0 = 1.,
    occupied_space_weight_1 = 6.,
    intensity_cost_function_options_0 = {
      weight = 0.5,
      huber_scale = 0.3,
      intensity_threshold = INTENSITY_THRESHOLD,
    },
    translation_weight = 5.,
    rotation_weight = 4e2,
    only_optimize_yaw = false,
    ceres_solver_options = {
      use_nonmonotonic_steps = false,
      max_num_iterations = 12,
      num_threads = 1,
    },
  },

  motion_filter = {
    max_time_seconds = 0.5,
    max_distance_meters = 0.1,
    max_angle_radians = 0.004,
  },

  rotational_histogram_size = 120,

  imu_gravity_time_constant = 10.,
  pose_extrapolator = {
    use_imu_based = false,
    constant_velocity = {
      imu_gravity_time_constant = 10.,
      pose_queue_duration = 0.001,
    },
    imu_based = {
      pose_queue_duration = 5.,
      gravity_constant = 9.806,
      pose_translation_weight = 1.,
      pose_rotation_weight = 1.,
      imu_acceleration_weight = 1.,
      imu_rotation_weight = 1.,
      odometry_translation_weight = 1.,
      odometry_rotation_weight = 1.,
      solver_options = {
        use_nonmonotonic_steps = false;
        max_num_iterations = 10;
        num_threads = 1;
      },
    },
  },

  submaps = {
    high_resolution = 0.10,
    high_resolution_max_range = 20.,
    low_resolution = 0.45,
    num_range_data = 160,
    range_data_inserter = {
      hit_probability = 0.55,
      miss_probability = 0.49,
      num_free_space_voxels = 2,
      intensity_threshold = INTENSITY_THRESHOLD,
    },
  },

  use_intensities = false,
}

Parameter Reference

Range Data Filtering

Parameter

Type

Description

min_range

float

Ignore returns closer (m)

max_range

float

Max sensor range (m)

num_accumulated_range_data

int

Scans to accumulate

voxel_filter_size

float

Initial voxel filter (m)

Adaptive Voxel Filters

Two filters for different purposes:

High-Resolution (local scan matching):

  • max_length = 2.0 — Max voxel size

  • min_num_points = 150 — Target point count

  • max_range = 15.0 — Affects points within 15m

Low-Resolution (loop closure):

  • max_length = 4.0 — Max voxel size

  • min_num_points = 200 — Target point count

  • max_range = 60.0 — Full range

Scan Matching

Real-Time Correlative (3D)

  • linear_search_window — Translation search (m)

  • angular_search_window — Rotation search (rad)

  • Smaller windows than 2D (3D search is expensive)

Ceres Scan Matcher (3D)

Parameter

Description

occupied_space_weight_0

Weight for high-res grid

occupied_space_weight_1

Weight for low-res grid

intensity_cost_function_options_0

Intensity-based matching config

translation_weight

Translation prior weight

rotation_weight

Rotation prior weight

only_optimize_yaw

Constrain to 2D yaw-only

ceres_solver_options

Ceres config

Intensity Cost Function (when use_intensities = true):

  • weight — Intensity term weight

  • huber_scale — Robust loss scale

  • intensity_threshold — Min intensity for returns

Motion Filter

Tighter thresholds than 2D (3D lidars have higher data rate):

  • max_time_seconds = 0.5

  • max_distance_meters = 0.1

  • max_angle_radians = 0.004 (~0.23°)

Rotational Histogram

rotational_histogram_size = 120 — Bins for rotational scan matching (branch-and-bound).

Pose Extrapolator

Same structure as 2D. IMU-based recommended for 3D.

Submaps (Hybrid Grid)

Parameter

Description

high_resolution

Near-range voxel size (m)

high_resolution_max_range

High-res range limit (m)

low_resolution

Far-range voxel size (m)

num_range_data

Insertions per submap

Range Data Inserter:

  • hit_probability / miss_probability — Log-odds updates

  • num_free_space_voxels — Free voxels along ray

  • intensity_threshold — Intensity filter

Intensities

use_intensities = false — Enable intensity-based scan matching. Requires intensity_cost_function_options_0 in Ceres config.

Tuning Guide

For Velodyne/Ouster 3D Lidars

  • voxel_filter_size = 0.15 (adjust for point density)

  • high_resolution = 0.10, low_resolution = 0.45

  • Enable use_intensities if lidar provides calibrated intensity

For Large Outdoor Environments

  • Increase max_range to sensor max

  • Increase high_resolution_max_range to 30-40m

  • Increase submaps.num_range_data to 200-300

For Fast Motion (Vehicles)

  • Enable pose_extrapolator.use_imu_based = true

  • Decrease motion_filter thresholds

  • Increase ceres_scan_matcher.translation_weight

For Indoor/Structured Environments

  • Decrease high_resolution to 0.05

  • Enable only_optimize_yaw = true if mostly planar

  • Use use_online_correlative_scan_matching = true for initialization

See Also