GLIM clean-room adapter Phase 3d: Jazzy live ROS 2 boundary¶
This is an additive, opt-in transport candidate. It is not part of the
active benchmark profile and it does not change the retained Phase 0--3c
receipts or the r2 selection. Humble is not claimed: this host has Jazzy
underlay support, while /opt/ros/humble is absent.
Boundary and ownership¶
phase3d/src/phase3d_node.cpp is the only ROS transport implementation. It
uses the host-owned ros2_conversion.hpp and pointcloud2_parser and the
Phase 3b GlimCoreSession; it does not use an upstream ROS bridge. The
production source guard scans Phase 3d as well as the earlier clean-room
surfaces and rejects bridge provenance tokens.
The node owns copied message payloads in a bounded table. The ordering queue
contains only (signed int64 nanoseconds, host arrival ordinal, kind) keys.
Messages are sorted by timestamp and then the host-assigned ordinal. A
nonzero reorder_window_ns is a bounded holdback window; EOF is the only
operation that force-flushes the remainder. A late item behind an already
submitted timestamp, queue exhaustion, duplicate ordinal, invalid timestamp,
payload-byte bound, allocation failure, or post-EOF input latches a terminal
error. There is no silent application-level drop. Input QoS is an explicit
parameter and defaults to reliable; best-effort is available only as an
explicit degraded transport setting because DDS loss cannot be detected
without sequence metadata.
max_cloud_bytes bounds one copied PointCloud2 and
max_pending_payload_bytes bounds all retained copied payloads. Accounting
is checked before copying and released only after serialized processing.
Lifecycle and output contract¶
The std_srvs/Trigger finalize service is the sole EOF API. It performs one
request, bounded force-drain, exact-core close, output validation, and one
internal trajectory/map seal. A second request is rejected. Callbacks and
core exceptions are translated into a terminal latch; destruction is
idempotent and never detaches a worker. Invalid frames, non-finite data,
calibration/frame mismatch, non-monotonic output, non-contiguous output order,
ROS stamp range overflow, quaternion shape errors, and PointCloud2 row-step
overflow fail before publication.
The internal seal is atomic: both required output messages are fully converted
before either publication call. ROS 2 delivery of two separate topics is not
transactional; therefore the completion diagnostic is emitted only after both
publish calls return, and a consumer must use that diagnostic plus the
latched counters to distinguish transport delivery from internal completion.
Trajectory is published as nav_msgs/Path; the map is one bounded,
little-endian sensor_msgs/PointCloud2 with explicit x/y/z/intensity/ring/time
fields. Both outputs use the contract frame, and the map completion stamp is
the final trajectory stamp.
Parameters that must be fixed before input¶
config_directory, sequence_id, lidar_frame, imu_frame,
trajectory_frame, map_frame, point_time_unit, both calibration transforms,
all six PointCloud2 field names/types, require_map_output, the QoS depth and
reliability, reorder window, payload limits, and all Phase 3b ledger/map
bounds are node parameters. Phase 3b preflights the config directory as
regular, non-symlink files with relative, contained JSON component names;
mapping files are required only when require_map_output=true.
Synthetic Jazzy evidence¶
The reproducible smoke uses only synthetic ROS messages (two LiDAR frames,
three IMU messages), the pinned Phase 1 exact-core prefixes, one CMake worker,
and /opt/ros/jazzy. It checks equal-stamp ordering, bounded holdback,
negative/overflow ROS stamps, trajectory quaternion validation, row-step
overflow, exact output frames/stamps, one path plus one map publication,
double-finalize rejection, and post-EOF rejection. No bag, dataset, GT,
scorer, benchmark, or active profile is used.
Final immutable evidence (the source manifest covers the Phase 3d tree and source guard; documentation is kept outside that manifest to avoid a self-hash cycle) is:
| mode | root | configure | build | CTest | install | node binary |
|---|---|---|---|---|---|---|
| normal | /tmp/glim-clean-room-phase3d-final-normal.KTzM3F |
d1b8645398685a747c9c838ac5a77e6453e21911635ce4be0651c194f5426896 |
8da45f7e7988fe5786eacc12170ea7d822034c2416772b53144b97e72009bf0f |
6f6f97f390a9e650461ed3726d2b68180121ec96daf3bad1478b01343f89ae00 |
a2af85cf5e63760155db7397f22ffbfb129dbcafee036ad56f3b9b0df1a113e0 |
9a7d3bac00243b8caa61287917d5ac420e78e2617ea5c6b997cc8e8c3d51d7d0 |
| ASAN/UBSAN | /tmp/glim-clean-room-phase3d-final-sanitize.jtcp6L |
edf8adbd2fd6386cd6006469cd2f7586ccc437eac1d65827975600c04d006030 |
8da45f7e7988fe5786eacc12170ea7d822034c2416772b53144b97e72009bf0f |
d2e4147160799a85261ff22552b398742e15b6f63ea46b7c7fb8936f45573645 |
7af766f0c634990de2d430f825a32a7c29842c96a3353727121589eeebe21ef0 |
c8a579d896af66f032e0bb99ea397989dea2ac6f2d91ef01779c28df23887a24 |
Both CTest runs are 3/3 with zero failures (10 gtest cases: 9 ingress/output
contract cases and 1 synthetic ROS graph case), and both installs contain the
node plus the nine host-owned headers. The normal install audit (including
ldd and bridge-token scan) is 69cacdfb6288b1e9c8563f4e44a01de3b1e66c1537cfeb658915db6246e04c97.
The deterministic source-manifest digest is
9f809c32336bb97fbaad5665c8602752a28526062a444e94254fbca0b424cb0e; normal
and sanitizer install-manifest digests are respectively
e006ea60a5375ee35a001886111ad6514ff91f94b3002f7db483006f8e6542f5 and
2a9ebdc1bfb7d53c9b12366c5941cec9993b085cbe6534da77c465e4538d3e24.
The manifest is path-independent because it is generated from the repository
root with sorted relative paths and a second hash over the resulting
sha256sum lines (generated files are outside the selected paths):
cd /path/to/lidar_slam_ros2
{
find docker/benchmark_adapters/glim_clean_room/phase3d -type f \
-not -path '*/__pycache__/*' -printf '%p\n'
printf '%s\n' docker/benchmark_adapters/glim_clean_room/tests/source_guard.py
} | LC_ALL=C sort | while IFS= read -r path; do sha256sum "$path"; done \
> /tmp/phase3d-root/source-manifest.sha256
sha256sum /tmp/phase3d-root/source-manifest.sha256
A prior sanitizer root /tmp/glim-clean-room-phase3d-sanitize.ijkRb2 is
retained as a superseded failure: CTest binaries were not linked with the
sanitizer runtime. The CMake fix was limited to adding the same ASAN/UBSAN
flags to both test targets; the final sanitizer root above is the corrected
run. A passing focused test is necessary but not sufficient for benchmark
eligibility; this candidate remains NOT_READY for a live production claim
and is not added to the active benchmark profile.
The install surface deliberately exports the node executable and all host-owned headers, while keeping the exact-core static link targets internal to this opt-in recipe. A downstream process consumes the installed node; downstream C++ linkage requires the separately pinned GLIM/GTSAM prefixes and must be configured explicitly rather than inheriting stale build-tree paths.