refactor(lab): restore canonical RAV004 replay
This commit is contained in:
@@ -8,6 +8,8 @@ from k1link.sessions.canonical_lab_spatial import (
|
||||
_TimedPoses,
|
||||
_bounded_local_slam,
|
||||
_estimate_sensor_height,
|
||||
_estimate_local_sensor_height,
|
||||
_gravity_stable_basis_map_from_body,
|
||||
_ground_origin_map,
|
||||
)
|
||||
|
||||
@@ -57,7 +59,7 @@ def test_local_slam_accumulates_source_increments_in_ground_body_frame() -> None
|
||||
),
|
||||
)
|
||||
basis = np.eye(3)
|
||||
ground_origin = _ground_origin_map(np.asarray([0.0, 0.0, 0.0]), basis, 0.32)
|
||||
ground_origin = _ground_origin_map(np.asarray([0.0, 0.0, 0.0]), 0.32)
|
||||
|
||||
local, frame_count, source_count = _bounded_local_slam(
|
||||
points,
|
||||
@@ -69,3 +71,59 @@ def test_local_slam_accumulates_source_increments_in_ground_body_frame() -> None
|
||||
assert frame_count == 3
|
||||
assert source_count == 3
|
||||
assert local[:, 2].tolist() == pytest.approx([0.0, 0.0, 0.0], abs=1e-6)
|
||||
|
||||
|
||||
def test_gravity_stable_body_frame_converts_rfu_to_forward_left_up() -> None:
|
||||
times = (0, 1_000_000_000, 2_000_000_000)
|
||||
poses = _TimedPoses(
|
||||
times_ns=times,
|
||||
translations=(
|
||||
np.asarray([0.0, 0.0, 0.4]),
|
||||
np.asarray([0.0, 1.0, 0.5]),
|
||||
np.asarray([0.0, 2.0, 0.3]),
|
||||
),
|
||||
quaternions_xyzw=tuple(
|
||||
np.asarray([0.25, 0.0, 0.0, np.sqrt(1.0 - 0.25**2)]) for _ in times
|
||||
),
|
||||
)
|
||||
|
||||
basis, source = _gravity_stable_basis_map_from_body(poses, 1_000_000_000)
|
||||
|
||||
assert source == "smoothed-pose-trajectory-tangent"
|
||||
assert basis[:, 0].tolist() == pytest.approx([0.0, 1.0, 0.0], abs=1e-7)
|
||||
assert basis[:, 1].tolist() == pytest.approx([-1.0, 0.0, 0.0], abs=1e-7)
|
||||
assert basis[:, 2].tolist() == pytest.approx([0.0, 0.0, 1.0], abs=1e-7)
|
||||
assert np.linalg.det(basis) == pytest.approx(1.0, abs=1e-7)
|
||||
|
||||
|
||||
def test_ground_origin_is_projected_only_along_map_gravity() -> None:
|
||||
origin = _ground_origin_map(np.asarray([4.0, -2.0, 1.25]), 0.32)
|
||||
assert origin.tolist() == pytest.approx([4.0, -2.0, 0.93], abs=1e-9)
|
||||
|
||||
|
||||
def test_sensor_height_tracks_current_source_window_instead_of_fixed_mount() -> None:
|
||||
times = tuple(index * 500_000_000 for index in range(8))
|
||||
points = _TimedPoints(
|
||||
times_ns=times,
|
||||
values=tuple(
|
||||
_calibration_cloud(0.18 if index < 4 else 1.05, index)
|
||||
for index in range(8)
|
||||
),
|
||||
)
|
||||
poses = _TimedPoses(
|
||||
times_ns=times,
|
||||
translations=tuple(np.zeros(3) for _ in times),
|
||||
quaternions_xyzw=tuple(np.asarray([0.0, 0.0, 0.0, 1.0]) for _ in times),
|
||||
)
|
||||
|
||||
low, low_samples, _, low_source = _estimate_local_sensor_height(
|
||||
points, poses, 500_000_000, 0.5,
|
||||
)
|
||||
high, high_samples, _, high_source = _estimate_local_sensor_height(
|
||||
points, poses, 3_000_000_000, 0.5,
|
||||
)
|
||||
|
||||
assert low == pytest.approx(0.18, abs=0.03)
|
||||
assert high == pytest.approx(1.05, abs=0.03)
|
||||
assert low_samples >= 3 and high_samples >= 3
|
||||
assert low_source == high_source == "local-source-cloud-ground-quantile-median"
|
||||
|
||||
@@ -489,7 +489,7 @@ def test_canonical_lab_spatial_frame_uses_ready_immutable_recording(
|
||||
assert resolved is not None and resolved.recording is not None
|
||||
generation = hashlib.sha256(payload).hexdigest()
|
||||
expected = {
|
||||
"schema_version": "missioncore.canonical-recorded-lab-spatial-frame/v2",
|
||||
"schema_version": "missioncore.canonical-recorded-lab-spatial-frame/v3",
|
||||
"target_time_ns": 500_000_000,
|
||||
"source_time_ns": 499_000_000,
|
||||
"pose_time_ns": 499_000_000,
|
||||
@@ -497,13 +497,13 @@ def test_canonical_lab_spatial_frame_uses_ready_immutable_recording(
|
||||
"coordinate_frame": "body-ground",
|
||||
"sensor_height": {
|
||||
"meters": 0.32,
|
||||
"source": "initial-source-cloud-lower-quantile-median",
|
||||
"source": "local-source-cloud-ground-quantile-median",
|
||||
"sample_count": 20,
|
||||
"mad_m": 0.03,
|
||||
"authority": "visual-derived",
|
||||
},
|
||||
"spatial_profile": {
|
||||
"profile_id": "source-paced-ground-v2",
|
||||
"profile_id": "source-paced-ground-v3",
|
||||
"local_slam_history_seconds": 5.0,
|
||||
"local_slam_radius_m": 30.0,
|
||||
"local_slam_voxel_size_m": 0.12,
|
||||
@@ -544,11 +544,11 @@ def test_canonical_lab_spatial_frame_uses_ready_immutable_recording(
|
||||
session_id=session.name,
|
||||
generation=generation,
|
||||
time_ns=500_000_000,
|
||||
profile="source-paced-ground-v2",
|
||||
profile="source-paced-ground-v3",
|
||||
))
|
||||
assert json.loads(response.body) == expected
|
||||
assert response.headers["etag"] == (
|
||||
f'"{generation}:source-paced-ground-v2:499000000"'
|
||||
f'"{generation}:source-paced-ground-v3:499000000"'
|
||||
)
|
||||
assert response.headers["cache-control"].endswith("immutable")
|
||||
finally:
|
||||
|
||||
@@ -22,6 +22,7 @@ from k1link.laboratory.evidence_report import verify_laboratory_evidence_result
|
||||
from k1link.laboratory.vegetation_policy_review import seal_vegetation_policy_review
|
||||
from k1link.laboratory.vegetation_shadow_lab import seal_vegetation_shadow_lab
|
||||
from k1link.web.vegetation_shadow_lab_api import (
|
||||
_mask_component_boxes,
|
||||
_route_tgs_anchor_payload,
|
||||
build_vegetation_shadow_lab_router,
|
||||
)
|
||||
@@ -29,6 +30,18 @@ from k1link.web.vegetation_shadow_lab_api import (
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def test_semantic_component_boxes_keep_distinct_objects_separate() -> None:
|
||||
mask = np.zeros((20, 30), dtype=np.uint8)
|
||||
mask[2:10, 3:8] = 4
|
||||
mask[4:12, 18:24] = 4
|
||||
mask[15:17, 3:5] = 4
|
||||
|
||||
assert _mask_component_boxes(mask, 4, minimum_pixels=20) == [
|
||||
(18, 4, 24, 12, 48),
|
||||
(3, 2, 8, 10, 40),
|
||||
]
|
||||
|
||||
|
||||
def test_route_tgs_anchor_payload_preserves_metric_evidence(tmp_path: Path) -> None:
|
||||
path = tmp_path / "tgs-evidence.npz"
|
||||
point_counts = np.arange(1, 11, dtype=np.int64)
|
||||
|
||||
Reference in New Issue
Block a user