# 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 ```lua 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 - [TrajectoryBuilderInterface](../mapping/trajectory_builder_interface.md) — Local SLAM implementation - [HybridGrid](../mapping/3d/hybrid_grid.md) — Submap representation - [ImuBasedPoseExtrapolator](../sensor/imu_data.md) — IMU integration