Skip to content

Add continuous-collision infrastructure for deformables - #3463

Closed
smallquail wants to merge 1 commit into
google-deepmind:mainfrom
smallquail:flex-continuous-collision
Closed

Add continuous-collision infrastructure for deformables#3463
smallquail wants to merge 1 commit into
google-deepmind:mainfrom
smallquail:flex-continuous-collision

Conversation

@smallquail

@smallquail smallquail commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

The standard discrete collision pipeline generates contact points at a configuration; this new module prices gaps along trajectories:

  • differentiable vertex-triangle / edge-edge / vertex-geom distance kernels with closest-point barycentrics (mjc_PtTri, mjc_SegSeg, mjc_GeomDist, plus sharp-feature extraction mjc_GeomVerts/mjc_GeomEdges);
  • swept-volume contact-candidate generation over the flex BVH (mjc_candidates);
  • per-pair gap evaluation with the gradient's direction and vertex weights (mjc_pairGap);
  • conservative advancement bounding each pair's time of impact (mjc_advance).

Design notes

  • mjcPair is the geometric identity of a candidate pair only. Solver state (multipliers, ages) and cached linearizations belong to the consumer, not to this struct — the module neither reads nor writes them.
  • No hard-coded constants. The two lengths the module needs are caller-supplied parameters:
    • the standoff cap bounds the rest gap: an active pair settles at a small positive distance δ = min(pair band, cap) rather than at zero. Strictly positive so the conservative advancement always sees a nonzero time of impact (a pair resting at exactly zero would lock the advance); the per-pair min keeps thin participants' skins proportionally thin, and the cap stops thick ones carrying a fat layer.
    • the detection band is the tracking reach, and is not a physical length: how early the broad phase starts holding a pair and how long the gap evaluation keeps it held. Wider costs candidates; narrower hands pairs to the consumer later.
  • Flex-flex gaps are measured at the midsurface, not skin-to-skin: where the mesh geometry is tighter than the combined radii (a string threaded through a hem), a skin gap is permanently negative and the pair would be discarded as invalid — losing CCD coverage exactly where tunneling is likeliest. The broad phase adds the radii back into its reach, so detection range is unchanged.
  • Engine-internal (MJAPI on entry points only for tests, marked not a supported API). No user-visible behavior change; changelog notes the new infrastructure.

Testing

engine_collision_continuous_test: distance kernels across their regions (interior/edge/vertex, crossing/collinear/parallel), geom signed distance and sharp features, the pair gap with its gradient verified by central differences at every involved vertex, the conservative advancement (analytic cap on a crossing sweep; the conservative closing-rate bound; small-motion early-out), and candidate generation on stacked cloths (pairs found at 2 mm, none at 0.5 m). Full suite: 1349/1349.

The discrete collision pipeline generates contact points at a configuration;
this module prices gaps along trajectories: differentiable vertex-triangle,
edge-edge and vertex-geom distance kernels with closest-point barycentrics,
swept-volume candidate generation over the flex bounding-volume hierarchy,
per-pair gap evaluation with the gradient's vertex weights, and a conservative
advancement that bounds each contact pair's time of impact.

Engine-internal, with no consumer in this change: it is the groundwork for
continuous-contact (IPC-style) solvers for flex, which will arrive as callers.
The mjcPair type carries the geometric identity of a candidate pair only;
solver state (multipliers, ages) and cached linearizations belong to the
consumer. The two lengths the module needs -- the standoff cap and the
detection band -- are caller-supplied parameters, not constants.

Flex-flex pairs measure their gap at the midsurface rather than skin-to-skin:
where mesh geometry is tighter than the combined radii (a string threaded
through a hem) a skin gap is permanently negative and the pair would be
discarded as invalid, losing CCD coverage exactly where tunneling is likeliest.
The broad phase adds the radii back into its reach, so detection range is
unchanged.

Tests cover the distance kernels, the geom sharp features, the pair gap with
its gradient checked by central differences at every involved vertex, the
conservative advancement (the analytic cap on a crossing sweep, the
conservative closing-rate bound, the small-motion early-out), and candidate
generation on stacked cloths (pairs within reach found, distant ones not).
@quagla
quagla requested a review from yuvaltassa August 5, 2026 12:31

@yuvaltassa yuvaltassa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you ask @kbayes to review? I feel like the unit tests could be improved and also would his eyes on this re consistency with the rest of the collision code.

Comment thread doc/changelog.rst
@quagla

quagla commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Superseded by b924ac6

@quagla quagla closed this Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants