Skip to content

Registration adapter HILTI exp04 gate receipt

Date: 2026-08-20 Status: frontend precision/performance and deterministic map-artifact non-regression gates passed; the absolute indoor profile retains one baseline violation

Scope

This receipt evaluates the Phase 1 built-in NDT adapter after static production integration into scanmatcher. It compares the adapter with the pre-migration frontend at the same source revision. The comparison is deliberately the offline scan_matcher_offline_runner path: it exercises the production ScanMatcherComponent and, only when --save-map is requested, exports the world-frame merge of the received MapArray submaps. It does not run graph_based_slam, loop closure, colored map authoring, or backend map refinement.

The input is the locally held HILTI 2022 exp04 sequence:

item value
rosbag2 /media/user/aiueo1/datasets/hilti2022/exp04_ros2
LiDAR topic /hesai/pandar
IMU topic /alphasense/imu
bag duration 125.814128037 s
LiDAR / IMU messages 1,258 / 50,198
metadata SHA-256 f256bd10ec4a65fec68ab91455108ba73ac3791043f81e05846be93922d21100
control-point GT /media/user/aiueo1/datasets/hilti2022/exp04_construction_upper_level_gt.txt
GT SHA-256 38cf516e51113254e4ae0207c790f740b19dee08665063e0d8df7bd277040c20
parameters configs/hilti2022/lidarslam_competitive_v2.yaml
parameter SHA-256 53312d748bc6f6ba8f12fab2a11490c5dc2bcbb5b722f318b48500237aac3e17

The baseline is /tmp/lidarslam-baseline-Vn3TiJ at commit 0c08b58f8524ea8ee5288982ca4a1b86450161b2, with the adapter changes absent. The current run uses the working tree at the same commit with the built-in adapter implementation included in the scanmatcher_component.cpp translation unit. Both trees received the same runner-only --save-map export patch; the baseline patch does not contain any registration implementation. The baseline and current parameter files have the same SHA-256.

Reproduction

Build the two isolated workspaces with the same Jazzy environment, then run three sequential runs for each workspace:

source /opt/ros/jazzy/setup.bash
bash scripts/run_frontend_determinism_check.sh \
  --bag /media/user/aiueo1/datasets/hilti2022/exp04_ros2 \
  --cloud-topic /hesai/pandar --imu-topic /alphasense/imu \
  --params configs/hilti2022/lidarslam_competitive_v2.yaml \
  --runs 3 --ros-domain-base 210 \
  --save-map \
  --output-dir /tmp/hilti-exp04-current-3x \
  --reference-tum \
    /media/user/aiueo1/datasets/hilti2022/exp04_construction_upper_level_gt.txt

bash /tmp/lidarslam-baseline-Vn3TiJ/scripts/run_frontend_determinism_check.sh \
  --bag /media/user/aiueo1/datasets/hilti2022/exp04_ros2 \
  --cloud-topic /hesai/pandar --imu-topic /alphasense/imu \
  --params /tmp/lidarslam-baseline-Vn3TiJ/configs/hilti2022/lidarslam_competitive_v2.yaml \
  --runs 3 --ros-domain-base 220 \
  --save-map \
  --output-dir /tmp/hilti-exp04-baseline-3x \
  --reference-tum \
    /media/user/aiueo1/datasets/hilti2022/exp04_construction_upper_level_gt.txt

The APE gate uses the historical dense-trajectory convention, not the runner's default nearest-neighbour report:

python3 scripts/ape_from_tum.py --interpolate --max-time-diff 3.0 \
  --ref /media/user/aiueo1/datasets/hilti2022/exp04_construction_upper_level_gt.txt \
  --est <run>/trajectory_frontend.tum --out <run>/ape_historical_interpolate.txt

The timed receipt is in /tmp/hilti-exp04-time.Vqxhvd. Each run was executed sequentially with /usr/bin/time -v and a private ROS domain. No output from the data directory was copied into the repository. Those resource numbers are the existing frontend runtime gate without --save-map; map export is an evidence-only artifact mode and is not used to claim a runtime budget.

Results

All six runs produced 1,258 poses and 10 frontend submaps. Every baseline run and every adapter run was byte-identical:

