Skip to content

Commit ec94bb4

Browse files
yuvaltassacopybara-github
authored andcommitted
Make constraint island discovery on by default.
Also fix latent bug in mjData serialization. PiperOrigin-RevId: 799505349 Change-Id: I299e7cc8133fa2ec0b339a7ff3d02543e06778b1
1 parent 4cf5c37 commit ec94bb4

File tree

27 files changed

+150
-84
lines changed

27 files changed

+150
-84
lines changed

doc/XMLreference.rst

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,14 @@ from its default.
587587
This flag enables the native convex collision detection pipeline instead of using the
588588
`libccd library <https://github.com/danfis/libccd>`__, see :ref:`convex collisions<coCCD>` for more details.
589589

590+
.. _option-flag-island:
591+
592+
:at:`island`: :at-val:`[disable, enable], "enable"`
593+
This flag enables discovery and construction of constraint islands: disjoint sets of constraints and
594+
degrees-of-freedom that do not interact and can be solved independently. Islanding is not yet supported by the PGS
595+
solver. See :ref:`soIsland` for more details. The :ref:`mjVIS_ISLAND <mjtVisFlag>` enables
596+
`island visualization <https://youtu.be/Vc1tq0fFvQA>`__.
597+
590598
.. _option-flag-eulerdamp:
591599

592600
:at:`eulerdamp`: :at-val:`[disable, enable], "enable"`
@@ -647,14 +655,6 @@ from its default.
647655
to instabilities that typically manifest as sliding or wobbling. The implementation of this feature depends on the
648656
selected convex collision pipeline, see :ref:`convex collisions<coCCD>` for more details.
649657

650-
.. _option-flag-island:
651-
652-
:at:`island`: :at-val:`[disable, enable], "disable"`
653-
This flag enables discovery of constraint islands: disjoint sets of constraints and
654-
degrees-of-freedom that do not interact. The flag currently has no effect on the physics pipeline, but enabling it
655-
allows for `island visualization <https://youtu.be/Vc1tq0fFvQA>`__.
656-
In a future release, the constraint solver will exploit the disjoint nature of constraint islands.
657-
658658
.. _compiler:
659659

660660
**compiler** (*)

doc/XMLschema.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@
3737
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
3838
| | | | :ref:`sensor<option-flag-sensor>` | :ref:`midphase<option-flag-midphase>` | :ref:`eulerdamp<option-flag-eulerdamp>` | :ref:`autoreset<option-flag-autoreset>` | |
3939
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
40-
| | | | :ref:`override<option-flag-override>` | :ref:`energy<option-flag-energy>` | :ref:`fwdinv<option-flag-fwdinv>` | :ref:`invdiscrete<option-flag-invdiscrete>` | |
40+
| | | | :ref:`nativeccd<option-flag-nativeccd>` | :ref:`island<option-flag-island>` | :ref:`override<option-flag-override>` | :ref:`energy<option-flag-energy>` | |
4141
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
42-
| | | | :ref:`multiccd<option-flag-multiccd>` | :ref:`island<option-flag-island>` | :ref:`nativeccd<option-flag-nativeccd>` | | |
42+
| | | | :ref:`fwdinv<option-flag-fwdinv>` | :ref:`invdiscrete<option-flag-invdiscrete>` | :ref:`multiccd<option-flag-multiccd>` | | |
4343
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
4444
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
4545
| mujoco |br| |L| | | .. table:: |

doc/changelog.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,16 @@ Upcoming version (not yet released)
77

88
General
99
^^^^^^^
10+
- Constraint island discovery and construction, previously an experimental feature, is now :ref:`documented<soIsland>`
11+
and promoted to default; disable it with :ref:`option/flag/island <option-flag-island>`. We expect islanding to be
12+
a strict improvement over the monolithic constraint solver, please let us know if you experience any issues.
13+
1014
.. admonition:: Breaking API changes
1115
:class: attention
1216

