feat(perception): add full camera-first shadow
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
# LAB E53 · полный camera-first shadow
|
||||
|
||||
Дата: 2026-07-30
|
||||
|
||||
Статус: принят технический диагностический shadow; camera detector не
|
||||
повышен до operational runtime
|
||||
|
||||
## Цель
|
||||
|
||||
Проверить на всех 4 489 кадрах RAVNOVES00 восстановленный архитектурный
|
||||
принцип:
|
||||
|
||||
```text
|
||||
camera detection and semantic class
|
||||
→ canonical E29 camera↔LiDAR association
|
||||
→ LiDAR metric support and range
|
||||
```
|
||||
|
||||
LiDAR не создаёт семантический класс. Camera-объект без квалифицированной
|
||||
LiDAR-поддержки остаётся camera-only объектом без выдуманной дальности.
|
||||
|
||||
## Неизменяемые входы
|
||||
|
||||
- E10 LiDAR pack:
|
||||
`e10-lidar-pack-576c994a6c814e2592dd6240ace3902a5db94843312c759a73ba0c9166157d2b`;
|
||||
- local surface:
|
||||
`k1-local-surface-23762244c8bdb97de26fb721ac957d7a00bc9a63571ac4cfa4be19c4effc7d55`;
|
||||
- camera candidate:
|
||||
`result-f4cebdea8a82698a5b8a65d2c3fbdb0428b88b9dc49fe45f8cb37d740ed83d02`;
|
||||
- accepted E29:
|
||||
`e29-camera-geometry-421a9d930638bef12cd5eb10979a477917fa4a389e655ed95f73ba4bd62e13dc`;
|
||||
- rig geometry:
|
||||
`ravnoves00-portable-k1/unbound-v1`.
|
||||
|
||||
Rig profile намеренно не содержит корпуса, трансформации LiDAR→body или
|
||||
физических размеров: RAVNOVES00 записан переносным K1 и не доказывает
|
||||
установку на транспортное средство.
|
||||
|
||||
## Метод
|
||||
|
||||
E53 потоково читает detector и E29 metadata, один раз материализует compressed
|
||||
source arrays и для каждого source-aligned кадра:
|
||||
|
||||
1. оставляет camera-классы `person`, `bicycle`, `car`, `motorcycle`, `bus`,
|
||||
`truck` с score не ниже 0.5;
|
||||
2. отбрасывает bbox больше 25% изображения;
|
||||
3. применяет без изменения профиль
|
||||
`camera-first-local-surface-validation/v1`;
|
||||
4. сохраняет camera semantic ownership;
|
||||
5. публикует LiDAR range только при связанном occupied support;
|
||||
6. измеряет adjacent-frame family+IoU continuity и source-bound overlap с E29;
|
||||
7. оставляет collision unavailable.
|
||||
|
||||
Сравнение с E29 и adjacent IoU не являются ground truth или persistent
|
||||
tracking truth.
|
||||
|
||||
## Отвергнутый первый проход
|
||||
|
||||
Первый immutable результат:
|
||||
|
||||
```text
|
||||
e53-camera-first-shadow-94eb57cce8dbfb0ea679486ed55aec32c2f38c93ae67e1c606787587cd3a0da5
|
||||
```
|
||||
|
||||
Он обработал все 4 489 кадров, но был отвергнут: p95 составил 210.7093 ms
|
||||
против заранее заданных 50 ms. Причина — обращение к compressed NPZ member
|
||||
`cloud_points_map` внутри frame loop, из-за чего массив 9.2 млн точек
|
||||
распаковывался повторно.
|
||||
|
||||
Исправление не меняло входы, пороги или ассоциацию: source arrays
|
||||
материализуются один раз до цикла.
|
||||
|
||||
## Принятый результат
|
||||
|
||||
```text
|
||||
e53-camera-first-shadow-e6f03cf8bfb15db86100239b060e13f914532618b7b99e811866e4e6a555186c
|
||||
```
|
||||
|
||||
| Измерение | Результат |
|
||||
| --- | ---: |
|
||||
| Кадры | 4 489 / 4 489 |
|
||||
| Кадры с LiDAR | 3 928 |
|
||||
| Кадры с camera candidates | 4 471 |
|
||||
| Принятые camera candidates | 48 944 |
|
||||
| Pathological large boxes отклонено | 946 |
|
||||
| Camera + LiDAR agree | 7 686 |
|
||||
| Camera-only | 34 940 |
|
||||
| Source unavailable | 6 318 |
|
||||
| Объекты с LiDAR range | 10 183 |
|
||||
| Доля объектов с range | 20.8054% |
|
||||
| E29 current family+IoU overlap | 18 199 / 19 625 = 92.7338% |
|
||||
| Adjacent family+IoU continuity | 31 476 / 48 933 = 64.3247% |
|
||||
| Frame latency p50 / p95 / max | 0.9881 / 1.7993 / 9.4521 ms |
|
||||
| Полный elapsed | 4 962.34 ms |
|
||||
| Peak-RSS growth | 36.8594 MiB |
|
||||
|
||||
Распределение camera candidates: 44 498 `car`, 2 341 `person`, 1 876
|
||||
`truck`, 142 `bicycle`, 66 `motorcycle`, 21 `bus`.
|
||||
|
||||
## Решение
|
||||
|
||||
Полный source-bound camera-first shadow технически принят:
|
||||
|
||||
- accounting и binding закрыты;
|
||||
- E29 association переиспользована;
|
||||
- latency и memory gate пройдены;
|
||||
- camera semantic ownership сохранён;
|
||||
- LiDAR-native class, false free space и collision не публикуются.
|
||||
|
||||
Mask R-CNN не принят как operational detector. Большое число camera candidates,
|
||||
64.32% adjacent continuity и 92.73% overlap с E29 требуют независимой
|
||||
source-bound quality review. E29 также не является ground truth.
|
||||
|
||||
Physical vehicle-body и LiDAR mount/extrinsic остаются отдельным измерительным
|
||||
gate. До их квалификации `recent-collision`, navigation, safety и commands
|
||||
остаются недоступны.
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"schema_version": "missioncore.e53-camera-first-shadow-profile/v1",
|
||||
"profile_id": "e53-ravnoves00-camera-first-full-shadow/v1",
|
||||
"expected": {
|
||||
"source_pack_id": "e10-lidar-pack-576c994a6c814e2592dd6240ace3902a5db94843312c759a73ba0c9166157d2b",
|
||||
"local_surface_model_id": "k1-local-surface-23762244c8bdb97de26fb721ac957d7a00bc9a63571ac4cfa4be19c4effc7d55",
|
||||
"detector_result_id": "result-f4cebdea8a82698a5b8a65d2c3fbdb0428b88b9dc49fe45f8cb37d740ed83d02",
|
||||
"baseline_e29_result_id": "e29-camera-geometry-421a9d930638bef12cd5eb10979a477917fa4a389e655ed95f73ba4bd62e13dc"
|
||||
},
|
||||
"camera_candidate": {
|
||||
"target_labels": [
|
||||
"person",
|
||||
"bicycle",
|
||||
"car",
|
||||
"motorcycle",
|
||||
"bus",
|
||||
"truck"
|
||||
],
|
||||
"label_groups": {
|
||||
"person": [
|
||||
"person"
|
||||
],
|
||||
"two-wheel": [
|
||||
"bicycle",
|
||||
"motorcycle"
|
||||
],
|
||||
"vehicle": [
|
||||
"car",
|
||||
"bus",
|
||||
"truck"
|
||||
]
|
||||
},
|
||||
"minimum_score": 0.5,
|
||||
"maximum_bbox_image_fraction": 0.25
|
||||
},
|
||||
"temporal": {
|
||||
"minimum_adjacent_family_iou": 0.25,
|
||||
"minimum_baseline_family_iou": 0.25,
|
||||
"interpretation": "adjacent-image-space-continuity-diagnostic-not-track-truth"
|
||||
},
|
||||
"acceptance": {
|
||||
"maximum_frame_latency_p95_ms": 50.0,
|
||||
"maximum_rss_growth_mib": 512.0,
|
||||
"require_complete_frame_accounting": true,
|
||||
"require_canonical_e29_association": true,
|
||||
"require_camera_semantic_ownership": true,
|
||||
"require_no_lidar_native_semantics": true,
|
||||
"require_no_false_free_space": true,
|
||||
"require_no_collision_authority": true,
|
||||
"require_upstream_immutability": true
|
||||
},
|
||||
"authority": {
|
||||
"commands_enabled": false,
|
||||
"navigation_or_safety_accepted": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"schema_version": "missioncore.rig-geometry/v1",
|
||||
"profile_id": "ravnoves00-portable-k1/unbound-v1",
|
||||
"rig_kind": "portable",
|
||||
"qualification": {
|
||||
"state": "unbound",
|
||||
"reason": "portable-k1-source-has-no-vehicle-body-or-measured-lidar-to-body-mount",
|
||||
"evidence_sha256": []
|
||||
},
|
||||
"coordinate_frames": {
|
||||
"lidar_frame": "k1-lidar",
|
||||
"body_frame": null,
|
||||
"body_from_lidar": null
|
||||
},
|
||||
"vehicle_body": null,
|
||||
"authority": {
|
||||
"commands_enabled": false,
|
||||
"navigation_or_safety_accepted": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Build the immutable full-source E53 camera-first shadow."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from k1link.compute.e53_camera_first_shadow import (
|
||||
build_e53_camera_first_shadow,
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--source-pack", type=Path, required=True)
|
||||
parser.add_argument("--local-surface", type=Path, required=True)
|
||||
parser.add_argument("--detector-result", type=Path, required=True)
|
||||
parser.add_argument("--baseline-e29", type=Path, required=True)
|
||||
parser.add_argument("--rig-geometry", type=Path, required=True)
|
||||
parser.add_argument("--profile", type=Path, required=True)
|
||||
parser.add_argument("--output-root", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
result = build_e53_camera_first_shadow(
|
||||
source_pack_root=args.source_pack,
|
||||
local_surface_root=args.local_surface,
|
||||
detector_result_root=args.detector_result,
|
||||
baseline_e29_root=args.baseline_e29,
|
||||
rig_geometry_path=args.rig_geometry,
|
||||
profile_path=args.profile,
|
||||
output_root=args.output_root,
|
||||
)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"result_id": result.result_id,
|
||||
"result_root": str(result.result_root),
|
||||
"accepted": result.report["acceptance"]["accepted"],
|
||||
"metrics": result.report["metrics"],
|
||||
"decision": result.report["decision"],
|
||||
},
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
)
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user