Commit Graph

2552 Commits

Author SHA1 Message Date
Yuval Tassa e9197e1e9d Use logarithmic sliders in the object launcher.
Projectile parameters are positive scale factors, best adjusted
multiplicatively. Replace the input boxes with logarithmic sliders
spanning 0.1x to 10x the seeded default, which sits at the geometric
midpoint of the range; mass spans 0.1x to 100x since heavy projectiles
are a common want. Ctrl+Click still allows typing values outside the
slider range, and each slider gets a reset button restoring its
default. Adds an ImGui_SliderLog widget operating on mjtNum.

PiperOrigin-RevId: 957071873
Change-Id: Id46eae28f73308d98681ccbeb2764c949f98f9d9
2026-07-31 08:08:00 -07:00
Copybara-Service de26b05861 Merge pull request #3439 from smallquail:flex-metric-blocks
PiperOrigin-RevId: 957063540
Change-Id: I86e7b2ec92c7b2acd1f1f7140e3b8a7578c48dbf
2026-07-31 08:07:22 -07:00
Matija Kecman f1f52a92b8 Add headless EGL/OSMesa OpenGL UI context rendering for web viewer
PiperOrigin-RevId: 957060514
Change-Id: I8a0df22255c5a938d18e172c638a8c83dfe64b1b
2026-07-31 04:36:14 -07:00
Yuval Tassa 47e1b1bd1f Seed object launcher defaults from model statistics.
PiperOrigin-RevId: 957053250
Change-Id: Iba103877136c31bf1310f2b55bd8cfc5593a87ec
2026-07-31 04:14:10 -07:00
Yuval Tassa 0f90722c1a Arm the object launcher by opening its window.
The launch key binding was gated behind a checkbox because it stayed
active with the plugin window closed. Condition it on the window being
open instead: the arming state is visible, so the checkbox is redundant
and the press-proof chord can relax to plain Enter. Text fields and
dialogs are unaffected: plugin chords are not checked while ImGui
captures the keyboard, and built-in shortcuts dispatch first.

PiperOrigin-RevId: 956796864
Change-Id: I4e5b2bdcaafbcc1b1ba113dd37ef8314b3ade49e
2026-07-30 16:26:17 -07:00
Yuval Tassa 24297edfda Add close button to Studio plugin windows.
Plugin windows could only be closed from the Plugins menu. Pass the
plugin's active flag to ImGui::Begin so the window gets a close button
that writes the same persisted state as the menu toggle. Skip the
update callback while the window is collapsed.

PiperOrigin-RevId: 956795070
Change-Id: I61cb5c26e7af935b6bb296f1b89142a72b0daca1
2026-07-30 16:22:52 -07:00
Matija Kecman 4dd70d2367 MuJoCo Web Viewer: add web client containing code that runs in the browser
PiperOrigin-RevId: 956698568
Change-Id: Ia4bebcb25b488d255994018da03e9115187b890c
2026-07-30 13:17:48 -07:00
Yuval Tassa a3425c72a7 Ignore unsupported light types in the classic renderer.
The classic renderer supports only directional and spot lights, but initLights() set GL light colors for every scene light before dispatching on type, and the render passes enabled GL light slots without filtering. Since no position was ever set for unsupported types (mjLIGHT_POINT, mjLIGHT_IMAGE), OpenGL's default eye-space position turned them into phantom headlights with the model light's diffuse color, washing out the scene. A cast-shadow image light additionally triggered a full shadow pass with an unset light projection.

Filter all light setup and enable sites on a shared type predicate, so unsupported light types contribute nothing. The no-lights ambient fallback now applies when no supported lights are present.

PiperOrigin-RevId: 956696548
Change-Id: Ic29763df7f9330f21d94f14501ae2559fd460f2b
2026-07-30 13:13:42 -07:00
Yuval Tassa 98ecadcdf2 Add reset buttons to Studio sliders.
Slider rows in the joints and controls tabs could only be reset through
a hidden right-click context menu. Replace it with a visible reset
button at the right edge of each row, disabled while the value is at
its reset target so the button column doubles as a modified indicator.
Rows split the remaining width equally between slider and label, and
labels clip at the button column. Adds an ImGui_ResetButton widget.

