feat: add passive K1 local surface replay

This commit is contained in:
DCCONSTRUCTIONS
2026-07-25 22:47:12 +03:00
parent cfe17e49bb
commit 04a658b218
16 changed files with 2715 additions and 21 deletions
+18
View File
@@ -106,6 +106,16 @@ from .lidar_ground import (
lidar_ground_frame_detail,
score_ground_labels,
)
from .lidar_local_surface import (
DEFAULT_K1_LOCAL_SURFACE_PROFILE,
K1_LOCAL_SURFACE_FRAME_SCHEMA,
K1_LOCAL_SURFACE_REPORT_SCHEMA,
K1_LOCAL_SURFACE_SCHEMA,
K1LocalSurfaceProfile,
K1LocalSurfaceV1,
build_k1_local_surface,
k1_local_surface_catalog_item,
)
from .lidar_replay import (
LIDAR_EQUIVALENCE_REPORT_SCHEMA,
LIDAR_QUALITY_REPORT_SCHEMA,
@@ -185,6 +195,7 @@ __all__ = [
"AnnotationWorkspaceError",
"COMPUTE_JOB_SCHEMA",
"DEFAULT_QUALIFICATION_FRAME_COUNT",
"DEFAULT_K1_LOCAL_SURFACE_PROFILE",
"EVALUATION_PACK_SCHEMA",
"EvaluationFrameRequest",
"EvaluationPackFrame",
@@ -195,6 +206,9 @@ __all__ = [
"LIDAR_GROUND_BENCHMARK_REPORT_SCHEMA",
"LIDAR_GROUND_BENCHMARK_SCHEMA",
"LIDAR_GROUND_FRAME_SCHEMA",
"K1_LOCAL_SURFACE_FRAME_SCHEMA",
"K1_LOCAL_SURFACE_REPORT_SCHEMA",
"K1_LOCAL_SURFACE_SCHEMA",
"LIDAR_FIELD_REVIEW_REPORT_SCHEMA",
"LIDAR_FIELD_REVIEW_SCHEMA",
"LIDAR_FIELD_REVIEW_WINDOW_SCHEMA",
@@ -217,6 +231,8 @@ __all__ = [
"LidarReadiness",
"LidarGroundBenchmarkV1",
"LidarGroundError",
"K1LocalSurfaceProfile",
"K1LocalSurfaceV1",
"LidarReplayError",
"LidarReplayPackV2",
"LidarReplayPointFrame",
@@ -280,7 +296,9 @@ __all__ = [
"build_lidar_replay_pack_v2",
"build_lidar_ground_annotation_template",
"build_lidar_ground_benchmark",
"build_k1_local_surface",
"lidar_ground_frame_detail",
"k1_local_surface_catalog_item",
"E10_LIDAR_PACK_SCHEMA",
"FIELD_REVIEW_ARRAYS_NAME",
"FIELD_REVIEW_MANIFEST_NAME",
File diff suppressed because it is too large Load Diff
+21
View File
@@ -420,6 +420,27 @@ app.include_router(
/ "lidar-ground-v1"
/ "benchmarks"
),
field_review_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "lidar-field-review-v1"
/ "reviews"
),
local_surface_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "k1-local-surface-v1"
/ "models"
),
e10_source_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "e10"
/ "lidar-packs"
),
dataset_admission_provider=lambda: (
REPOSITORY_ROOT / ".runtime" / "dataset-gateway" / "admission.json"
),
+125
View File
@@ -9,11 +9,14 @@ from typing import Annotated, Any, Final
from fastapi import APIRouter, HTTPException, Query, Response
from k1link.compute import (
E10LidarFieldSource,
K1LocalSurfaceV1,
LidarFieldReviewV1,
LidarGroundBenchmarkV1,
LidarGroundError,
LidarReplayError,
LidarReplayPackV2,
k1_local_surface_catalog_item,
lidar_field_review_catalog_item,
lidar_ground_benchmark_catalog_item,
lidar_ground_frame_detail,
@@ -34,9 +37,12 @@ from k1link.datasets import (
LIDAR_CATALOG_SCHEMA: Final = "missioncore.lidar-replay-pack-catalog/v1"
LIDAR_GROUND_CATALOG_SCHEMA: Final = "missioncore.lidar-ground-benchmark-catalog/v1"
LIDAR_FIELD_REVIEW_CATALOG_SCHEMA: Final = "missioncore.lidar-field-review-catalog/v1"
K1_LOCAL_SURFACE_CATALOG_SCHEMA: Final = "missioncore.k1-local-surface-catalog/v1"
_PACK_ID = re.compile(r"^lidar-replay-pack-[a-f0-9]{64}$")
_BENCHMARK_ID = re.compile(r"^ground-benchmark-[a-f0-9]{64}$")
_FIELD_REVIEW_ID = re.compile(r"^lidar-field-review-[a-f0-9]{64}$")
_LOCAL_SURFACE_ID = re.compile(r"^k1-local-surface-[a-f0-9]{64}$")
_E10_PACK_ID = re.compile(r"^e10-lidar-pack-[a-f0-9]{64}$")
RootProvider = Callable[[], Path | None]
DatasetArtifactProvider = Callable[[], Path | None]
@@ -56,11 +62,23 @@ def configured_lidar_field_review_root() -> Path | None:
return Path(value).expanduser().absolute() if value else None
def configured_k1_local_surface_root() -> Path | None:
value = os.environ.get("MISSIONCORE_K1_LOCAL_SURFACE_ROOT", "").strip()
return Path(value).expanduser().absolute() if value else None
def configured_e10_lidar_source_root() -> Path | None:
value = os.environ.get("MISSIONCORE_E10_LIDAR_SOURCE_ROOT", "").strip()
return Path(value).expanduser().absolute() if value else None
def build_lidar_router(
*,
root_provider: RootProvider = configured_lidar_replay_root,
ground_root_provider: RootProvider = configured_lidar_ground_root,
field_review_root_provider: RootProvider = configured_lidar_field_review_root,
local_surface_root_provider: RootProvider = configured_k1_local_surface_root,
e10_source_root_provider: RootProvider = configured_e10_lidar_source_root,
dataset_admission_provider: DatasetArtifactProvider = configured_dataset_admission_manifest,
dataset_preview_provider: DatasetArtifactProvider = configured_dataset_preview,
dataset_rellis_preview_provider: DatasetArtifactProvider = lambda: None,
@@ -483,4 +501,111 @@ def build_lidar_router(
headers={"Cache-Control": "private, max-age=31536000, immutable"},
)
@router.get("/local-surfaces")
def list_k1_local_surfaces(
limit: int = Query(default=10, ge=1, le=50),
) -> dict[str, Any]:
root = local_surface_root_provider()
if root is None or not root.is_dir():
return {
"schema_version": K1_LOCAL_SURFACE_CATALOG_SCHEMA,
"configured": root is not None,
"items": [],
"valid_total": 0,
"invalid_total": 0,
"access": "read-only",
}
items: list[dict[str, object]] = []
invalid_total = 0
candidates = sorted(
(
candidate
for candidate in root.iterdir()
if candidate.is_dir()
and _LOCAL_SURFACE_ID.fullmatch(candidate.name) is not None
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
for candidate in candidates:
try:
model = K1LocalSurfaceV1(candidate)
try:
items.append(k1_local_surface_catalog_item(model))
finally:
model.close()
except (LidarGroundError, OSError):
invalid_total += 1
return {
"schema_version": K1_LOCAL_SURFACE_CATALOG_SCHEMA,
"configured": True,
"items": items[:limit],
"valid_total": len(items),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/local-surfaces/{model_id}/frames/{frame_index}")
def get_k1_local_surface_frame(
model_id: str,
frame_index: int,
) -> dict[str, object]:
if _LOCAL_SURFACE_ID.fullmatch(model_id) is None or frame_index < 0:
raise HTTPException(
status_code=404,
detail="K1 local-surface frame не найден",
)
model_root = local_surface_root_provider()
source_root = e10_source_root_provider()
if model_root is None or not model_root.is_dir():
raise HTTPException(
status_code=503,
detail="K1 local-surface storage не настроен",
)
if source_root is None or not source_root.is_dir():
raise HTTPException(
status_code=503,
detail="E10 LiDAR source storage не настроен",
)
model_path = model_root / model_id
if not model_path.is_dir():
raise HTTPException(
status_code=404,
detail="K1 local-surface model не найден",
)
try:
model = K1LocalSurfaceV1(model_path)
try:
source_pack_id = model.identity.get("source_pack_id")
if (
not isinstance(source_pack_id, str)
or _E10_PACK_ID.fullmatch(source_pack_id) is None
):
raise LidarGroundError("K1 local-surface source id is invalid")
source_path = source_root / source_pack_id
if not source_path.is_dir():
raise HTTPException(
status_code=404,
detail="Связанный E10 LiDAR source не найден",
)
source = E10LidarFieldSource(source_path)
try:
return model.frame_detail(source, frame_index)
finally:
source.close()
finally:
model.close()
except IndexError as exc:
raise HTTPException(
status_code=404,
detail="K1 local-surface frame не найден",
) from exc
except HTTPException:
raise
except (LidarGroundError, OSError) as exc:
raise HTTPException(
status_code=409,
detail="K1 local-surface evidence не прошло проверку целостности",
) from exc
return router