17+
- The promotion of islanding to default involved removing the enable flag ``mjENBL_ISLAND`` and
18+
converting it to a disable flag :ref:`mjDSBL_ISLAND <mjtDisableBit>`.
19+
1320
- The update of ``mjData.qacc_warmstart`` was moved from the end of the solver call (:ref:`mj_fwdConstraint`) to the
1421
end of :ref:`mj_step`, and is now updated with all other state variables. This change makes :ref:`mj_forward`
1522
fully idempotent.
@@ -43,6 +50,11 @@ MJX
4350

4451
- ``ten_length`` was moved from ``mjx.Data._impl.ten_length`` to a public field ``mjx.Data.ten_length``.
4552

53+
Bug fixes
54+
^^^^^^^^^
55+
- Fixed a latent bug where MjData objects were not serialized correctly by the Python bindings when islanding was
56+
enabled.
57+
4658

4759
Version 3.3.5 (August 8, 2025)
4860
------------------------------

doc/computation/index.rst

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,15 +1362,45 @@ representations of the constraint Jacobian and related matrices.
13621362
axes. The right panel illustrates our solution to this problem. We still update one contact at a time, but within a
13631363
contact we update along non-orthogonal axes adapted to the constraint surface, as follows. First, we optimize the
13641364
quadratic cost along the ray from the tip of the cone through the current solution. Then we slice the cone with a
1365-
hyperplane passing through the current solution and orthogonal to the contact normal. This yields an ellipsoid -which
1366-
can be up to 5-dimensional given our contact model. Now we optimize the quadratic cost within this ellipsoid. This is
1367-
an instance of quadratically constrained quadratic programming (QCQP). Since there is only one scalar constraint
1365+
hyperplane passing through the current solution and orthogonal to the contact normal. This yields an ellipsoid which
1366+
can be up to 5-dimensional, given our contact model. Now we optimize the quadratic cost within this ellipsoid. This
1367+
is an instance of quadratically constrained quadratic programming (QCQP). Since there is only one scalar constraint
13681368
(however nonlinear it may be), the dual is a scalar optimization problem over the unknown Lagrange multiplier. We
13691369
solve this problem with Newton's method applied until convergence -- which in practice takes less than 10 iterations,
13701370
and involves small matrices. Overall this algorithm has similar behavior to PGS for pyramidal cones, but it can
13711371
handle elliptic cones without approximating them. It does more work per contact, however the contact dimensionality
13721372
is smaller, and these two factors roughly balance each other.
13731373

1374+
.. _soIsland:
1375+
1376+
Constraint islands
1377+
~~~~~~~~~~~~~~~~~~
1378+
1379+
.. image:: ../images/computation/island.svg
1380+
:width: 58%
1381+
:align: right
1382+
1383+
Consider the abstract graph defined by degrees of freedom (dofs) and constraints. A vertex is all the dofs in a single
1384+
kinematic subtree; an edge is a constraint (a contact or equality) between two bodies belonging to different subtrees. A
1385+
*constraint island* is a disjoint sub-graph which can be solved for independently, because constraint forces cannot
1386+
propagate between islands. Constraint island discovery and construction ("islanding") invloves finding the disjoint
1387+
subgraphs and reordering both the dofs and constraints to make them memory-contiguous. This amounts to a
1388+
block-diagonalization of the constraint Jacobian :math:`J`, as illustrated in the figure. On the left is the monolithic
1389+
Jacobian of size :math:`\nc \times \nv`, where we use the :ref:`corresponding <Framework>` size names from MuJoCo's data
1390+
structures ``mjData.nefc`` and ``mjModel.nv``. On the right is the block-diagonalized Jacobian with 3 islands that can
1391+
be solved indepenently. Note that islanding also identifies unconstrained dofs, so ``mjData.nidof``, the total number of
1392+
dofs in all islands, might be smaller than ``mjModel.nv``. While islanding is not free (see implementation in
1393+
`engine_island.c <https://github.com/google-deepmind/mujoco/blob/main/src/engine/engine_island.c>`__), it is worth the
1394+
effort:
1395+
1396+
- Different islands require different numbers of iterations to converge, and a monolithic solve would run for the
1397+
number required by the slowest island.
1398+
- Unconstrained dofs are completely untouched by the solver, which otherwise needs to discover that they are unaffected.
1399+
- Solving separate islands can be multi-threaded.
1400+
1401+
Islanding is not yet supported by the PGS solver.
1402+
1403+
13741404
.. _soParameters:
13751405