PiperOrigin-RevId: 956627705
Change-Id: I9c178f6cd1cc806c7ffd6f531acf7f2d470d9346
2026-07-30 11:10:26 -07:00
Haroon Qureshi 58a54ef474 Move resource provider registration into a separate library.
PiperOrigin-RevId: 956506812
Change-Id: I9acde018e282171f41e0f8c756cd02b39c35dc67
2026-07-30 07:19:08 -07:00
Yuval Tassa 6c86e12567 Make the selection outline occlusion-aware in the filament renderer.
PiperOrigin-RevId: 956489408
Change-Id: I948493587eb154cac6e0fc31d5df987967405ff8
2026-07-30 06:38:18 -07:00
Yuval Tassa 60889f5e85 Add favicon to MuJoCo Live.
PiperOrigin-RevId: 956476524
Change-Id: I3f33cd09764e1236999b7d269045a2f8c2a8236e
2026-07-30 06:09:12 -07:00
Yuval Tassa 6a4a289c3e Open macOS file dialogs in the directory of the seeded path.
OpenFileDialog and SaveFileDialog hardcoded the user's Documents directory
and placed the full seed path in the name field. Studio seeds dialogs with
the current model's path, so File > Open now starts in the model's
directory with the filename pre-filled, falling back to Documents when no
path is available. Also avoids passing a potentially non-NUL-terminated
string_view to stringWithUTF8String.

PiperOrigin-RevId: 955869713
Change-Id: I7563f2cb2e39089883d5e37a3d259055c26e146c
2026-07-29 07:25:15 -07:00
Yuval Tassa 5800dfc929 Improve Studio help window with fixes, completions, and task grouping.
Fix, complete, and group Studio's help window by task.

PiperOrigin-RevId: 955869367
Change-Id: I5ae7b3661dd80a1273d8c9fecee303c361c102c3
2026-07-29 07:24:11 -07:00
Alessio 55d13aec5f Replace the flex metric factorization with a block preconditioner
Every step, the flex block of the implicit effective metric M + K was
factorized by sparse Cholesky, because K depends on the configuration. On
model/flex/bag.xml, added here, that is roughly half the step, against a
comparable share for the constraint solve it exists to accelerate.

Keep only the metric's per-vertex 3x3 diagonal blocks, prefactored. Neither
consumer needs the exact inverse: the CG constraint solver only wants a
preconditioner, and qacc_smooth can come from an iterative solve using those
blocks. They are O(n) to build and to apply, but weaker, so CG runs about twice
the iterations and qacc_smooth becomes an iteration rather than a direct solve.
Net, the bag model steps roughly twice as fast.

The preconditioner, by metric state. Inactive, meaning no flex elasticity or an
explicit integrator: M^-1, unchanged. Bending only (nefmK == 0): M^-1 plus the
exact constant bending factor from mj_setConst on the dofs it covers,
unchanged; that factor is built at model compile time and costs nothing per
step. Per-step stiffness: M^-1 plus the 3x3 blocks, where before it was a
per-step sparse Cholesky, or, when M couples across the flex block, an inner
PCG of up to 50 iterations run once per outer CG iteration.

Only models carrying per-step stretch stiffness change in wall-clock. Both
ponchos hold their timing and take slightly fewer CG iterations than before,
because the preconditioner is now symmetric: it applies M^-1 and the covered
blocks to disjoint sets of dofs, where previously the two overlapped and the
operator was not symmetric, which PCG requires.

mjd_effSolve is the accurate solve of (M + K)x = b; what used to carry that
name only preconditions and is now mjd_effPrec. Its CG guarded the division by
pAp with mjMINVAL, an absolute floor on a quantity that scales with the square
of the right-hand side, so a small b aborted the solve while the curvature was
healthy: four flex models were quietly left short of tolerance. For an SPD
metric the guard is positivity, and with that the same solves converge. The qacc_smooth call site in
mj_fwdAcceleration is textually unchanged but now reaches the iterative solve,
which converges on opt.tolerance rather than a hardcoded threshold, floored in
mjUSESINGLE builds where the squared target is unreachable in float. Reaching
the iteration cap names the ill-conditioned flex stiffness and then reports it
through mjWARN_INERTIA, rather than returning an under-converged result.
Covered dofs are located by walking the covered rows of the stiffness matrix,
as they need not be 3-aligned from dof 0: any joint declared before a flexcomp
shifts them.

mjData.efm_L_rownnz, efm_L_rowadr and efm_L_colind described the sparsity of
the deleted factorization and are removed: left NULL with nonzero mjxmacro
extents they made the Python bindings hand back uninitialized arrays.
efm_active loses the value 2 for the same reason, nothing selects a solve path
on preconditioner exactness any more. Both are recorded under breaking changes.

model/flex/bag.xml is added because no shipped model carried per-step stretch
stiffness. The ponchos are bending-only and trampoline.xml uses an explicit
integrator, so the metric never activates there. It is excluded from
WriteReadCompareTest: stretch stiffness amplifies rest geometry that XML rounds
on save.
2026-07-29 14:36:15 +01:00
Copybara-Service d400914e97 Merge pull request #3437 from smallquail:flex-rotation-fix
PiperOrigin-RevId: 955127380
Change-Id: Ie31ab56f7d64dd1a2266828c0fcd3683b55768a5
2026-07-28 02:17:23 -07:00
Alessio d895888da4 Use the inlined mji_ 3x3 helpers throughout engine_derivative.c
Convert the four remaining mju_mulMat{,T}{Vec,Mat}3 call sites in this
file to their inlined mji_ equivalents, so the file is consistent after
the review change to the stretch paths. Aliasing is unaffected: the
inlined variants mark the result restrict, and every call already
required a distinct result (the public versions overwrite res while
reading vec).
2026-07-28 09:14:26 +01:00
Alessio a6743d8e0d Address review: blank line, and use the inlined mji_ 3x3 helpers
Per review on #3437: add the missing blank line above the new comment
block, and use the internal inlined mji_mulMat{,T}{Vec,Mat}3 helpers
rather than the public mju_ ones, matching fe9dc584. Six call sites in
the two stretch paths; pre-existing mju_ calls elsewhere in the file are
left alone.
2026-07-28 09:09:38 +01:00
Michael Moss 1db801460b Update MuJoCo version to 3.11.1 following the 3.11.0 release
PiperOrigin-RevId: 954833728
Change-Id: I1c006cdd72072c6821d7b3c28d8ac320de19b8c5
2026-07-27 14:35:26 -07:00
Alessio 55b43414dd Fix stretch stiffness basis for flexes in rotated parent bodies
The implicit effective metric assembles the stretch stiffness from
world-space edge vectors, but a flex vertex body's slide dofs are
expressed in its parent body's frame. When that frame is rotated the
assembled operator is therefore not the Jacobian of the passive stretch
force, which mj_flexPassiveStretch already maps into the dof frame with
xmat^T. The metric is then inconsistent with the force it linearizes:
implicit integration loses its stability guarantee, and models that the
same flex handles comfortably in an unrotated frame diverge.

Apply the matching change of basis in both places that build or apply the
stretch stiffness: mjd_flexStretch_mul rotates the input dof vector into
world and the scattered result back, and mjd_flexStiff_assemble sandwiches
each 3x3 block as R_bi^T * blk * R_bj. Both are no-ops when the parent is
unrotated. Bending needs no change: its blocks are isotropic, and
R^T (q I) R = q I.

This completes the fix in fe9dc584, which covered the passive force paths
and the interp (trilinear) derivative but not the standard stretch one.

On a mesh flex inside a body with a 90-degree rotation, the metric's
directional agreement with the force Jacobian goes from cos = 0.57 to
cos = 1.0, and a hanging sheet that previously reached 176% strain
settles at 0.87%.
2026-07-27 20:08:31 +01:00
Matija Kecman e23b504201 Change how ImGui clip rect scaling and scissor computation works in imgui_bridge to fix flickering and clipping errors in the web viewer
Avoid mutating ImGui draw lists in place by scaling clip rects locally during scissor computation instead of calling ScaleClipRects. This prevents clip rects from growing exponentially on persistent draw lists, such as streamed remote UI. Additionally, clamp the scaled clip rects to the viewport boundaries to prevent Filament's scissor test from rejecting out-of-bounds rects, while avoiding resetting to full-window scissors which would disable clipping.

