scene_service.state.data_assoc¶
Cross-frame data association: turn a batch of per-frame `Detection`s into either updates of existing SceneObject records or allocations of new ones. v1 algorithm:
spatial gating per class (_GATE_RADIUS_M)
class-match (only same-class candidates considered)
Hungarian (scipy.optimize.linear_sum_assignment) min-cost matching
unmatched detections → allocate new SceneObject
unmatched objects → mark_stale handles them; we don’t touch them here
matched pairs → ObjectRegistry.update_object_pose (EMA blend)
Not implemented in v1 (deferred): Kalman filtering, IoU-based gating, appearance embeddings, learned association.
Functions
|
Resolve detections against the registry. |
Classes
|
One per-frame perception output. |
- class scene_service.state.data_assoc.Detection(cls: str, pose: Pose3D, bbox: BBox3D, confidence: float, source: str = 'perception')[source]¶
Bases:
objectOne per-frame perception output. Stable id is NOT supplied — it’s this layer’s job to assign / find one. pose is in map frame (ingest does the TF transform before producing Detection).
- cls: str¶
- confidence: float¶
- source: str = 'perception'¶
- scene_service.state.data_assoc.associate(registry: ObjectRegistry, detections: list[Detection], *, now: float | None = None) tuple[list[str], list[str]][source]¶
Resolve detections against the registry. Caller must hold registry.lock().
Returns (matched_ids, new_ids) for logging / metrics. The registry is mutated in place: matched detections EMA-update existing records, unmatched detections allocate new ones, unmatched objects are NOT touched (mark_stale runs separately on a periodic tick).