# cartographer/mapping/submaps.h ## Overview `Submap` classes represent local map regions as probabilistic grids. They are the fundamental building blocks of Cartographer's mapping system. Separate implementations exist for 2D and 3D. ## Class Hierarchy ``` Submap (abstract) ├── Submap2D │ ├── ProbabilityGrid (grid_2d.h) │ └── TSDF (tsdf_2d.h) -- alternative representation └── Submap3D └── HybridGrid (3d/hybrid_grid.h) ``` ## Class: `cartographer::mapping::Submap` ### Interface ```cpp class Submap { public: explicit Submap(const transform::Rigid3d& local_pose); virtual ~Submap() {} const transform::Rigid3d& local_pose() const { return local_pose_; } int num_range_data() const { return num_range_data_; } bool insertion_finished() const { return insertion_finished_; } void set_insertion_finished() { insertion_finished_ = true; } // Subclasses implement grid access virtual std::unique_ptr ToProto() const = 0; virtual void UpdateFromProto(const proto::Submap& proto) = 0; protected: const transform::Rigid3d local_pose_; int num_range_data_ = 0; bool insertion_finished_ = false; }; ``` ### Members - `local_pose` — Pose of submap origin in the local trajectory frame - `num_range_data` — Number of range data insertions into this submap - `insertion_finished` — True when submap has received all its range data ## Class: `cartographer::mapping::Submap2D` Located in `2d/submap_2d.h/.cc`. ### Grid Types 1. **ProbabilityGrid** — Occupancy grid with log-odds representation (default) 2. **TSDF** — Truncated Signed Distance Function grid (alternative) ### Configuration From `trajectory_builder_2d.lua`: ```lua submaps = { num_range_data = 90, grid_options_2d = { grid_type = "PROBABILITY_GRID", -- or "TSDF" resolution = 0.05, }, range_data_inserter = { range_data_inserter_type = "PROBABILITY_GRID_INSERTER_2D", probability_grid_range_data_inserter = { insert_free_space = true, hit_probability = 0.55, miss_probability = 0.49, }, tsdf_range_data_inserter = { truncation_distance = 0.3, maximum_weight = 10., update_free_space = false, -- normal estimation options... }, }, } ``` ### Probability Grid Inserter Updates occupancy using log-odds: - **Hit** (return): `log(hit_probability / (1 - hit_probability))` - **Miss** (free space): `log(miss_probability / (1 - miss_probability))` Default: hit=0.55, miss=0.49 → slight preference for free space. ### TSDF Inserter Stores truncated signed distance to surface. Supports: - Free space updates (optional) - Normal estimation for surface reconstruction - Weighted fusion of multiple scans ## Class: `cartographer::mapping::Submap3D` Located in `3d/submap_3d.h/.cc`. ### Hybrid Grid 3D submaps use a **HybridGrid** — a sparse 3D voxel grid implemented as a hash map (`std::unordered_map`). ### Structure Each submap has two resolutions: - **High resolution** (e.g., 0.10m) — Near range, up to `high_resolution_max_range` (e.g., 20m) - **Low resolution** (e.g., 0.45m) — Far range, up to `max_range` (e.g., 60m) ### Configuration From `trajectory_builder_3d.lua`: ```lua 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 = 40, }, } ``` ### Insertion For each return point: 1. Mark voxel as occupied (update hit probability) 2. Mark `num_free_space_voxels` voxels along ray as free 3. Optionally use intensity for weighting ## Submap Lifecycle ``` 1. Created by TrajectoryBuilder (AddSubmap) 2. Receives range data insertions (num_range_data times) 3. Marked insertion_finished = true 4. New submap created, previous becomes "finished" 5. After loop closure, may be trimmed (overlapping_submaps_trimmer_2d) ``` ## Serialization Submaps are serialized as part of the pose graph state: ```proto message Submap { SubmapId id; Rigid3d local_pose; int32 num_range_data; bool insertion_finished; // Grid data (ProbabilityGrid/TSDF/HybridGrid) } ``` ## Usage ```cpp // Access submap data from pose graph auto submap_data = pose_graph->GetSubmapData(); for (const auto& [submap_id, data] : submap_data) { // data.submap->local_pose() -- submap origin // data.submap->grid() -- access grid cells } // For 2D probability grid auto* prob_grid = dynamic_cast(submap->grid()); for (const auto& cell : prob_grid->cells()) { float prob = prob_grid->GetProbability(cell.index); } ``` ## See Also - [ProbabilityGrid](2d/probability_grid.md) — 2D occupancy grid - [Submap2D](2d/submap_2d.md) — 2D submap representation - [HybridGrid](3d/hybrid_grid.md) — 3D sparse voxel grid