The draw geometry is now immutable in the Update function (ImGui texture state is still mutated).

PiperOrigin-RevId: 954277141
Change-Id: Ifdf6866bb4eabaca44b020ea40acc246428b4f0b
2026-07-26 13:35:03 -07:00
Michael Moss 59d84a714d Update dependencies ahead of the 3.11.0 release (retry).
Also updates MuJoCo files needed to address changes in Filament.
- "build with clang on windows" patch to sync context lines, remove some
  upstream conflicts, disable Clang thread-safety attribute errors, and
  allow running on MSYS2.
- Skip building Filament samples.
- Add missing <string_view> to material_manager.cc.
2026-07-24 15:27:31 +00:00
Sam Haves dd4d0585ee Fix missing timer end calls on early returns in collision and actuation
PiperOrigin-RevId: 953348565
Change-Id: I64b563e29b2d620df46d50d12dde9215885f41d6
2026-07-24 07:05:45 -07:00
Alessio Quaglino fe9dc58477 Fix flexcomp instability when parent body has non-identity quaternion
Fast path in mj_flexPassiveInterp, mj_flexPassiveBendInterp, and
mj_flexPassiveStretch assumed body slide joints are world-aligned
(J = I). When parent body has a non-identity quaternion, joint axes
are rotated (J = R_body), causing wrong force mapping and instability
(NaN/Inf in QACC).

Fix: project world-frame forces onto body local frame via
mju_mulMatTVec3(R_body^T, force) before adding to qfrc_spring/damper.
Also fix the derivative paths:
- mjd_flexInterp_kernel fast path: R^T * K_rot * R * vec
- mjd_flexStiff_assemble (CSR): R_bi^T * K_rot_block * R_bj

The CSR-assembled stiffness matrix is the actual path used by the
implicit CG solver (mj_flexCG gate). The test uses solver="CG" to
activate this path; without it, flex stiffness is integrated
explicitly and no derivative fix can help.

