Mesh-based Non-collision Constraints #771
Conversation
There was a problem hiding this comment.
🤖 Isaac Lab Review Bot — PR #771
Mesh-based Non-collision Constraints
Summary
This PR adds sphere-to-SDF mesh collision support as an alternative to AABB overlap detection. The architecture is clean — CollisionMode.MESH integrates well into the existing NoCollisionLossStrategy dispatch, and the greedy sphere decomposition + Warp SDF kernel approach is sound. The test suite is thorough (542 lines!) with good coverage of dispatch routing, gradient flow, and integration.
Findings
| # | Severity | Finding |
|---|---|---|
| 1 | 🟡 Warning | Validator creates fresh WarpMeshManager per call — cache never reused |
| 2 | 🟡 Warning | Scale applied post-transform in extract_trimesh_from_usd may be incorrect for nested prims |
| 3 | 🔵 Suggestion | object_base.py abstract method has no explicit return None |
| 4 | 🔵 Suggestion | Sentinel warning pattern on function object is not thread-safe |
| 5 | 🔵 Suggestion | Consider documenting the rotated-anchor limitation more prominently |
See inline comments for details.
Update (5e86ed0a): Reviewed incremental changes since 655ac73.
Addressed Findings
- ✅ Finding #1 resolved —
_get_cpu_mesh_manager()now lazily creates and caches theWarpMeshManageron the instance, eliminating redundant allocations per validation call. Good fix. - ✅ Finding #2 resolved — Removed erroneous
.Ttranspose onComputeLocalToWorldTransforminusd_helpers.py. USD returns row-major matrices; the transpose was producing incorrect vertex transforms for nested prims.
Other Changes
- Validation logic refactored (
_validate_placement): Mesh mode now skips AABB validation entirely (elsebranch). Previously both checks ran in mesh mode — the AABB check was redundant and could produce false negatives for non-convex shapes. Clean improvement. - Test suite trimmed: Removed
test_sphere_count_respects_budget,test_cache_key_differs_for_different_meshes,test_dispatch_falls_back_when_obj_is_none, andtest_mesh_zero_loss_separated_cylinders. These removals look intentional (simplified scope / covered elsewhere), though removing cache-key differentiation test reduces regression coverage on the caching layer.
Remaining Observations
- Findings #3–#5 from original review remain unaddressed (low priority, suggestions only).
- The new
_get_cpu_mesh_manageruseshasattrcheck — works fine butOptionalattribute initialized in__init__would be more explicit.
Overall: Good incremental improvement. The two main warnings from the initial review are resolved. No new concerns.
Update (729d892c): Reviewed incremental changes since 5e86ed0a.
Changes in this push (2 files)
-
relation_loss_strategies.py— Addedparent_pos_resolved.expand(batch_size, -1)before the per-batch loop. This fixes a shape mismatch whenparent_pos_resolvedis not already batch-expanded (e.g., single parent broadcast to multiple children). Correct fix. -
warp_mesh_manager.py— Wrappedgetattr(obj, "scale", ...)intuple()for cache key computation. This prevents unhashable types (e.g., numpy arrays or torch tensors returned by.scale) from breaking the dict lookup. Necessary bugfix.
Assessment
Both changes are small, targeted bugfixes. No new concerns introduced. All previous suggestions (#3–#5) remain low-priority and unaddressed.
Greptile SummaryThis PR introduces mesh-based non-collision constraints for the placement solver via sphere-to-SDF queries (Warp). It adds
Confidence Score: 3/5The core MESH-mode solver path can silently miss collision penalties for yaw-rotated anchors, causing the optimizer to converge to positions inside those anchors before the validation pass rejects them. The vectorized mesh cache stores the anchor's un-rotated local bounding box as the broadphase gate. For any anchor with a non-zero yaw (e.g., a table rotated 45-90 degrees), the unrotated AABB underestimates the anchor's extent on one axis, so the broadphase can declare separated for a child that is actually inside the true footprint. The SDF check is skipped and the pair contributes zero loss; the optimizer has no gradient signal to push the child away. The validation path correctly inflates the anchor bbox, so placed objects are eventually rejected, but without a working loss signal the solver wastes attempts and may consistently fail to find valid placements. isaaclab_arena/relations/relation_solver.py - specifically _build_vectorized_cache where pair_p_bbox_min/max is stored for anchor objects without applying the anchor's yaw rotation. Important Files Changed
Sequence DiagramsequenceDiagram
participant OP as ObjectPlacer
participant RS as RelationSolver
participant WMM as WarpMeshManager
participant SDK as warp_sdf_kernels
OP->>RS: solve(objects, initial_positions, env_bboxes, orientations)
RS->>RS: _prepare_mesh_collision_cache(state, on_pairs)
RS->>WMM: "get_warp_mesh(parent_mesh, obj=anchor)"
RS->>WMM: "get_query_spheres(child_mesh, obj=child)"
RS->>RS: _build_vectorized_cache (fwd + rev)
Note over RS: Cache stores pair_p_bbox_min/max unrotated for anchors
loop optimization iterations
RS->>RS: _compute_no_overlap_loss_mesh(state)
RS->>RS: AABB broadphase using pair_p_bbox_min/max
Note over RS: Rotated-anchor broadphase may false-separate
RS->>SDK: multi_mesh_sdf(active_centers, mesh_id_array)
SDK-->>RS: sdf_values
RS->>RS: "penetration = relu(radii + clearance - sdf)"
RS->>RS: segment-reduce to pair_mean to total_loss
end
RS-->>OP: solved positions
OP->>OP: _validate_placement to _validate_no_overlap_mesh
OP->>WMM: get_query_spheres / get_warp_mesh (CPU, cached)
OP->>OP: _centers_in_target_frame applies src_yaw and tgt_yaw
OP->>SDK: mesh_sdf(centers_in_b, warp_a)
SDK-->>OP: sdf_values
OP-->>OP: overlap check to accept or reject placement
Reviews (6): Last reviewed commit: "supoort for rotation, verification of al..." | Re-trigger Greptile |
729d892 to
db06239
Compare
Signed-off-by: zhx06 <zihaox@nvidia.com>
Signed-off-by: zhx06 <zihaox@nvidia.com>
Signed-off-by: zhx06 <zihaox@nvidia.com>
ef73a02 to
7c46283
Compare
Summary
Add mesh-based non-collision constraints via sphere-to-SDF
Detailed description
CollisionMode.MESHas an alternative to AABB for no-overlap constraints, using greedy sphere decomposition + differentiable Warp SDF queries against actual collision geometry.--collision_mode meshenables the new path.Core files
relations/warp_sdf_kernels.py— differentiable SDF queries on Warp meshesrelations/warp_mesh_manager.py— sphere decomposition and mesh cachingrelations/relation_solver.py— vectorized mesh collision loss during optimizationrelations/object_placer.py— mesh collision validation at placement timerelations/relation_loss_strategies.py— per-pair mesh loss for the strategy API