feat: qualify complete K1 replay on worker
This commit is contained in:
@@ -1327,8 +1327,8 @@ def build_k1_local_surface(
|
||||
"status": "replay-experiment-only",
|
||||
"production_promotion": False,
|
||||
"next_gate": (
|
||||
"run the accepted profile through a bounded latest-wins live-shadow "
|
||||
"queue without commands, free-space or safety authority"
|
||||
"qualify a separate dynamic-observation layer; physical K1 "
|
||||
"acquisition remains a later commissioning gate"
|
||||
),
|
||||
},
|
||||
"authority": {
|
||||
|
||||
@@ -4,6 +4,7 @@ import math
|
||||
import threading
|
||||
import time
|
||||
from collections import Counter, deque
|
||||
from collections.abc import Callable
|
||||
from dataclasses import asdict, dataclass
|
||||
from typing import Any, Final, Literal
|
||||
|
||||
@@ -767,6 +768,7 @@ class K1LocalSurfaceShadowRuntime:
|
||||
profile: K1LocalSurfaceProfile = DEFAULT_K1_LOCAL_SURFACE_PROFILE,
|
||||
queue_capacity: int = 2,
|
||||
result_capacity: int = 8,
|
||||
result_observer: Callable[[K1LocalSurfaceShadowResult], None] | None = None,
|
||||
) -> None:
|
||||
if (
|
||||
not session_id
|
||||
@@ -779,6 +781,7 @@ class K1LocalSurfaceShadowRuntime:
|
||||
self.profile = profile
|
||||
self._queue = LatestWinsQueue[K1LocalSurfaceShadowInput](queue_capacity)
|
||||
self._result_capacity = result_capacity
|
||||
self._result_observer = result_observer
|
||||
self._results: deque[K1LocalSurfaceShadowResult] = deque(maxlen=result_capacity)
|
||||
self._result_dropped = 0
|
||||
self._processed = 0
|
||||
@@ -788,6 +791,8 @@ class K1LocalSurfaceShadowRuntime:
|
||||
self._result_age_ms: deque[float] = deque(maxlen=512)
|
||||
self._last_error: str | None = None
|
||||
self._inflight = False
|
||||
self._first_published_monotonic_ns: int | None = None
|
||||
self._last_published_monotonic_ns: int | None = None
|
||||
self._condition = threading.Condition()
|
||||
self._closed = False
|
||||
self._estimator = K1LocalSurfaceShadowEstimator(profile)
|
||||
@@ -802,6 +807,9 @@ class K1LocalSurfaceShadowRuntime:
|
||||
with self._condition:
|
||||
if self._closed:
|
||||
raise RuntimeError("K1 local-surface shadow runtime is closed")
|
||||
if self._first_published_monotonic_ns is None:
|
||||
self._first_published_monotonic_ns = value.published_monotonic_ns
|
||||
self._last_published_monotonic_ns = value.published_monotonic_ns
|
||||
self._queue.publish(value)
|
||||
|
||||
def publish_views(
|
||||
@@ -849,6 +857,16 @@ class K1LocalSurfaceShadowRuntime:
|
||||
queue_snapshot = self._queue.snapshot()
|
||||
with self._condition:
|
||||
latest = self._results[-1] if self._results else None
|
||||
source_span_seconds = (
|
||||
0.0
|
||||
if self._first_published_monotonic_ns is None
|
||||
or self._last_published_monotonic_ns is None
|
||||
else (
|
||||
self._last_published_monotonic_ns
|
||||
- self._first_published_monotonic_ns
|
||||
)
|
||||
/ 1_000_000_000
|
||||
)
|
||||
return {
|
||||
"schema_version": K1_LOCAL_SURFACE_SHADOW_SCHEMA,
|
||||
"mode": "live-shadow-diagnostic-only",
|
||||
@@ -856,6 +874,14 @@ class K1LocalSurfaceShadowRuntime:
|
||||
"profile": self.profile.to_dict(),
|
||||
"queue_policy": "bounded-latest-wins",
|
||||
"queue": asdict(queue_snapshot),
|
||||
"delivery": {
|
||||
"source_span_seconds": source_span_seconds,
|
||||
"effective_fps": (
|
||||
self._processed / source_span_seconds
|
||||
if source_span_seconds > 0
|
||||
else 0.0
|
||||
),
|
||||
},
|
||||
"results": {
|
||||
"capacity": self._result_capacity,
|
||||
"depth": len(self._results),
|
||||
@@ -891,7 +917,9 @@ class K1LocalSurfaceShadowRuntime:
|
||||
self._inflight = True
|
||||
try:
|
||||
result = self._estimator.process(value)
|
||||
except (LidarGroundError, ValueError, np.linalg.LinAlgError) as exc:
|
||||
if self._result_observer is not None:
|
||||
self._result_observer(result)
|
||||
except Exception as exc:
|
||||
with self._condition:
|
||||
self._failed += 1
|
||||
self._last_error = type(exc).__name__
|
||||
@@ -922,10 +950,12 @@ class K1LocalSurfaceShadowCoordinator:
|
||||
future_pose_wait_ms: float = 25.0,
|
||||
retention_seconds: float = 3.0,
|
||||
result_capacity: int = 8,
|
||||
result_observer: Callable[[K1LocalSurfaceShadowResult], None] | None = None,
|
||||
) -> None:
|
||||
self.profile = profile
|
||||
self._queue_capacity = point_capacity
|
||||
self._result_capacity = result_capacity
|
||||
self._result_observer = result_observer
|
||||
self._binder = K1LocalSurfacePoseBinder(
|
||||
maximum_pose_binding_ms=profile.maximum_pose_binding_ms,
|
||||
point_capacity=point_capacity,
|
||||
@@ -953,6 +983,7 @@ class K1LocalSurfaceShadowCoordinator:
|
||||
profile=self.profile,
|
||||
queue_capacity=self._queue_capacity,
|
||||
result_capacity=self._result_capacity,
|
||||
result_observer=self._result_observer,
|
||||
)
|
||||
self._session_id = session_id
|
||||
|
||||
|
||||
@@ -363,7 +363,7 @@ class LivePerceptionIngress:
|
||||
"control": 4,
|
||||
"camera-init": 1,
|
||||
"camera-frame": 2,
|
||||
"lidar": 2,
|
||||
"lidar": 8,
|
||||
"pose": 16,
|
||||
}
|
||||
_MAX_PAYLOAD_BYTES: Final[dict[LiveIngressModality, int]] = {
|
||||
|
||||
Reference in New Issue
Block a user