artifact baseline runs 1–3 adapter runs 1–3
trajectory_frontend.tum MD5 59f87bc57455e69b23ce05c07e47b3b2 59f87bc57455e69b23ce05c07e47b3b2
submaps_frontend.csv MD5 16743fe8d14fa35a623e921d9da37930 16743fe8d14fa35a623e921d9da37930
map.pcd MD5 16454b536af73b5486af2460c0920507 16454b536af73b5486af2460c0920507

The compressed binary map.pcd is 1,921,184 bytes and has SHA-256 bbf742a1d223c0d21b9a85be705282bde71e73cae0e941f20a85049b472550fd on both sides. The export applies each submap pose to its local cloud in message order, matching ScanMatcherComponent::publishMap(); it does not re-run registration or use adapter-specific state.

Using --interpolate --max-time-diff 3.0, all six runs scored identically:

metric baseline adapter
paired GT points 7 / 7 7 / 7
APE translation RMSE (SE(3) Umeyama) 10.439764002361335 m 10.439764002361335 m
APE max time gap 0.10001611709594727 s 0.10001611709594727 s

The per-run /usr/bin/time -v measurements were:

run baseline wall [s] adapter wall [s] baseline peak RSS [KiB] adapter peak RSS [KiB]
1 48.44 49.95 112,016 112,508
2 48.95 48.49 111,772 111,888
3 49.94 48.29 112,400 112,088
median / max 48.95 48.49 112,400 112,508

The adapter wall median is -0.94% versus baseline; peak RSS is +0.10%. The corresponding median processing RTF (wall / bag_duration) is 0.3891 versus 0.3854 (-0.94%). Both are within the Phase 1 +5% wall/RTF and +10% RSS budgets. This gate therefore shows no HILTI exp04 frontend precision or resource regression, but it does not establish an absolute accuracy claim against the separate README RKO-LIO/GLIM comparison.

Map-quality gate status

The geometric evaluator was run with the frozen common command scripts/run_map_quality_check.sh --setup install/setup.bash --downsample 0.1 and no threshold profile on run1/map.pcd from each side. All six reports were byte-identical within each side and across baseline/current: report MD5 4825eec68fb4442de70cc39d42b0b53a. The shared report is:

metric baseline adapter
input / evaluated points 129,726 / 110,283 129,726 / 110,283
mean map entropy [nats] -1.858672907 -1.858672907
MME valid fraction 0.788852316 0.788852316
plane patches 1,882 1,882
thickness RMS mean [m] 0.044694491 0.044694491
thickness RMS p95 [m] 0.105756330 0.105756330
planar coverage 0.369340696 0.369340696
occupied root voxels 12,579 12,579

This closes the frontend map-artifact determinism and adapter non-regression gate: no metric or map bytes changed. As a separate absolute reference, configs/map_quality_profiles/indoor_construction.yaml was run on both artifacts. It gives the same single violation on both sides, mme_valid_fraction=0.788852316 < 0.90; its other four thresholds pass. This is a pre-existing profile failure, not an adapter regression, so this receipt does not claim an absolute indoor release-profile pass.

The colored profile configs/colored_map_quality_profiles/hilti_exp04_report_only.yaml was not passed to the geometric evaluator: it contains RGB/image alignment and APE fields and is not a valid run_map_quality_check.sh profile. No colored-map quality claim is made because this frontend runner emits no images, colors, or backend pointcloud_map bundle. The map-quality evidence here is the real world-frame PCD plus the existing deterministic geometric evaluator, not a trajectory/submap proxy.

The raw command outputs remain in /tmp/hilti-exp04-map-* and /tmp/hilti-exp04-quality-*; they are intentionally not copied into the repository.

Verification

The current tree was built with colcon build --packages-select scanmatcher graph_based_slam --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release. The scanmatcher CTest suite passed 10/10, including the two new test_offline_map_export cases. The changed C++ files passed ament_copyright and ament_cpplint. Final documentation checks are python3 -m mkdocs build --strict (exit 0), python3 -m pytest graph_based_slam/test/test_docs_entrypoints.py -q (6 passed), and git diff --check (pass).