Add geom adhesion: contacts that pull, via translated friction cones.

https://youtu.be/GioWwB36XHI

The new geom attribute adhesion (units of force, signed; pair-level
override) translates the contact friction cone along its normal so
that the force origin lies strictly inside it. Consequences: each
contact can pull with up to the given force before breaking, and the
tangential friction budget becomes mu*(f_N + adhesion) -- the
Mohr-Coulomb yield condition with cohesion c = mu*adhesion -- so
lightly-squeezed grasps retain a guaranteed friction floor.

A translated cone factors exactly into {constant attractive force}
+ {original cone}, so no solver kernels change. The implementation is
this factorization: a constant attraction along contact normals
accumulated into the new mjData.qfrc_adhesion (summed into
qfrc_passive), plus a bias of adhesive contact rows' reference
acceleration (aref += R*adhesion), which makes resting penetration
exactly independent of adhesion. Contacts of adhesive pairs remain
active throughout the gap zone, producing rows with positive violation
whose reference acceleration pulls: a tether that resists pull-off
smoothly, captures objects released within the band into steady
contact, and detaches at the specified force. Adhesion values of the
two geoms combine by sum; explicit pairs override.

mj_contactForce reports the net interface force (cone force minus the
adhesive pull), whose normal component can now be negative. Negative
adhesion is allowed and produces a repulsive offset (air hockey).

PiperOrigin-RevId: 950858148
Change-Id: I879c08eba7ae501e5c0f8c2f807167344da4c2bc
This commit is contained in:
Yuval Tassa
2026-07-20 08:35:17 -07:00
committed by Copybara-Service
parent b942c9f922
commit a264d0bc8b
28 changed files with 784 additions and 50 deletions
+39 -2
View File
@@ -2797,6 +2797,29 @@ helps clarify the role of bodies and geoms in MuJoCo.
additionally displays an arrow along the tangential surface velocity at the contact point. This attribute can be
modified at runtime.
.. _body-geom-adhesion:
.. youtube:: GioWwB36XHI
:align: right
:width: 40%
:at:`adhesion`: :at-val:`real, "0"`
Adhesive force of contacts with this geom, in units of force. Geometrically, the friction cone is translated down
along the normal so that the force origin lies strictly inside it: each contact can pull with up to ``adhesion``
before breaking, and the friction budget becomes :math:`\mu(f_N + \text{adhesion})`. Contacts resist sliding even
under zero normal force, the defining property of cohesive materials. This is useful for sticky materials (tape,
gecko feet, tacky rubber) and as a physical stabilizer for grasping. The adhesion of a contact is the sum of the
values of the two contacting geoms, or the value of the higher-:ref:`priority<body-geom-priority>` geom if priorities
differ; an explicit contact :ref:`pair<contact-pair>` overrides both. Note that adhesion is *per contact*: a box face
resting on a plane generates four contact points and therefore four times the pull-off force of a single-point
contact. To let adhesion act across a small separation (attraction at a distance), set :ref:`gap<body-geom-gap>` to
the desired interaction range. This can be used to model magnets. Resting penetration is unaffected by adhesion (the
compression behavior of the contact is unchanged; only a tensile branch is added), and :ref:`mj_contactForce` reports
the net interface force, whose normal component can be negative under tension. The underlying model is described in
the :ref:`Computation chapter<soAdhesion>`. For adhesion as a *controlled* force — switched on and off like a vacuum
gripper, dividing a total force between a body's contacts and pressing the bodies together — see the :ref:`adhesion
actuator<actuator-adhesion>`.
.. _body-geom-fromto:
:at:`fromto`: :at-val:`real(6), optional`
@@ -3488,10 +3511,12 @@ joints and tendons have different sets of attributes, while all geoms in the com
.. _composite-geom-surfacevel:
.. _composite-geom-adhesion:
.. |body/composite/geom attrib list| replace::
:at:`type`, :at:`contype`, :at:`conaffinity`, :at:`condim`, :at:`group`, :at:`priority`, :at:`size`, :at:`material`,
:at:`rgba`, :at:`friction`, :at:`mass`, :at:`density`, :at:`solmix`, :at:`solref`, :at:`solimp`, :at:`margin`,
:at:`gap`, :at:`surfacevel`
:at:`gap`, :at:`surfacevel`, :at:`adhesion`
|body/composite/geom attrib list|
Same meaning as regular :ref:`geom <body-geom>` attributes.
@@ -4224,6 +4249,12 @@ friction can only be created with this element.
``margin`` and ``margin + gap`` are included in ``mjData.contact`` as inactive contacts but no contact forces are
generated.
.. _contact-pair-adhesion:
:at:`adhesion`: :at-val:`real, "0"`
Adhesive force of contacts generated by this pair, overriding the sum of the geoms'
:ref:`adhesion<body-geom-adhesion>` values. See there for detailed semantics.
.. _contact-exclude:
@@ -6415,7 +6446,9 @@ geckos and insects rather than an industrial vacuum gripper. In order to enable
:ref:`gap<body-geom-gap>` attribute of the body's geoms to a positive value. This creates a layer around each geom where
contacts are detected but no contact forces are generated, and the adhesive force can act across this gap. In the video
above, such inactive contacts are blue, while active contacts are orange. An adhesion actuator's length is always 0.
:at:`ctrlrange` is required and must also be nonnegative (no repulsive forces are allowed). The underlying :el:`general`
:at:`ctrlrange` is required and must also be nonnegative (no repulsive forces are allowed). For adhesion as a
*passive* property of the contacting surfaces — always on, per contact, and leaving resting penetration unaffected —
see the :ref:`geom/adhesion<body-geom-adhesion>` attribute. The underlying :el:`general`
attributes are set as follows:
=========== ======= =========== ========
@@ -9586,6 +9619,8 @@ if omitted.
.. _default-geom-surfacevel:
.. _default-geom-adhesion:
.. _default-geom-fromto:
.. _default-geom-axisangle:
@@ -9754,6 +9789,8 @@ if omitted.
.. _default-pair-margin:
.. _default-pair-adhesion:
:el-prefix:`default/` |-| **pair** |?|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^