LaserPerception v0.1.0 — PointPillars + TensorRT + ROS 2 with honest deployment benchmarks

Final M6 update: a failed byte-exact ROS test turned into a representation-boundary result

I’ve now finished the KITTI Raw cross-domain validation work for LaserPerception, including the ROS 2 integration stage.

The original goal for that stage sounded simple: replay official KITTI Raw through PointCloud2 + time-aware TF + the live multi-sweep builder and require the resulting model-ready cloud to match the frozen offline reference byte-for-byte.

That test failed at the first frame containing history.

The difference was tiny—one float32-scale transform discrepancy—but I kept the failure rather than adding a tolerance and traced it through the full transform path.

The useful result was that the error was not coming from tf2.

KITTI’s serialized pose rotation was slightly non-orthonormal. ROS TF represents rotation as a unit quaternion, so converting that matrix into a legal TF rotation maps it onto an orthonormal SO(3) rotation. In the diagnostic ladder:

frozen matrix → WSL matrix → unit-quaternion projection → real tf2 → builder storage

the unit-quaternion representation produced the dominant float32 change, while real lookup_transform_full reproduced the projected rotation exactly at the float32 boundary.

The effect was also accumulation-dependent.

With one historical sweep, the projected path changed coordinate-bearing feature bytes but preserved the complete discrete voxel structure: same pillar keys, ordering, coors, num_points, and retained point membership.

At H10, enough tiny coordinate changes accumulated for six points in the diagnostic frame to cross voxel boundaries. That changed point membership, TensorRT outputs, and eventually produced 302 detections instead of the frozen offline result’s 301.

Because the original matrix literally cannot be transported unchanged through unit-quaternion TF, I preregistered a final protocol against an independently generated ROS-representable projected reference instead of weakening the original gate with a tolerance.

Final result:

  • 24/24 early/startup H10 targets byte-exact
  • 856/856 full H10/H5 corpus conditions byte-exact
  • 860/860 unique live ROS conditions byte-exact overall
  • 0 TF failures, rejected frames, or history resets
  • ten frozen detector sentinels passed the pre-existing parity-v2 semantic envelope
  • exported detections: 113 / 113
  • high-confidence matches: 81 / 81 in both directions
  • all continuous checks: 81 / 81
  • class mismatches: 0
  • continuous outliers: 0
  • final Detection3DArray conversion: 10 / 10

One other result I found useful: the projected and original offline model-ready hashes differ for all 856 conditions, but the point count is identical for 856/856—880,487,994 points on both sides. So the representation shift perturbed coordinates without changing the range-filter population anywhere in the frozen corpus.

The claim is deliberately narrow. This validates the recorded ROS 2 software path—PointCloud2 transport, timestamps, unit-quaternion TF, time-aware fixed-frame composition, live history selection, builder orchestration, and detector publication. It does not claim physical-LiDAR validation, real-time performance, or that ROS reproduces the original non-orthonormal matrix bytes.

Full write-up:

M6 technical note:

Final M6c result:

Repository:

I’d be interested in how other ROS perception teams handle this when validating a live TF pipeline against an offline reference whose source rotations are matrix-native or numerically off SO(3). Do you define the oracle before or after the TF-representable projection?