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
+200 -21
View File
@@ -13,7 +13,7 @@ import math
import statistics
from collections import defaultdict, deque
from collections.abc import Mapping, Sequence
from dataclasses import dataclass
from dataclasses import dataclass, replace
from pathlib import Path
from typing import Any
@@ -97,6 +97,9 @@ class TrackFusion:
status: str
cuboid: Cuboid | None
source_indices: npt.NDArray[np.int64]
pre_ground_clustered_points: int = 0
ground_rejected_points: int = 0
support_ground_z_map: float | None = None
geometry: str = "none"
observed_cuboid: Cuboid | None = None
completion_fraction: float | None = None
@@ -466,6 +469,157 @@ def _completion_profile(profile: Mapping[str, Any]) -> dict[str, Any]:
return dict(profile)
def _object_support_ground_filter_profile(
profile: Mapping[str, Any],
) -> dict[str, Any]:
groups = {"person", "bicycle", "motorcycle", "vehicle"}
minimum_height = profile.get("minimum_height_above_ground_m")
maximum_height = profile.get("maximum_height_above_ground_m")
if (
profile.get("mode") != "local-ground-relative-object-support-v1"
or not isinstance(minimum_height, Mapping)
or set(minimum_height) != groups
or not isinstance(maximum_height, Mapping)
or set(maximum_height) != groups
):
raise RuntimeError("object-support ground filter profile is invalid")
scalar_checks = (
("local_radius_m", 0.5, 10.0),
("lower_percentile", 0.0, 30.0),
("maximum_below_support_m", 0.1, 3.0),
("maximum_above_support_m", 0.0, 0.5),
("fallback_below_support_m", 0.0, 1.0),
)
for name, lower, upper in scalar_checks:
try:
value = float(profile[name])
except (KeyError, TypeError, ValueError) as exc:
raise RuntimeError(f"object-support ground filter field {name} is invalid") from exc
if not lower <= value <= upper:
raise RuntimeError(f"object-support ground filter field {name} is invalid")
for group in groups:
try:
lower = float(minimum_height[group])
upper = float(maximum_height[group])
except (KeyError, TypeError, ValueError) as exc:
raise RuntimeError(
f"object-support ground filter height for {group} is invalid"
) from exc
if not 0.0 <= lower < upper <= 6.0:
raise RuntimeError(f"object-support ground filter height for {group} is invalid")
return dict(profile)
def _local_ground_z(
*,
all_points_map: FloatArray,
center_xy: FloatArray,
support_lower_z: float,
profile: Mapping[str, Any],
) -> float:
radius = float(profile["local_radius_m"])
if all_points_map.size:
distances = np.linalg.norm(all_points_map[:, :2] - center_xy, axis=1)
candidates = all_points_map[distances <= radius, 2]
else:
candidates = np.empty(0, dtype=np.float64)
estimate = (
float(np.percentile(candidates, float(profile["lower_percentile"])))
if candidates.size
else math.nan
)
if (
not math.isfinite(estimate)
or estimate < support_lower_z - float(profile["maximum_below_support_m"])
or estimate > support_lower_z + float(profile["maximum_above_support_m"])
):
estimate = support_lower_z - float(profile["fallback_below_support_m"])
return estimate
def _filter_object_support_by_ground(
indices: npt.NDArray[np.int64],
points_map: FloatArray,
*,
group: str,
profile: Mapping[str, Any],
) -> tuple[npt.NDArray[np.int64], float | None, int]:
"""Remove local ground only from one object's fitting support.
`points_map` is never modified or reduced. The returned indices are a
per-object view used by range/cuboid fitting; mapping, terrain and
traversability consumers continue to receive the complete cloud.
"""
if indices.size == 0:
return indices, None, 0
support = points_map[indices]
support_lower_z = float(np.percentile(support[:, 2], 5.0))
ground_z = _local_ground_z(
all_points_map=points_map,
center_xy=np.median(support[:, :2], axis=0),
support_lower_z=support_lower_z,
profile=profile,
)
minimum = ground_z + float(profile["minimum_height_above_ground_m"][group])
maximum = ground_z + float(profile["maximum_height_above_ground_m"][group])
keep = (support[:, 2] >= minimum) & (support[:, 2] <= maximum)
filtered = indices[keep]
return filtered, ground_z, int(indices.size - filtered.size)
def _support_overlap_fraction(
one: npt.NDArray[np.int64],
two: npt.NDArray[np.int64],
) -> float:
if one.size == 0 or two.size == 0:
return 0.0
shared = np.intersect1d(one, two, assume_unique=False).size
return float(shared / min(one.size, two.size))
def _suppress_duplicate_support_fusions(
fusions: Sequence[TrackFusion],
*,
overlap_threshold: float,
) -> tuple[TrackFusion, ...]:
accepted: list[TrackFusion] = []
suppressed: set[int] = set()
for item in sorted(fusions, key=lambda value: (-value.score, value.track_id)):
if item.cuboid is None:
continue
if any(
other.association_group == item.association_group
and _support_overlap_fraction(other.source_indices, item.source_indices)
>= overlap_threshold
for other in accepted
):
suppressed.add(item.track_id)
else:
accepted.append(item)
if not suppressed:
return tuple(fusions)
return tuple(
replace(
item,
distance_smoothed_m=None,
status="rejected-duplicate-lidar-support",
cuboid=None,
source_indices=np.empty(0, dtype=np.int64),
geometry="none",
observed_cuboid=None,
completion_fraction=None,
ground_z_map=None,
orientation_source=None,
temporal_status=None,
support_coverage_fraction=None,
)
if item.track_id in suppressed
else item
for item in fusions
)
class CuboidCompletionTracker:
"""Complete visible LiDAR surfaces into provenance-marked, smoothed cuboids.
@@ -667,24 +821,12 @@ class CuboidCompletionTracker:
center_xy: FloatArray,
support_lower_z: float,
) -> float:
ground = self.profile["ground"]
radius = float(ground["local_radius_m"])
if all_points_map.size:
distances = np.linalg.norm(all_points_map[:, :2] - center_xy, axis=1)
candidates = all_points_map[distances <= radius, 2]
else:
candidates = np.empty(0, dtype=np.float64)
if candidates.size:
estimate = float(np.percentile(candidates, float(ground["lower_percentile"])))
else:
estimate = math.nan
if (
not math.isfinite(estimate)
or estimate < support_lower_z - float(ground["maximum_below_support_m"])
or estimate > support_lower_z + float(ground["maximum_above_support_m"])
):
estimate = support_lower_z - float(ground["fallback_below_support_m"])
return estimate
return _local_ground_z(
all_points_map=all_points_map,
center_xy=center_xy,
support_lower_z=support_lower_z,
profile=self.profile["ground"],
)
@staticmethod
def _amodal_axis_center(lower: float, upper: float, size: float, sensor: float) -> float:
@@ -732,6 +874,17 @@ def fuse_tracks(
session_seconds: float | None = None,
) -> tuple[TrackFusion, ...]:
vehicle_labels = set(str(value) for value in association["vehicle_labels"])
ground_filter = association.get("object_support_ground_filter")
if ground_filter is not None:
if not isinstance(ground_filter, Mapping):
raise RuntimeError("object-support ground filter profile is invalid")
ground_filter = _object_support_ground_filter_profile(ground_filter)
duplicate_overlap_value = association.get("support_duplicate_overlap_threshold")
duplicate_overlap_threshold = (
None if duplicate_overlap_value is None else float(duplicate_overlap_value)
)
if duplicate_overlap_threshold is not None and not 0.0 < duplicate_overlap_threshold <= 1.0:
raise RuntimeError("support duplicate overlap threshold is invalid")
accepted_tracks: list[dict[str, Any]] = []
for track in sorted(tracks, key=lambda value: float(value["score"]), reverse=True):
label = str(track["label"])
@@ -767,11 +920,21 @@ def fuse_tracks(
allowed = np.asarray(association["semantic_ids"][group], dtype=np.uint8)
compatible = candidates[np.isin(sampled_semantic[candidates], allowed)]
clustered = _depth_cluster(compatible, depths, association)
selected = _spatial_cluster(
selected_before_ground = _spatial_cluster(
source_indices[clustered],
points_lidar,
float(association["spatial_cluster_radius_m"][group]),
)
selected = selected_before_ground
support_ground_z = None
ground_rejected_points = 0
if ground_filter is not None:
selected, support_ground_z, ground_rejected_points = _filter_object_support_by_ground(
selected_before_ground,
points_map,
group=group,
profile=ground_filter,
)
ranges = np.linalg.norm(points_lidar[selected], axis=1)
p10 = None if ranges.size == 0 else float(np.percentile(ranges, 10))
median = None if ranges.size == 0 else float(np.median(ranges))
@@ -786,6 +949,12 @@ def fuse_tracks(
support_coverage_fraction = None
if compatible.size == 0:
status = "rejected-no-semantic-lidar-support"
elif (
selected_before_ground.size >= minimum
and selected.size < minimum
and ground_rejected_points > 0
):
status = "rejected-ground-only-or-insufficient-object-support"
elif selected.size < minimum:
status = f"rejected-fewer-than-{minimum}-clustered-points"
else:
@@ -861,6 +1030,9 @@ def fuse_tracks(
status=status,
cuboid=cuboid,
source_indices=selected,
pre_ground_clustered_points=int(selected_before_ground.size),
ground_rejected_points=ground_rejected_points,
support_ground_z_map=support_ground_z,
geometry=geometry,
observed_cuboid=observed_cuboid,
completion_fraction=completion_fraction,
@@ -870,7 +1042,11 @@ def fuse_tracks(
support_coverage_fraction=support_coverage_fraction,
)
)
return tuple(result)
if duplicate_overlap_threshold is None:
return tuple(result)
return _suppress_duplicate_support_fusions(
result, overlap_threshold=duplicate_overlap_threshold
)
def fusion_document(item: TrackFusion) -> dict[str, Any]:
@@ -883,6 +1059,9 @@ def fusion_document(item: TrackFusion) -> dict[str, Any]:
"candidate_projected_points": item.candidate_points,
"semantic_compatible_points": item.semantic_points,
"clustered_points": item.clustered_points,
"pre_ground_clustered_points": item.pre_ground_clustered_points,
"ground_rejected_points": item.ground_rejected_points,
"support_ground_z_map": item.support_ground_z_map,
"distance_p10_m": item.distance_p10_m,
"distance_median_m": item.distance_median_m,
"distance_smoothed_m": item.distance_smoothed_m,
@@ -0,0 +1,543 @@
#!/usr/bin/env python3
"""Materialize LAB E19 from immutable E14 detections, masks, and LiDAR.
The detector and semantic models are deliberately not rerun: LAB E19 changes
only calibrated LiDAR association, cuboid fitting, and presentation. The
parent result and LiDAR pack are validated first, then a new content-addressed
integrated-perception result is written without modifying either input.
"""
from __future__ import annotations
import argparse
import copy
import hashlib
import json
import os
import platform
import shutil
import tempfile
from collections import Counter
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
import numpy as np
from e10_fusion_runtime import (
CuboidCompletionTracker,
LidarReplayPack,
WorldStateProjector,
_completion_profile,
_object_support_ground_filter_profile,
canonical_json,
clearance,
distance_history,
fuse_tracks,
fusion_document,
project_points,
sha256,
)
from k1link.compute.integrated_perception import (
FUSION_SCHEMA,
IDENTITY_SCHEMA,
REPORT_SCHEMA,
RESULT_SCHEMA,
SEMANTIC_SCHEMA,
WORLD_SCHEMA,
validate_integrated_perception_result,
)
PIPELINE_ID = "fixed-e14-yolox-eomt-e19-ground-aware-refusion/v1"
def arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--job", type=Path, required=True)
parser.add_argument("--parent-result", type=Path, required=True)
parser.add_argument("--lidar-packs-root", type=Path, required=True)
parser.add_argument("--profile", type=Path, required=True)
parser.add_argument("--output-root", type=Path, required=True)
return parser.parse_args()
def read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise RuntimeError(f"JSON root is not an object: {path}")
return value
def read_rows(path: Path) -> list[dict[str, Any]]:
rows = []
with path.open(encoding="utf-8") as stream:
for line in stream:
value = json.loads(line)
if not isinstance(value, dict):
raise RuntimeError(f"JSONL row is not an object: {path}")
rows.append(value)
return rows
def write_json(path: Path, value: object) -> None:
path.write_bytes(canonical_json(value) + b"\n")
os.chmod(path, 0o600)
def write_row(stream: Any, value: object) -> None:
stream.write(canonical_json(value).decode() + "\n")
def artifact(
path: Path,
kind: str,
media_type: str,
schema_version: str | None = None,
) -> dict[str, Any]:
value = {
"kind": kind,
"path": path.name,
"media_type": media_type,
"byte_length": path.stat().st_size,
"sha256": sha256(path),
}
if schema_version is not None:
value["schema_version"] = schema_version
return value
def read_profile(path: Path) -> tuple[dict[str, Any], str]:
resolved = path.resolve(strict=True)
profile = read_object(resolved)
association = profile.get("association")
if (
profile.get("schema_version") != "missioncore.e10-integrated-perception-profile/v1"
or profile.get("profile_id") != "lab-e19-ground-aware-cuboids-v1"
or profile.get("mode") != "full-session-qualification"
or not isinstance(association, dict)
or not isinstance(profile.get("cuboid_completion"), dict)
):
raise RuntimeError("LAB E19 profile contract is invalid")
ground_filter = association.get("object_support_ground_filter")
if not isinstance(ground_filter, dict):
raise RuntimeError("LAB E19 ground filter is missing")
_object_support_ground_filter_profile(ground_filter)
_completion_profile(profile["cuboid_completion"])
overlap = float(association.get("support_duplicate_overlap_threshold", 0.0))
if not 0.0 < overlap <= 1.0:
raise RuntimeError("LAB E19 support overlap threshold is invalid")
return profile, sha256(resolved)
def color_for(group: str, track_id: int) -> tuple[int, int, int]:
seed = hashlib.sha256(f"e10:{group}:{track_id}".encode()).digest()
return tuple(64 + value % 176 for value in seed[:3])
def materialize(args: argparse.Namespace) -> Path:
parent = validate_integrated_perception_result(
args.job,
args.parent_result,
args.lidar_packs_root,
)
if not parent.accepted:
raise RuntimeError("LAB E19 parent result is not accepted")
profile, profile_sha256 = read_profile(args.profile)
parent_result = read_object(parent.result_root / "result.json")
parent_report = read_object(parent.report_path)
parent_identity = parent_result["identity"]
parent_configuration = parent_identity["configuration"]
semantic_rows = read_rows(parent.semantic_path)
parent_fusion_rows = read_rows(parent.fusion_path)
parent_world_rows = read_rows(parent.world_path)
if not (
len(parent_fusion_rows) == len(parent_world_rows) == parent.frame_count
and profile["selection"]["required_frame_count"] == parent.frame_count
):
raise RuntimeError("LAB E19 parent selection changed")
identity = {
"schema_version": IDENTITY_SCHEMA,
"job_id": parent_identity["job_id"],
"input_sha256": parent_identity["input_sha256"],
"session_id": parent_identity["session_id"],
"source_id": parent_identity["source_id"],
"lidar_pack_id": parent_identity["lidar_pack_id"],
"selection": copy.deepcopy(parent_identity["selection"]),
"configuration": {
"pipeline": PIPELINE_ID,
"profile": profile,
"profile_sha256": profile_sha256,
"detector_profile_sha256": parent_configuration["detector_profile_sha256"],
"semantic_profile_sha256": parent_configuration["semantic_profile_sha256"],
"runner_sha256": sha256(Path(__file__).resolve(strict=True)),
"fusion_runtime_sha256": sha256(
Path(__file__).with_name("e10_fusion_runtime.py").resolve(strict=True)
),
"orchestrator_sha256": sha256(Path(__file__).resolve(strict=True)),
"container_image": parent_configuration["container_image"],
"valid_fov": copy.deepcopy(parent_configuration["valid_fov"]),
"refusion": {
"mode": "immutable-parent-detections-semantics-lidar-v1",
"parent_result_id": parent.result_id,
"parent_result_json_sha256": sha256(parent.result_root / "result.json"),
"parent_fusion_sha256": sha256(parent.fusion_path),
"parent_arrays_sha256": sha256(parent.arrays_path),
"detector_rerun": False,
"semantic_rerun": False,
"full_point_cloud_mutated": False,
},
},
"models": copy.deepcopy(parent_identity["models"]),
}
identity_sha256 = hashlib.sha256(canonical_json(identity)).hexdigest()
result_id = f"e10-integrated-perception-{identity_sha256}"
output_root = args.output_root.expanduser().absolute()
output_root.mkdir(mode=0o700, parents=True, exist_ok=True)
final = output_root / result_id
if final.exists():
validate_integrated_perception_result(args.job, final, args.lidar_packs_root)
return final
staging = Path(tempfile.mkdtemp(prefix=".e19-refusion-", dir=output_root))
os.chmod(staging, 0o700)
lidar = LidarReplayPack(parent.pack_root, expected_job_id=parent.job.job_id)
final_created = False
try:
semantic_path = staging / "semantic-frames.jsonl"
shutil.copyfile(parent.semantic_path, semantic_path)
os.chmod(semantic_path, 0o600)
fusion_path = staging / "fusion-frames.jsonl"
world_path = staging / "world-state.jsonl"
gpu_path = staging / "gpu-telemetry.jsonl"
with np.load(parent.arrays_path, allow_pickle=False) as parent_arrays:
frame_times_ns = parent_arrays["frame_times_ns"].copy()
semantic_frame_indices = parent_arrays["semantic_frame_indices"].copy()
semantic_masks = parent_arrays["semantic_masks"].copy()
if not np.array_equal(
semantic_frame_indices,
np.asarray([row["frame_index"] for row in semantic_rows], dtype=np.int64),
):
raise RuntimeError("LAB E19 semantic mask binding changed")
semantic_by_source = {
int(row["source_frame_index"]): mask
for row, mask in zip(semantic_rows, semantic_masks, strict=True)
}
history = distance_history(int(profile["association"]["distance_history_frames"]))
completion = CuboidCompletionTracker(profile["cuboid_completion"])
projector = WorldStateProjector(float(profile["world_state"]["velocity_history_limit_s"]))
support_offsets = [0]
support_points: list[np.ndarray] = []
support_colors: list[np.ndarray] = []
box_offsets = [0]
box_centers: list[tuple[float, float, float]] = []
box_half_sizes: list[tuple[float, float, float]] = []
box_quaternions: list[tuple[float, float, float, float]] = []
box_colors: list[tuple[int, int, int, int]] = []
status_counts: Counter[str] = Counter()
fusion_state_counts: Counter[str] = Counter()
accepted_cuboids = 0
old_accepted_cuboids = 0
ground_rejected_points = 0
tracks_with_ground_rejections = 0
duplicate_support_rejections = 0
fused_frames = 0
with (
fusion_path.open("x", encoding="utf-8", newline="\n") as fusion_stream,
world_path.open("x", encoding="utf-8", newline="\n") as world_stream,
):
for index, (parent_fusion, parent_world) in enumerate(
zip(parent_fusion_rows, parent_world_rows, strict=True)
):
session_seconds = float(parent_fusion["session_seconds"])
source_frame_index = int(parent_fusion["source_frame_index"])
old_accepted_cuboids += sum(
str(item.get("cuboid_status", "")).startswith("accepted-")
for item in parent_fusion["objects"]
)
lidar_frame = lidar.frame(index)
points_lidar = np.empty((0, 3), dtype=np.float64)
fusions = ()
fusion_state = str(parent_fusion["fusion_state"])
if fusion_state == "fused":
if lidar_frame is None:
raise RuntimeError(f"LAB E19 lost LiDAR frame {index}")
semantic_source = parent_fusion.get("semantic_source_frame_index")
semantic_map = semantic_by_source.get(int(semantic_source))
if semantic_map is None:
raise RuntimeError(f"LAB E19 lost semantic source {semantic_source}")
points_map, position, quaternion = lidar_frame
pixels, depths, source_indices, points_lidar = project_points(
points_map,
position,
quaternion,
lidar.profile,
)
fusions = fuse_tracks(
tracks=parent_fusion["objects"],
semantic_map=semantic_map,
pixels=pixels,
depths=depths,
source_indices=source_indices,
points_map=points_map,
points_lidar=points_lidar,
association=profile["association"],
distance_history=history,
completion_tracker=completion,
sensor_position_map=position,
session_seconds=session_seconds,
)
fused_frames += 1
fusion_state_counts[fusion_state] += 1
accepted = [item for item in fusions if item.cuboid is not None]
accepted_cuboids += len(accepted)
for item in fusions:
status_counts[item.status] += 1
ground_rejected_points += item.ground_rejected_points
tracks_with_ground_rejections += item.ground_rejected_points > 0
duplicate_support_rejections += (
item.status == "rejected-duplicate-lidar-support"
)
frame_support = []
frame_support_colors = []
for item in accepted:
if lidar_frame is None:
raise RuntimeError("LAB E19 accepted a cuboid without LiDAR")
color = color_for(item.association_group, item.track_id)
values = lidar_frame[0][item.source_indices].astype(np.float32)
frame_support.append(values)
frame_support_colors.append(
np.tile(np.asarray([color], dtype=np.uint8), (values.shape[0], 1))
)
box_centers.append(item.cuboid.center_map)
box_half_sizes.append(item.cuboid.half_size)
box_quaternions.append(item.cuboid.quaternion_xyzw)
box_colors.append((*color, 88))
if frame_support:
support = np.concatenate(frame_support)
colors = np.concatenate(frame_support_colors)
support_points.append(support)
support_colors.append(colors)
support_offsets.append(support_offsets[-1] + support.shape[0])
else:
support_offsets.append(support_offsets[-1])
box_offsets.append(box_offsets[-1] + len(accepted))
clearance_state = clearance(
points_lidar,
profile["world_state"]["clearance"],
)
world = projector.project(
frame_index=index,
source_frame_index=source_frame_index,
session_seconds=session_seconds,
fusion_state=fusion_state,
fusions=fusions,
points_lidar=points_lidar,
clearance_state=clearance_state,
delivery=parent_world["delivery"],
)
write_row(
fusion_stream,
{
"schema_version": FUSION_SCHEMA,
"frame_index": index,
"source_frame_index": source_frame_index,
"session_seconds": session_seconds,
"fusion_state": fusion_state,
"semantic_status": parent_fusion["semantic_status"],
"semantic_source_frame_index": parent_fusion.get(
"semantic_source_frame_index"
),
"objects": [fusion_document(item) for item in fusions],
},
)
write_row(world_stream, world)
fusion_stream.flush()
world_stream.flush()
os.fsync(fusion_stream.fileno())
os.fsync(world_stream.fileno())
os.chmod(fusion_path, 0o600)
os.chmod(world_path, 0o600)
arrays_path = staging / "transient-perception.npz"
np.savez_compressed(
arrays_path,
frame_times_ns=frame_times_ns,
semantic_frame_indices=semantic_frame_indices,
semantic_masks=semantic_masks,
support_offsets=np.asarray(support_offsets, dtype=np.int64),
support_points=np.concatenate(support_points)
if support_points
else np.empty((0, 3), dtype=np.float32),
support_colors=np.concatenate(support_colors)
if support_colors
else np.empty((0, 3), dtype=np.uint8),
box_offsets=np.asarray(box_offsets, dtype=np.int64),
box_centers=np.asarray(box_centers, dtype=np.float32).reshape((-1, 3)),
box_half_sizes=np.asarray(box_half_sizes, dtype=np.float32).reshape((-1, 3)),
box_quaternions=np.asarray(box_quaternions, dtype=np.float32).reshape((-1, 4)),
box_colors=np.asarray(box_colors, dtype=np.uint8).reshape((-1, 4)),
)
os.chmod(arrays_path, 0o600)
with gpu_path.open("x", encoding="utf-8", newline="\n") as gpu_stream:
write_row(
gpu_stream,
{
"schema_version": "missioncore.e19-refusion-telemetry/v1",
"gpu_used": False,
"parent_result_id": parent.result_id,
"reason": "detector and semantic inference outputs reused immutably",
},
)
gpu_stream.flush()
os.fsync(gpu_stream.fileno())
os.chmod(gpu_path, 0o600)
acceptance_profile = profile["acceptance"]
checks = {
"parent_result_accepted": parent.accepted,
"frame_accounting": len(parent_fusion_rows) == parent.frame_count,
"minimum_lidar_fused_frames": fused_frames
>= int(acceptance_profile["minimum_lidar_fused_frames"]),
"minimum_accepted_cuboids": accepted_cuboids
>= int(acceptance_profile["minimum_accepted_cuboids"]),
"ground_filter_exercised": ground_rejected_points > 0,
"duplicate_support_filter_exercised": duplicate_support_rejections > 0,
"full_point_cloud_preserved": True,
}
accepted = all(checks.values())
created_at = datetime.now(UTC).isoformat(timespec="milliseconds").replace("+00:00", "Z")
parent_metrics = parent_report.get("metrics", {})
metrics = {
"source_span_seconds": parent_metrics.get("source_span_seconds"),
"detector": copy.deepcopy(parent_metrics.get("detector")),
"semantic": copy.deepcopy(parent_metrics.get("semantic")),
"fusion": {
"fused_frames": fused_frames,
"fusion_state_counts": dict(fusion_state_counts),
"accepted_cuboids": accepted_cuboids,
"parent_accepted_cuboids": old_accepted_cuboids,
"accepted_change_fraction": (
accepted_cuboids / old_accepted_cuboids - 1.0 if old_accepted_cuboids else None
),
"rejection_counts": dict(status_counts),
"ground_points_excluded_from_box_fitting": ground_rejected_points,
"track_observations_with_ground_exclusions": tracks_with_ground_rejections,
"duplicate_support_rejections": duplicate_support_rejections,
},
"refusion": {
"gpu_used": False,
"detector_rerun": False,
"semantic_rerun": False,
"parent_result_id": parent.result_id,
},
}
report = {
"schema_version": REPORT_SCHEMA,
"result_id": result_id,
"created_at_utc": created_at,
"state": "accepted" if accepted else "rejected",
"ground_truth": False,
"identity": identity,
"runtime": {
"hostname": platform.node(),
"python": platform.python_version(),
"numpy": np.__version__,
"execution": "cpu-only-refusion-of-validated-parent",
},
"metrics": metrics,
"acceptance": {
"accepted": accepted,
"checks": checks,
"navigation_or_safety_accepted": False,
},
"limitations": [
"Detector and semantic inference are inherited from the validated E14 parent.",
"This is a recorded refusion result, not a physical live K1 gate.",
"The complete point cloud is an immutable input and is not modified.",
"Completed cuboids remain class-prior diagnostic geometry, not 3D ground truth.",
"Navigation and safety authority remain disabled.",
],
}
report_path = staging / "run-report.json"
write_json(report_path, report)
artifacts = [
artifact(
semantic_path,
"e10-semantic-frames",
"application/x-ndjson",
SEMANTIC_SCHEMA,
),
artifact(
fusion_path,
"e10-fusion-frames",
"application/x-ndjson",
FUSION_SCHEMA,
),
artifact(
world_path,
"e10-world-state",
"application/x-ndjson",
WORLD_SCHEMA,
),
artifact(arrays_path, "e10-transient-perception", "application/x-npz"),
artifact(gpu_path, "worker-gpu-telemetry", "application/x-ndjson"),
artifact(
report_path,
"e10-run-report",
"application/json",
REPORT_SCHEMA,
),
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": created_at,
"acceptance_state": report["state"],
"ground_truth": False,
"publication_scope": "recorded-integrated-realtime-qualification-only",
"frames_processed": parent.frame_count,
"artifacts": artifacts,
}
write_json(staging / "result.json", result)
os.rename(staging, final)
final_created = True
validate_integrated_perception_result(args.job, final, args.lidar_packs_root)
return final
except BaseException:
if staging.exists():
shutil.rmtree(staging)
if final_created and final.exists():
shutil.rmtree(final)
raise
finally:
lidar.close()
def main() -> int:
result = materialize(arguments())
report = read_object(result / "run-report.json")
print(
json.dumps(
{
"result_root": str(result),
"result_id": result.name,
"accepted": report["acceptance"]["accepted"],
"fusion": report["metrics"]["fusion"],
},
ensure_ascii=False,
sort_keys=True,
)
)
return 0
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,172 @@
{
"schema_version": "missioncore.e10-integrated-perception-profile/v1",
"profile_id": "lab-e19-ground-aware-cuboids-v1",
"mode": "full-session-qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"selection": {
"required_frame_count": 4489,
"required_source_start_frame_index": 0,
"required_source_end_frame_index": 4488,
"minimum_source_span_seconds": 448.0
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"association": {
"box_inset": {
"bottom_fraction": 0.02,
"horizontal_fraction": 0.05,
"top_fraction": 0.04
},
"depth_cluster_gap_fraction": 0.06,
"depth_cluster_minimum_gap_m": 0.5,
"group_nms_iou_threshold": 0.5,
"support_duplicate_overlap_threshold": 0.6,
"object_support_ground_filter": {
"mode": "local-ground-relative-object-support-v1",
"local_radius_m": 2.5,
"lower_percentile": 8.0,
"maximum_below_support_m": 1.2,
"maximum_above_support_m": 0.15,
"fallback_below_support_m": 0.25,
"minimum_height_above_ground_m": {
"person": 0.08,
"bicycle": 0.08,
"motorcycle": 0.08,
"vehicle": 0.12
},
"maximum_height_above_ground_m": {
"person": 2.5,
"bicycle": 2.5,
"motorcycle": 2.5,
"vehicle": 4.5
}
},
"maximum_cuboid_span_m": 15.0,
"maximum_distance_innovation_fraction": 0.25,
"maximum_distance_innovation_m": 1.5,
"maximum_oriented_extent_m": {
"bicycle": [3.5, 2.0, 2.5],
"motorcycle": [3.5, 2.0, 2.5],
"person": [1.5, 1.5, 2.8],
"vehicle": [12.5, 4.0, 4.5]
},
"minimum_cuboid_extent_m": 0.15,
"minimum_support_points": {
"bicycle": 4,
"motorcycle": 4,
"person": 4,
"vehicle": 8
},
"semantic_ids": {
"bicycle": [2],
"motorcycle": [3],
"person": [1],
"vehicle": [4, 5]
},
"spatial_cluster_radius_m": {
"bicycle": 0.9,
"motorcycle": 0.9,
"person": 0.9,
"vehicle": 1.5
},
"vehicle_labels": ["car", "truck", "bus"],
"distance_history_frames": 5
},
"cuboid_completion": {
"mode": "class-prior-amodal-v1",
"failure_policy": "reject",
"classes": {
"person": {
"nominal_size_m": [0.55, 0.55, 1.72],
"minimum_size_m": [0.35, 0.35, 1.3],
"maximum_size_m": [1.2, 1.2, 2.3],
"support_padding_m": [0.12, 0.12, 0.12]
},
"bicycle": {
"nominal_size_m": [1.8, 0.65, 1.5],
"minimum_size_m": [1.2, 0.4, 1.0],
"maximum_size_m": [2.5, 1.2, 2.2],
"support_padding_m": [0.18, 0.12, 0.12]
},
"motorcycle": {
"nominal_size_m": [2.1, 0.8, 1.45],
"minimum_size_m": [1.4, 0.5, 1.0],
"maximum_size_m": [3.0, 1.4, 2.2],
"support_padding_m": [0.2, 0.14, 0.14]
},
"car": {
"nominal_size_m": [4.5, 1.85, 1.55],
"minimum_size_m": [3.2, 1.45, 1.2],
"maximum_size_m": [5.8, 2.4, 2.3],
"support_padding_m": [0.25, 0.18, 0.15]
},
"truck": {
"nominal_size_m": [7.0, 2.5, 3.0],
"minimum_size_m": [4.8, 1.8, 1.8],
"maximum_size_m": [12.5, 3.2, 4.2],
"support_padding_m": [0.35, 0.22, 0.2]
},
"bus": {
"nominal_size_m": [10.5, 2.55, 3.2],
"minimum_size_m": [7.0, 2.1, 2.5],
"maximum_size_m": [13.5, 3.2, 4.2],
"support_padding_m": [0.4, 0.24, 0.2]
}
},
"ground": {
"local_radius_m": 2.5,
"lower_percentile": 8.0,
"maximum_below_support_m": 1.2,
"maximum_above_support_m": 0.15,
"fallback_below_support_m": 0.25
},
"orientation": {
"minimum_anisotropy_ratio": 1.35,
"face_width_switch_fraction": 1.05
},
"temporal": {
"center_alpha": 0.4,
"size_alpha": 0.2,
"yaw_alpha": 0.25,
"maximum_center_innovation_m": 2.0,
"maximum_yaw_innovation_degrees": 55.0,
"maximum_idle_s": 1.0,
"confirmation_hits": 3
},
"minimum_support_coverage_fraction": 0.75
},
"world_state": {
"velocity_history_limit_s": 1.0,
"clearance": {
"sector_count": 72,
"minimum_range_m": 0.5,
"maximum_range_m": 30.0,
"ground_percentile": 5.0,
"minimum_height_above_ground_m": 0.2,
"maximum_height_above_ground_m": 3.0,
"front_half_angle_degrees": 15.0
}
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"maximum_p95_world_state_age_ms": 175.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 400.0,
"minimum_fresh_semantic_coverage": 0.9,
"minimum_lidar_fused_frames": 3500,
"minimum_accepted_cuboids": 1500,
"require_zero_failures": true
}
}
@@ -26,6 +26,7 @@ from e10_fusion_runtime import (
LidarReplayPack,
WorldStateProjector,
_completion_profile,
_object_support_ground_filter_profile,
canonical_json,
clearance,
distance_history,
@@ -160,6 +161,14 @@ def read_profile(path: Path) -> tuple[dict[str, Any], str]:
if not isinstance(completion, dict):
raise RuntimeError("LAB E13 cuboid completion contract is invalid")
_completion_profile(completion)
ground_filter = association.get("object_support_ground_filter")
if ground_filter is not None:
if not isinstance(ground_filter, dict):
raise RuntimeError("object-support ground filter contract is invalid")
_object_support_ground_filter_profile(ground_filter)
duplicate_overlap = association.get("support_duplicate_overlap_threshold")
if duplicate_overlap is not None and not 0.0 < float(duplicate_overlap) <= 1.0:
raise RuntimeError("support duplicate overlap contract is invalid")
return profile, sha256(resolved)