Ported from GitHub PR https://github.com/google-deepmind/mujoco/pull/3379
Original author: Devansh (https://github.com/devansh0703)
Fixes https://github.com/google-deepmind/mujoco/issues/3364

PiperOrigin-RevId: 952789284
Change-Id: If924f7160dd16c0cc88170d80e6e605da0fe2e04
2026-07-23 09:02:21 -07:00
Haroon Qureshi e1f6953efa Remove ModelObjects as a dependency on ModelDecorations.
Also allow users to Clear() the decorations explicitly.

PiperOrigin-RevId: 952152025
Change-Id: Ieb21d59986b127b4646c8c5721d33920d14dff85
2026-07-22 09:01:26 -07:00
Sam Haves 1a5af23558 Add <stem>/model.xml search path to mjz_decoder.
PiperOrigin-RevId: 952128127
Change-Id: I8a514297d84026a6028b2416e43df9b5a2a92bbb
2026-07-22 08:11:56 -07:00
Haroon Qureshi b6ab11dc6b Rename LightManager to ModelLights and RenderableManager to ModelRenderables.
This better reflects the purpose of these classes.

PiperOrigin-RevId: 952123609
Change-Id: Ib14c54c3d9b137258ebc706590aca3b2e80015fe
2026-07-22 08:03:32 -07:00
Haroon Qureshi ed7ba6027f Move SceneDecorator to support module.
Also rename it to ModelDecorations.

PiperOrigin-RevId: 952088857
Change-Id: I476d616ec950962f781614e39b75d3d59fdcfcd1
2026-07-22 06:48:33 -07:00
Haroon Qureshi ba9a65031b Allow mesh data to be reuploaded without having to recreate the mesh.
Splits mjrfMeshData into config+data parts.

PiperOrigin-RevId: 952042545
Change-Id: I19a572a0f591fa0d33bbc2c32b974efc075310f4
2026-07-22 04:56:30 -07:00
Google DeepMind d3166cb630 Fix cylinder bias stack overrun in XML parsing
PiperOrigin-RevId: 952016771
Change-Id: I49657d41ad96a6bd1f7f9d5e6b6491c5a229d244
2026-07-22 03:53:45 -07:00
Matija Kecman 0b1ed5b356 platform/ux: general C++ platform UX updates & spec adjustments.
* Enhances ImGui dialogs to support keyboard shortcuts (Enter/Escape) and filters.
* Adjusts GUI layouts for simulation speed and compiler settings.
* Exposes additional model fields in the XML spec generator.

PiperOrigin-RevId: 951988061
Change-Id: I4927c12a8882ba4e91e6098355ec2f5db35c2747
2026-07-22 02:46:30 -07:00
Copybara-Service 91bb075108 Merge pull request #3250 from gholmes829:fix/accumulate-inertia-com-frame-order
PiperOrigin-RevId: 951758696
Change-Id: I99f3502b15b84e2fffc58f4b608844148479ca3e
2026-07-21 16:21:08 -07:00
Yuval Tassa 259e6c4dc6 Fix MSVC ASan compilation by avoiding GCC/Clang specific stack instrumentation
PiperOrigin-RevId: 951656966
Change-Id: I51294e6a95c39f4037e8feb2aee45e69cb51beb0
2026-07-21 13:09:23 -07:00
gholmes829 0e1e0c7f96 Fix COM frame composition in mjCBody::AccumulateInertia 2026-07-21 15:02:14 -05:00
Yuval Tassa 072e963fa0 Add SO3 transmission and native orientation actuator.
https://youtu.be/17XpwnqyCXs

New transmission type mjTRN_SO3: a relative orientation, targeting a ball
joint or a site+refsite pair. It is the first transmission with more than
one force output: its length is the norm of the expmap vector of the
relative rotation and its moment axes are the 3 rows of the
relative rotational Jacobian, without projecting onto per-actuator gears.

New force law mjGAIN_SO3/mjBIAS_SO3: a geodesic PD servo, force =
kp * log(q_current^-1 * q_target) - kv * velocity, exact for arbitrary axis
combinations with a unique equilibrium at every commanded orientation.
Error, moment rows and velocity all live in the child frame (joint or
site): the right-difference error is the gradient of the geodesic
potential in that frame. The parent-frame (left) error is not: driving
child-frame torques with it pumps energy at large angles, settling into
steady-spinning limit cycles (the SO3LargeAngleConvergence test). The
integrator variant stores the 3D orientation setpoint in act (actnum = 3,
re-anchored to a bounded representative at integration time). Exposed in
MJCF as <orientation joint=|site=+refsite= kp kv|dampratio>, or via
<general gaintype="so3" biastype="so3">.

The setpoint input has two charts: an expmap target (3 controls, default)
or a quaternion target (4 controls) -- <orientation input="quat">, the
first actuator with different input and output widths. The signature is
recorded in a new per-actuator field actuator_ctrlspec (mjtCtrlChart),
whose meaning is scoped by the gain type the way gain/bias parameters are;
ctrlnum is derived from it at compile time and remains the layout
authority. An explicit field rather than width inference or a prm slot:
width-as-chart cannot express same-width signatures (upcoming servo input
subsets), and prm slots are the input_mode pattern this stack retires.
The force law normalizes the commanded quaternion, making it scale- and
antipodally-invariant. The all-zero ctrl still maps to the identity via
mju_normalize4, but it is a degenerate point (a nudge of any component
commands a half-turn), so quat inputs reset to the identity quaternion:
new mj_resetCtrl sets neutral ctrl values (zero, except qw = 1), called
by mj_resetData and the viewers' Clear All. The quat chart is
restricted to dyntype 'none': integrating a quaternion setpoint linearly
is not meaningful on the manifold. New mjsActuator.ctrlspec field carries
the signature through the spec and XML round-trip.

Actuator sensors (actuatorpos/vel/frc) now report one value per force
output; dim = 3 on an SO3 actuator.

As the first actuator with nu != nactuator, this commit also makes the
viewers multi-input aware: the control sliders in simulate and studio,
which indexed per-actuator arrays by control index (out of bounds on
this model class), are generated per control and labeled with the
actuator name plus an input suffix ("orient/qw"), via the new
introspection helper mj_actuatorInputName -- the single source of truth
for input names, extended by each new multi-input type (quaternion
components are w-first: qw, qx, qy, qz). Slider ranges now honor a
defined ctrlrange even when ctrllimited is false: range is the UI hint,
limited is the clamp -- wrapped and expmap setpoints are unbounded but
still want finite sliders, while quat components are truly bounded.

The rotational demo model is orientation.xml under
test/engine/testdata/actuation/, upgraded to a three-way contrast:
per-axis wrapped servos vs an expmap-commanded vs a quat-commanded
orientation actuator, on identical checker-textured boxes. It is loaded
by the mixed-axis contrast and input-name tests, and doubles as the
viewer test model (slider groups of 3 independent, 3 grouped, 4 grouped).

PiperOrigin-RevId: 951607063
Change-Id: If235dba8e2f2ca72672e7c62531a27e967c6a373
2026-07-21 11:36:13 -07:00
Haroon Qureshi a8545ac7cc Improve flex rendering.
RenderableManager is responsible for rendering the "skinned" flexes
which represent the correct "final" look of a flex. This now includes
1D flexes which are rendered as a sequence of capsules (similar to
tendons).

SceneDecorator is responsible for rendering the debug (unskinned)
versions of flexes. This includes the vertices (small spheres for each
vertex), edges (thin cynlinders for each edge), and faces (triangles
for each face, including sublayers).

PiperOrigin-RevId: 951595046
Change-Id: Iebc6fd7a747a602813b6457333bd9fa5915e28d3
2026-07-21 11:15:37 -07:00
Copybara-Service 7bfa10e1e2 Merge pull request #3354 from Nas01010101:fix/ktx-classic-renderer-skip
PiperOrigin-RevId: 951520219
Change-Id: Ib6a1a8c553140e2e6c99055a579facf51e0d7f5a
2026-07-21 09:01:02 -07:00
Yuval Tassa 426cb5481d Fix sparse-path rotational Jacobian misalignment in mj_jacSum
PiperOrigin-RevId: 951341459
Change-Id: I18bc27765b3147a5eb520e3026317e9a5a2dfc30
2026-07-21 02:02:12 -07:00
Copybara-Service a1f38c8e6e Merge pull request #3396 from teerthsharma:topo/linear-island-scratch
PiperOrigin-RevId: 951110709
Change-Id: I0c9c96365a5667172c1d676026ab797b7f8e8137
2026-07-20 16:16:35 -07:00
teerthsharma 7ae4f22693 Restore flex island invariants in comments
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:43 +05:30
teerthsharma cdda847191 Restore static-constraint island diagnostic
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:43 +05:30
teerthsharma 8d9f230514 Export disjoint-set island helpers directly
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:42 +05:30
teerthsharma 5d91d878c2 Benchmark and expose disjoint-set islands
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:42 +05:30
teerthsharma ba2782140f Revert unvalidated island topology cache
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:42 +05:30
teerthsharma bc32db7f25 Cache island topology data
Store island topology in `mjData` so repeated island solves can reuse stable connect/weld equality partitions. Add cache invalidation checks for active equality changes and cover the fast path with an island regression test.

Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:42 +05:30
teerthsharma 03203e2f32 Update engine_island.c
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:41 +05:30
teerthsharma 52ddcbc81a Build native islands directly from constraint incidence
Signed-off-by: teerthsharma <teerths57@gmail.com>
2026-07-20 22:27:41 +05:30
Copybara-Service 5ea4c3a58c Merge pull request #3406 from devshahofficial:agent/pr3157-attach-mjcwrap
PiperOrigin-RevId: 950890116
Change-Id: I95331186f166e84b94c3fcac555c9d446a421010
2026-07-20 09:39:43 -07:00
Yuval Tassa a264d0bc8b 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
2026-07-20 08:35:45 -07:00
Michael Moss b942c9f922 Update MuJoCo version to 3.11.0 in preparation for breaking changes release.
PiperOrigin-RevId: 950824721
Change-Id: Icc06b10ea69f5dd84e100eb75233f1598c2cbf88
2026-07-20 07:26:25 -07:00