feat(perception): add E34 temporal occupied layer

This commit is contained in:
DCCONSTRUCTIONS
2026-07-27 16:55:40 +03:00
parent 95c6540691
commit 621084fcd6
22 changed files with 4732 additions and 104 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+158
View File
@@ -24,6 +24,11 @@ from k1link.compute.e33_worker_shadow import (
E33WorkerShadowResult,
read_e33_worker_shadow_result,
)
from k1link.compute.e34_temporal_occupied_replay import (
E34TemporalOccupiedReplay,
E34TemporalOccupiedReplayError,
read_e34_temporal_occupied_replay,
)
LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
"missioncore.laboratory-advanced-catalog/v1"
@@ -32,6 +37,7 @@ LABORATORY_ADVANCED_CATALOG_SCHEMA: Final = (
_E31_RESULT_ID = re.compile(r"^e31-source-qualification-[a-f0-9]{64}$")
_E32_RESULT_ID = re.compile(r"^e32-track-geometry-[a-f0-9]{64}$")
_E33_RESULT_ID = re.compile(r"^e33-worker-shadow-[a-f0-9]{64}$")
_E34_RESULT_ID = re.compile(r"^e34-temporal-occupied-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
@@ -73,6 +79,15 @@ def _read_e33_cached(
return read_e33_worker_shadow_result(Path(root_text))
@lru_cache(maxsize=16)
def _read_e34_cached(
root_text: str,
signature: tuple[int, ...],
) -> E34TemporalOccupiedReplay:
del signature
return read_e34_temporal_occupied_replay(Path(root_text))
def _configured_root(provider: RootProvider) -> Path | None:
value = provider()
if value is None:
@@ -294,6 +309,113 @@ def _project_e33(
}
def _project_e34(result: E34TemporalOccupiedReplay) -> dict[str, object]:
identity = _object(result.manifest.get("identity"), "E34 identity")
profile = _object(identity.get("profile"), "E34 profile")
layer = _object(profile.get("layer"), "E34 layer")
association = _object(profile.get("association"), "E34 association")
metrics = _object(result.report.get("metrics"), "E34 metrics")
frames = _object(metrics.get("frames"), "E34 frames")
components = _object(metrics.get("components"), "E34 components")
occupancy = _object(metrics.get("occupancy"), "E34 occupancy")
aging = _object(metrics.get("aging"), "E34 aging")
map_frame = _object(metrics.get("map_frame"), "E34 map frame")
runtime = _object(metrics.get("runtime"), "E34 runtime")
frame_processing = _object(
runtime.get("frame_processing_ms"),
"E34 frame processing",
)
acceptance = _object(result.report.get("acceptance"), "E34 acceptance")
if acceptance.get("accepted") is not True:
raise ValueError("E34 result is not accepted")
return {
"result_id": result.result_id,
"created_at_utc": result.manifest.get("created_at_utc"),
"source_session_id": identity.get("source_session_id"),
"status": result.manifest.get("acceptance_state"),
"e32_result_id": identity.get("e32_result_id"),
"e33_result_id": identity.get("e33_result_id"),
"profile_id": profile.get("profile_id"),
"pipeline_id": identity.get("pipeline"),
"coordinate_frame": identity.get("coordinate_frame"),
"configuration": {
"voxel_size_m": layer.get("voxel_size_m"),
"occupied_ttl_seconds": layer.get("occupied_ttl_seconds"),
"maximum_active_components": layer.get(
"maximum_active_components"
),
"maximum_cells_per_component": layer.get(
"maximum_cells_per_component"
),
"geometry_maximum_gap_seconds": association.get(
"geometry_maximum_gap_seconds"
),
"geometry_maximum_centroid_distance_m": association.get(
"geometry_maximum_centroid_distance_m"
),
},
"metrics": {
"source_frames": frames.get("source"),
"processed_frames": frames.get("processed"),
"frames_with_current_layer": frames.get("with_current_layer"),
"held_only_frames": frames.get("held_only"),
"unknown_empty_frames": frames.get("unknown_empty"),
"created_components": components.get("created"),
"camera_created_components": components.get("camera_created"),
"geometry_created_components": components.get("geometry_created"),
"geometry_reassociated_components": components.get(
"geometry_reassociated_components"
),
"exact_camera_associations": components.get(
"exact_camera_associations"
),
"geometry_spatial_reassociations": components.get(
"geometry_spatial_reassociations"
),
"held_publications": components.get("held_publications"),
"expired_components": components.get("expired"),
"peak_active_components": components.get("peak_active"),
"maximum_observed_span_seconds": components.get(
"maximum_observed_span_seconds"
),
"continuity_fraction": components.get("continuity_fraction"),
"geometry_only_reassociation_fraction": components.get(
"geometry_only_reassociation_fraction"
),
"e32_current_point_rows": occupancy.get(
"e32_current_point_rows"
),
"e34_consumed_current_point_rows": occupancy.get(
"e34_consumed_current_point_rows"
),
"current_cell_rows": occupancy.get("current_cell_rows"),
"held_cell_rows": occupancy.get("held_cell_rows"),
"stored_cell_rows": occupancy.get("stored_cell_rows"),
"free_cell_rows": occupancy.get("free_cell_rows"),
"peak_cells_per_component": occupancy.get(
"peak_cells_per_component"
),
"maximum_held_age_seconds": aging.get(
"maximum_held_age_seconds"
),
"maximum_expiry_delay_seconds": aging.get(
"maximum_expiry_delay_seconds"
),
"maximum_replay_materialization_delay_seconds": aging.get(
"maximum_replay_materialization_delay_seconds"
),
"map_frame_jump_candidates": map_frame.get("jump_candidates"),
"frame_processing_p95_ms": frame_processing.get("p95"),
"build_elapsed_ms": runtime.get("build_elapsed_ms"),
},
"review": copy.deepcopy(result.review),
"acceptance": copy.deepcopy(acceptance),
"decision": copy.deepcopy(result.report.get("decision")),
"authority": copy.deepcopy(result.report.get("authority")),
"access": "read-only",
}
def _empty_catalog(configured: bool) -> dict[str, object]:
return {
"schema_version": LABORATORY_ADVANCED_CATALOG_SCHEMA,
@@ -310,6 +432,7 @@ def build_advanced_laboratory_router(
e31_root_provider: RootProvider = lambda: None,
e32_root_provider: RootProvider = lambda: None,
e33_root_provider: RootProvider = lambda: None,
e34_root_provider: RootProvider = lambda: None,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/laboratory", tags=["laboratory"])
@@ -434,4 +557,39 @@ def build_advanced_laboratory_router(
"invalid_total": invalid_total,
}
@router.get("/e34/results")
def list_e34_results(
limit: int = Query(default=1, ge=1, le=10),
) -> dict[str, object]:
root = _configured_root(e34_root_provider)
if root is None:
return _empty_catalog(False)
candidates = _candidates(root, _E34_RESULT_ID)
items: list[dict[str, object]] = []
invalid_total = 0
for candidate in candidates:
try:
result = _read_e34_cached(
str(candidate.resolve()),
_result_signature(candidate),
)
if not result.accepted:
raise ValueError("E34 result is not accepted")
if len(items) < limit:
items.append(_project_e34(result))
except (
E34TemporalOccupiedReplayError,
KeyError,
OSError,
TypeError,
ValueError,
):
invalid_total += 1
return {
**_empty_catalog(True),
"items": items,
"candidate_total": len(candidates),
"invalid_total": invalid_total,
}
return router
+7
View File
@@ -520,6 +520,13 @@ app.include_router(
/ "e33"
/ "results"
),
e34_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e34"
/ "results"
),
)
)
app.include_router(