13761406
Parameters
@@ -1694,7 +1724,8 @@ The stages below compute quantities that depend on the generalized positions ``m
16941724
7. Compute the sparse factorization of the joint-space inertia matrix: :ref:`mj_factorM`
16951725
8. Construct the list of active contacts. This includes both broad-phase and near-phase collision detection:
16961726
:ref:`mj_collision`
1697-
9. Construct the constraint Jacobian and compute the constraint residuals: :ref:`mj_makeConstraint`
1727+
9. Construct the constraint Jacobian, compute the constraint residuals, construct islands: :ref:`mj_makeConstraint`,
1728+
``mj_island`` (not yet exposed in the API)
16981729
10. Compute the actuator lengths and moment arms: :ref:`mj_transmission`
16991730
11. Compute the matrices and vectors needed by the constraint solvers: :ref:`mj_projectConstraint`
17001731
12. Compute sensor data that only depends on position, and the potential energy if enabled: :ref:`mj_sensorPos`,

doc/images/computation/island.svg

Lines changed: 1 addition & 0 deletions
Loading

doc/includes/references.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,9 @@ typedef enum mjtDisableBit_ { // disable default feature bitflags
464464
mjDSBL_EULERDAMP = 1<<14, // implicit integration of joint damping in Euler integrator
465465
mjDSBL_AUTORESET = 1<<15, // automatic reset when numerical issues are detected
466466
mjDSBL_NATIVECCD = 1<<16, // native convex collision detection
467+
mjDSBL_ISLAND = 1<<17, // constraint island discovery
467468

468-
mjNDISABLE = 17 // number of disable flags
469+
mjNDISABLE = 18 // number of disable flags
469470
} mjtDisableBit;
470471
typedef enum mjtEnableBit_ { // enable optional feature bitflags
471472
mjENBL_OVERRIDE = 1<<0, // override contact parameters
@@ -474,9 +475,8 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
474475
mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics
475476
// experimental features:
476477
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
477-
mjENBL_ISLAND = 1<<5, // constraint island discovery
478478

479-
mjNENABLE = 6 // number of enable flags
479+
mjNENABLE = 5 // number of enable flags
480480
} mjtEnableBit;
481481
typedef enum mjtJoint_ { // type of degree of freedom
482482
mjJNT_FREE = 0, // global position and orientation (quat) (7)

include/mujoco/mjmodel.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ typedef enum mjtDisableBit_ { // disable default feature bitflags
6666
mjDSBL_EULERDAMP = 1<<14, // implicit integration of joint damping in Euler integrator
6767
mjDSBL_AUTORESET = 1<<15, // automatic reset when numerical issues are detected
6868
mjDSBL_NATIVECCD = 1<<16, // native convex collision detection
69+
mjDSBL_ISLAND = 1<<17, // constraint island discovery
6970

70-
mjNDISABLE = 17 // number of disable flags
71+
mjNDISABLE = 18 // number of disable flags
7172
} mjtDisableBit;
7273

7374

@@ -78,9 +79,8 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
7879
mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics
7980
// experimental features:
8081
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
81-
mjENBL_ISLAND = 1<<5, // constraint island discovery
8282

83-
mjNENABLE = 6 // number of enable flags
83+
mjNENABLE = 5 // number of enable flags
8484
} mjtEnableBit;
8585

8686

0 commit comments

Comments
 (0)