feat(perception): add lossless lidar replay v2
This commit is contained in:
@@ -7,6 +7,13 @@ successfully is not evidence that its LiDAR assumptions are satisfied. In
|
||||
particular, the accepted E10 replay pack v1 has no intensity, and the current K1
|
||||
stream is a vendor map increment rather than an unregistered sensor sweep.
|
||||
|
||||
`missioncore.lidar-replay-pack/v2` closes the field-retention gap without
|
||||
rewriting v1. Its manifest binds exact raw/metadata evidence, logical point/pose
|
||||
content, an immutable scanner-quality report and a source-vs-persisted
|
||||
equivalence report. The React surface reads those reports through the read-only
|
||||
`/api/v1/lidar/replay-packs` boundary; CUDA/TensorRT and ROS do not move into the
|
||||
browser.
|
||||
|
||||
## Boundary
|
||||
|
||||
```text
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# LiDAR worker: product value, evidence boundary and implementation roadmap
|
||||
|
||||
Date: 2026-07-25
|
||||
Status: accepted architecture plan; L0 contract implemented
|
||||
Status: accepted architecture plan; L0 and L1 implemented
|
||||
Scope: real scanner records, replay and future live shadow processing
|
||||
Explicitly out of scope: Unreal U0/U1, Gaussian assets and simulator rendering
|
||||
|
||||
@@ -63,6 +63,12 @@ The executable truth is
|
||||
`src/k1link/compute/lidar_contract.py`. It assesses each stage as `ready`,
|
||||
`degraded` or `blocked` and refuses to infer absent sensor fields.
|
||||
|
||||
`missioncore.lidar-replay-pack/v2` is now the admitted field-retaining replay
|
||||
input. It preserves raw integer XYZ, derived map XYZ, raw uint32 `rgbi`, its
|
||||
verified intensity low byte, source/payload identity, header seq/stamp/scaler,
|
||||
exact host epoch/monotonic receive times and the independent pose stream. Pack
|
||||
v1 remains immutable for E10–E26.
|
||||
|
||||
## 3. Current system result
|
||||
|
||||
The existing camera-heavy E10–E26 line is valuable and remains in place:
|
||||
@@ -156,21 +162,36 @@ memory, zero-copy or batching optimizations are accepted.
|
||||
existing external worker report.
|
||||
- [x] Keep authority diagnostic-only.
|
||||
|
||||
### L1 — lossless replay v2 and scanner quality
|
||||
### L1 — lossless replay v2 and scanner quality — complete
|
||||
|
||||
- [ ] Create a new replay schema; do not rewrite pack v1.
|
||||
- [ ] Preserve XYZ, intensity, source sequence/header stamp/scaler and exact
|
||||
- [x] Create a new replay schema; do not rewrite pack v1.
|
||||
- [x] Preserve XYZ, intensity, source sequence/header stamp/scaler and exact
|
||||
host capture/receive times.
|
||||
- [ ] Record explicitly absent ring, per-point time and IMU fields.
|
||||
- [ ] Add bounded reports for frame gaps, arrival jitter, points/frame, range
|
||||
distribution, intensity distribution and pose coverage.
|
||||
- [ ] Compare live-vs-replay decoding byte-for-byte on a frozen slice.
|
||||
- [ ] Publish the report to the React observation view without bundling a
|
||||
- [x] Record explicitly absent ring, per-point time and IMU fields.
|
||||
- [x] Add immutable reports for sequence gaps, arrival jitter, points/frame,
|
||||
intensity distribution and pose coverage. Sensor-frame range remains
|
||||
explicitly unavailable because the source is a vendor map increment.
|
||||
- [x] Compare source native capture vs persisted replay fields byte-for-byte on
|
||||
a frozen real slice.
|
||||
- [x] Publish the report to the React observation view without bundling a
|
||||
desktop renderer.
|
||||
|
||||
Exit: a recording cannot be called detector-ready when required fields were
|
||||
dropped, and an operator can distinguish scanner dropout from model failure.
|
||||
|
||||
Accepted real slice:
|
||||
|
||||
- session `20260719T220917Z_viewer_live`;
|
||||
- 66 point frames, 226,963 points and 70 pose frames;
|
||||
- 24 arrays compared, zero mismatches, identical logical content SHA-256;
|
||||
- pose coverage 100% at a 100 ms host-arrival gate;
|
||||
- 3,439 mean points/frame;
|
||||
- point-frame interval p50 80.4 ms, p95 186.6 ms and maximum 1,153.4 ms;
|
||||
- intensity p50 248 and p95 255 on the verified `[0, 255]` low byte.
|
||||
|
||||
The long interval tail is evidence to investigate in the scanner/transport
|
||||
quality line. It is not repaired or hidden by replay.
|
||||
|
||||
### L2 — geometric baseline
|
||||
|
||||
- [ ] Run Patchwork++ over the frozen XYZI slice.
|
||||
|
||||
@@ -45,7 +45,8 @@ be mistaken for geometric validity.
|
||||
- Nvblox is blocked until the LiDAR scan geometry and timing/pose contract are
|
||||
admitted.
|
||||
- LiDAR odometry and LiDAR-inertial SLAM are blocked for current K1 evidence.
|
||||
- L1 lossless replay and scanner-quality telemetry precede new model installs.
|
||||
- L1 lossless replay and scanner-quality telemetry are implemented and precede
|
||||
new model installs.
|
||||
- Future scanners, simulation providers and datasets can use the same
|
||||
readiness contract without being forced into K1-specific code.
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# ADR 0019: preserve LiDAR fields before detector evaluation
|
||||
|
||||
Date: 2026-07-25
|
||||
Status: accepted and implemented
|
||||
|
||||
## Context
|
||||
|
||||
The accepted E10 LiDAR replay pack v1 is bound to the E10–E26 result line. It
|
||||
stores camera-selected map XYZ and pose but drops the verified intensity byte,
|
||||
raw `rgbi`, raw integer coordinates, source header fields and exact host
|
||||
timestamps. Mutating that schema would invalidate historical evidence while
|
||||
still leaving detector and scanner-quality assumptions implicit.
|
||||
|
||||
Mission Core also needs one operator surface that can distinguish capture
|
||||
quality from later model quality. A successful worker process or a visually
|
||||
plausible point cloud is not that evidence.
|
||||
|
||||
## Decision
|
||||
|
||||
1. Add the separate immutable `missioncore.lidar-replay-pack/v2`; never rewrite
|
||||
E10 replay pack v1.
|
||||
2. Bind each v2 pack to the source raw capture and aligned metadata hashes.
|
||||
3. Preserve point capture sequence, payload size, exact host epoch and
|
||||
monotonic receive times, header seq/stamp/scaler, raw integer XYZ, derived
|
||||
map XYZ, raw uint32 `rgbi` and its verified uint8 intensity low byte.
|
||||
4. Preserve pose messages independently with their source/header/timing,
|
||||
position, quaternion, distance and accuracy fields.
|
||||
5. Hash the canonical logical arrays, not only the compressed NPZ bytes.
|
||||
6. Re-decode the immutable source and compare all persisted arrays before a
|
||||
pack is accepted. Any mismatch fails the pack.
|
||||
7. Publish a separate hashed scanner-quality report: cadence, density,
|
||||
intensity, sequence anomalies and nearest-pose coverage.
|
||||
8. Expose only path-free, read-only catalog/detail responses to React.
|
||||
9. Deduplicate superseded producers by logical content identity in the UI.
|
||||
10. Keep command, navigation and safety authority false.
|
||||
|
||||
## Consequences
|
||||
|
||||
- PointPillars now has retained XYZI evidence for replay, but remains degraded
|
||||
because K1 supplies vendor-mapped increments rather than admitted raw sweeps.
|
||||
- Scanner/transport timing tails become visible before model tuning.
|
||||
- Reprocessing can compare new worker/model generations against exactly the
|
||||
same point and pose evidence.
|
||||
- The browser displays qualification facts but never loads raw NPZ payloads or
|
||||
runs GPU perception.
|
||||
- Ring, per-point time, scan geometry and IMU remain explicitly absent.
|
||||
- Nvblox, LiDAR odometry and LIO/SLAM remain blocked.
|
||||
|
||||
## Accepted real evidence
|
||||
|
||||
The first accepted real pack was built from
|
||||
`20260719T220917Z_viewer_live`: 66 point frames, 226,963 points, 70 pose frames,
|
||||
24 exact array comparisons and zero mismatches. Pose coverage was 100% at the
|
||||
100 ms host-arrival threshold. Point-frame interval was p50 80.4 ms, p95
|
||||
186.6 ms and maximum 1,153.4 ms.
|
||||
|
||||
## References
|
||||
|
||||
- `src/k1link/compute/lidar_replay.py`
|
||||
- `src/k1link/web/lidar_api.py`
|
||||
- `apps/control-station/src/workspaces/LidarQualityWorkspace.tsx`
|
||||
- `docs/13_LIDAR_WORKER_PRODUCT_AND_ROADMAP.md`
|
||||
Reference in New Issue
Block a user