feat(perception): integrate calibrated operator pipeline
Add calibrated K1 projection, recorded and near-live perception qualification, unified Rerun operator layers, bounded replay admission, audited viewer controls, worker experiments, and lab evidence.
This commit is contained in:
+174
-2
@@ -19,16 +19,23 @@ from k1link.device_plugins.xgrids_k1.mqtt.capture import (
|
||||
from k1link.device_plugins.xgrids_k1.rrd_export import (
|
||||
RECORDED_CAMERA_VIEW_ID,
|
||||
RECORDED_METRICS_VIEW_ID,
|
||||
RECORDED_PERCEPTION_3D_VIEW_ID,
|
||||
RECORDED_POINTS_VISUALIZER_ID,
|
||||
RECORDED_ROOT_CONTAINER_ID,
|
||||
RECORDED_SPATIAL_VIEW_ID,
|
||||
RECORDED_VIEW_POINT_DECIMATION_THRESHOLD,
|
||||
RECORDED_VIEW_POINT_FRAME_STRIDE,
|
||||
RECORDED_VIEW_POINT_STRIDE,
|
||||
SESSION_TIMELINE,
|
||||
RrdExportCancelled,
|
||||
RrdExportError,
|
||||
_recorded_blueprint,
|
||||
_recorded_view_points,
|
||||
_should_publish_recorded_point_frame,
|
||||
export_k1mqtt_to_rrd,
|
||||
recorded_blueprint_rrd,
|
||||
)
|
||||
from k1link.viewer.recorded import recorded_blueprint as viewer_recorded_blueprint
|
||||
from k1link.viewer.rerun_bridge import RerunSceneSettings
|
||||
|
||||
|
||||
@@ -45,6 +52,57 @@ def _point_payload(x: float) -> bytes:
|
||||
)
|
||||
|
||||
|
||||
def test_recorded_operator_projection_thins_only_dense_point_batches() -> None:
|
||||
assert RECORDED_VIEW_POINT_FRAME_STRIDE == 5
|
||||
count = RECORDED_VIEW_POINT_DECIMATION_THRESHOLD + 3
|
||||
positions = export_module.np.arange(
|
||||
count * 3,
|
||||
dtype=export_module.np.float32,
|
||||
).reshape((-1, 3))
|
||||
intensities = export_module.np.arange(count, dtype=export_module.np.uint8)
|
||||
rgb = export_module.np.arange(count * 3, dtype=export_module.np.uint8).reshape((-1, 3))
|
||||
|
||||
projected_positions, projected_intensities, projected_rgb = _recorded_view_points(
|
||||
positions,
|
||||
intensities,
|
||||
rgb,
|
||||
)
|
||||
|
||||
assert projected_rgb is not None
|
||||
assert export_module.np.array_equal(
|
||||
projected_positions,
|
||||
positions[::RECORDED_VIEW_POINT_STRIDE],
|
||||
)
|
||||
assert export_module.np.array_equal(
|
||||
projected_intensities,
|
||||
intensities[::RECORDED_VIEW_POINT_STRIDE],
|
||||
)
|
||||
assert export_module.np.array_equal(projected_rgb, rgb[::RECORDED_VIEW_POINT_STRIDE])
|
||||
|
||||
small_positions = positions[:RECORDED_VIEW_POINT_DECIMATION_THRESHOLD]
|
||||
small_intensities = intensities[:RECORDED_VIEW_POINT_DECIMATION_THRESHOLD]
|
||||
same_positions, same_intensities, no_rgb = _recorded_view_points(
|
||||
small_positions,
|
||||
small_intensities,
|
||||
None,
|
||||
)
|
||||
assert same_positions is small_positions
|
||||
assert same_intensities is small_intensities
|
||||
assert no_rgb is None
|
||||
|
||||
|
||||
def test_recorded_operator_projection_uses_stable_two_hz_point_cadence() -> None:
|
||||
published = [
|
||||
frame_number
|
||||
for frame_number in range(1, 13)
|
||||
if _should_publish_recorded_point_frame(frame_number)
|
||||
]
|
||||
|
||||
assert published == [1, 6, 11]
|
||||
with pytest.raises(ValueError, match="positive"):
|
||||
_should_publish_recorded_point_frame(0)
|
||||
|
||||
|
||||
def _pose_payload(x: float) -> bytes:
|
||||
return struct.pack("<ffffffff", x, 2.0, 3.0, 99.0, 1.0, 0.0, 0.0, 0.0)
|
||||
|
||||
@@ -191,8 +249,19 @@ def test_recorded_blueprint_accumulates_point_frames_on_session_timeline() -> No
|
||||
assert line_grid.visible.as_arrow_array().to_pylist() == [False]
|
||||
point_behavior, point_visualizer = spatial_view.visualizer_overrides["/world/points"]
|
||||
trajectory_behavior = spatial_view.visualizer_overrides["/world/trajectory"]
|
||||
perception_behavior = spatial_view.visualizer_overrides["/world/perception"]
|
||||
assert point_behavior.visible.as_arrow_array().to_pylist() == [False]
|
||||
assert trajectory_behavior.visible.as_arrow_array().to_pylist() == [True]
|
||||
assert perception_behavior.visible.as_arrow_array().to_pylist() == [False]
|
||||
perception_3d_view = blueprint.root_container.contents[2]
|
||||
assert perception_3d_view.origin == "/world"
|
||||
assert "VisibleTimeRanges" not in perception_3d_view.properties
|
||||
assert perception_3d_view.visualizer_overrides[
|
||||
"/world/perception"
|
||||
].visible.as_arrow_array().to_pylist() == [True]
|
||||
assert perception_3d_view.visualizer_overrides[
|
||||
"/world/perception/lidar"
|
||||
].visible.as_arrow_array().to_pylist() == [False]
|
||||
point_overrides = {
|
||||
str(batch.component_descriptor()): batch.as_arrow_array().to_pylist()
|
||||
for batch in point_visualizer.overrides
|
||||
@@ -235,8 +304,10 @@ def test_dynamic_blueprint_reuses_scene_ids_without_playback_mutation() -> None:
|
||||
assert first_view.id == second_view.id == RECORDED_SPATIAL_VIEW_ID
|
||||
assert first.root_container.contents[1].id == RECORDED_CAMERA_VIEW_ID
|
||||
assert second.root_container.contents[1].id == RECORDED_CAMERA_VIEW_ID
|
||||
assert first.root_container.contents[2].id == RECORDED_METRICS_VIEW_ID
|
||||
assert second.root_container.contents[2].id == RECORDED_METRICS_VIEW_ID
|
||||
assert first.root_container.contents[2].id == RECORDED_PERCEPTION_3D_VIEW_ID
|
||||
assert second.root_container.contents[2].id == RECORDED_PERCEPTION_3D_VIEW_ID
|
||||
assert first.root_container.contents[3].id == RECORDED_METRICS_VIEW_ID
|
||||
assert second.root_container.contents[3].id == RECORDED_METRICS_VIEW_ID
|
||||
|
||||
first_point_behavior, first_point_visualizer = first_view.visualizer_overrides["/world/points"]
|
||||
second_point_behavior, second_point_visualizer = second_view.visualizer_overrides[
|
||||
@@ -262,6 +333,107 @@ def test_dynamic_blueprint_reuses_scene_ids_without_playback_mutation() -> None:
|
||||
assert str(RECORDED_POINTS_VISUALIZER_ID).encode() in payload
|
||||
|
||||
|
||||
def test_viewer_blueprint_reset_is_bounded_and_recreates_render_views() -> None:
|
||||
initial = viewer_recorded_blueprint(
|
||||
RerunSceneSettings(accumulation_seconds=12.0),
|
||||
include_initial_playback_state=False,
|
||||
active_view="perception",
|
||||
view_reset_generation=0,
|
||||
)
|
||||
reset = viewer_recorded_blueprint(
|
||||
RerunSceneSettings(accumulation_seconds=12.0),
|
||||
include_initial_playback_state=False,
|
||||
active_view="perception",
|
||||
view_reset_generation=1,
|
||||
)
|
||||
restored = viewer_recorded_blueprint(
|
||||
RerunSceneSettings(accumulation_seconds=12.0),
|
||||
include_initial_playback_state=False,
|
||||
active_view="perception",
|
||||
view_reset_generation=0,
|
||||
)
|
||||
|
||||
assert initial.root_container.id == restored.root_container.id
|
||||
assert reset.root_container.id != initial.root_container.id
|
||||
assert initial.root_container.contents[0].id != reset.root_container.contents[0].id
|
||||
assert restored.root_container.contents[0].id == initial.root_container.contents[0].id
|
||||
assert initial.root_container.active_tab == 1
|
||||
assert reset.root_container.active_tab == 1
|
||||
assert initial.root_container.contents[1].id != reset.root_container.contents[1].id
|
||||
assert initial.root_container.contents[2].id != reset.root_container.contents[2].id
|
||||
assert restored.root_container.contents[1].id == initial.root_container.contents[1].id
|
||||
assert restored.root_container.contents[2].id == initial.root_container.contents[2].id
|
||||
cuboids = viewer_recorded_blueprint(
|
||||
RerunSceneSettings(accumulation_seconds=12.0),
|
||||
include_initial_playback_state=False,
|
||||
active_view="perception3d",
|
||||
)
|
||||
assert cuboids.root_container.active_tab == 2
|
||||
assert cuboids.root_container.id != initial.root_container.id
|
||||
cuboid_view = cuboids.root_container.contents[2]
|
||||
assert cuboid_view.origin == "/world"
|
||||
assert "VisibleTimeRanges" not in cuboid_view.properties
|
||||
cuboid_points, cuboid_point_visualizer = cuboid_view.visualizer_overrides[
|
||||
"/world/points"
|
||||
]
|
||||
cuboid_perception = cuboid_view.visualizer_overrides["/world/perception"]
|
||||
cuboid_diagnostic_lidar = cuboid_view.visualizer_overrides[
|
||||
"/world/perception/lidar"
|
||||
]
|
||||
assert cuboid_points.visible.as_arrow_array().to_pylist() == [True]
|
||||
assert cuboid_point_visualizer.id != initial.root_container.contents[0].visualizer_overrides[
|
||||
"/world/points"
|
||||
][1].id
|
||||
assert cuboid_perception.visible.as_arrow_array().to_pylist() == [True]
|
||||
assert cuboid_diagnostic_lidar.visible.as_arrow_array().to_pylist() == [False]
|
||||
perception_behavior = initial.root_container.contents[0].visualizer_overrides[
|
||||
"/world/perception"
|
||||
]
|
||||
assert perception_behavior.visible.as_arrow_array().to_pylist() == [False]
|
||||
|
||||
|
||||
def test_viewer_blueprint_unifies_original_video_and_independent_ai_layers() -> None:
|
||||
blueprint = viewer_recorded_blueprint(
|
||||
RerunSceneSettings(accumulation_seconds=12.0),
|
||||
include_initial_playback_state=False,
|
||||
unified_perception=True,
|
||||
show_detections_2d=True,
|
||||
show_segmentation=True,
|
||||
show_cuboids_3d=False,
|
||||
)
|
||||
|
||||
assert type(blueprint.root_container).__name__ == "Horizontal"
|
||||
camera_view, spatial_view = blueprint.root_container.contents
|
||||
assert camera_view.origin == "/perception/camera"
|
||||
assert spatial_view.origin == "/world"
|
||||
assert camera_view.visualizer_overrides[
|
||||
"/perception/camera/image"
|
||||
].visible.as_arrow_array().to_pylist() == [True]
|
||||
assert camera_view.visualizer_overrides[
|
||||
"/perception/camera/detections"
|
||||
].visible.as_arrow_array().to_pylist() == [True]
|
||||
assert camera_view.visualizer_overrides[
|
||||
"/perception/camera/segmentation"
|
||||
].visible.as_arrow_array().to_pylist() == [True]
|
||||
semantic_behavior, semantic_time_ranges = spatial_view.visualizer_overrides[
|
||||
"/world/perception/semantic_points"
|
||||
]
|
||||
cuboid_behavior, cuboid_time_ranges = spatial_view.visualizer_overrides[
|
||||
"/world/perception/boxes3d"
|
||||
]
|
||||
assert semantic_behavior.visible.as_arrow_array().to_pylist() == [True]
|
||||
assert cuboid_behavior.visible.as_arrow_array().to_pylist() == [False]
|
||||
assert semantic_time_ranges.ranges.as_arrow_array().to_pylist() == []
|
||||
assert cuboid_time_ranges.ranges.as_arrow_array().to_pylist() == []
|
||||
visible_ranges = spatial_view.properties["VisibleTimeRanges"]
|
||||
assert visible_ranges.ranges.as_arrow_array().to_pylist() == [
|
||||
{
|
||||
"timeline": SESSION_TIMELINE,
|
||||
"range": {"start": -12_000_000_000, "end": 0},
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_export_preserves_every_decodable_frame_and_source_timeline(tmp_path: Path) -> None:
|
||||
capture = _write_capture(
|
||||
tmp_path,
|
||||
|
||||
Reference in New Issue
Block a user