feat(lidar): add point-aligned ground review

This commit is contained in:
DCCONSTRUCTIONS
2026-07-25 09:44:38 +03:00
parent 75a3e669d9
commit 2dfb34ef21
15 changed files with 1548 additions and 140 deletions
+69 -11
View File
@@ -12,6 +12,7 @@ from fastapi.routing import APIRoute
from k1link.compute import (
DEFAULT_GROUND_BENCHMARK_PROFILE,
K1_LIDAR_PACK_V2_PROFILE,
GroundBenchmarkProfile,
GroundSegmentation,
LidarGroundBenchmarkV1,
LidarGroundError,
@@ -21,6 +22,7 @@ from k1link.compute import (
PatchworkPPGroundSegmenter,
build_lidar_ground_annotation_template,
build_lidar_ground_benchmark,
lidar_ground_frame_detail,
score_ground_labels,
)
from k1link.web.lidar_api import build_lidar_router
@@ -147,9 +149,7 @@ def test_local_percentile_ground_is_point_aligned_and_non_mutating() -> None:
xyzi = np.column_stack((xyz, np.ones(xyz.shape[0]))).astype(np.float32)
unchanged = xyzi.copy()
result = LocalPercentileGroundSegmenter(
profile=DEFAULT_GROUND_BENCHMARK_PROFILE
).segment(xyzi)
result = LocalPercentileGroundSegmenter(profile=DEFAULT_GROUND_BENCHMARK_PROFILE).segment(xyzi)
assert result.ground_mask.shape == (10,)
assert result.assigned_mask.all()
@@ -169,10 +169,7 @@ def test_ground_benchmark_is_immutable_diagnostic_evidence(tmp_path: Path) -> No
assert result.report["status"] == "diagnostic-only"
assert result.report["input_domain"]["accepted"] is False
assert result.report["labels"]["metrics_available"] is False
assert (
result.report["decision"]["status"]
== "do-not-promote-on-current-vendor-map"
)
assert result.report["decision"]["status"] == "do-not-promote-on-current-vendor-map"
assert result.arrays["current_ground"].shape == (20,)
assert result.arrays["candidate_ground"].shape == (20,)
finally:
@@ -195,6 +192,66 @@ def test_ground_benchmark_is_immutable_diagnostic_evidence(tmp_path: Path) -> No
LidarGroundBenchmarkV1(output)
def test_operator_height_correction_is_explicit_and_stays_diagnostic(
tmp_path: Path,
) -> None:
replay = _Replay()
observed_z: list[np.ndarray] = []
class RecordingCandidate(_Candidate):
def segment(self, xyzi: np.ndarray) -> GroundSegmentation:
observed_z.append(xyzi[:, 2].copy())
return super().segment(xyzi)
profile = GroundBenchmarkProfile(
profile_id="k1-handheld-operator-height-ground-ab/v1",
patchwork_sensor_height_proxy_m=1.27,
patchwork_map_vertical_origin_offset_m=1.27,
patchwork_height_evidence="operator-estimated",
)
output = build_lidar_ground_benchmark(
replay, # type: ignore[arg-type]
tmp_path / "benchmarks",
patchwork=RecordingCandidate(),
profile=profile,
)
result = LidarGroundBenchmarkV1(output)
try:
normalization = result.report["input_domain"]["normalization"]
assert normalization == {
"height_evidence": "operator-estimated",
"map_vertical_origin_offset_m": 1.27,
"sensor_height_m": 1.27,
}
assert result.report["input_domain"]["physical_sensor_height_known"] is False
frame = lidar_ground_frame_detail(
result,
replay, # type: ignore[arg-type]
0,
)
finally:
result.close()
np.testing.assert_allclose(
observed_z[0],
replay._points[0][:, 2] - 1.27,
atol=1e-6,
)
assert frame["schema_version"] == "missioncore.lidar-ground-frame/v1"
assert frame["point_count"] == 10
assert frame["coordinate_frame"] == "map"
assert frame["ground_truth"] is False
assert frame["masks"]["disagreement"]
assert str(tmp_path) not in repr(frame)
def test_ground_profile_rejects_unattested_height_configuration() -> None:
with pytest.raises(LidarGroundError, match="without height evidence"):
GroundBenchmarkProfile(patchwork_sensor_height_proxy_m=1.27)
with pytest.raises(LidarGroundError, match="positive sensor height"):
GroundBenchmarkProfile(patchwork_height_evidence="operator-estimated")
def test_annotation_template_starts_all_ignore_and_never_ground_truth(
tmp_path: Path,
) -> None:
@@ -234,6 +291,10 @@ def test_ground_api_is_read_only_path_free_and_pack_filtered(
router,
"/api/v1/lidar/ground-benchmarks/{benchmark_id}",
)
_endpoint(
router,
"/api/v1/lidar/ground-benchmarks/{benchmark_id}/frames/{frame_index}",
)
catalog = catalog_route( # type: ignore[operator]
pack_id=replay.pack_id,
@@ -241,10 +302,7 @@ def test_ground_api_is_read_only_path_free_and_pack_filtered(
)
detail = detail_route(benchmark_id=output.name) # type: ignore[operator]
assert (
catalog["schema_version"]
== "missioncore.lidar-ground-benchmark-catalog/v1"
)
assert catalog["schema_version"] == "missioncore.lidar-ground-benchmark-catalog/v1"
assert catalog["valid_total"] == 1
assert catalog["items"][0]["decision"]["production_promotion"] is False
assert detail["benchmark"]["benchmark_id"] == output.name