Summary
With the documented grasping recipe (cone="elliptic" impratio="10"), a 45 g capsule pinched
between two μ=0.7 pads at a measured normal load of 12–60 N — Coulomb static capacity 20–95×
the 0.44 N gravity load — does not hang in place: it slips downward through the grip at a
steady ~50–155 µm/s (and ~1500–2300 µm/s at impratio="1" / pyramidal). The slip is pure
tangential creep (a rotation discriminator rules out rolling; the pads are joint-locked in z),
it scales ≈ linearly with 1/impratio, and noslip_iterations="10" reduces it ~110× (to
1.4 µm/s). In other words, the regularized friction model appears to have no static-friction
stick state: any constant tangential load far inside the friction cone produces a steady
drift. For grasp-and-hold scenarios this means friction-held objects sink out of grippers on
robot timescales (155 µm/s ≈ 9 mm/min at the documented recipe).
Environment
- mujoco 3.8.1 (PyPI
mujoco), numpy, Python 3.12, Linux x86_64, CPU
- Pure stock MuJoCo — no wrappers, no other dependencies
Minimal repro
Two pad boxes on damped x-slides squeeze a horizontal free capsule (r=4 mm, m=45 g) 2 mm past
first contact via position actuators; gravity pulls the capsule down with W = 0.44 N; the
capsule's z is tracked for 2 s after a 0.5 s settle:
import numpy as np
import mujoco
MJCF_TEMPLATE = """
<mujoco model="friction_vertical_leak">
<option timestep="0.002" gravity="0 0 -9.81" cone="{cone}" impratio="{impratio}"
noslip_iterations="{noslip}"/>
<worldbody>
<body name="padL" pos="-0.0125 0 0">
<joint name="jL" type="slide" axis="1 0 0" damping="100"/>
<geom name="gL" type="box" size="0.008 0.030 0.020" mass="0.2"
friction="0.7 0.005 0.0001" condim="{condim}" {solref_attr}/>
</body>
<body name="padR" pos="0.0125 0 0">
<joint name="jR" type="slide" axis="1 0 0" damping="100"/>
<geom name="gR" type="box" size="0.008 0.030 0.020" mass="0.2"
friction="0.7 0.005 0.0001" condim="{condim}" {solref_attr}/>
</body>
<body name="rod" pos="0 0 0">
<freejoint/>
<geom name="grod" type="capsule" fromto="0 -0.05 0 0 0.05 0" size="0.004" mass="0.045"
friction="0.7 0.005 0.0001" condim="{condim}" {solref_attr}/>
</body>
</worldbody>
<actuator>
<position name="aL" joint="jL" kp="20000" ctrlrange="-0.02 0.02"/>
<position name="aR" joint="jR" kp="20000" ctrlrange="-0.02 0.02"/>
</actuator>
</mujoco>
"""
SETTLE_S, MEASURE_S, SQUEEZE_M = 0.5, 2.0, 0.002
def run_case(cone="elliptic", impratio=10, condim=3, solref=None, noslip=0):
solref_attr = f'solref="{solref[0]} {solref[1]}"' if solref else ""
xml = MJCF_TEMPLATE.format(cone=cone, impratio=impratio, condim=condim,
solref_attr=solref_attr, noslip=noslip)
m = mujoco.MjModel.from_xml_string(xml)
d = mujoco.MjData(m)
d.ctrl[0] = +(0.0005 + SQUEEZE_M)
d.ctrl[1] = -(0.0005 + SQUEEZE_M)
for _ in range(int(SETTLE_S / m.opt.timestep)):
mujoco.mj_step(m, d)
z0 = float(d.qpos[2 + 2])
f6, N_tot = np.zeros(6), 0.0
for ci in range(d.ncon):
g1, g2 = d.contact.geom[ci]
names = {mujoco.mj_id2name(m, mujoco.mjtObj.mjOBJ_GEOM, int(g1)),
mujoco.mj_id2name(m, mujoco.mjtObj.mjOBJ_GEOM, int(g2))}
if "grod" in names:
mujoco.mj_contactForce(m, d, ci, f6)
N_tot += abs(float(f6[0]))
q_start = d.qpos[2 + 3:2 + 7].copy()
n_meas = int(MEASURE_S / m.opt.timestep)
for _ in range(n_meas):
mujoco.mj_step(m, d)
drop_um = (z0 - float(d.qpos[2 + 2])) * 1e6
rot = 2 * float(np.arccos(min(1.0, abs(float(np.dot(q_start, d.qpos[2 + 3:2 + 7]))))))
print(f"{cone:9} imp={impratio:<3} condim={condim} solref={solref or 'default'} "
f"noslip={noslip}: N={N_tot:5.1f} N (margin {0.7 * N_tot / 0.441:5.1f}x) "
f"drop={drop_um:7.1f} um/2s ({drop_um / MEASURE_S:7.2f} um/s) "
f"roll-equiv={rot * 0.004 * 1e6:5.1f} um")
for kw in (dict(cone="elliptic", impratio=10), dict(cone="elliptic", impratio=1),
dict(cone="elliptic", impratio=100), dict(cone="pyramidal", impratio=1),
dict(cone="elliptic", impratio=10, condim=6),
dict(cone="elliptic", impratio=10, solref=(0.002, 1)),
dict(cone="elliptic", impratio=10, noslip=10)):
run_case(**kw)
Observed (mujoco 3.8.1)
cone imp cd solref nslip | N[N] marg | drop[um/2s] um/s um/step | rot[mrad] rollequiv
elliptic 10 3 default(0.02,1) 0 | 12.4 19.7 | 310.0 154.99 0.31 | 0.47 1.9
elliptic 1 3 default(0.02,1) 0 | 12.4 19.7 | 3103.6 1551.79 3.1036 | 5.06 20.2
elliptic 100 3 default(0.02,1) 0 | 12.4 19.7 | 30.7 15.33 0.0307 | 0.11 0.4
pyramidal 1 3 default(0.02,1) 0 | 26.8 42.5 | 4602.5 2301.23 4.6025 | 6.39 25.6
elliptic 10 6 default(0.02,1) 0 | 12.4 19.7 | 307.0 153.48 0.307 | 0.35 1.4
elliptic 10 3 (0.002, 1) 0 | 59.7 94.6 | 102.6 51.32 0.1026 | 0.53 2.1
elliptic 10 3 default(0.02,1) 10 | 12.4 19.7 | 2.8 1.41 0.0028 | 0.42 1.7
(The last row: noslip_iterations=10 cuts the creep ~110×, 155 → 1.41 µm/s.)
Expected
Coulomb statics: at margins of 20–95× the load, zero steady-state slip — the capsule hangs.
Analysis (empirical characterization)
- Pure tangential creep, not rolling and not pad motion: the rod's total rotation over the
window is 0.1–6.4 mrad → a roll-equivalent displacement of 0.4–26 µm, < 1 % of the observed
drops; the pads are slide-joint-locked in z (verified zero z motion).
- Rate ∝ 1/impratio (1552 → 155 → 15.3 µm/s for impratio 1 → 10 → 100 at identical N):
consistent with the tangential regularization stiffness scaling.
condim=6 (adds rolling/torsional rows): no effect on the vertical creep (310 → 307 µm/2s) —
as expected for a non-rolling mode.
- Stiffer
solref=(0.002,1): N rises 12.4 → 59.7 N at the same squeeze; the creep improves only
~3× (155 → 51 µm/s) while the Coulomb margin rose to 95× — the leak does not close with
contact stiffness.
noslip_iterations=10: 110× reduction (155 → 1.4 µm/s) — the post-pass appears to be the
one switch that approximates a stick state.
- The behavior looks inherent to the regularized friction solution (a finite tangential-force ↔
slip-velocity mapping near the origin), not an integration artifact: the rate is steady over
the window and timestep-consistent per-step values are listed.
Why this matters
The documentation recommends cone="elliptic" with elevated impratio for grasping. At that
recipe, any friction-held object under constant gravity drifts ~9 mm/min through a firm pinch
(and faster through softer/lower-impratio contacts). For manipulation tasks that hold objects
for seconds-to-minutes (pick-and-place, cable routing, insertion), friction grasps measurably
leak even at high normal loads, which is easy to misattribute to controller or model errors.
Questions / asks (suggestion tone)
- Is this steady small-load creep the expected/intended behavior of the regularized
friction model? If so, a docs note in the grasping guidance would save users a long
diagnosis (we can draft one).
- Is
noslip_iterations the recommended remedy for grasp-and-hold (and what are its
known costs/caveats at scale)?
- Is there guidance for sizing
impratio against the expected load ratio (creep budget per
our table ≈ 1550/impratio µm/s at default solref)?
- Would a true stick state / velocity deadband option be in scope for the solver roadmap?
We are happy to contribute the repro as a test case or a documentation PR if any of these are
useful.
Summary
With the documented grasping recipe (
cone="elliptic" impratio="10"), a 45 g capsule pinchedbetween two μ=0.7 pads at a measured normal load of 12–60 N — Coulomb static capacity 20–95×
the 0.44 N gravity load — does not hang in place: it slips downward through the grip at a
steady ~50–155 µm/s (and ~1500–2300 µm/s at
impratio="1"/ pyramidal). The slip is puretangential creep (a rotation discriminator rules out rolling; the pads are joint-locked in z),
it scales ≈ linearly with
1/impratio, andnoslip_iterations="10"reduces it ~110× (to1.4 µm/s). In other words, the regularized friction model appears to have no static-friction
stick state: any constant tangential load far inside the friction cone produces a steady
drift. For grasp-and-hold scenarios this means friction-held objects sink out of grippers on
robot timescales (155 µm/s ≈ 9 mm/min at the documented recipe).
Environment
mujoco), numpy, Python 3.12, Linux x86_64, CPUMinimal repro
Two pad boxes on damped x-slides squeeze a horizontal free capsule (r=4 mm, m=45 g) 2 mm past
first contact via position actuators; gravity pulls the capsule down with W = 0.44 N; the
capsule's z is tracked for 2 s after a 0.5 s settle:
Observed (mujoco 3.8.1)
(The last row:
noslip_iterations=10cuts the creep ~110×, 155 → 1.41 µm/s.)Expected
Coulomb statics: at margins of 20–95× the load, zero steady-state slip — the capsule hangs.
Analysis (empirical characterization)
window is 0.1–6.4 mrad → a roll-equivalent displacement of 0.4–26 µm, < 1 % of the observed
drops; the pads are slide-joint-locked in z (verified zero z motion).
consistent with the tangential regularization stiffness scaling.
condim=6(adds rolling/torsional rows): no effect on the vertical creep (310 → 307 µm/2s) —as expected for a non-rolling mode.
solref=(0.002,1): N rises 12.4 → 59.7 N at the same squeeze; the creep improves only~3× (155 → 51 µm/s) while the Coulomb margin rose to 95× — the leak does not close with
contact stiffness.
noslip_iterations=10: 110× reduction (155 → 1.4 µm/s) — the post-pass appears to be theone switch that approximates a stick state.
slip-velocity mapping near the origin), not an integration artifact: the rate is steady over
the window and timestep-consistent per-step values are listed.
Why this matters
The documentation recommends
cone="elliptic"with elevatedimpratiofor grasping. At thatrecipe, any friction-held object under constant gravity drifts ~9 mm/min through a firm pinch
(and faster through softer/lower-impratio contacts). For manipulation tasks that hold objects
for seconds-to-minutes (pick-and-place, cable routing, insertion), friction grasps measurably
leak even at high normal loads, which is easy to misattribute to controller or model errors.
Questions / asks (suggestion tone)
friction model? If so, a docs note in the grasping guidance would save users a long
diagnosis (we can draft one).
noslip_iterationsthe recommended remedy for grasp-and-hold (and what are itsknown costs/caveats at scale)?
impratioagainst the expected load ratio (creep budget perour table ≈ 1550/impratio µm/s at default solref)?
We are happy to contribute the repro as a test case or a documentation PR if any of these are
useful.