# cartographer/mapping/3d/range_data_inserter_3d.h ## Overview `RangeDataInserter3D` inserts 3D range data (hits and misses) into a `HybridGrid`, and optionally an `IntensityHybridGrid`, using precomputed log-odds lookup tables. It is the 3D counterpart of the 2D probability-grid range data inserter and is used by `Submap3D` to update its high- and low-resolution hybrid grids. ## Class: `cartographer::mapping::RangeDataInserter3D` ### Construction ```cpp explicit RangeDataInserter3D(const proto::RangeDataInserterOptions3D& options); ``` Precomputes two lookup tables via `ComputeLookupTableToApplyOdds(Odds(p))`: - `hit_table_` from `hit_probability` (must be > 0.5). - `miss_table_` from `miss_probability` (must be < 0.5). ### Insert ```cpp void Insert(const sensor::RangeData& range_data, HybridGrid* hybrid_grid, IntensityHybridGrid* intensity_hybrid_grid) const; ``` Insertion order: 1. **Hits.** Every point in `range_data.returns` is rasterized into its voxel and the `hit_table_` is applied with `ApplyLookupTable`. Hits are inserted before misses so that a hit in a cell is never overwritten by a miss in the same cell — hits have priority. 2. **Misses.** `InsertMissesIntoGrid` casts a ray from `range_data.origin` to each hit voxel. The number of samples along the ray equals the Chebyshev distance between the origin and hit cells, and only the last `num_free_space_voxels` voxels before the hit are updated with `miss_table_` (for performance). This frees up space directly in front of surfaces. 3. **Intensities.** If an intensity grid is provided and the point cloud carries intensities, points with intensity above `intensity_threshold` are skipped and the rest are added via `IntensityHybridGrid::AddIntensity`. 4. `hybrid_grid->FinishUpdate()` finalizes the batch of updates for the grid's internal caching. ```cpp void InsertMissesIntoGrid(const std::vector& miss_table, const Eigen::Vector3f& origin, const sensor::PointCloud& returns, HybridGrid* hybrid_grid, const int num_free_space_voxels); ``` ## Options `proto::RangeDataInserterOptions3D`: | Field | Type | Meaning | |-------|------|---------| | `hit_probability` | double | Occupancy probability applied to hit voxels (must be > 0.5) | | `miss_probability` | double | Occupancy probability applied to miss voxels (must be < 0.5) | | `num_free_space_voxels` | int | Number of voxels before each hit updated as free space | | `intensity_threshold` | double | Only intensities below this value are inserted | ## Configuration From `trajectory_builder_3d.lua` (embedded in `submaps`): ```lua range_data_inserter = { hit_probability = 0.55, miss_probability = 0.49, num_free_space_voxels = 5, intensity_threshold = 0.95, } ``` `CreateRangeDataInserterOptions3D()` reads the four keys and validates the hit/miss probability bounds. ## Role in the SLAM Pipeline `Submap3D::InsertData` uses this inserter to update the high-resolution hybrid grid, the low-resolution hybrid grid, and (when configured) the intensity hybrid grid. Because a `RangeDataInserter3D` instance is shared between submaps, the precomputed lookup tables are built once. ## See Also - [Submap3D](submap_3d.md) — Owns and applies the inserter - [HybridGrid](hybrid_grid.md) — The grid being updated - [RangeData](../../sensor/range_data.md) — The input data structure - [ProbabilityGrid](../2d/probability_grid.md) — 2D counterpart