feat(perception): qualify inline temporal stability

This commit is contained in:
DCCONSTRUCTIONS
2026-07-24 09:10:07 +03:00
parent cfc7b062da
commit 23181c867b
16 changed files with 2250 additions and 218 deletions
+7 -7
View File
@@ -28,11 +28,11 @@ def test_e15_worker_package_is_minimal_hash_addressed_projection(tmp_path: Path)
manifest = module.validate_worker_package(package)
assert package.name == f"e15-worker-package-{manifest['identity_sha256']}"
assert manifest["identity"]["classification"] == (
"minimal-live-worker-import-projection"
)
assert len(manifest["artifacts"]) == 11
assert manifest["identity"]["classification"] == ("minimal-live-worker-import-projection")
assert len(manifest["artifacts"]) == 12
assert (package / "k1link" / "compute" / "inline_temporal.py").is_file()
assert not (package / "k1link" / "device_plugins" / "xgrids_k1" / "mqtt").exists()
assert "observation" not in (
package / "k1link" / "device_plugins" / "xgrids_k1" / "__init__.py"
).read_text()
assert (
"observation"
not in (package / "k1link" / "device_plugins" / "xgrids_k1" / "__init__.py").read_text()
)
+126
View File
@@ -0,0 +1,126 @@
from __future__ import annotations
from pathlib import Path
import numpy as np
import pytest
from k1link.compute.inline_temporal import (
StreamingSemanticStabilizer,
TemporalStabilizer,
read_inline_profile,
stabilize_world_state,
)
def _profile() -> dict[str, object]:
root = Path(__file__).resolve().parents[1]
profile, digest = read_inline_profile(
root / "experiments" / "perception" / "e23_inline_temporal_profile.json"
)
assert len(digest) == 64
return profile
def _object(track_id: int, box: list[float]) -> dict[str, object]:
return {
"association_group": "vehicle",
"bbox_xyxy": box,
"candidate_projected_points": 20,
"clustered_points": 14,
"completion_fraction": 0.9,
"cuboid_center_map": [10.0, 2.0, 0.8],
"cuboid_half_size": [2.25, 0.925, 0.775],
"cuboid_quaternion_xyzw": [0.0, 0.0, 0.0, 1.0],
"cuboid_status": "accepted-class-prior-amodal-v1",
"distance_median_m": 10.2,
"distance_p10_m": 9.8,
"distance_smoothed_m": 10.1,
"geometry": "class-prior-completed-from-visible-lidar-support",
"ground_rejected_points": 0,
"ground_z_map": 0.0,
"label": "car",
"observed_cuboid_center_map": [10.0, 2.0, 0.8],
"observed_cuboid_half_size": [2.25, 0.925, 0.775],
"observed_cuboid_quaternion_xyzw": [0.0, 0.0, 0.0, 1.0],
"orientation_source": "support-pca",
"pre_ground_clustered_points": 14,
"score": 0.9,
"semantic_compatible_points": 18,
"support_coverage_fraction": 0.8,
"support_ground_z_map": None,
"temporal_status": "confirmed",
"track_id": track_id,
}
def test_e23_profile_pins_inline_stage_and_has_no_control_authority() -> None:
profile = _profile()
assert profile["stage"] == "warm-worker-after-fusion-before-result-publication"
assert profile["bounds"]["maximum_track_states"] == 128
assert profile["bounds"]["semantic_history_masks"] == 1
assert profile["authority"] == {
"commands_enabled": False,
"navigation_or_safety_accepted": False,
}
def test_e23_inline_tracking_is_bounded_and_updates_world_state() -> None:
stabilizer = TemporalStabilizer(_profile())
first = stabilizer.update(
frame_index=0,
session_seconds=0.0,
objects=[_object(10, [100.0, 100.0, 200.0, 200.0])],
)
second = stabilizer.update(
frame_index=1,
session_seconds=0.1,
objects=[_object(11, [102.0, 100.0, 202.0, 200.0])],
)
world = stabilize_world_state(
{
"objects": [
{
"track_id": 11,
"velocity_status": "observed",
}
],
"delivery": {},
},
second,
{},
)
assert first[0]["track_id"] == 10
assert second[0]["track_id"] == 10
assert second[0]["cuboid_status"] == "accepted-temporally-stabilized-e23-v1"
assert world["delivery"]["temporal_stability"] == "e23-inline-bounded"
assert world["objects"][0]["track_id"] == 10
assert stabilizer.snapshot()["peak_track_states"] <= 128
def test_e23_semantic_state_keeps_only_one_mask_and_rejects_islands() -> None:
stabilizer = StreamingSemanticStabilizer(_profile())
first = np.zeros((600, 800), dtype=np.uint8)
second = first.copy()
second[20, 20] = 4
second[100:110, 100:110] = 7
stabilizer.update(first)
output = stabilizer.update(second)
snapshot = stabilizer.snapshot()
assert output[20, 20] == 0
assert np.all(output[102:108, 102:108] == 7)
assert snapshot["history_masks"] == 1
assert snapshot["frames"] == 2
assert snapshot["unsupported_change_reduction_fraction"] > 0
def test_e23_profile_rejects_non_object_json(tmp_path: Path) -> None:
profile_path = tmp_path / "profile.json"
profile_path.write_text("[]", encoding="utf-8")
with pytest.raises(RuntimeError, match="profile is invalid"):
read_inline_profile(profile_path)