scene_service.scene_graph.geometry¶
Deterministic geometric relation predicates and cache-invalidation signatures, shared by the scene-graph builder/store.
This is the single source of truth for “what the bounding boxes alone
say” — the contact/containment judgements that were historically split
between state/relations.py (the 1 Hz RelationEngine) and the
GeometryHint cues in scene_graph/relations.py. Operating on
SceneGraphNode.bbox_center / bbox_extent keeps it usable from the
scene-graph layer without importing the state-layer structs.
- Two roles:
geometric_relation— when geometry alone is decisive, name the relation (so the builder can later skip the LLM); otherwise returnNoneand leave it to the LLM.geometry_signature— a coarse, jitter-stable fingerprint of a pair’s relational geometry, used as part of the relation cache key so a cached edge invalidates when the spatial configuration actually changes (not on every EMA position wobble).
Functions
|
Deterministic contact/containment edges over a node list. |
|
Return |
|
Coarse, jitter-stable fingerprint of a pair's relational geometry. |
- scene_service.scene_graph.geometry.compute_geometric_edges(nodes: list[SceneGraphNode]) list[SceneGraphEdge][source]¶
Deterministic contact/containment edges over a node list.
For each unordered pair (i<j) ask
geometric_relationand emit amethod="geometric"edge only when geometry decides a contact or containment relation (on_top_of/under/inside/contains).nearand ambiguous (None) pairs are skipped: proximity is served separately (get_object_context.nearby_objects) and ambiguous nesting is left to the LLM. One edge per pair (the inverse direction is implied — consumers read edges touching either endpoint).reachable_byis NOT produced here: it needs the gripper object, which lives in the registry, not in this node set — the fast loop adds it. O(N²) over a small node set (N<80); each call is cheap.
- scene_service.scene_graph.geometry.geometric_relation(a: SceneGraphNode, b: SceneGraphNode) tuple[str, float] | None[source]¶
Return
(relation, confidence)fromatobwhen the bounding boxes alone decide it, elseNone(defer to the LLM).- Decision order (strongest first):
arests onb→on_top_of(high)brests ona→under(high)a’s center insideb(only) →inside(high)b’s center insidea(only) →contains(high)mutual containment / ambiguous nesting →
None(LLM disambiguates)centers within proximity radius →
near(medium)otherwise →
None
Returns geometric-spatial relations only; semantic relations (
attached_to/part_of/same_object) are never produced here and remain the LLM’s job.
- scene_service.scene_graph.geometry.geometry_signature(hint: GeometryHint) str[source]¶
Coarse, jitter-stable fingerprint of a pair’s relational geometry.
Quantizes the continuous cues (distance, xy_overlap) into buckets and keeps the already-discrete cues (vertical_order, containment) as-is. Same spatial configuration → same string (cache hit, no recompute); a real change → different string (cache miss → re-evaluate). Unlike a raw-coordinate key it does not drift on sub-bucket EMA jitter.