feat(perception): integrate calibrated operator pipeline
Add calibrated K1 projection, recorded and near-live perception qualification, unified Rerun operator layers, bounded replay admission, audited viewer controls, worker experiments, and lab evidence.
This commit is contained in:
+79
-6
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import shutil
|
||||
from collections.abc import AsyncIterator, Iterable
|
||||
from contextlib import asynccontextmanager, suppress
|
||||
@@ -14,7 +15,13 @@ from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import ValidationError
|
||||
|
||||
from k1link import __version__
|
||||
from k1link.compute import RecordedPerceptionOverlayStore
|
||||
from k1link.compute import (
|
||||
IntegratedPerceptionOverlayStore,
|
||||
RecordedCalibratedFusionStore,
|
||||
RecordedPerceptionEpochStore,
|
||||
RecordedPerceptionOverlayMux,
|
||||
RecordedPerceptionOverlayStore,
|
||||
)
|
||||
from k1link.sessions import (
|
||||
MaterializedRecording,
|
||||
RecordedMediaInspector,
|
||||
@@ -42,6 +49,22 @@ REPOSITORY_ROOT = Path(__file__).resolve().parents[3]
|
||||
INVALID_REQUEST_DETAIL = "Некорректные параметры запроса."
|
||||
|
||||
|
||||
def _resolve_media_tool(name: str) -> Path | None:
|
||||
"""Resolve media tools under interactive shells and minimal launchd PATHs."""
|
||||
|
||||
discovered = shutil.which(name)
|
||||
candidates = (
|
||||
Path(discovered) if discovered is not None else None,
|
||||
Path("/opt/homebrew/bin") / name,
|
||||
Path("/usr/local/bin") / name,
|
||||
Path("/usr/bin") / name,
|
||||
)
|
||||
for candidate in candidates:
|
||||
if candidate is not None and candidate.is_file() and os.access(candidate, os.X_OK):
|
||||
return candidate
|
||||
return None
|
||||
|
||||
|
||||
plugin_environment = load_installed_device_plugins(REPOSITORY_ROOT)
|
||||
plugin_catalog: DevicePluginCatalog = plugin_environment.catalog
|
||||
plugin_dispatcher: DevicePluginDispatcher = plugin_environment.dispatcher
|
||||
@@ -53,19 +76,68 @@ session_recording_materializer = SessionRecordingMaterializer(
|
||||
session_recorded_media_inspector = RecordedMediaInspector(
|
||||
session_store.data_dir / "recorded-media-preparations"
|
||||
)
|
||||
_ffmpeg = shutil.which("ffmpeg")
|
||||
_ffprobe = shutil.which("ffprobe")
|
||||
session_perception_overlay_store = (
|
||||
_ffmpeg = _resolve_media_tool("ffmpeg")
|
||||
_ffprobe = _resolve_media_tool("ffprobe")
|
||||
session_legacy_perception_overlay_store = (
|
||||
RecordedPerceptionOverlayStore(
|
||||
jobs_root=REPOSITORY_ROOT / ".runtime" / "compute-jobs",
|
||||
results_root=REPOSITORY_ROOT / ".runtime" / "compute-results",
|
||||
cache_root=session_store.data_dir / "perception-overlays",
|
||||
ffmpeg_path=Path(_ffmpeg),
|
||||
ffprobe_path=Path(_ffprobe),
|
||||
ffmpeg_path=_ffmpeg,
|
||||
ffprobe_path=_ffprobe,
|
||||
)
|
||||
if _ffmpeg is not None and _ffprobe is not None
|
||||
else None
|
||||
)
|
||||
session_calibrated_fusion_store = RecordedCalibratedFusionStore(
|
||||
jobs_root=REPOSITORY_ROOT / ".runtime" / "compute-jobs",
|
||||
perception_results_root=REPOSITORY_ROOT / ".runtime" / "compute-results",
|
||||
fusion_results_root=REPOSITORY_ROOT / ".runtime" / "compute-fusions",
|
||||
cache_root=session_store.data_dir / "calibrated-fusion-overlays",
|
||||
)
|
||||
session_previous_perception_overlay_store = RecordedPerceptionOverlayMux(
|
||||
session_calibrated_fusion_store, session_legacy_perception_overlay_store
|
||||
)
|
||||
session_integrated_perception_store = (
|
||||
IntegratedPerceptionOverlayStore(
|
||||
jobs_root=REPOSITORY_ROOT / ".runtime" / "compute-jobs",
|
||||
results_root=(
|
||||
REPOSITORY_ROOT
|
||||
/ ".runtime"
|
||||
/ "compute-experiments"
|
||||
/ "e10"
|
||||
/ "worker-results"
|
||||
),
|
||||
lidar_packs_root=(
|
||||
REPOSITORY_ROOT
|
||||
/ ".runtime"
|
||||
/ "compute-experiments"
|
||||
/ "e10"
|
||||
/ "lidar-packs"
|
||||
),
|
||||
cache_root=session_store.data_dir / "integrated-perception-overlays",
|
||||
ffmpeg_path=_ffmpeg,
|
||||
)
|
||||
if _ffmpeg is not None
|
||||
else None
|
||||
)
|
||||
session_perception_overlay_store = RecordedPerceptionOverlayMux(
|
||||
session_integrated_perception_store or session_previous_perception_overlay_store,
|
||||
(
|
||||
session_previous_perception_overlay_store
|
||||
if session_integrated_perception_store is not None
|
||||
else None
|
||||
),
|
||||
)
|
||||
session_perception_epoch_store = (
|
||||
RecordedPerceptionEpochStore(
|
||||
jobs_root=REPOSITORY_ROOT / ".runtime" / "compute-jobs",
|
||||
results_root=REPOSITORY_ROOT / ".runtime" / "compute-results",
|
||||
ffprobe_path=_ffprobe,
|
||||
)
|
||||
if _ffprobe is not None
|
||||
else None
|
||||
)
|
||||
|
||||
|
||||
def _prepare_recorded_media_for_launch(
|
||||
@@ -320,6 +392,7 @@ app.include_router(
|
||||
recording_preparation_manager=session_recording_preparation_manager,
|
||||
media_inspector=session_recorded_media_inspector,
|
||||
perception_overlay_provider=session_perception_overlay_store,
|
||||
perception_media_provider=session_perception_epoch_store,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user