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:
committed by
Copybara-Service
parent
b942c9f922
commit
a264d0bc8b
@@ -0,0 +1,54 @@
|
||||
<mujoco model="Magnetic fridge door">
|
||||
<!-- The two dark strips are magnets, modeled with adhesion: within the gap band
|
||||
(the magnet's range) they attract with the summed adhesion of the pair, so a
|
||||
nearly-closed door snaps shut on its own and stays latched; pulling harder
|
||||
than the pull-off force pops it open cleanly. Drag the door with Ctrl+drag
|
||||
after double-clicking it. -->
|
||||
|
||||
<option cone="elliptic"/>
|
||||
|
||||
<statistic center="0 0 .4" extent="1.4" meansize="0.03"/>
|
||||
|
||||
<visual>
|
||||
<headlight diffuse=".8 .8 .8" ambient=".3 .3 .3"/>
|
||||
<map stiffness="30"/>
|
||||
</visual>
|
||||
|
||||
<asset>
|
||||
<texture type="skybox" builtin="gradient" rgb1=".5 .6 .7" rgb2=".9 .9 .95" width="32" height="512"/>
|
||||
<material name="body" rgba=".92 .92 .94 1" reflectance=".3"/>
|
||||
<material name="inside" rgba=".8 .8 .82 1"/>
|
||||
<material name="magnet" rgba=".2 .2 .22 1"/>
|
||||
</asset>
|
||||
|
||||
<worldbody>
|
||||
<light pos="1.5 -.5 2" dir="-.6 .2 -.75" diffuse=".7 .7 .7" intensity="200000"/>
|
||||
<geom name="floor" type="plane" size="2 2 .01" rgba=".7 .75 .7 1"/>
|
||||
|
||||
<!-- cabinet: interior x [-.35 0], y [-.25 .25], z [0 .8] -->
|
||||
<geom name="left" type="box" size=".175 .015 .4" pos="-.175 -.235 .4" material="body"/>
|
||||
<geom name="right" type="box" size=".175 .015 .4" pos="-.175 .235 .4" material="body"/>
|
||||
<geom name="top" type="box" size=".175 .25 .015" pos="-.175 0 .785" material="body"/>
|
||||
<geom name="bottom" type="box" size=".175 .25 .015" pos="-.175 0 .03" material="body"/>
|
||||
<geom name="back" type="box" size=".015 .25 .4" pos="-.335 0 .4" material="body"/>
|
||||
<geom name="shelf" type="box" size=".155 .21 .008" pos="-.18 0 .4" material="inside"/>
|
||||
|
||||
<!-- frame magnet strip, just inside the right wall's front edge -->
|
||||
<geom name="magnet1" type="box" size=".005 .01 .3" pos="-.015 .19 .4" material="magnet" adhesion="1.5" gap=".003"/>
|
||||
|
||||
<body name="door" pos="0 -.25 .42">
|
||||
<joint name="hinge" pos="0 0 0" axis="0 0 -1" range="0 135" damping=".08" stiffness="0.05"/>
|
||||
<geom name="hinge" type="cylinder" size=".007" fromto="0 0 -.37 0 0 .37" rgba=".4 .4 .42 1" contype="0" conaffinity="0"/>
|
||||
<geom name="panel" type="box" size=".015 .24 .37" pos=".015 .25 0" material="body" mass="1.5"/>
|
||||
<body name="handle">
|
||||
<geom name="handle" type="capsule" size=".012" fromto=".06 .46 -.12 .06 .46 .12" rgba=".4 .4 .42 1" mass=".1"/>
|
||||
</body>
|
||||
<geom name="magnet2" type="box" size=".005 .01 .3" pos="-.005 .44 0" material="magnet" adhesion="1.5" gap=".003" mass=".05"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
|
||||
<keyframe>
|
||||
<key name="open" qpos="1.6"/>
|
||||
<key name="ajar" qpos=".006"/>
|
||||
</keyframe>
|
||||
</mujoco>
|
||||
@@ -0,0 +1,115 @@
|
||||
<mujoco model="Sand castles">
|
||||
<!-- Adhesion is Mohr-Coulomb cohesion: the shear strength of a contact is
|
||||
mu*(N + adhesion), nonzero even without confining pressure, and contacts
|
||||
resist tension up to the summed adhesion of the two geoms. Three identical
|
||||
cubes of grains differ only in adhesion: dry sand avalanches to its angle
|
||||
of repose, damp sand slumps but holds a mound, wet sand stands as a castle.
|
||||
The small gap is the moisture film: grains within it form tensile bridges. -->
|
||||
|
||||
<option solver="CG" timestep="4e-3"/>
|
||||
|
||||
<statistic center="0 0 .15" extent="1.2"/>
|
||||
|
||||
<visual>
|
||||
<headlight diffuse=".8 .8 .8" ambient=".3 .3 .3"/>
|
||||
<quality shadowsize="8192"/>
|
||||
</visual>
|
||||
|
||||
<asset>
|
||||
<texture type="skybox" builtin="gradient" rgb1=".4 .6 .8" rgb2=".9 .9 .95" width="32" height="512"/>
|
||||
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
|
||||
<material name="grid" texture="grid" texrepeat="6 3" reflectance=".2"/>
|
||||
</asset>
|
||||
|
||||
<default>
|
||||
<geom type="sphere" size=".01" friction="1 .005 .005" solref=".01 1"/>
|
||||
<default class="dry">
|
||||
<geom rgba=".87 .78 .55 1" adhesion=".002" gap=".001"/>
|
||||
</default>
|
||||
<default class="damp">
|
||||
<geom rgba=".72 .58 .38 1" adhesion=".02" gap=".001"/>
|
||||
</default>
|
||||
<default class="wet">
|
||||
<geom rgba=".5 .38 .25 1" adhesion=".05" gap=".001"/>
|
||||
</default>
|
||||
</default>
|
||||
|
||||
<worldbody>
|
||||
<light pos=".5 -1 1.5" dir="-.3 .6 -.8" diffuse=".7 .7 .7"/>
|
||||
<geom name="floor" type="plane" size="1.2 .6 .01" material="grid"/>
|
||||
<geom name="rail-x" type="plane" size=".6 .05 .01" pos="-1.2 0 .05" xyaxes="0 1 0 0 0 1" rgba=".5 .5 .5 .15"/>
|
||||
<geom name="rail+x" type="plane" size=".6 .05 .01" pos="1.2 0 .05" xyaxes="0 -1 0 0 0 1" rgba=".5 .5 .5 .15"/>
|
||||
<geom name="rail-y" type="plane" size="1.2 .05 .01" pos="0 -.6 .05" xyaxes="-1 0 0 0 0 1" rgba=".5 .5 .5 .15"/>
|
||||
<geom name="rail+y" type="plane" size="1.2 .05 .01" pos="0 .6 .05" xyaxes="1 0 0 0 0 1" rgba=".5 .5 .5 .15"/>
|
||||
|
||||
<body name="ramp1" mocap="true" pos="-.4 0 .02" euler="0 18 0">
|
||||
<geom type="box" size=".1 .12 .06" rgba=".35 .42 .28 1"/>
|
||||
</body>
|
||||
<body name="ramp2" mocap="true" pos="0 0 .02" euler="0 18 0">
|
||||
<geom type="box" size=".1 .12 .06" rgba=".35 .42 .28 1"/>
|
||||
</body>
|
||||
<body name="ramp3" mocap="true" pos=".4 0 .02" euler="0 18 0">
|
||||
<geom type="box" size=".1 .12 .06" rgba=".35 .42 .28 1"/>
|
||||
</body>
|
||||
|
||||
<site name="adhesion = 0.002" size="1e-5" pos="-.45 0 .4"/>
|
||||
<replicate count="3" offset="0 0 .02828">
|
||||
<replicate count="6" offset=".02 0 0">
|
||||
<replicate count="6" offset="0 .02 0">
|
||||
<body name="a" pos="-0.45 -.05 .29" childclass="dry">
|
||||
<freejoint/>
|
||||
<geom/>
|
||||
</body>
|
||||
</replicate>
|
||||
</replicate>
|
||||
<replicate count="5" offset=".02 0 0">
|
||||
<replicate count="5" offset="0 .02 0">
|
||||
<body name="a2" pos="-0.44 -.04 .30414" childclass="dry">
|
||||
<freejoint/>
|
||||
<geom/>
|
||||
</body>
|
||||
</replicate>
|
||||
</replicate>
|
||||
</replicate>
|
||||
|
||||
<site name="adhesion = 0.02" size="1e-5" pos="-.05 0 .4"/>
|
||||
<replicate count="3" offset="0 0 .02828">
|
||||
<replicate count="6" offset=".02 0 0">
|
||||
<replicate count="6" offset="0 .02 0">
|
||||
<body name="b" pos="-0.05 -.05 .29" childclass="damp">
|
||||
<freejoint/>
|
||||
<geom/>
|
||||
</body>
|
||||
</replicate>
|
||||
</replicate>
|
||||
<replicate count="5" offset=".02 0 0">
|
||||
<replicate count="5" offset="0 .02 0">
|
||||
<body name="b2" pos="-0.04 -.04 .30414" childclass="damp">
|
||||
<freejoint/>
|
||||
<geom/>
|
||||
</body>
|
||||
</replicate>
|
||||
</replicate>
|
||||
</replicate>
|
||||
|
||||
<site name="adhesion = 0.05" size="1e-5" pos=".35 0 .4"/>
|
||||
<replicate count="3" offset="0 0 .02828">
|
||||
<replicate count="6" offset=".02 0 0">
|
||||
<replicate count="6" offset="0 .02 0">
|
||||
<body name="c" pos="0.35 -.05 .29" childclass="wet">
|
||||
<freejoint/>
|
||||
<geom/>
|
||||
</body>
|
||||
</replicate>
|
||||
</replicate>
|
||||
<replicate count="5" offset=".02 0 0">
|
||||
<replicate count="5" offset="0 .02 0">
|
||||
<body name="c2" pos="0.36 -.04 .30414" childclass="wet">
|
||||
<freejoint/>
|
||||
<geom/>
|
||||
</body>
|
||||
</replicate>
|
||||
</replicate>
|
||||
</replicate>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
Reference in New Issue
Block a user