feat(lidar): add ground segmentation diagnostic benchmark

This commit is contained in:
DCCONSTRUCTIONS
2026-07-25 02:09:27 +03:00
parent e4fdd9fa20
commit 75a3e669d9
14 changed files with 2235 additions and 15 deletions
+36
View File
@@ -69,6 +69,25 @@ from .lidar_contract import (
lidar_readiness_document,
sensor_frame_xyzi,
)
from .lidar_ground import (
DEFAULT_GROUND_BENCHMARK_PROFILE,
LIDAR_GROUND_ANNOTATION_TEMPLATE_SCHEMA,
LIDAR_GROUND_BENCHMARK_REPORT_SCHEMA,
LIDAR_GROUND_BENCHMARK_SCHEMA,
PATCHWORKPP_SOURCE_COMMIT,
PATCHWORKPP_SOURCE_TAG,
PATCHWORKPP_SOURCE_URL,
GroundBenchmarkProfile,
GroundSegmentation,
LidarGroundBenchmarkV1,
LidarGroundError,
LocalPercentileGroundSegmenter,
PatchworkPPGroundSegmenter,
build_lidar_ground_annotation_template,
build_lidar_ground_benchmark,
lidar_ground_benchmark_catalog_item,
score_ground_labels,
)
from .lidar_replay import (
LIDAR_EQUIVALENCE_REPORT_SCHEMA,
LIDAR_QUALITY_REPORT_SCHEMA,
@@ -151,7 +170,12 @@ __all__ = [
"EVALUATION_PACK_SCHEMA",
"EvaluationFrameRequest",
"EvaluationPackFrame",
"GroundBenchmarkProfile",
"GroundSegmentation",
"LatestWinsQueue",
"LIDAR_GROUND_ANNOTATION_TEMPLATE_SCHEMA",
"LIDAR_GROUND_BENCHMARK_REPORT_SCHEMA",
"LIDAR_GROUND_BENCHMARK_SCHEMA",
"LIDAR_EVIDENCE_PROFILE_SCHEMA",
"LIDAR_EQUIVALENCE_REPORT_SCHEMA",
"LIDAR_QUALITY_REPORT_SCHEMA",
@@ -169,6 +193,8 @@ __all__ = [
"LidarPoseStatus",
"LidarQualityMonitor",
"LidarReadiness",
"LidarGroundBenchmarkV1",
"LidarGroundError",
"LidarReplayError",
"LidarReplayPackV2",
"LidarReplayPointFrame",
@@ -190,6 +216,12 @@ __all__ = [
"K1_LAB_LIDAR_PACK_V1_PROFILE",
"K1_LIDAR_PACK_V2_PROFILE",
"K1_LIVE_LIDAR_PROFILE",
"DEFAULT_GROUND_BENCHMARK_PROFILE",
"LocalPercentileGroundSegmenter",
"PATCHWORKPP_SOURCE_COMMIT",
"PATCHWORKPP_SOURCE_TAG",
"PATCHWORKPP_SOURCE_URL",
"PatchworkPPGroundSegmenter",
"QueueSnapshot",
"RecordedCalibratedFusion",
"RecordedCalibratedFusionStore",
@@ -224,6 +256,8 @@ __all__ = [
"prepare_recorded_qualification_slice",
"assess_lidar_profile",
"build_lidar_replay_pack_v2",
"build_lidar_ground_annotation_template",
"build_lidar_ground_benchmark",
"DetectionFrame",
"ObjectDetection",
"RecordedPerceptionOverlayError",
@@ -246,6 +280,8 @@ __all__ = [
"lidar_readiness_document",
"lidar_pack_catalog_item",
"lidar_pack_detail",
"lidar_ground_benchmark_catalog_item",
"score_ground_labels",
"sensor_frame_xyzi",
"verify_lidar_replay_equivalence",
]
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -407,7 +407,14 @@ app.include_router(
/ "compute-experiments"
/ "lidar-replay-v2"
/ "packs"
)
),
ground_root_provider=lambda: (
REPOSITORY_ROOT
/ ".runtime"
/ "compute-experiments"
/ "lidar-ground-v1"
/ "benchmarks"
),
)
)
+104
View File
@@ -9,14 +9,21 @@ from typing import Any, Final
from fastapi import APIRouter, HTTPException, Query
from k1link.compute import (
LidarGroundBenchmarkV1,
LidarGroundError,
LidarReplayError,
LidarReplayPackV2,
lidar_ground_benchmark_catalog_item,
lidar_pack_catalog_item,
lidar_pack_detail,
)
LIDAR_CATALOG_SCHEMA: Final = "missioncore.lidar-replay-pack-catalog/v1"
LIDAR_GROUND_CATALOG_SCHEMA: Final = (
"missioncore.lidar-ground-benchmark-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}$")
RootProvider = Callable[[], Path | None]
@@ -25,9 +32,15 @@ def configured_lidar_replay_root() -> Path | None:
return Path(value).expanduser().absolute() if value else None
def configured_lidar_ground_root() -> Path | None:
value = os.environ.get("MISSIONCORE_LIDAR_GROUND_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,
) -> APIRouter:
router = APIRouter(prefix="/api/v1/lidar", tags=["lidar"])
@@ -107,4 +120,95 @@ def build_lidar_router(
detail="LiDAR replay pack не прошёл проверку целостности",
) from exc
@router.get("/ground-benchmarks")
def list_lidar_ground_benchmarks(
pack_id: str | None = Query(default=None),
limit: int = Query(default=20, ge=1, le=100),
) -> dict[str, Any]:
if pack_id is not None and _PACK_ID.fullmatch(pack_id) is None:
raise HTTPException(status_code=404, detail="LiDAR replay pack не найден")
root = ground_root_provider()
if root is None or not root.is_dir():
return {
"schema_version": LIDAR_GROUND_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 _BENCHMARK_ID.fullmatch(candidate.name) is not None
),
key=lambda candidate: candidate.stat().st_mtime_ns,
reverse=True,
)
for candidate in candidates:
try:
benchmark = LidarGroundBenchmarkV1(candidate)
try:
if (
pack_id is None
or benchmark.identity.get("replay_pack_id") == pack_id
):
items.append(
lidar_ground_benchmark_catalog_item(benchmark)
)
finally:
benchmark.close()
except (LidarGroundError, OSError):
invalid_total += 1
return {
"schema_version": LIDAR_GROUND_CATALOG_SCHEMA,
"configured": True,
"items": items[:limit],
"valid_total": len(items),
"invalid_total": invalid_total,
"access": "read-only",
}
@router.get("/ground-benchmarks/{benchmark_id}")
def get_lidar_ground_benchmark(benchmark_id: str) -> dict[str, object]:
if _BENCHMARK_ID.fullmatch(benchmark_id) is None:
raise HTTPException(
status_code=404,
detail="LiDAR ground benchmark не найден",
)
root = ground_root_provider()
if root is None or not root.is_dir():
raise HTTPException(
status_code=503,
detail="LiDAR ground storage не настроен",
)
candidate = root / benchmark_id
if not candidate.is_dir():
raise HTTPException(
status_code=404,
detail="LiDAR ground benchmark не найден",
)
try:
benchmark = LidarGroundBenchmarkV1(candidate)
try:
return {
"schema_version": (
"missioncore.lidar-ground-benchmark-detail/v1"
),
"benchmark": lidar_ground_benchmark_catalog_item(benchmark),
"report": benchmark.report,
"access": "read-only",
}
finally:
benchmark.close()
except (LidarGroundError, OSError) as exc:
raise HTTPException(
status_code=409,
detail="LiDAR ground benchmark не прошёл проверку целостности",
) from exc
return router