refactor(perception): isolate detector runtime
This commit is contained in:
@@ -139,7 +139,7 @@
|
||||
},
|
||||
"wheel": {
|
||||
"name": "nodedc_mission_core-0.1.0-py3-none-any.whl",
|
||||
"sha256": "df756938f2c212fb6d1770c83569e5366c708d70d74e0434895a21be55a16102"
|
||||
"sha256": "4158784fd40b70c7213b629ed39d664fd2f12eab1c9242ec9a6ebbb366e3dd5a"
|
||||
}
|
||||
},
|
||||
"rollback": {
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
"admission": "reuse"
|
||||
},
|
||||
{
|
||||
"module": "k1link.compute.yolox_object_detector",
|
||||
"role": "frozen source-neutral YOLOX preprocess, Triton transport and postprocess",
|
||||
"admission": "adapt-behind-provider"
|
||||
"module": "k1link.perception.yolox_object_detector",
|
||||
"role": "product-owned frozen YOLOX preprocess, Triton transport and postprocess",
|
||||
"admission": "product-owned"
|
||||
}
|
||||
],
|
||||
"historical_wrappers": [
|
||||
|
||||
@@ -686,7 +686,7 @@ duplicate development server or Worker 006 mutation was introduced.
|
||||
The product detector seam is implemented without importing the immutable E46J
|
||||
wrapper:
|
||||
|
||||
- `k1link.compute.yolox_object_detector` contains only the frozen raw-KB4
|
||||
- `k1link.perception.yolox_object_detector` contains only the frozen raw-KB4
|
||||
valid-FOV fill, top-left bilinear letterbox, Triton V2 binary HTTP transport,
|
||||
standard YOLOX decode, fixed score/class-wise NMS and FOV/box validation;
|
||||
- `k1link.perception.detector.FrozenYoloxDetectorProvider` turns exactly one
|
||||
|
||||
@@ -25,7 +25,7 @@ WHEEL_NAME = "nodedc_mission_core-0.1.0-py3-none-any.whl"
|
||||
RUNNER_NAME = RUNNER.name
|
||||
PATCH_ID = re.compile(r"^[A-Za-z0-9._-]{1,96}$")
|
||||
EXPECTED_BASELINE_SHA256 = "ea10359339e6cce31b5780a2710299771cab7cc0c1c2a2b56a1621f786b31fa8"
|
||||
EXPECTED_WHEEL_SHA256 = "df756938f2c212fb6d1770c83569e5366c708d70d74e0434895a21be55a16102"
|
||||
EXPECTED_WHEEL_SHA256 = "4158784fd40b70c7213b629ed39d664fd2f12eab1c9242ec9a6ebbb366e3dd5a"
|
||||
PAYLOAD_FILES = (
|
||||
RUNNER_NAME,
|
||||
WHEEL_NAME,
|
||||
|
||||
@@ -1,213 +1,6 @@
|
||||
"""Object-centric, source-neutral Mission Core perception product boundary."""
|
||||
"""Object-centric, source-neutral Mission Core perception product boundary.
|
||||
|
||||
from .adapters import (
|
||||
PerceptionAdapterError,
|
||||
observations_from_track_geometry,
|
||||
temporal_obstacles_from_e34_projection,
|
||||
)
|
||||
from .baseline import (
|
||||
BASELINE_PROFILE_ID,
|
||||
BASELINE_SCHEMA,
|
||||
BaselineContractError,
|
||||
BaselineProfile,
|
||||
BaselineVerification,
|
||||
load_m4_baseline,
|
||||
validate_reuse_inventory,
|
||||
verify_m4_baseline,
|
||||
verify_m4_execution_source,
|
||||
)
|
||||
from .contracts import (
|
||||
LOCAL_OBSTACLE_MAP_SCHEMA,
|
||||
OBJECT_PROPOSAL_SCHEMA,
|
||||
OBSTACLE_OBSERVATION_SCHEMA,
|
||||
SOURCE_ENVELOPE_SCHEMA,
|
||||
TEMPORAL_OBSTACLE_SCHEMA,
|
||||
THREAT_ASSESSMENT_SCHEMA,
|
||||
BoundingRegion2D,
|
||||
ClockBasis,
|
||||
CorridorIntersection,
|
||||
EvidenceBasis,
|
||||
EvidenceCurrentness,
|
||||
FalseAuthority,
|
||||
GridCell,
|
||||
HistorySample,
|
||||
LocalObstacleMap,
|
||||
MetricGeometry,
|
||||
ModalityOutcome,
|
||||
ModalityStatus,
|
||||
MotionState,
|
||||
ObjectProposal2D,
|
||||
ObstacleObservation,
|
||||
PerceptionContractError,
|
||||
QualificationState,
|
||||
SourceAccounting,
|
||||
SourceEnvelope,
|
||||
TemporalObstacle,
|
||||
TemporalState,
|
||||
ThreatAssessment,
|
||||
ThreatAuthority,
|
||||
ThreatDecision,
|
||||
TimestampBundle,
|
||||
validate_exclusive_point_ownership,
|
||||
)
|
||||
from .detector import (
|
||||
FROZEN_YOLOX_MODEL_ID,
|
||||
FROZEN_YOLOX_PREPROCESS_ID,
|
||||
FROZEN_YOLOX_PROVIDER_ID,
|
||||
DetectorProviderError,
|
||||
DetectorProviderSnapshot,
|
||||
FrozenYoloxDetectorProvider,
|
||||
proposals_from_detections,
|
||||
)
|
||||
from .detector_replay import run_detector_replay
|
||||
from .detector_replay_result import (
|
||||
DETECTOR_REPLAY_FRAME_SCHEMA,
|
||||
DETECTOR_REPLAY_RESULT_SCHEMA,
|
||||
DETECTOR_RUNTIME_IDENTITY_SCHEMA,
|
||||
M4_DETECTOR_REPLAY_GATE,
|
||||
DetectorReplayFrame,
|
||||
DetectorReplayGate,
|
||||
DetectorReplayMetrics,
|
||||
DetectorReplayResult,
|
||||
DetectorReplayResultError,
|
||||
DetectorRuntimeIdentity,
|
||||
read_detector_replay_result,
|
||||
require_m4_detector_replay_acceptance,
|
||||
)
|
||||
from .graph import (
|
||||
GRAPH_RESULT_SCHEMA,
|
||||
REFERENCE_GRAPH_ID,
|
||||
TERMINAL_OUTCOME_SCHEMA,
|
||||
DeliveredFrame,
|
||||
GraphExecutionError,
|
||||
GraphRunResult,
|
||||
GraphState,
|
||||
ReferencePerceptionGraphV1,
|
||||
TerminalOutcome,
|
||||
TerminalOutcomeType,
|
||||
)
|
||||
from .providers import (
|
||||
REFERENCE_GRAPH_CONFIG_SCHEMA,
|
||||
DetectorProvider,
|
||||
GeometryAssociationProvider,
|
||||
GraphAuthority,
|
||||
MotionProvider,
|
||||
ProviderContractError,
|
||||
ProviderPin,
|
||||
ProviderRole,
|
||||
QueuePolicy,
|
||||
ReferencePerceptionGraphConfig,
|
||||
SourcePacket,
|
||||
SourceProvider,
|
||||
TemporalStateProvider,
|
||||
ThreatProvider,
|
||||
)
|
||||
from .recorded_source import (
|
||||
DecodedRecordedSource,
|
||||
LiveSourceAdapter,
|
||||
PyAvRecordedImageDecoder,
|
||||
RecordedFrameReference,
|
||||
RecordedImageDecoder,
|
||||
RecordedRavnoves00Source,
|
||||
RecordedSourceError,
|
||||
ReplayPacing,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"BASELINE_PROFILE_ID",
|
||||
"BASELINE_SCHEMA",
|
||||
"BaselineContractError",
|
||||
"BaselineProfile",
|
||||
"BaselineVerification",
|
||||
"load_m4_baseline",
|
||||
"validate_reuse_inventory",
|
||||
"verify_m4_execution_source",
|
||||
"verify_m4_baseline",
|
||||
"PerceptionAdapterError",
|
||||
"observations_from_track_geometry",
|
||||
"temporal_obstacles_from_e34_projection",
|
||||
"LOCAL_OBSTACLE_MAP_SCHEMA",
|
||||
"OBJECT_PROPOSAL_SCHEMA",
|
||||
"OBSTACLE_OBSERVATION_SCHEMA",
|
||||
"SOURCE_ENVELOPE_SCHEMA",
|
||||
"TEMPORAL_OBSTACLE_SCHEMA",
|
||||
"THREAT_ASSESSMENT_SCHEMA",
|
||||
"BoundingRegion2D",
|
||||
"ClockBasis",
|
||||
"CorridorIntersection",
|
||||
"EvidenceBasis",
|
||||
"EvidenceCurrentness",
|
||||
"FalseAuthority",
|
||||
"GridCell",
|
||||
"HistorySample",
|
||||
"LocalObstacleMap",
|
||||
"MetricGeometry",
|
||||
"ModalityOutcome",
|
||||
"ModalityStatus",
|
||||
"MotionState",
|
||||
"ObjectProposal2D",
|
||||
"ObstacleObservation",
|
||||
"PerceptionContractError",
|
||||
"QualificationState",
|
||||
"SourceAccounting",
|
||||
"SourceEnvelope",
|
||||
"TemporalObstacle",
|
||||
"TemporalState",
|
||||
"ThreatAssessment",
|
||||
"ThreatAuthority",
|
||||
"ThreatDecision",
|
||||
"TimestampBundle",
|
||||
"validate_exclusive_point_ownership",
|
||||
"FROZEN_YOLOX_MODEL_ID",
|
||||
"FROZEN_YOLOX_PREPROCESS_ID",
|
||||
"FROZEN_YOLOX_PROVIDER_ID",
|
||||
"DetectorProviderError",
|
||||
"DetectorProviderSnapshot",
|
||||
"FrozenYoloxDetectorProvider",
|
||||
"proposals_from_detections",
|
||||
"DETECTOR_REPLAY_FRAME_SCHEMA",
|
||||
"DETECTOR_REPLAY_RESULT_SCHEMA",
|
||||
"DETECTOR_RUNTIME_IDENTITY_SCHEMA",
|
||||
"M4_DETECTOR_REPLAY_GATE",
|
||||
"DetectorReplayFrame",
|
||||
"DetectorReplayGate",
|
||||
"DetectorReplayMetrics",
|
||||
"DetectorReplayResult",
|
||||
"DetectorReplayResultError",
|
||||
"DetectorRuntimeIdentity",
|
||||
"read_detector_replay_result",
|
||||
"require_m4_detector_replay_acceptance",
|
||||
"run_detector_replay",
|
||||
"REFERENCE_GRAPH_CONFIG_SCHEMA",
|
||||
"DetectorProvider",
|
||||
"GeometryAssociationProvider",
|
||||
"GraphAuthority",
|
||||
"MotionProvider",
|
||||
"ProviderContractError",
|
||||
"ProviderPin",
|
||||
"ProviderRole",
|
||||
"QueuePolicy",
|
||||
"ReferencePerceptionGraphConfig",
|
||||
"SourcePacket",
|
||||
"SourceProvider",
|
||||
"TemporalStateProvider",
|
||||
"ThreatProvider",
|
||||
"GRAPH_RESULT_SCHEMA",
|
||||
"REFERENCE_GRAPH_ID",
|
||||
"TERMINAL_OUTCOME_SCHEMA",
|
||||
"DeliveredFrame",
|
||||
"GraphExecutionError",
|
||||
"GraphRunResult",
|
||||
"GraphState",
|
||||
"ReferencePerceptionGraphV1",
|
||||
"TerminalOutcome",
|
||||
"TerminalOutcomeType",
|
||||
"LiveSourceAdapter",
|
||||
"DecodedRecordedSource",
|
||||
"PyAvRecordedImageDecoder",
|
||||
"RecordedFrameReference",
|
||||
"RecordedImageDecoder",
|
||||
"RecordedRavnoves00Source",
|
||||
"RecordedSourceError",
|
||||
"ReplayPacing",
|
||||
]
|
||||
The package initializer is deliberately side-effect free. Runtime code imports
|
||||
the concrete contract, provider, graph or source module it needs; importing the
|
||||
product namespace must not initialize legacy compute, device, web or MQTT code.
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,9 @@ from typing import Final
|
||||
import numpy as np
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
from .contracts import BoundingRegion2D, ObjectProposal2D
|
||||
from .providers import SourcePacket
|
||||
from .yolox_object_detector import (
|
||||
FROZEN_YOLOX_CONFIG,
|
||||
YOLOX_MODEL_ID,
|
||||
YOLOX_MODEL_VERSION,
|
||||
@@ -24,9 +26,6 @@ from k1link.compute.yolox_object_detector import (
|
||||
preprocess_raw_kb4,
|
||||
)
|
||||
|
||||
from .contracts import BoundingRegion2D, ObjectProposal2D
|
||||
from .providers import SourcePacket
|
||||
|
||||
FROZEN_YOLOX_PROVIDER_ID: Final = "triton-yolox-s-raw-kb4/v1"
|
||||
FROZEN_YOLOX_MODEL_ID: Final = f"{YOLOX_MODEL_ID}:{YOLOX_MODEL_VERSION}"
|
||||
FROZEN_YOLOX_PREPROCESS_ID: Final = "raw-kb4-valid-fov-letterbox/v1"
|
||||
|
||||
@@ -9,11 +9,6 @@ import urllib.parse
|
||||
from pathlib import Path
|
||||
from threading import Event
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
TritonHttpInferenceBackend,
|
||||
load_valid_fov_mask,
|
||||
)
|
||||
|
||||
from .baseline import load_m4_baseline, verify_m4_execution_source
|
||||
from .detector import FrozenYoloxDetectorProvider
|
||||
from .detector_replay import run_detector_replay
|
||||
@@ -28,6 +23,10 @@ from .recorded_source import (
|
||||
RecordedRavnoves00Source,
|
||||
ReplayPacing,
|
||||
)
|
||||
from .yolox_object_detector import (
|
||||
TritonHttpInferenceBackend,
|
||||
load_valid_fov_mask,
|
||||
)
|
||||
|
||||
|
||||
def _arguments() -> argparse.Namespace:
|
||||
|
||||
@@ -8,12 +8,6 @@ from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
from .contracts import ObjectProposal2D, SourceEnvelope
|
||||
from .detector import (
|
||||
FROZEN_YOLOX_MODEL_ID,
|
||||
@@ -21,6 +15,11 @@ from .detector import (
|
||||
FROZEN_YOLOX_PROVIDER_ID,
|
||||
DetectorProviderSnapshot,
|
||||
)
|
||||
from .yolox_object_detector import (
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
DETECTOR_REPLAY_RESULT_SCHEMA: Final = "missioncore.perception-detector-replay-result/v1"
|
||||
DETECTOR_REPLAY_RECEIPT_SCHEMA: Final = "missioncore.perception-detector-replay-receipt/v1"
|
||||
|
||||
@@ -10,14 +10,6 @@ import uuid
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
FROZEN_YOLOX_CONFIG,
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_MODEL_VERSION,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
from .baseline import (
|
||||
BASELINE_CAMERA_STREAM_SHA256,
|
||||
BASELINE_FILE_SHA256,
|
||||
@@ -57,6 +49,13 @@ from .detector_replay_validation import (
|
||||
)
|
||||
from .detector_replay_validation import validate_frame_accounting
|
||||
from .recorded_source import RECORDED_SOURCE_PROVIDER_ID
|
||||
from .yolox_object_detector import (
|
||||
FROZEN_YOLOX_CONFIG,
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_MODEL_VERSION,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
|
||||
def seal_detector_replay_result(
|
||||
|
||||
@@ -6,14 +6,6 @@ import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
FROZEN_YOLOX_CONFIG,
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_MODEL_VERSION,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
from .baseline import (
|
||||
BASELINE_CAMERA_STREAM_SHA256,
|
||||
BASELINE_FILE_SHA256,
|
||||
@@ -53,6 +45,13 @@ from .detector_replay_contracts import (
|
||||
detector_replay_accepted,
|
||||
)
|
||||
from .recorded_source import RECORDED_SOURCE_PROVIDER_ID
|
||||
from .yolox_object_detector import (
|
||||
FROZEN_YOLOX_CONFIG,
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_MODEL_VERSION,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
|
||||
def read_detector_replay_result(root: Path) -> DetectorReplayResult:
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
"""Source-neutral frozen YOLOX preprocessing, inference transport and postprocessing."""
|
||||
"""Perception-owned frozen YOLOX preprocessing, transport and postprocessing."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -11,11 +11,6 @@ import numpy as np
|
||||
import pytest
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
from k1link.perception.contracts import (
|
||||
ClockBasis,
|
||||
ModalityOutcome,
|
||||
@@ -34,6 +29,11 @@ from k1link.perception.detector_replay_result import (
|
||||
require_m4_detector_replay_acceptance,
|
||||
)
|
||||
from k1link.perception.providers import SourcePacket
|
||||
from k1link.perception.yolox_object_detector import (
|
||||
YOLOX_CONFIG_SHA256,
|
||||
YOLOX_MODEL_SHA256,
|
||||
YOLOX_VALID_FOV_SHA256,
|
||||
)
|
||||
|
||||
|
||||
class _Source:
|
||||
|
||||
@@ -19,6 +19,20 @@ REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
PERCEPTION_ROOT = REPOSITORY_ROOT / "src" / "k1link" / "perception"
|
||||
BASELINE_PATH = REPOSITORY_ROOT / "config" / "perception" / "m4-recorded-realtime-baseline-v1.json"
|
||||
REUSE_PATH = REPOSITORY_ROOT / "config" / "perception" / "m4-reuse-inventory-v1.json"
|
||||
DETECTOR_RUNTIME_MODULES = (
|
||||
"__init__.py",
|
||||
"baseline.py",
|
||||
"contracts.py",
|
||||
"detector.py",
|
||||
"detector_replay.py",
|
||||
"detector_replay_cli.py",
|
||||
"detector_replay_contracts.py",
|
||||
"detector_replay_result.py",
|
||||
"detector_replay_validation.py",
|
||||
"providers.py",
|
||||
"recorded_source.py",
|
||||
"yolox_object_detector.py",
|
||||
)
|
||||
|
||||
|
||||
def _imports(path: Path) -> set[str]:
|
||||
@@ -151,6 +165,22 @@ def test_perception_contracts_import_no_compute_lab_graph_or_web_module() -> Non
|
||||
assert forbidden == set()
|
||||
|
||||
|
||||
def test_perception_package_initializer_is_side_effect_free() -> None:
|
||||
assert _imports(PERCEPTION_ROOT / "__init__.py") == set()
|
||||
|
||||
|
||||
def test_detector_runtime_closure_imports_no_legacy_compute_package() -> None:
|
||||
violations = {
|
||||
name: sorted(
|
||||
module
|
||||
for module in _imports(PERCEPTION_ROOT / name)
|
||||
if module.startswith("k1link.compute")
|
||||
)
|
||||
for name in DETECTOR_RUNTIME_MODULES
|
||||
}
|
||||
assert {name: modules for name, modules in violations.items() if modules} == {}
|
||||
|
||||
|
||||
def test_new_perception_boundary_has_no_experiment_specific_imports() -> None:
|
||||
violations: dict[str, str] = {}
|
||||
for path in PERCEPTION_ROOT.glob("*.py"):
|
||||
|
||||
@@ -9,14 +9,6 @@ import numpy as np
|
||||
import pytest
|
||||
from numpy.typing import NDArray
|
||||
|
||||
from k1link.compute.yolox_object_detector import (
|
||||
FrozenYoloxConfig,
|
||||
TritonHttpInferenceBackend,
|
||||
YoloxDetection,
|
||||
YoloxDetectorError,
|
||||
postprocess_yolox,
|
||||
preprocess_raw_kb4,
|
||||
)
|
||||
from k1link.perception.contracts import (
|
||||
ClockBasis,
|
||||
ModalityOutcome,
|
||||
@@ -31,6 +23,14 @@ from k1link.perception.detector import (
|
||||
proposals_from_detections,
|
||||
)
|
||||
from k1link.perception.providers import SourcePacket
|
||||
from k1link.perception.yolox_object_detector import (
|
||||
FrozenYoloxConfig,
|
||||
TritonHttpInferenceBackend,
|
||||
YoloxDetection,
|
||||
YoloxDetectorError,
|
||||
postprocess_yolox,
|
||||
preprocess_raw_kb4,
|
||||
)
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
E46J_FRAMES = (
|
||||
|
||||
Reference in New Issue
Block a user