feat(perception): qualify E31 source binding
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# LAB E31 — source-time, calibration and self-mask qualification
|
||||
|
||||
Date: 2026-07-27
|
||||
Status: accepted for diagnostic E32 binding; navigation, safety and command
|
||||
authority are false
|
||||
Immutable result:
|
||||
`e31-source-qualification-b2460a5eb143688c7eea6821b2277e13aea79868abe81d83f7e78548c119159a`
|
||||
|
||||
## Decision under test
|
||||
|
||||
E31 tests whether the exact RAVNOVES00 source binding used by E29/E30 is
|
||||
specific and stable enough to enter E32 full replay. It does not tune E29,
|
||||
infer a raw LiDAR firing timestamp, invent a sensor height or promote the
|
||||
result to navigation.
|
||||
|
||||
The gate is fail closed. It requires:
|
||||
|
||||
1. the immutable A3 engineering generation and complete human-exception
|
||||
generation;
|
||||
2. complete accounting of source-time bindings;
|
||||
3. the exact factory KB4 calibration identity;
|
||||
4. a predeclared offset sweep over evidenced camera↔LiDAR correspondences;
|
||||
5. a source-evidenced self-mask decision that cannot silently erase accepted
|
||||
object evidence.
|
||||
|
||||
## Immutable input chain
|
||||
|
||||
- Source pack:
|
||||
`e10-lidar-pack-576c994a6c814e2592dd6240ace3902a5db94843312c759a73ba0c9166157d2b`.
|
||||
- Local-surface model:
|
||||
`k1-local-surface-23762244c8bdb97de26fb721ac957d7a00bc9a63571ac4cfa4be19c4effc7d55`.
|
||||
- E30 materialization:
|
||||
`e30-materialization-841af926d8d28ab93538c46d8f31278a2234c4d1c12c7dc4dc296b249d59735a`.
|
||||
- A3 engineering generation:
|
||||
`e30-engineering-generation-62a4fea10dea9b77f69ceac1af5bf0e4928d9c7716083c22258a03670fe5bd4f`.
|
||||
- A3 human generation:
|
||||
`e30-review-generation-7982a882558d0be690b4c7092e328c080bfcbf52478a220452be7e887a588250`.
|
||||
- Factory calibration content identity:
|
||||
`05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9`.
|
||||
- Camera binding: `sensor.camera.right`, `camera_1`, KB4, `800×600`.
|
||||
|
||||
Every input result and artifact digest is verified before E31 runs. Existing
|
||||
results are re-opened only when the complete content identity matches.
|
||||
|
||||
## Source-time audit
|
||||
|
||||
The recording has 4,489 source frames. LiDAR/pose bindings exist for 3,928
|
||||
frames (`87.50%`); 561 unavailable frames remain explicitly unavailable.
|
||||
|
||||
| timing relation | absolute p50 | absolute p95 | maximum | declared gate |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| LiDAR ↔ camera | 25.303 ms | 70.789 ms | 99.574 ms | 100 ms |
|
||||
| pose ↔ point cloud | 6.784 ms | 21.854 ms | 73.798 ms | 100 ms |
|
||||
|
||||
These are recorded host-monotonic arrival relations. They are not hardware
|
||||
firing timestamps.
|
||||
|
||||
## Offset sensitivity
|
||||
|
||||
The correspondence set contains 87 A3 items where the projection was
|
||||
`aligned`, point ownership was `object` and the E29 item was semantic. For each
|
||||
hypothesis E31 selects the nearest available recorded cloud, projects it with
|
||||
the camera-frame pose and evaluates occupied support inside the exact E29 bbox
|
||||
inset (`0.03`).
|
||||
|
||||
| host-arrival hypothesis | evaluable | supported | supported fraction |
|
||||
| ---: | ---: | ---: | ---: |
|
||||
| -200 ms | 79 | 63 | 79.75% |
|
||||
| -150 ms | 83 | 66 | 79.52% |
|
||||
| -100 ms | 81 | 70 | 86.42% |
|
||||
| -50 ms | 87 | 78 | 89.66% |
|
||||
| 0 ms | 87 | 87 | 100.00% |
|
||||
| +50 ms | 87 | 80 | 91.95% |
|
||||
| +100 ms | 83 | 69 | 83.13% |
|
||||
| +150 ms | 84 | 71 | 84.52% |
|
||||
| +200 ms | 83 | 69 | 83.13% |
|
||||
|
||||
Zero offset is retained. Its support deficit relative to the best hypothesis is
|
||||
zero. The p95 bbox support-centroid residual is `0.3947` bbox diagonals. This is
|
||||
a diagnostic correspondence residual, not a measured calibration-target
|
||||
residual.
|
||||
|
||||
## Calibration and self-mask result
|
||||
|
||||
The loaded factory calibration exactly matches the source-pack identity. The
|
||||
camera-from-LiDAR rotation determinant is `1.00000037`, the maximum
|
||||
orthonormal residual is `5.30e-7`, and translation norm is `0.1005 m`.
|
||||
|
||||
Eight A3 `self_points` person cases support a source-session semantic exclusion
|
||||
rectangle:
|
||||
|
||||
```text
|
||||
normalized xyxy = [0.191196, 0.730990, 0.625038, 0.992935]
|
||||
application = person bbox centre inside rectangle
|
||||
observed collateral = 0
|
||||
```
|
||||
|
||||
This mask is bound to the source session and detector rule. It is not a
|
||||
transferable physical vehicle mask.
|
||||
|
||||
The two geometry `self_points` cases cannot support a generic projected point
|
||||
mask. Their union would erase 69 selected points from one accepted object and
|
||||
22 from another. E31 therefore rejects that mask and retains the two exact A3
|
||||
correction item identities instead.
|
||||
|
||||
Physical body dimensions and a body-frame mount transform are unavailable.
|
||||
E31 records both as absent; it does not substitute a guessed height.
|
||||
|
||||
## Decision
|
||||
|
||||
All ten predeclared requirements pass. The result status is
|
||||
`accepted-diagnostic-source-profile` and `eligible_for_e32=true`.
|
||||
|
||||
Acceptance means only:
|
||||
|
||||
- E32 may bind this exact source session, factory calibration, zero
|
||||
host-arrival offset and source-scoped semantic mask;
|
||||
- unavailable source evidence remains unavailable;
|
||||
- the unsafe generic geometry mask remains disabled;
|
||||
- the result has no command, navigation or safety authority.
|
||||
|
||||
It does not establish transfer to another physical mount. That remains an E36
|
||||
question with a second eligible real source.
|
||||
|
||||
## Reproduction
|
||||
|
||||
```bash
|
||||
PYTHONPATH=src .venv/bin/python \
|
||||
experiments/perception/run_e31_source_qualification.py \
|
||||
--source-pack .runtime/compute-experiments/e10/lidar-packs/e10-lidar-pack-576c994a6c814e2592dd6240ace3902a5db94843312c759a73ba0c9166157d2b \
|
||||
--local-surface .runtime/compute-experiments/k1-local-surface-v1/models/k1-local-surface-23762244c8bdb97de26fb721ac957d7a00bc9a63571ac4cfa4be19c4effc7d55 \
|
||||
--calibration .runtime/mission-core/evidence/sessions/private/device-calibration/20260720T105432Z_k1_factory_calibration_2e0e51ae5485 \
|
||||
--materialization .runtime/compute-experiments/e30/materializations/e30-materialization-841af926d8d28ab93538c46d8f31278a2234c4d1c12c7dc4dc296b249d59735a \
|
||||
--engineering-generation .runtime/compute-experiments/e30/engineering-generations/e30-engineering-generation-62a4fea10dea9b77f69ceac1af5bf0e4928d9c7716083c22258a03670fe5bd4f \
|
||||
--human-generation .runtime/compute-experiments/e30/human-review-generations/e30-review-generation-7982a882558d0be690b4c7092e328c080bfcbf52478a220452be7e887a588250
|
||||
```
|
||||
|
||||
The immutable result contains:
|
||||
|
||||
- `qualification-report.json`;
|
||||
- `binding-profile.json`;
|
||||
- `offset-sweep.json`;
|
||||
- 87 per-item correspondence score rows;
|
||||
- a digest-bound manifest.
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build the immutable LAB E31 source qualification profile."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from k1link.compute.e31_source_qualification import (
|
||||
build_e31_source_qualification,
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--source-pack", type=Path, required=True)
|
||||
parser.add_argument("--local-surface", type=Path, required=True)
|
||||
parser.add_argument("--calibration", type=Path, required=True)
|
||||
parser.add_argument("--materialization", type=Path, required=True)
|
||||
parser.add_argument("--engineering-generation", type=Path, required=True)
|
||||
parser.add_argument("--human-generation", type=Path, required=True)
|
||||
parser.add_argument(
|
||||
"--output-root",
|
||||
type=Path,
|
||||
default=Path(".runtime/compute-experiments/e31/source-qualifications"),
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
result = build_e31_source_qualification(
|
||||
source_pack_root=args.source_pack,
|
||||
local_surface_root=args.local_surface,
|
||||
calibration_snapshot_root=args.calibration,
|
||||
materialization_root=args.materialization,
|
||||
engineering_generation_root=args.engineering_generation,
|
||||
human_generation_root=args.human_generation,
|
||||
output_root=args.output_root,
|
||||
)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"result_id": result.result_id,
|
||||
"result_root": str(result.result_root),
|
||||
"status": result.report["status"],
|
||||
"eligible_for_e32": result.report["eligible_for_e32"],
|
||||
"requirements": result.report["requirements"],
|
||||
"authority": result.report["authority"],
|
||||
},
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user