feat(perception): seal M4.8S reference graph replay

This commit is contained in:
DCCONSTRUCTIONS
2026-08-25 16:44:26 +03:00
parent 33cef2fdea
commit 05590867b7
12 changed files with 2578 additions and 1 deletions
+34
View File
@@ -110,6 +110,10 @@ _RollingItem = _Temporal | _StopSignal
_ThreatItem = _Temporal | _Rolled | _StopSignal
_QueueItem = SourcePacket | _Detected | _Associated | _Temporal | _Rolled | _StopSignal
_QueueItemT = TypeVar("_QueueItemT", bound=_QueueItem)
DeliveryEvidenceObserver = Callable[
[DeliveredFrame, SourcePacket, tuple[ObjectProposal2D, ...], frozenset[str], int],
None,
]
class ReferencePerceptionGraphV1:
@@ -127,6 +131,8 @@ class ReferencePerceptionGraphV1:
threat: ThreatProvider,
telemetry_identity: PipelineTelemetryIdentity | None = None,
telemetry_sink: PipelineTelemetrySink | None = None,
delivery_observer: Callable[[DeliveredFrame, int], None] | None = None,
delivery_evidence_observer: DeliveryEvidenceObserver | None = None,
clock_ns: Callable[[], int] = time.monotonic_ns,
) -> None:
if config.graph_id != REFERENCE_GRAPH_ID:
@@ -145,6 +151,8 @@ class ReferencePerceptionGraphV1:
run_mode=GraphRunMode.SOURCE_PACED_LATEST_WINS,
telemetry_identity=telemetry_identity,
telemetry_sink=telemetry_sink,
delivery_observer=delivery_observer,
delivery_evidence_observer=delivery_evidence_observer,
clock_ns=clock_ns,
)
@@ -162,6 +170,8 @@ class ReferencePerceptionGraphV1:
run_mode: GraphRunMode,
telemetry_identity: PipelineTelemetryIdentity | None,
telemetry_sink: PipelineTelemetrySink | None,
delivery_observer: Callable[[DeliveredFrame, int], None] | None,
delivery_evidence_observer: DeliveryEvidenceObserver | None,
clock_ns: Callable[[], int],
) -> None:
if (telemetry_identity is None) is not (telemetry_sink is None):
@@ -177,6 +187,8 @@ class ReferencePerceptionGraphV1:
self.run_mode = run_mode
self.telemetry_identity = telemetry_identity
self.telemetry_sink = telemetry_sink
self.delivery_observer = delivery_observer
self.delivery_evidence_observer = delivery_evidence_observer
self._clock_ns = clock_ns
self._state = GraphState.CREATED
self._state_lock = Lock()
@@ -510,6 +522,23 @@ class ReferencePerceptionGraphV1:
obstacle_map=obstacle_map,
threats=threats,
)
completed_ns = self._now()
with self._result_lock:
admitted_at_ns = self._admitted_at_ns[item.packet.envelope.sequence]
completion_age_ns = item.packet.envelope.source_age_ns + max(
0,
completed_ns - admitted_at_ns,
)
if self.delivery_observer is not None:
self.delivery_observer(delivery, completion_age_ns)
if self.delivery_evidence_observer is not None:
self.delivery_evidence_observer(
delivery,
item.packet,
item.proposals,
item.associated_proposal_ids,
completion_age_ns,
)
with self._result_lock:
self._deliveries.append(delivery)
self._terminal(
@@ -845,6 +874,8 @@ class ReferencePerceptionGraphV2(ReferencePerceptionGraphV1):
run_mode: GraphRunMode,
telemetry_identity: PipelineTelemetryIdentity | None = None,
telemetry_sink: PipelineTelemetrySink | None = None,
delivery_observer: Callable[[DeliveredFrame, int], None] | None = None,
delivery_evidence_observer: DeliveryEvidenceObserver | None = None,
clock_ns: Callable[[], int] = time.monotonic_ns,
) -> None:
if config.graph_id != REFERENCE_GRAPH_ID_V2:
@@ -865,6 +896,8 @@ class ReferencePerceptionGraphV2(ReferencePerceptionGraphV1):
run_mode=run_mode,
telemetry_identity=telemetry_identity,
telemetry_sink=telemetry_sink,
delivery_observer=delivery_observer,
delivery_evidence_observer=delivery_evidence_observer,
clock_ns=clock_ns,
)
@@ -903,6 +936,7 @@ __all__ = [
"REFERENCE_GRAPH_ID_V2",
"TERMINAL_OUTCOME_SCHEMA",
"DeliveredFrame",
"DeliveryEvidenceObserver",
"GraphExecutionError",
"GraphRunResult",
"GraphRunResultV2",
+198
View File
@@ -0,0 +1,198 @@
"""Class-aware advisory projection over one delivered reference-graph frame."""
from __future__ import annotations
import re
from dataclasses import dataclass
from enum import StrEnum
from typing import Final
from .contracts import FalseAuthority, MotionState, ThreatDecision
from .graph_contracts import DeliveredFrame
from .object_understanding import AdvisoryResponse
M48S_ADVISORY_SCHEMA: Final = "missioncore.m48s-semantic-advisory/v0"
M48S_ADVISORY_POLICY_ID: Final = "m48s-behavior-relevant-object-advisory/v0"
_IDENTIFIER = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$")
class AdvisoryFamily(StrEnum):
GENERIC_OBSTACLE = "generic-obstacle"
PERSON = "person"
ANIMAL = "animal"
LIGHT_ROAD_USER = "light-road-user"
VEHICLE = "vehicle"
class M48sAdvisoryError(ValueError):
"""A semantic advisory escaped its bounded shadow-only policy."""
@dataclass(frozen=True, slots=True)
class M48sSemanticAdvisory:
component_id: str
semantic_hint: str | None
family: AdvisoryFamily
motion: MotionState
threat_decision: ThreatDecision
responses: tuple[AdvisoryResponse, ...]
reason_codes: tuple[str, ...]
policy_id: str = M48S_ADVISORY_POLICY_ID
authority: FalseAuthority = FalseAuthority()
def __post_init__(self) -> None:
if _IDENTIFIER.fullmatch(self.component_id) is None:
raise M48sAdvisoryError("advisory component id is invalid")
if self.semantic_hint is not None and _IDENTIFIER.fullmatch(self.semantic_hint) is None:
raise M48sAdvisoryError("advisory semantic hint is invalid")
if self.policy_id != M48S_ADVISORY_POLICY_ID:
raise M48sAdvisoryError("advisory policy identity changed")
if not self.responses or len(set(self.responses)) != len(self.responses):
raise M48sAdvisoryError("advisory responses must be unique and nonempty")
if not self.reason_codes or len(set(self.reason_codes)) != len(self.reason_codes):
raise M48sAdvisoryError("advisory reasons must be unique and nonempty")
if self.threat_decision is ThreatDecision.THREAT and (
AdvisoryResponse.STOP not in self.responses
):
raise M48sAdvisoryError("replay threat must retain a stop advisory")
if self.family is AdvisoryFamily.GENERIC_OBSTACLE and (
AdvisoryResponse.ROUTE_AROUND not in self.responses
and AdvisoryResponse.STOP not in self.responses
):
raise M48sAdvisoryError("generic obstacles must remain route-around advisories")
def to_dict(self) -> dict[str, object]:
return {
"schema_version": M48S_ADVISORY_SCHEMA,
"policy_id": self.policy_id,
"component_id": self.component_id,
"semantic_hint": self.semantic_hint,
"family": self.family.value,
"motion": self.motion.value,
"threat_decision": self.threat_decision.value,
"responses": [item.value for item in self.responses],
"reason_codes": list(self.reason_codes),
"authority": self.authority.to_dict(),
}
def project_m48s_advisories(
delivery: DeliveredFrame,
) -> tuple[M48sSemanticAdvisory, ...]:
"""Project class-specific caution without changing occupancy or graph threats."""
threat_by_component = {item.component_id: item.decision for item in delivery.threats}
advisories = [
_project(
component_id=obstacle.component_id,
semantic_hint=obstacle.semantic_hint,
motion=obstacle.motion,
threat_decision=threat_by_component[obstacle.component_id],
)
for obstacle in (*delivery.obstacle_map.occupied, *delivery.obstacle_map.unknown)
]
advisories.extend(
_project(
component_id=proposal.proposal_id,
semantic_hint=proposal.semantic_hint,
motion=MotionState.UNKNOWN,
threat_decision=threat_by_component[proposal.proposal_id],
)
for proposal in delivery.obstacle_map.camera_uncertainty
)
return tuple(advisories)
def advisory_policy_matrix() -> dict[AdvisoryFamily, tuple[AdvisoryResponse, ...]]:
"""Expose the fixed class-family policy for executable contract checks."""
return {
AdvisoryFamily.GENERIC_OBSTACLE: (AdvisoryResponse.ROUTE_AROUND,),
AdvisoryFamily.PERSON: (
AdvisoryResponse.YIELD,
AdvisoryResponse.REDUCE_SPEED,
),
AdvisoryFamily.ANIMAL: (
AdvisoryResponse.REDUCE_SPEED,
AdvisoryResponse.STOP,
),
AdvisoryFamily.LIGHT_ROAD_USER: (
AdvisoryResponse.YIELD,
AdvisoryResponse.REDUCE_SPEED,
AdvisoryResponse.MONITOR,
),
AdvisoryFamily.VEHICLE: (
AdvisoryResponse.MONITOR,
AdvisoryResponse.YIELD,
),
}
def _project(
*,
component_id: str,
semantic_hint: str | None,
motion: MotionState,
threat_decision: ThreatDecision,
) -> M48sSemanticAdvisory:
family = _family(semantic_hint)
responses = list(advisory_policy_matrix()[family])
reasons = [f"family-{family.value}"]
if motion is MotionState.UNKNOWN:
reasons.append("unknown-motion-conservative")
elif motion is MotionState.MOVING:
reasons.append("observed-moving")
if AdvisoryResponse.REDUCE_SPEED not in responses:
responses.append(AdvisoryResponse.REDUCE_SPEED)
else:
reasons.append("observed-stationary-not-permanent")
if threat_decision is ThreatDecision.THREAT:
reasons.append("reference-graph-replay-threat")
responses.insert(0, AdvisoryResponse.STOP)
elif threat_decision is ThreatDecision.UNKNOWN:
reasons.append("reference-graph-threat-unknown")
else:
reasons.append("reference-graph-threat-clear-at-observation")
return M48sSemanticAdvisory(
component_id=component_id,
semantic_hint=semantic_hint,
family=family,
motion=motion,
threat_decision=threat_decision,
responses=tuple(dict.fromkeys(responses)),
reason_codes=tuple(reasons),
)
def _family(semantic_hint: str | None) -> AdvisoryFamily:
if semantic_hint == "person":
return AdvisoryFamily.PERSON
if semantic_hint in {
"bird",
"cat",
"dog",
"horse",
"sheep",
"cow",
"elephant",
"bear",
"zebra",
"giraffe",
}:
return AdvisoryFamily.ANIMAL
if semantic_hint in {"bicycle", "motorcycle", "skateboard"}:
return AdvisoryFamily.LIGHT_ROAD_USER
if semantic_hint in {"car", "bus", "truck"}:
return AdvisoryFamily.VEHICLE
return AdvisoryFamily.GENERIC_OBSTACLE
__all__ = [
"M48S_ADVISORY_POLICY_ID",
"M48S_ADVISORY_SCHEMA",
"AdvisoryFamily",
"M48sAdvisoryError",
"M48sSemanticAdvisory",
"advisory_policy_matrix",
"project_m48s_advisories",
]
@@ -0,0 +1,252 @@
"""Shadow assembly for RF-DETR inside the source-neutral reference graph."""
from __future__ import annotations
import hashlib
import json
from collections.abc import Callable, Iterator
from dataclasses import dataclass
from pathlib import Path
from threading import Event
from .baseline import load_m4_baseline
from .detector import RF_DETR_SHADOW_PROVIDER_ID, RfDetrShadowDetectorProvider
from .geometry import (
Ravnoves00GeometryAssociationProvider,
RecordedGeometryStore,
load_geometry_profile,
)
from .graph import DeliveryEvidenceObserver, ReferencePerceptionGraphV2
from .graph_contracts import DeliveredFrame, GraphRunMode
from .motion import ClassIndependentMotionEstimator
from .providers import (
ProviderRole,
ReferencePerceptionGraphConfigV2,
SourcePacket,
SourceProvider,
)
from .recorded_source import (
DecodedRecordedSource,
PyAvRecordedImageDecoder,
RecordedRavnoves00Source,
ReplayPacing,
)
from .reference_graph_runtime import ReferenceGraphRuntimePaths
from .rf_detr_object_detector import (
RF_DETR_ENGINE_SHA256,
RF_DETR_MODEL_ID,
RF_DETR_MODEL_VERSION,
TritonRfDetrHttpInferenceBackend,
)
from .rolling_map import RollingLocalObstacleMapProvider, load_rolling_map_profile
from .temporal import BoundedSpatialTemporalProvider, load_temporal_motion_profile
from .threat import (
DualEvidenceReplayThreatProvider,
RecordedReplayBodyFrameResolver,
load_replay_threat_profile,
)
from .yolox_object_detector import load_valid_fov_mask
class M48sReferenceGraphRuntimeError(RuntimeError):
"""The RF-DETR graph shadow cannot be assembled from its pinned inputs."""
@dataclass(slots=True)
class M48sReferenceGraphRuntime:
"""Own one RF-DETR shadow graph and its persistent inference transport."""
graph: ReferencePerceptionGraphV2
inference_backend: TritonRfDetrHttpInferenceBackend
def close(self) -> None:
self.inference_backend.close()
def __enter__(self) -> M48sReferenceGraphRuntime:
return self
def __exit__(self, *args: object) -> None:
self.close()
def build_m48s_reference_graph_runtime(
*,
paths: ReferenceGraphRuntimePaths,
detector_profile: Path,
triton_origin: str,
run_mode: GraphRunMode,
delivery_observer: Callable[[DeliveredFrame, int], None] | None = None,
delivery_evidence_observer: DeliveryEvidenceObserver | None = None,
maximum_frames: int | None = None,
) -> M48sReferenceGraphRuntime:
"""Instantiate the complete graph with only its detector pin replaced."""
config = _load_graph_config(paths.graph_config)
pinned_files = {
ProviderRole.SOURCE: paths.baseline_profile,
ProviderRole.DETECTOR: detector_profile,
ProviderRole.GEOMETRY: paths.geometry_profile,
ProviderRole.TEMPORAL: paths.temporal_motion_profile,
ProviderRole.MOTION: paths.temporal_motion_profile,
ProviderRole.ROLLING: paths.rolling_map_profile,
ProviderRole.THREAT: paths.threat_profile,
}
_validate_provider_digests(config, pinned_files)
_validate_detector_profile(detector_profile)
load_m4_baseline(paths.baseline_profile)
geometry_profile = load_geometry_profile(paths.geometry_profile)
temporal_motion_profile = load_temporal_motion_profile(paths.temporal_motion_profile)
rolling_map_profile = load_rolling_map_profile(paths.rolling_map_profile)
threat_profile = load_replay_threat_profile(paths.threat_profile)
if maximum_frames is not None and maximum_frames < 1:
raise M48sReferenceGraphRuntimeError("maximum frame count must be positive")
source: SourceProvider = DecodedRecordedSource(
source=RecordedRavnoves00Source(
camera_index_path=paths.camera_index,
source_pack_path=paths.source_pack,
pacing=(
ReplayPacing.ONE_X
if run_mode is GraphRunMode.SOURCE_PACED_LATEST_WINS
else ReplayPacing.UNCAPPED
),
),
decoder=PyAvRecordedImageDecoder(paths.video),
)
if maximum_frames is not None:
source = _LimitedSource(source, maximum_frames)
backend = TritonRfDetrHttpInferenceBackend(triton_origin)
try:
store = RecordedGeometryStore(
source_pack_path=paths.source_pack,
local_surface_path=paths.local_surface,
profile=geometry_profile,
)
body_frame_resolver = RecordedReplayBodyFrameResolver(
store,
profile=threat_profile.body_frame,
)
graph = ReferencePerceptionGraphV2(
config=config,
source=source,
detector=RfDetrShadowDetectorProvider(
mask=load_valid_fov_mask(paths.valid_fov_mask),
backend=backend,
),
geometry=Ravnoves00GeometryAssociationProvider(store=store),
temporal=BoundedSpatialTemporalProvider(
point_resolver=store,
profile=temporal_motion_profile,
),
motion=ClassIndependentMotionEstimator(profile=temporal_motion_profile),
rolling=RollingLocalObstacleMapProvider(
pose_resolver=store,
profile=rolling_map_profile,
),
threat=DualEvidenceReplayThreatProvider(
body_frame_resolver=body_frame_resolver,
profile=threat_profile,
),
run_mode=run_mode,
delivery_observer=delivery_observer,
delivery_evidence_observer=delivery_evidence_observer,
)
except Exception:
backend.close()
raise
return M48sReferenceGraphRuntime(graph=graph, inference_backend=backend)
class _LimitedSource:
"""Bound a pilot without changing source or graph provider identity."""
def __init__(self, source: SourceProvider, maximum_frames: int) -> None:
self.source = source
self.maximum_frames = maximum_frames
self.provider_id = source.provider_id
def packets(self, stop_event: Event) -> Iterator[SourcePacket]:
packets = self.source.packets(stop_event)
for _index in range(self.maximum_frames):
try:
packet = next(packets)
except StopIteration:
return
yield packet
def _load_graph_config(path: Path) -> ReferencePerceptionGraphConfigV2:
try:
document = json.loads(path.resolve(strict=True).read_text("utf-8"))
return ReferencePerceptionGraphConfigV2.from_dict(document)
except (OSError, json.JSONDecodeError, ValueError) as exc:
raise M48sReferenceGraphRuntimeError("RF-DETR graph config is invalid") from exc
def _validate_provider_digests(
config: ReferencePerceptionGraphConfigV2,
pinned_files: dict[ProviderRole, Path],
) -> None:
pins = {pin.role: pin for pin in config.providers}
if set(pins) != set(pinned_files):
raise M48sReferenceGraphRuntimeError("RF-DETR graph provider pins are incomplete")
for role, path in pinned_files.items():
if _sha256_file(path) != pins[role].sha256:
raise M48sReferenceGraphRuntimeError(
f"{role.value} provider profile digest changed"
)
def _validate_detector_profile(path: Path) -> None:
try:
document = json.loads(path.resolve(strict=True).read_text("utf-8"))
model = document["model"]
status = document["status"]
authority = document["authority"]
except (OSError, KeyError, TypeError, json.JSONDecodeError) as exc:
raise M48sReferenceGraphRuntimeError("RF-DETR profile is incomplete") from exc
if (
document.get("schema_version")
!= "missioncore.rf-detr-risk-shadow-profile/v0"
or document.get("provider_id") != RF_DETR_SHADOW_PROVIDER_ID
or model.get("model_id") != RF_DETR_MODEL_ID
or model.get("model_version") != RF_DETR_MODEL_VERSION
or model.get("worker_006_rtx4090_tensorrt_11_engine_sha256")
!= RF_DETR_ENGINE_SHA256
or status.get("detector_load_gate_passed") is not True
or status.get("production_accepted") is not False
or any(
authority.get(key) is not False
for key in (
"candidate_accepted",
"commands_enabled",
"actuation_allowed",
"navigation_or_safety_accepted",
)
)
):
raise M48sReferenceGraphRuntimeError("RF-DETR shadow profile identity changed")
def _sha256_file(path: Path) -> str:
try:
resolved = path.resolve(strict=True)
except OSError as exc:
raise M48sReferenceGraphRuntimeError("pinned RF-DETR graph input is missing") from exc
if resolved.is_symlink() or not resolved.is_file():
raise M48sReferenceGraphRuntimeError(
"pinned RF-DETR graph input must be a regular file"
)
digest = hashlib.sha256()
with resolved.open("rb") as handle:
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
__all__ = [
"M48sReferenceGraphRuntime",
"M48sReferenceGraphRuntimeError",
"build_m48s_reference_graph_runtime",
]
@@ -0,0 +1,426 @@
"""Bounded camera, LiDAR, and world-state projection of sealed M4.8S replay evidence."""
from __future__ import annotations
import copy
import json
import math
import statistics
from dataclasses import dataclass
from itertools import pairwise
from pathlib import Path
from threading import RLock
from typing import Final
import numpy as np
from .geometry import RecordedGeometryStore
from .geometry_math import project_map_points_kb4
from .recorded_source import RECORDED_REPRESENTATION_ID
from .spatial_evidence import project_metric_obstacles_to_body, sample_points_in_body_frame
from .threat import (
DEFAULT_REPLAY_THREAT_PROFILE_PATH,
RecordedReplayBodyFrameResolver,
load_replay_threat_profile,
)
from .threat_timeline import (
RECORDED_LOCAL_SURFACE_POINT_LIMIT,
RECORDED_LOCAL_SURFACE_RADIUS_M,
RECORDED_LOCAL_SURFACE_VOXEL_SIZE_M,
RECORDED_LOCAL_SURFACE_WINDOW_SECONDS,
RECORDED_SPATIAL_CHUNK_SCHEMA,
RECORDED_SPATIAL_FRAME_SCHEMA,
RECORDED_SPATIAL_MAX_CHUNK_FRAMES,
RECORDED_SPATIAL_POINT_LIMIT,
RECORDED_SPATIAL_TIMELINE_SCHEMA,
)
FRAME_EVIDENCE_SCHEMA: Final = "missioncore.m48s-reference-graph-frame-evidence/v0"
EXPECTED_FRAME_COUNT: Final = 4_489
class M48sReplayTimelineError(RuntimeError):
"""The sealed M4.8S evidence cannot produce an exact bounded timeline."""
@dataclass(frozen=True, slots=True)
class _LedgerIndex:
offsets_by_sequence: dict[int, int]
class M48sReplayTimeline:
"""Read source-indexed chunks while preserving latest-wins world-state gaps."""
def __init__(self, *, repository_root: Path, result_root: Path, result_id: str) -> None:
self.repository_root = repository_root.resolve(strict=True)
self.result_root = result_root.resolve(strict=True)
self.result_id = result_id
self.frames_path = (
self.result_root / "reference-graph-replay-frames.jsonl"
).resolve(strict=True)
self.worker_path = (
self.result_root / "reference-graph-replay-worker-result.json"
).resolve(strict=True)
if (
self.frames_path.parent != self.result_root
or self.worker_path.parent != self.result_root
or self.frames_path.is_symlink()
or self.worker_path.is_symlink()
):
raise M48sReplayTimelineError("M4.8S replay artifacts are invalid")
self.profile = load_replay_threat_profile(
self.repository_root / DEFAULT_REPLAY_THREAT_PROFILE_PATH
)
self.store = RecordedGeometryStore.from_repository(self.repository_root)
if self.store.profile.frame_count != EXPECTED_FRAME_COUNT:
raise M48sReplayTimelineError("M4.8S source frame count changed")
self.body_frames = RecordedReplayBodyFrameResolver(
self.store,
profile=self.profile.body_frame,
)
self.source_times_ns = tuple(
self.store.temporal_binding_for_index(sequence).source_time_ns
for sequence in range(EXPECTED_FRAME_COUNT)
)
if any(right <= left for left, right in pairwise(self.source_times_ns)):
raise M48sReplayTimelineError("M4.8S source clock is not monotonic")
worker = _object(json.loads(self.worker_path.read_text("utf-8")), "worker result")
self.outcomes = _terminal_outcomes(worker)
self.index = _index_ledger(self.frames_path, self.source_times_ns, self.outcomes)
self._lock = RLock()
def metadata(self) -> dict[str, object]:
intervals = [
(current - previous) / 1_000_000_000
for previous, current in pairwise(self.source_times_ns)
]
nominal_interval = statistics.median(intervals)
return {
"schema_version": RECORDED_SPATIAL_TIMELINE_SCHEMA,
"result_id": self.result_id,
"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": EXPECTED_FRAME_COUNT,
"frame_times_ns": list(self.source_times_ns),
"timeline_start_seconds": self.source_times_ns[0] / 1_000_000_000,
"timeline_end_seconds": self.source_times_ns[-1] / 1_000_000_000,
"nominal_frame_interval_seconds": nominal_interval,
"nominal_rate_hz": 1 / nominal_interval,
"max_chunk_frames": RECORDED_SPATIAL_MAX_CHUNK_FRAMES,
"point_sample_limit": RECORDED_SPATIAL_POINT_LIMIT,
"maximum_source_points_per_frame": self.store.maximum_current_point_count,
"point_delivery": "exact-current-increment",
"camera_point_delivery": "factory-kb4-projected-current-increment",
"camera_point_sample_limit": RECORDED_SPATIAL_POINT_LIMIT,
"world_state_delivery": "source-paced-latest-wins",
"world_state_frame_count": len(self.index.offsets_by_sequence),
"superseded_frame_count": sum(value == "superseded" for value in self.outcomes.values()),
"local_surface_visualization": {
"derivation": "bounded-registered-increment-accumulation",
"window_seconds": RECORDED_LOCAL_SURFACE_WINDOW_SECONDS,
"voxel_size_m": RECORDED_LOCAL_SURFACE_VOXEL_SIZE_M,
"radius_m": RECORDED_LOCAL_SURFACE_RADIUS_M,
"point_limit": RECORDED_LOCAL_SURFACE_POINT_LIMIT,
"authority": "visual-derived",
},
"image_width": 800,
"image_height": 600,
"rig": {
"length_m": self.profile.rig.body_length_m,
"width_m": self.profile.rig.body_width_m,
"nominal_sensor_height_m": self.profile.rig.nominal_sensor_height_m,
},
"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
),
"prediction_horizon_seconds": self.profile.corridor.prediction_horizon_seconds,
},
"ground_truth": False,
"authority": "replay-simulated",
"access": "read-only-bounded-recorded-replay",
}
def chunk(self, *, start_sequence: int, frame_count: int) -> dict[str, object]:
if not 0 <= start_sequence < EXPECTED_FRAME_COUNT:
raise M48sReplayTimelineError("M4.8S timeline start is invalid")
if not 1 <= frame_count <= RECORDED_SPATIAL_MAX_CHUNK_FRAMES:
raise M48sReplayTimelineError("M4.8S timeline chunk size is invalid")
stop = min(EXPECTED_FRAME_COUNT, start_sequence + frame_count)
with self._lock:
frames = [self._project_frame(sequence) for sequence in range(start_sequence, stop)]
return {
"schema_version": RECORDED_SPATIAL_CHUNK_SCHEMA,
"result_id": self.result_id,
"start_sequence": start_sequence,
"frame_count": len(frames),
"next_sequence": stop if stop < EXPECTED_FRAME_COUNT else None,
"frames": frames,
"ground_truth": False,
"authority": "replay-simulated",
"access": "read-only-bounded-recorded-replay",
}
def _project_frame(self, sequence: int) -> dict[str, object]:
terminal_outcome = self.outcomes[sequence]
row = self._row(sequence)
frame_id = (
_text(_object(row["source_envelope"], "source envelope").get("frame_id"), "frame id")
if row is not None
else f"frame-{sequence:06d}"
)
binding = self.store.temporal_binding_for_index(sequence)
frame = self.store.frame_for_index(sequence)
body_frame = self.body_frames.body_frame_for_frame(frame_id)
point_cloud: list[list[float]] = []
point_source_count = 0
projected_points: list[list[float]] = []
projected_source_count = 0
projected_front_count = 0
projected_total = 0
if frame is not None:
projected = project_map_points_kb4(
frame.points_map,
position_map_xyz=frame.sensor_position_map,
orientation_map_from_lidar_xyzw=frame.sensor_orientation_xyzw,
profile=frame.projection,
)
projected_source_count = projected.source_point_count
projected_front_count = projected.camera_front_point_count
projected_total = projected.projected_point_count
stride = max(1, math.ceil(projected_total / RECORDED_SPATIAL_POINT_LIMIT))
indices = np.arange(0, projected_total, stride, dtype=np.int64)[
:RECORDED_SPATIAL_POINT_LIMIT
]
if indices.size:
xy = projected.pixels_xy[indices]
depth = projected.depths_m[indices, None]
projected_points = np.round(np.concatenate((xy, depth), axis=1), 4).tolist()
if body_frame is not None:
point_cloud, point_source_count = sample_points_in_body_frame(
frame.points_map,
body_frame,
point_limit=RECORDED_SPATIAL_POINT_LIMIT,
)
metric_visuals: list[dict[str, object]] = []
camera_proposals: list[dict[str, object]] = []
assessments: list[dict[str, object]] = []
if row is not None:
envelope = _object(row.get("source_envelope"), "source envelope")
timestamps = _object(envelope.get("timestamps"), "source timestamps")
if (
envelope.get("sequence") != sequence
or timestamps.get("source_ns") != binding.source_time_ns
or terminal_outcome != "delivered"
):
raise M48sReplayTimelineError("M4.8S delivered frame binding changed")
delivery = _object(row.get("delivery"), "delivery")
obstacle_map = _object(delivery.get("obstacle_map"), "obstacle map")
assessments = _objects(delivery.get("threats"), "threats")
assessment_by_component = {
_text(item.get("component_id"), "assessment component"): item
for item in assessments
}
metric_rows: list[dict[str, object]] = []
for obstacle in (
*_objects(obstacle_map.get("occupied"), "occupied obstacles"),
*_objects(obstacle_map.get("unknown"), "unknown obstacles"),
):
component_id = _text(obstacle.get("component_id"), "component id")
centroid = obstacle.get("last_centroid_xyz_m")
if centroid is None:
continue
metric_rows.append(
{
"component_id": component_id,
"state": obstacle.get("state"),
"motion": obstacle.get("motion"),
"centroid_map_xyz_m": centroid,
"cells": obstacle.get("cells"),
"assessment": assessment_by_component[component_id],
}
)
if body_frame is not None:
metric_visuals = project_metric_obstacles_to_body(
metric_rows,
body_frame,
occupied_voxel_size_m=self.profile.corridor.occupied_voxel_size_m,
)
associated = set(_strings(row.get("associated_proposal_ids"), "associated ids"))
for proposal in _objects(row.get("detector_proposals"), "detector proposals"):
proposal_id = _text(proposal.get("proposal_id"), "proposal id")
region = _object(proposal.get("region"), "proposal region")
assessment = assessment_by_component.get(proposal_id)
camera_proposals.append(
{
"proposal_id": proposal_id,
"bbox_xyxy": [
region.get("x_min"),
region.get("y_min"),
region.get("x_max"),
region.get("y_max"),
],
"objectness": proposal.get("objectness"),
"semantic_hint": proposal.get("semantic_hint"),
"occupied_support": proposal_id in associated,
"range_m": None,
"threat_decision": None if assessment is None else assessment.get("decision"),
"threat_reason_codes": []
if assessment is None
else assessment.get("reason_codes"),
}
)
return {
"schema_version": RECORDED_SPATIAL_FRAME_SCHEMA,
"sequence": sequence,
"frame_id": frame_id,
"source_time_ns": binding.source_time_ns,
"session_seconds": binding.source_time_ns / 1_000_000_000,
"source_available": binding.source_available,
"spatial_available": body_frame is not None and frame is not None,
"world_state_available": row is not None,
"terminal_outcome": terminal_outcome,
"body_frame": None
if body_frame is None
else {
"origin_map_xyz_m": list(body_frame.origin_map_xyz_m),
"basis_map_from_body": [list(value) for value in body_frame.basis_map_from_body],
},
"point_cloud_body_xyz_m": point_cloud,
"point_cloud_source_count": point_source_count,
"point_cloud_sample_count": len(point_cloud),
"point_cloud_layer": "current-increment",
"camera_projected_points_xyd": projected_points,
"camera_projected_source_count": projected_source_count,
"camera_projected_front_count": projected_front_count,
"camera_projected_point_count": projected_total,
"camera_projected_sample_count": len(projected_points),
"camera_projection": "factory-kb4-exact",
"rolling_map_component_count": sum(
item.get("state") == "retained" for item in metric_visuals
),
"metric_obstacles": metric_visuals,
"camera_proposals": camera_proposals,
"decision_counts": _decision_counts(assessments),
"camera_url": (
"/api/v1/laboratory/m48s/fixed-class-detector/"
f"{self.result_id}/timeline/frames/{sequence}/camera"
),
"ground_truth": False,
"authority": "replay-simulated",
}
def _row(self, sequence: int) -> dict[str, object] | None:
offset = self.index.offsets_by_sequence.get(sequence)
if offset is None:
return None
with self.frames_path.open("rb") as stream:
stream.seek(offset)
line = stream.readline()
value = json.loads(line)
if not isinstance(value, dict) or value.get("schema_version") != FRAME_EVIDENCE_SCHEMA:
raise M48sReplayTimelineError("M4.8S frame row is invalid")
return value
def _index_ledger(
path: Path,
source_times_ns: tuple[int, ...],
outcomes: dict[int, str],
) -> _LedgerIndex:
offsets: dict[int, int] = {}
with path.open("rb") as stream:
while True:
offset = stream.tell()
line = stream.readline()
if not line:
break
row = json.loads(line)
if not isinstance(row, dict) or row.get("schema_version") != FRAME_EVIDENCE_SCHEMA:
raise M48sReplayTimelineError("M4.8S ledger schema changed")
envelope = _object(row.get("source_envelope"), "source envelope")
timestamps = _object(envelope.get("timestamps"), "source timestamps")
sequence = envelope.get("sequence")
if (
not isinstance(sequence, int)
or isinstance(sequence, bool)
or not 0 <= sequence < EXPECTED_FRAME_COUNT
or sequence in offsets
or outcomes.get(sequence) != "delivered"
or timestamps.get("source_ns") != source_times_ns[sequence]
):
raise M48sReplayTimelineError("M4.8S ledger source binding changed")
offsets[sequence] = offset
delivered = {sequence for sequence, outcome in outcomes.items() if outcome == "delivered"}
if set(offsets) != delivered:
raise M48sReplayTimelineError("M4.8S ledger does not match delivered outcomes")
return _LedgerIndex(offsets)
def _terminal_outcomes(worker: dict[str, object]) -> dict[int, str]:
execution = _object(worker.get("execution"), "execution")
loops = execution.get("loops")
if not isinstance(loops, list) or len(loops) != 1:
raise M48sReplayTimelineError("M4.8S worker loop identity changed")
details = _object(loops[0], "worker loop").get("terminal_outcome_details")
result: dict[int, str] = {}
for item in _objects(details, "terminal outcomes"):
sequence = item.get("sequence")
outcome = item.get("outcome")
if (
not isinstance(sequence, int)
or isinstance(sequence, bool)
or outcome not in {"delivered", "superseded"}
or sequence in result
):
raise M48sReplayTimelineError("M4.8S terminal outcome is invalid")
result[sequence] = outcome
if sorted(result) != list(range(EXPECTED_FRAME_COUNT)):
raise M48sReplayTimelineError("M4.8S terminal outcomes are incomplete")
return result
def _decision_counts(assessments: list[dict[str, object]]) -> dict[str, int]:
result = {"threat": 0, "not-threat": 0, "unknown": 0}
for assessment in assessments:
decision = assessment.get("decision")
if not isinstance(decision, str) or decision not in result:
raise M48sReplayTimelineError("M4.8S threat decision is invalid")
result[decision] += 1
return result
def _object(value: object, label: str) -> dict[str, object]:
if not isinstance(value, dict):
raise M48sReplayTimelineError(f"M4.8S {label} is invalid")
return value
def _objects(value: object, label: str) -> list[dict[str, object]]:
if not isinstance(value, list) or any(not isinstance(item, dict) for item in value):
raise M48sReplayTimelineError(f"M4.8S {label} are invalid")
return copy.deepcopy(value)
def _strings(value: object, label: str) -> list[str]:
if not isinstance(value, list) or any(not isinstance(item, str) for item in value):
raise M48sReplayTimelineError(f"M4.8S {label} are invalid")
return value
def _text(value: object, label: str) -> str:
if not isinstance(value, str) or not value:
raise M48sReplayTimelineError(f"M4.8S {label} is invalid")
return value
__all__ = ["M48sReplayTimeline", "M48sReplayTimelineError"]