fix(lab): stabilize recorded spatial playback

This commit is contained in:
DCCONSTRUCTIONS
2026-08-06 08:51:10 +03:00
parent 9df9f58ab8
commit e38f2fb1da
11 changed files with 316 additions and 99 deletions
+11 -1
View File
@@ -276,6 +276,13 @@ class RecordedGeometryStore:
points.setflags(write=False)
return points
@property
def maximum_current_point_count(self) -> int:
"""Return the immutable source-pack upper bound for one recorded increment."""
counts = np.diff(np.asarray(self._source["cloud_offsets"], dtype=np.int64))
return int(counts.max(initial=0))
def pose_values_for_frame(
self,
frame_id: str,
@@ -946,7 +953,10 @@ def _camera_unavailable_observation(
)
def _load_npz(path: Path, label: str) -> dict[str, npt.NDArray[np.generic]]:
def _load_npz(
path: Path,
label: str,
) -> dict[str, npt.NDArray[np.generic]]:
try:
with np.load(path, allow_pickle=False) as archive:
return {name: np.asarray(archive[name]) for name in archive.files}
+10 -1
View File
@@ -14,6 +14,7 @@ from threading import RLock
from typing import Final
from .geometry import RecordedGeometryStore
from .recorded_source import RECORDED_REPRESENTATION_ID
from .spatial_evidence import (
project_metric_obstacles_to_body,
sample_points_in_body_frame,
@@ -32,7 +33,7 @@ from .threat_replay import (
RECORDED_SPATIAL_TIMELINE_SCHEMA: Final = "missioncore.recorded-spatial-evidence-timeline/v1"
RECORDED_SPATIAL_CHUNK_SCHEMA: Final = "missioncore.recorded-spatial-evidence-chunk/v1"
RECORDED_SPATIAL_FRAME_SCHEMA: Final = "missioncore.recorded-spatial-evidence-frame/v1"
RECORDED_SPATIAL_POINT_LIMIT: Final = 2_000
RECORDED_SPATIAL_POINT_LIMIT: Final = 4_096
RECORDED_SPATIAL_MAX_CHUNK_FRAMES: Final = 24
_EXPECTED_FRAME_COUNT: Final = 4_489
_SOURCE_TIME = re.compile(rb'"source_time_ns":([0-9]+)')
@@ -80,6 +81,10 @@ class RecordedThreatTimeline:
or self.store.profile.frame_count != _EXPECTED_FRAME_COUNT
):
raise RecordedThreatTimelineError("recorded timeline geometry identity changed")
if self.store.maximum_current_point_count > RECORDED_SPATIAL_POINT_LIMIT:
raise RecordedThreatTimelineError(
"recorded timeline exact point delivery exceeds its declared bound"
)
self.body_frames = RecordedReplayBodyFrameResolver(
self.store,
profile=self.profile.body_frame,
@@ -99,6 +104,7 @@ class RecordedThreatTimeline:
"recorded_source": {
"session_id": self.profile.session_id,
"source_id": self.profile.source_id,
"representation_id": RECORDED_REPRESENTATION_ID,
"synchronization": "host-arrival-best-effort",
},
"frame_count": len(times),
@@ -109,6 +115,8 @@ class RecordedThreatTimeline:
"nominal_rate_hz": 1 / nominal_interval,
"max_chunk_frames": RECORDED_SPATIAL_MAX_CHUNK_FRAMES,
"point_sample_limit": RECORDED_SPATIAL_POINT_LIMIT,
"point_delivery": "exact-current-increment",
"maximum_source_points_per_frame": self.store.maximum_current_point_count,
"image_width": 800,
"image_height": 600,
"rig": {
@@ -119,6 +127,7 @@ class RecordedThreatTimeline:
"corridor": {
"forward_length_m": self.profile.corridor.forward_length_m,
"rear_margin_m": self.profile.corridor.rear_margin_m,
"occupied_voxel_size_m": self.profile.corridor.occupied_voxel_size_m,
"half_width_m": (
self.profile.rig.body_width_m / 2 + self.profile.corridor.lateral_clearance_m
),
+2
View File
@@ -13,6 +13,7 @@ from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from pydantic import ValidationError
from starlette.middleware.gzip import GZipMiddleware
from k1link import __version__
from k1link.artifact_gateway import configured_artifact_gateway
@@ -414,6 +415,7 @@ app = FastAPI(
openapi_url="/api/openapi.json",
lifespan=app_lifespan,
)
app.add_middleware(GZipMiddleware, minimum_size=1_024, compresslevel=5)
@app.exception_handler(RequestValidationError)