feat(perception): add ground-aware cuboid refusion

This commit is contained in:
DCCONSTRUCTIONS
2026-07-23 08:24:37 +03:00
parent b53d6d5a45
commit a0706fd5d8
8 changed files with 1116 additions and 114 deletions
+94
View File
@@ -120,6 +120,22 @@ def test_e13_profile_pins_provenance_marked_amodal_completion() -> None:
assert profile["cuboid_completion"]["temporal"]["confirmation_hits"] == 3
def test_e19_profile_adds_ground_aware_support_without_mutating_e14() -> None:
_fusion, runner = _worker_modules()
root = Path(__file__).resolve().parents[1] / "experiments" / "perception" / "worker"
e14, _e14_digest = runner.read_profile(root / "e14_full_session_amodal_profile.json")
e19, _e19_digest = runner.read_profile(root / "e19_ground_aware_cuboid_profile.json")
assert "object_support_ground_filter" not in e14["association"]
assert "support_duplicate_overlap_threshold" not in e14["association"]
assert e19["profile_id"] == "lab-e19-ground-aware-cuboids-v1"
assert (
e19["association"]["object_support_ground_filter"]["mode"]
== "local-ground-relative-object-support-v1"
)
assert e19["association"]["support_duplicate_overlap_threshold"] == 0.6
def test_e14_profile_combines_full_session_and_amodal_gates() -> None:
_fusion, runner = _worker_modules()
profile_path = (
@@ -278,6 +294,84 @@ def test_e13_temporal_filter_reduces_cuboid_center_jitter() -> None:
assert outputs[-1].temporal_status == "confirmed"
def test_e19_ground_filter_preserves_cloud_and_excludes_ground_from_box_support() -> None:
fusion, runner = _worker_modules()
profile, _digest = runner.read_profile(
Path(__file__).resolve().parents[1]
/ "experiments"
/ "perception"
/ "worker"
/ "e19_ground_aware_cuboid_profile.json"
)
ground = np.asarray(
[[x, y, 0.0] for x in (9.5, 10.0, 10.5) for y in (-0.6, 0.0, 0.6)],
dtype=np.float64,
)
vehicle = np.asarray(
[[x, y, z] for x in (9.8, 10.2) for y in (-0.4, 0.4) for z in (0.3, 0.9, 1.4)],
dtype=np.float64,
)
cloud = np.concatenate((ground, vehicle))
unchanged = cloud.copy()
indices = np.arange(cloud.shape[0], dtype=np.int64)
filtered, ground_z, rejected = fusion._filter_object_support_by_ground(
indices,
cloud,
group="vehicle",
profile=profile["association"]["object_support_ground_filter"],
)
assert ground_z == 0.0
assert rejected == ground.shape[0]
assert filtered.tolist() == list(range(ground.shape[0], cloud.shape[0]))
np.testing.assert_array_equal(cloud, unchanged)
def test_e19_duplicate_tracks_cannot_publish_the_same_lidar_support_twice() -> None:
fusion, _runner = _worker_modules()
cuboid = fusion.Cuboid(
center_map=(10.0, 0.0, 0.8),
half_size=(2.25, 0.925, 0.775),
quaternion_xyzw=(0.0, 0.0, 0.0, 1.0),
)
def item(track_id: int, score: float, indices: list[int]) -> object:
source = np.asarray(indices, dtype=np.int64)
return fusion.TrackFusion(
track_id=track_id,
label="car",
association_group="vehicle",
score=score,
bbox_xyxy=(100.0, 100.0, 200.0, 200.0),
candidate_points=source.size,
semantic_points=source.size,
clustered_points=source.size,
distance_p10_m=9.5,
distance_median_m=10.0,
distance_smoothed_m=10.0,
status="accepted-class-prior-amodal-v1",
cuboid=cuboid,
source_indices=source,
)
result = fusion._suppress_duplicate_support_fusions(
[
item(10, 0.91, [1, 2, 3, 4, 5]),
item(11, 0.72, [1, 2, 3, 4]),
item(12, 0.80, [20, 21, 22, 23]),
],
overlap_threshold=0.6,
)
by_track = {value.track_id: value for value in result}
assert by_track[10].cuboid is not None
assert by_track[11].cuboid is None
assert by_track[11].status == "rejected-duplicate-lidar-support"
assert by_track[11].source_indices.size == 0
assert by_track[12].cuboid is not None
def test_e10_semantic_binding_is_explicit_about_freshness() -> None:
_fusion, runner = _worker_modules()
assert runner.semantic_binding(None, 2.0, 750.0) == ("unavailable", None)