|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |
Launch files
Messages
Services
Plugins
Recent questions tagged mola_metric_maps at Robotics Stack Exchange
|
mola_metric_maps package from mola repomola mola_bridge_ros2 mola_demos mola_input_lidar_bin_dataset mola_input_rawlog mola_input_rosbag2 mola_input_video mola_kernel mola_launcher mola_metric_maps mola_msgs mola_pose_list mola_relocalization mola_traj_tools mola_viz mola_viz_imgui mola_yaml |
ROS Distro
|
Package Summary
| Version | 3.2.0 |
| License | GPLv3 |
| Build type | AMENT_CMAKE |
| Use | RECOMMENDED |
Repository Summary
| Checkout URI | https://github.com/MOLAorg/mola.git |
| VCS Type | git |
| VCS Version | develop |
| Last Updated | 2026-08-29 |
| Dev Status | DEVELOPED |
| Released | RELEASED |
| Contributing |
Help Wanted (-)
Good First Issues (-) Pull Requests to Review (-) |
Package Description
Additional Links
Maintainers
- Jose-Luis Blanco-Claraco
Authors
mola_metric_maps
Advanced metric map classes for LiDAR odometry and SLAM, built on the
generic mrpt::maps::CMetricMap interface. All maps are serializable,
visualizable, and integrate with the mp2p_icp
registration library.
Map classes
Production-quality maps
| Class | Header | Description |
|---|---|---|
mola::HashedVoxelPointCloud |
HashedVoxelPointCloud.h |
Flat sparse hash map of cubic voxels. Up to 32 points per voxel stored without heap allocation (fixed array SSO). Backend: tsl::robin_map. Implements NearestNeighborsCapable. |
mola::SparseVoxelPointCloud |
SparseVoxelPointCloud.h |
Two-level voxel map: sparse outer blocks + 32³ inner FixedDenseGrid3D. Tracks per-voxel point means; supports voxel-mean ICP matching. Implements NearestNeighborsCapable. The primary workhorse map in MOLA LO/SLAM. |
mola::NDT |
NDT.h |
Normal Distributions Transform map (Magnusson 2007). Fits a Gaussian per voxel; planar voxels expose NearestPlaneCapable, non-planar ones expose NearestNeighborsCapable. Enables automatic point-to-point vs. point-to-plane pairing selection. |
mola::KeyframePointCloudMap |
KeyframePointCloudMap.h |
Keyframe-based map: each keyframe holds a local point cloud plus a SE(3) pose. Supports map corrections without re-inserting points (just update poses). Implements IcpPrepareCapable, NearestPointWithCovCapable, and MetricMapMergeCapable. |
Experimental / work-in-progress maps
| Class | Header | Status |
|---|---|---|
mola::SparseTreesPointCloud |
SparseTreesPointCloud.h |
Coarse 3D grid of independent CSimplePointsMap sub-maps, each with its own KD-tree. Functionally complete but not benchmarked against the hash-based alternatives for typical SLAM workloads. |
mola::OccGrid |
OccGrid.h |
Wraps mrpt::maps::COccupancyGridMap2D with a super-resolution likelihood cache. The cache infrastructure is in place but likelihood population is not yet implemented (// TODO). Not used in any production pipeline. |
Utility / internal classes
| Class | Header | Description |
|---|---|---|
mola::index3d_t<T> |
index3d_t.h |
Discrete 3D integer index. Works as key in std::map and std::unordered_map / tsl::robin_map via the index3d_hash functor, which implements the Teschner et al. (2003) spatial hash. |
mola::FixedDenseGrid3D<T,N,C> |
FixedDenseGrid3D.h |
Dense NxNxN grid (N=2^SIDE_NUM_BITS) allocated with calloc for fast zero-init. Used as the inner block in SparseVoxelPointCloud. Requires trivially-copyable cell types. |
Build and install
Refer to the root MOLA repository.
License
Copyright (C) 2018-2026 Jose Luis Blanco jlblanco@ual.es, University of Almeria
This package is released under the GNU GPL v3 license as open source for research and evaluation purposes only. Commercial licenses available upon request, for this package alone or in combination with the complete SLAM system.
Changelog for package mola_metric_maps
3.2.0 (2026-08-21)
- Merge pull request #195 from MOLAorg/feat/cov2cov-ambiguity-gating mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov
- Merge branch 'develop' into feat/cov2cov-ambiguity-gating
- mola_metric_maps: remove the ambiguity gate from nn_search_cov2cov() Companion to the removal in mp2p_icp#89: firstToSecondDistanceMin/ firstToSecondMinRange were not yet justified by results. Drop the gate logic (and the k=2 / radius-inflated query it required) from IncrementalPointCloud and KeyframePointCloudMap's exact and approximate-cov paths, the flat compat stand-in, and the corresponding test coverage, keeping the range-adaptive matching distance.
- mola_metric_maps: build against mp2p_icp releases without MatchingDistanceProfile rosdep resolves mp2p_icp to the last released binary package in every CI job, so this tree has to compile against an mp2p_icp that predates MatchingDistanceProfile. Adds MatchingDistanceProfileCompat.h, which either aliases the real type or, when the header is absent, supplies a flat-only stand-in with the same small surface. The search implementations are written against that alias and so stay free of preprocessor branches; only the public overload, and the tests that exercise the ambiguity gate, are guarded by MP2P_ICP_HAS_MATCHING_DISTANCE_PROFILE. Both map classes now implement the flat-threshold overload (still the pure virtual upstream) as a forwarder into a shared private nn_search_cov2cov_impl(), so the two public entry points cannot drift apart.
- mola_metric_maps: adopt mp2p_icp::MatchingDistanceProfile in nn_search_cov2cov Follows the mp2p_icp interface change: nn_search_cov2cov() now receives a MatchingDistanceProfile instead of a flat float search distance. Implemented in IncrementalPointCloud and in both KeyframePointCloudMap paths (exact and approximate-cov). The flat, ungated default keeps a dedicated fast path in all three: no per-point range is computed and the KD-tree query stays k=1, so the previous behavior is reproduced exactly and at the same cost. When the ambiguity test is active for a query point, the search radius is inflated by the ratio, so any runner-up able to disqualify the winner is guaranteed to lie inside it, and the best two candidates are kept. In the approximate-cov path the runner-up may live in a different keyframe than the winner, so the best two are folded across all active keyframes rather than per keyframe. Range is measured in the query point's own untransformed (sensor) frame. Tests added for the ambiguity gate in both map classes.
- Merge pull request #193 from MOLAorg/fix/incremental-map-pairing-order Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order
- Give IncrementalPointCloud::nn_search_cov2cov() a canonical pairing order The same defect fixed for KeyframePointCloudMap in bfe6cb2e, which did not cover this map class: the parallel path accumulates correspondences into a tbb::enumerable_thread_specific and merges it by iteration, whose order is unspecified. The permutation is not cosmetic, it reaches the solver, which sums the normal equations over the pairing list in order. This class needs a stronger fix than the keyframe map did, because here the sequential path was not canonical either. The live local points come from snapshotLiveIndices(), a depth-first walk of the k-d tree, so they arrive in tree-topology order rather than in slot order. Tombstones and rebuilds change that shape, so with async_rebuild enabled the pairing order varied between runs even single-threaded. The sort is therefore applied to the shared intermediate match list, before the pairings are assembled, which pins both paths to the same order and makes the result independent of the tree shape a rebuild happened to leave behind. Two sibling call sites in this file already sort that snapshot for the same reason. Sorting the intermediate list rather than the output pairings also keeps the comparison on an 8-byte key instead of a full pairing, and gives the assembly pass ascending access into the coordinate and covariance buffers. Each local point yields at most one match, so its slot is a unique key and the resulting order is total. test_pairing_order_is_canonical asserts ascending local_idx and identical order across repeated calls, over a cloud with tombstones so tree order really does diverge from slot order, and large enough that TBB splits the range across workers. It fails without this change with "Pairings are not in canonical (ascending local_idx) order".
- silent a gcc warning (safe)
- Merge remote-tracking branch 'origin/feat/map-frame-gauge-change' into feat/map-frame-gauge-change
- Merge branch 'develop' into feat/map-frame-gauge-change
- Contributors: Jose Luis Blanco-Claraco
3.1.1 (2026-08-10)
- mola_metric_maps: fix calloc arg order and nodiscard warnings on newer GCC.
- Give nn_search_cov2cov() a canonical pairing order. The parallel path merged per-thread correspondences in unspecified order, making ICP results non-deterministic run to run; now sorted by local_idx to match the sequential path.
- IncrementalPointCloud: rebuild the k-d tree on a global SE(3) re-map. changeCoordinatesReference() rewrote coordinates in place without resizing, so the k-d tree kept stale split planes and nearest-neighbor queries silently returned wrong results. Fixes #186.
File truncated at 100 lines see the full file
Package Dependencies
| Deps | Name |
|---|---|
| ros_environment | |
| ament_cmake_xmllint | |
| ament_cmake_gtest | |
| ament_cmake | |
| ament_lint_auto | |
| ament_lint_common | |
| mola_common | |
| mola_kernel | |
| mrpt_libmaps | |
| mp2p_icp | |
| nanoflann_vendor |
System Dependencies
Dependant Packages
| Name | Deps |
|---|---|
| mola | |
| mola_lidar_odometry | |
| mola_sm_loop_closure |