Set nativeccd as default.
PiperOrigin-RevId: 731343200 Change-Id: I315779017b676f3d118e0d38ee53a515272f50b8
This commit is contained in:
committed by
Copybara-Service
parent
4f691eeae4
commit
ed16f2daf2
@@ -499,16 +499,11 @@ Returns the smallest signed distance between two geoms and optionally the segmen
|
||||
Returned distances are bounded from above by ``distmax``. |br| If no collision of distance smaller than ``distmax`` is
|
||||
found, the function will return ``distmax`` and ``fromto``, if given, will be set to (0, 0, 0, 0, 0, 0).
|
||||
|
||||
.. admonition:: Positive ``distmax`` values
|
||||
:class: note
|
||||
.. admonition:: different (correct) behavior under `nativeccd`
|
||||
:class: note
|
||||
|
||||
.. TODO: b/339596989 - Improve mjc_Convex.
|
||||
|
||||
For some colliders, a large, positive ``distmax`` will result in an accurate measurement. However, for collision
|
||||
pairs which use the general ``mjc_Convex`` collider, the result will be approximate and likely inaccurate.
|
||||
This is considered a bug to be fixed in a future release.
|
||||
In order to determine whether a geom pair uses ``mjc_Convex``, inspect the table at the top of
|
||||
`engine_collision_driver.c <https://github.com/google-deepmind/mujoco/blob/main/src/engine/engine_collision_driver.c>`__.
|
||||
As explained in :ref:`Collision Detection<coDistance>`, distances are inaccurate when using the
|
||||
:ref:`legacy CCD pipeline<coCCD>`, and its use is discouraged.
|
||||
|
||||
.. _mj_contactForce:
|
||||
|
||||
|
||||
@@ -222,16 +222,11 @@ Returns the smallest signed distance between two geoms and optionally the segmen
|
||||
Returned distances are bounded from above by ``distmax``. |br| If no collision of distance smaller than ``distmax`` is
|
||||
found, the function will return ``distmax`` and ``fromto``, if given, will be set to (0, 0, 0, 0, 0, 0).
|
||||
|
||||
.. admonition:: Positive ``distmax`` values
|
||||
:class: note
|
||||
.. admonition:: different (correct) behavior under `nativeccd`
|
||||
:class: note
|
||||
|
||||
.. TODO: b/339596989 - Improve mjc_Convex.
|
||||
|
||||
For some colliders, a large, positive ``distmax`` will result in an accurate measurement. However, for collision
|
||||
pairs which use the general ``mjc_Convex`` collider, the result will be approximate and likely inaccurate.
|
||||
This is considered a bug to be fixed in a future release.
|
||||
In order to determine whether a geom pair uses ``mjc_Convex``, inspect the table at the top of
|
||||
`engine_collision_driver.c <https://github.com/google-deepmind/mujoco/blob/main/src/engine/engine_collision_driver.c>`__.
|
||||
As explained in :ref:`Collision Detection<coDistance>`, distances are inaccurate when using the
|
||||
:ref:`legacy CCD pipeline<coCCD>`, and its use is discouraged.
|
||||
|
||||
.. _mj_fullM:
|
||||
|
||||
|
||||
+13
-20
@@ -582,6 +582,12 @@ from its default.
|
||||
This flag disables the mid-phase collision filtering using a static AABB bounding volume hierarchy (a BVH binary
|
||||
tree). If disabled, all geoms pairs that are allowed to collide are checked for collisions.
|
||||
|
||||
.. _option-flag-nativeccd:
|
||||
|
||||
:at:`nativeccd`: :at-val:`[disable, enable], "enable"`
|
||||
This flag enables the native convex collision detection pipeline instead of using the
|
||||
`libccd library <https://github.com/danfis/libccd>`__, see :ref:`convex collisions<coCCD>` for more details.
|
||||
|
||||
.. _option-flag-eulerdamp:
|
||||
|
||||
:at:`eulerdamp`: :at-val:`[disable, enable], "enable"`
|
||||
@@ -635,14 +641,12 @@ from its default.
|
||||
|
||||
.. _option-flag-multiccd:
|
||||
|
||||
:at:`multiccd`: :at-val:`[disable, enable], "disable"` |nbsp| |nbsp| |nbsp| (experimental feature)
|
||||
:at:`multiccd`: :at-val:`[disable, enable], "disable"`
|
||||
This flag enables multiple-contact collision detection for geom pairs that use a general-purpose convex-convex
|
||||
collider e.g., mesh-mesh collisions. This can be useful when the contacting geoms have a flat surface, and the
|
||||
collider e.g., mesh-mesh collisions. This can be useful when the contacting geoms have a flat surface and the
|
||||
single contact point generated by the convex-convex collider cannot accurately capture the surface contact, leading
|
||||
to instabilities that typically manifest as sliding or wobbling. Multiple contact points are found by rotating the
|
||||
two geoms by ±1e-3 radians around the tangential axes and re-running the collision function. If a new contact is
|
||||
detected it is added, allowing for up to 4 additional contact points. This feature is currently considered
|
||||
experimental, and both the behavior and the way it is activated may change in the future.
|
||||
to instabilities that typically manifest as sliding or wobbling. The implementation of this feature depends on the
|
||||
selected convex collision pipeline, see :ref:`convex collisions<coCCD>` for more details.
|
||||
|
||||
.. _option-flag-island:
|
||||
|
||||
@@ -652,12 +656,6 @@ from its default.
|
||||
allows for `island visualization <https://youtu.be/Vc1tq0fFvQA>`__.
|
||||
In a future release, the constraint solver will exploit the disjoint nature of constraint islands.
|
||||
|
||||
.. _option-flag-nativeccd:
|
||||
|
||||
:at:`nativeccd`: :at-val:`[disable, enable], "disable"`
|
||||
This flag enables the native convex collision detection pipeline instead of using the
|
||||
`libccd library <https://github.com/danfis/libccd>`__.
|
||||
|
||||
.. _compiler:
|
||||
|
||||
**compiler** (*)
|
||||
@@ -6977,16 +6975,11 @@ pipeline. These 3 sensors share some common properties:
|
||||
to geom-geom penetration) will be reported by :ref:`sensor/distance<sensor-distance>`.
|
||||
In order to determine collision properties of non-penetrating geom pairs, a positive :at:`cutoff` is required.
|
||||
|
||||
.. admonition:: Positive cutoff values
|
||||
.. admonition:: different (correct) behavior under `nativeccd`
|
||||
:class: note
|
||||
|
||||
.. TODO: b/339596989 - Improve mjc_Convex.
|
||||
|
||||
For some colliders, a positive :at:`cutoff` will result in an accurate measurement. However, for collision
|
||||
pairs which use the general ``mjc_Convex`` collider, the result will be approximate and likely inaccurate.
|
||||
This is considered a bug to be fixed in a future release.
|
||||
In order to determine whether a geom pair uses ``mjc_Convex``, inspect the table at the top of
|
||||
`engine_collision_driver.c <https://github.com/google-deepmind/mujoco/blob/main/src/engine/engine_collision_driver.c>`__.
|
||||
As explained in :ref:`Collision Detection<coDistance>`, distances are inaccurate when using the
|
||||
:ref:`legacy CCD pipeline<coCCD>`, and its use is discouraged.
|
||||
|
||||
:at:`geom1`, :at:`geom2`, :at:`body1`, :at:`body2`
|
||||
For all 3 collision sensor types, the two colliding geoms can be specified explicitly using the :at:`geom1` and
|
||||
|
||||
+21
-2
@@ -23,6 +23,23 @@ Feature promotion
|
||||
<https://github.com/google-deepmind/mujoco/blob/main/model/flex/gripper_trilinear.xml>`__ flexes for modeling
|
||||
deformable gripper pads.
|
||||
|
||||
|
||||
- .. image:: images/computation/ccd_light.gif
|
||||
:width: 20%
|
||||
:align: right
|
||||
:class: only-light
|
||||
|
||||
.. image:: images/computation/ccd_dark.gif
|
||||
:width: 20%
|
||||
:align: right
|
||||
:class: only-dark
|
||||
|
||||
The native convex collision detection pipeline introduced in 3.2.3 and enabled by the
|
||||
:ref:`nativeccd<option-flag-nativeccd>` flag, is now the default. See the section on
|
||||
:ref:`Convex Collision Detection<coCCD>` for more details.
|
||||
|
||||
**Migration:** If the new pipeline breaks your workflow, set :ref:`nativeccd<option-flag-nativeccd>` to "disable".
|
||||
|
||||
General
|
||||
^^^^^^^
|
||||
- Add support for custom plots in the MuJoCo viewer by exposing a ``viewport`` property, a ``set_figures`` method,
|
||||
@@ -36,6 +53,8 @@ General
|
||||
.. admonition:: Breaking API changes
|
||||
:class: attention
|
||||
|
||||
- As mentioned above, the native convex collision detection pipeline is now the default, which may break some
|
||||
workflows. In this case, set :ref:`nativeccd<option-flag-nativeccd>` to "disable" to restore the old behavior.
|
||||
- Added :ref:`mjs_setDeepCopy` API function. When the deep copy flag is 0, attaching a model will not copy it to the
|
||||
parent, so the original references to the child can be used to modify the parent after attachment. The default
|
||||
behavior is to perform such a shallow copy. The old behavior of creating a deep copy of the child model while
|
||||
@@ -184,8 +203,8 @@ General
|
||||
|
||||
1. The Newton solver no longer requires ``nv*nv`` memory allocation, allowing for much larger models. See e.g.,
|
||||
`100_humanoids.xml <https://github.com/google-deepmind/mujoco/blob/main/model/humanoid/100_humanoids.xml>`__.
|
||||
Two quadratic-memory allocations still remain to be fully sparsified: ``mjData.actuator_moment`` and the matrices used
|
||||
by the PGS solver.
|
||||
Two quadratic-memory allocations still remain to be fully sparsified: ``mjData.actuator_moment`` and the matrices
|
||||
used by the PGS solver.
|
||||
2. Removed the :at:`solid` and :at:`membrane` plugins and moved the associated computations into the engine. See `3D
|
||||
example model <https://github.com/google-deepmind/mujoco/blob/main/model/flex/floppy.xml>`__ and `2D example model
|
||||
<https://github.com/google-deepmind/mujoco/blob/main/model/flex/trampoline.xml>`__ for examples of flex objects
|
||||
|
||||
+96
-17
@@ -1539,27 +1539,106 @@ Filtering
|
||||
|
||||
Checking
|
||||
~~~~~~~~
|
||||
Detailed collision checking, also known as *near-phase* or narrow-phase_ collision detection, is performed by functions
|
||||
that depend on the geom types in the pair. The table of narrow-phase collision functions can be inspected at the top of
|
||||
`engine_collision_driver.c <https://github.com/google-deepmind/mujoco/blob/main/src/engine/engine_collision_driver.c>`__
|
||||
and exposed to users who wish to install their own colliders as :ref:`mjCOLLISIONFUNC`. MuJoCo supports several
|
||||
primitive geometric shapes: plane, sphere, capsule, cylinder, ellipsoid, and box. It also supports triangulated meshes and
|
||||
height-fields.
|
||||
|
||||
Detailed collision checking is performed by functions that depend on the geom types in the pair. MuJoCo supports several
|
||||
primitive geometric shapes: plane, sphere, capsule, cylinder, ellipsoid, box. It also supports triangulated meshes and
|
||||
height fields.
|
||||
.. _narrow-phase: https://en.wikipedia.org/wiki/Collision_detection#Narrow_phase
|
||||
|
||||
We have chosen to limit collision detection to *convex* geoms. All primitive types are convex. Height fields are not
|
||||
convex but internally they are treated as unions of triangular prisms (using custom collision pruning beyond the filters
|
||||
described above). Meshes specified by the user can be non-convex, and are rendered as such. For collision purposes
|
||||
however they are replaced with their convex hulls. Mesh collisions are based on the Minkowski Portal Refinement (MPR)
|
||||
algorithm as implemented in `libccd <https://github.com/danfis/libccd>`__. It has tolerance and maximum iteration
|
||||
parameters exposed as ``mjModel.opt.ccd_tolerance`` and ``mjModel.opt.ccd_iterations`` respectively. MPR operates on the
|
||||
convex hull implicitly, however pre-computing that hull can substantially improve performance for large meshes. The
|
||||
model compiler does that by default, using the `qhull <http://www.qhull.org/>`__ library.
|
||||
With the notable exception of :ref:`SDF plugins<exSDF>` (see documentation therein), collision detection is limited to
|
||||
*convex* geoms. All primitive types are convex. Height-fields are not convex but internally they are treated as a
|
||||
collection of triangular prisms (using custom collision pruning beyond the filters described above). Meshes specified by
|
||||
the user can be non-convex, and are rendered as such. For collision purposes however they are replaced with their convex
|
||||
hulls (visualized with the 'H' key in :ref:`simulate <saSimulate>`), computed by the `qhull <http://www.qhull.org/>`__
|
||||
library.
|
||||
|
||||
.. _coCCD:
|
||||
|
||||
Convex collisions
|
||||
^^^^^^^^^^^^^^^^^
|
||||
All collisions involving pairs of geoms that do not have an analytic collider (e.g., meshes), are handled by one of two
|
||||
general-purpose convex collision detection (CCD) pipelines:
|
||||
|
||||
native pipeline (default)
|
||||
The native CCD pipeline ("nativeccd") is implemented natively in MuJoCo, based on the Gilbert-Johnson-Keerthi and
|
||||
Expanding Polytope algorithms (GJK_ / EPA_). The native pipeline is both faster and more robust than the MPR-based
|
||||
pipeline.
|
||||
|
||||
libccd pipeline (legacy)
|
||||
This legacy pipeline is based on the libccd_ library, and uses Minkowski Portal Refinement (MPR_). It is activated by
|
||||
disabling the :ref:`nativeccd<option-flag-nativeccd>` flag.
|
||||
|
||||
.. _libccd: https://github.com/danfis/libccd
|
||||
.. _MPR: https://en.wikipedia.org/wiki/Minkowski_Portal_Refinement
|
||||
.. _GJK: https://en.wikipedia.org/wiki/Gilbert%E2%80%93Johnson%E2%80%93Keerthi_distance_algorithm
|
||||
.. _EPA: http://scroll.stanford.edu/courses/cs468-01-fall/Papers/van-den-bergen.pdf
|
||||
|
||||
Both pipelines are controlled by a tolerance (in units of distance) and maximum iteration parameters exposed as
|
||||
``mjOption.ccd_tolerance`` (:ref:`ccd_tolerance<option-ccd_tolerance>`) and ``mjOption.ccd_iterations``
|
||||
(:ref:`ccd_iterations<option-ccd_iterations>`), respectively.
|
||||
|
||||
.. _coMultiCCD:
|
||||
|
||||
Multiple contacts
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Some colliders can return more than one contact per colliding pair to model line or surface contacts, as when two flat
|
||||
objects touch. For example the capsule-plane and box-plane colliders can return up to two or four contacts,
|
||||
respectively. Standard general-purpose convex collision algorithms like MPR and GJK always return a single contact
|
||||
point, which is problematic for surface contact scenarios (e.g., box-stacking). Both of MuJoCo's CCD pipelines can
|
||||
return multiple points per contacting pair ("multiccd"). This behavior is controlled by the
|
||||
:ref:`multiccd<option-flag-multiccd>` flag, but is implemented in different ways with different trade-offs:
|
||||
|
||||
libccd pipeline (legacy)
|
||||
Multiple contact points are found by rotating the two geoms by ±1e-3 radians around the tangential axes and
|
||||
re-running the collision routine. If a new contact is detected it is added, allowing for up to 4 additional contact
|
||||
points. This method is effective, but increases the cost of each collision call by a factor of 5.
|
||||
|
||||
native pipeline
|
||||
Native multiccd discovers multiple contacts using a novel analysis of the contacting surfaces at the solution,
|
||||
avoiding full re-runs of the collision routine, and is thus effectively "free". Note that native multiccd currently
|
||||
does not support positive contact margins. If one of the two geoms has a positive margin, native multiccd will fall
|
||||
back to legacy algorithm.
|
||||
|
||||
.. _coDistance:
|
||||
|
||||
Geom distance
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. image:: ../images/computation/ccd_light.gif
|
||||
:width: 25%
|
||||
:align: right
|
||||
:class: only-light
|
||||
|
||||
.. image:: ../images/computation/ccd_dark.gif
|
||||
:width: 25%
|
||||
:align: right
|
||||
:class: only-dark
|
||||
|
||||
The narrow-phase collision functions described :ref:`above<coChecking>` drive the :ref:`mj_geomDistance` function and
|
||||
associated :ref:`collision-sensors`. Due to the limitations of MPR, the legacy pipeline will return incorrect values
|
||||
(top) except at very small distances relative to the geom sizes, and is discouraged for this use case. In
|
||||
contrast, the GJK-based native pipeline (bottom), computes the correct values at all distances.
|
||||
|
||||
Convex decomposition
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In order to model a non-convex object other than a height field, the user must decompose it into a union of convex geoms
|
||||
(which can be primitive shapes or meshes) and attach them to the same body. Open tools like the `CoACD library
|
||||
<https://github.com/SarahWeiii/CoACD>`__ can be used outside MuJoCo to automate this process. Finally, all built-in
|
||||
collision functions can be replaced with custom callbacks. This can be used to incorporate a general-purpose "triangle
|
||||
soup" collision detector for example. However we do not recommend such an approach. Pre-processing the geometry and
|
||||
representing it as a union of convex geoms takes some work, but it pays off at runtime and yields both faster and more
|
||||
stable simulation.
|
||||
(which can be primitive shapes or meshes) and attach them to the same body. A height-field is essentially a shape that
|
||||
is automatically-decomposed into prisms
|
||||
|
||||
Open mesh-decomposition tools like the
|
||||
`CoACD library <https://github.com/SarahWeiii/CoACD>`__ can be used outside MuJoCo to automate this process. Finally,
|
||||
all built-in collision functions can be replaced with custom callbacks. This can be used to incorporate a
|
||||
general-purpose "triangle soup" collision detector for example. However we do not recommend such an approach.
|
||||
Pre-processing the geometry and representing it as a union of convex geoms takes some work, but it pays off at runtime
|
||||
and yields both faster and more stable simulation.
|
||||
|
||||
The exception to this rule are :ref:`SDF plugins<exSDF>` (see documentation therein), which in
|
||||
`certain cases <https://github.com/google-deepmind/mujoco/blob/main/plugin/sdf/README.md#gear>`__ can be efficient,
|
||||
but other requirements and limitations.
|
||||
|
||||
.. _Pipeline:
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 300 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 267 KiB |
@@ -429,8 +429,9 @@ typedef enum mjtDisableBit_ { // disable default feature bitflags
|
||||
mjDSBL_MIDPHASE = 1<<13, // mid-phase collision filtering
|
||||
mjDSBL_EULERDAMP = 1<<14, // implicit integration of joint damping in Euler integrator
|
||||
mjDSBL_AUTORESET = 1<<15, // automatic reset when numerical issues are detected
|
||||
mjDSBL_NATIVECCD = 1<<16, // native convex collision detection
|
||||
|
||||
mjNDISABLE = 16 // number of disable flags
|
||||
mjNDISABLE = 17 // number of disable flags
|
||||
} mjtDisableBit;
|
||||
typedef enum mjtEnableBit_ { // enable optional feature bitflags
|
||||
mjENBL_OVERRIDE = 1<<0, // override contact parameters
|
||||
@@ -440,9 +441,8 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
|
||||
// experimental features:
|
||||
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
|
||||
mjENBL_ISLAND = 1<<5, // constraint island discovery
|
||||
mjENBL_NATIVECCD = 1<<6, // native convex collision detection
|
||||
|
||||
mjNENABLE = 7 // number of enable flags
|
||||
mjNENABLE = 6 // number of enable flags
|
||||
} mjtEnableBit;
|
||||
typedef enum mjtJoint_ { // type of degree of freedom
|
||||
mjJNT_FREE = 0, // global position and orientation (quat) (7)
|
||||
|
||||
+30
-35
@@ -66,9 +66,9 @@ directly from the top-level ``mjx`` module.
|
||||
Structs
|
||||
-------
|
||||
|
||||
Before running MJX functions on an accelerator device, structs must be copied onto the device via the ``mjx.put_model`` and ``mjx.put_data``
|
||||
functions. Placing an :ref:`mjModel` on device yields an ``mjx.Model``. Placing an :ref:`mjData` on device yields
|
||||
an ``mjx.Data``:
|
||||
Before running MJX functions on an accelerator device, structs must be copied onto the device via the ``mjx.put_model``
|
||||
and ``mjx.put_data`` functions. Placing an :ref:`mjModel` on device yields an ``mjx.Model``. Placing an :ref:`mjData` on
|
||||
device yields an ``mjx.Data``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -86,12 +86,10 @@ These MJX variants mirror their MuJoCo counterparts but have a few key differenc
|
||||
express domain randomization (in the case of ``mjx.Model``) or high-throughput simulation for reinforcement learning
|
||||
(in the case of ``mjx.Data``).
|
||||
#. Numpy arrays in ``mjx.Model`` and ``mjx.Data`` are structural fields that control the output of JIT compilation.
|
||||
Modifying these arrays will force JAX to recompile MJX functions. As an example,
|
||||
``jnt_limited`` is a numpy array passed by reference from :ref:`mjModel`, which determines if joint limit
|
||||
constraints should be applied. If ``jnt_limited`` is modified, JAX will
|
||||
re-compile MJX functions.
|
||||
On the other hand, ``jnt_range`` is a JAX array that can be modified at runtime, and will only apply to joints with limits
|
||||
as specified by the ``jnt_limited`` field.
|
||||
Modifying these arrays will force JAX to recompile MJX functions. As an example, ``jnt_limited`` is a numpy array
|
||||
passed by reference from :ref:`mjModel`, which determines if joint limit constraints should be applied. If
|
||||
``jnt_limited`` is modified, JAX will re-compile MJX functions. On the other hand, ``jnt_range`` is a JAX array that
|
||||
can be modified at runtime, and will only apply to joints with limits as specified by the ``jnt_limited`` field.
|
||||
|
||||
|
||||
Neither ``mjx.Model`` nor ``mjx.Data`` are meant to be constructed manually. An ``mjx.Data`` may be created by calling
|
||||
@@ -110,9 +108,9 @@ Using ``mjx.make_data`` may be preferable when constructing batched ``mjx.Data``
|
||||
Functions
|
||||
---------
|
||||
|
||||
MuJoCo functions are exposed as MJX functions of the same name, but following
|
||||
`PEP 8 <https://peps.python.org/pep-0008/>`__-compliant names. Most of the :ref:`main simulation <Mainsimulation>` and
|
||||
some of the :ref:`sub-components <Subcomponents>` for forward simulation are available from the top-level ``mjx`` module.
|
||||
MuJoCo functions are exposed as MJX functions of the same name, but following `PEP 8
|
||||
<https://peps.python.org/pep-0008/>`__-compliant names. Most of the :ref:`main simulation <Mainsimulation>` and some of
|
||||
the :ref:`sub-components <Subcomponents>` for forward simulation are available from the top-level ``mjx`` module.
|
||||
|
||||
MJX functions are not `JIT compiled <https://jax.readthedocs.io/en/latest/jax-101/02-jitting.html>`__ by default -- we
|
||||
leave it to the user to JIT MJX functions, or JIT their own functions that reference MJX functions. See the
|
||||
@@ -225,7 +223,8 @@ The following features are **fully supported** in MJX:
|
||||
- ``PLANE``, ``HFIELD``, ``SPHERE``, ``CAPSULE``, ``BOX``, ``MESH`` are fully implemented. ``ELLIPSOID`` and
|
||||
``CYLINDER`` are implemented but only collide with other primitives, note that ``BOX`` is implemented as a mesh.
|
||||
* - :ref:`Constraint <mjtConstraint>`
|
||||
- ``EQUALITY``, ``LIMIT_JOINT``, ``CONTACT_FRICTIONLESS``, ``CONTACT_PYRAMIDAL``, ``CONTACT_ELLIPTIC``, ``FRICTION_DOF``, ``FRICTION_TENDON``
|
||||
- ``EQUALITY``, ``LIMIT_JOINT``, ``CONTACT_FRICTIONLESS``, ``CONTACT_PYRAMIDAL``, ``CONTACT_ELLIPTIC``,
|
||||
``FRICTION_DOF``, ``FRICTION_TENDON``
|
||||
* - :ref:`Equality <mjtEq>`
|
||||
- ``CONNECT``, ``WELD``, ``JOINT``, ``TENDON``
|
||||
* - :ref:`Integrator <mjtIntegrator>`
|
||||
@@ -315,22 +314,19 @@ Single scene simulation
|
||||
carefully optimized for CPU. MJX works best when simulating thousands or tens of thousands of scenes in parallel.
|
||||
|
||||
Collisions between large meshes
|
||||
MJX supports collisions between convex mesh geometries. However the convex collision algorithms
|
||||
in MJX are implemented differently than in MuJoCo. MJX uses a branchless version of the
|
||||
`Separating Axis Test <https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2013/slides/822403Gregorius_Dirk_TheSeparatingAxisTest.pdf>`__
|
||||
(SAT) to determine if geometries are colliding with convex meshes, while MuJoCo uses the Minkowski Portal Refinement (MPR)
|
||||
algorithm as implemented in `libccd <https://github.com/danfis/libccd>`__.
|
||||
SAT works well for smaller meshes but suffers in both runtime and memory for larger meshes.
|
||||
MJX supports collisions between convex mesh geometries. However the convex collision algorithms in MJX are implemented
|
||||
differently than in MuJoCo. MJX uses a branchless version of the `Separating Axis Test
|
||||
<https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2013/slides/822403Gregorius_Dirk_TheSeparatingAxisTest.pdf>`__
|
||||
(SAT) to determine if geometries are colliding with convex meshes, while MuJoCo uses either MPR or GJK/EPA, see
|
||||
:ref:`Collision Detection<coChecking>` for more details. SAT works well for smaller meshes but suffers in both runtime
|
||||
and memory for larger meshes.
|
||||
|
||||
For
|
||||
collisions with convex meshes and primitives, the convex decompositon of the mesh should have
|
||||
roughly **200 vertices or less** for reasonable performance. For convex-convex collisions,
|
||||
the convex mesh should have roughly **fewer than 32 vertices**. We recommend using
|
||||
:ref:`maxhullvert<asset-mesh-maxhullvert>` in the MuJoCo compiler to achieve desired convex mesh properties.
|
||||
With careful
|
||||
tuning, MJX can simulate scenes with mesh collisions -- see the MJX
|
||||
`shadow hand <https://github.com/google-deepmind/mujoco/tree/main/mjx/mujoco/mjx/test_data/shadow_hand>`__
|
||||
config for an example. Speeding up mesh collision detection is an active area of development for MJX.
|
||||
For collisions with convex meshes and primitives, the convex decompositon of the mesh should have roughly **200
|
||||
vertices or less** for reasonable performance. For convex-convex collisions, the convex mesh should have roughly
|
||||
**fewer than 32 vertices**. We recommend using :ref:`maxhullvert<asset-mesh-maxhullvert>` in the MuJoCo compiler to
|
||||
achieve desired convex mesh properties. With careful tuning, MJX can simulate scenes with mesh collisions -- see the
|
||||
MJX `shadow hand <https://github.com/google-deepmind/mujoco/tree/main/mjx/mujoco/mjx/test_data/shadow_hand>`__ config
|
||||
for an example. Speeding up mesh collision detection is an active area of development for MJX.
|
||||
|
||||
Large, complex scenes with many contacts
|
||||
Accelerators exhibit poor performance for
|
||||
@@ -392,13 +388,12 @@ For MJX to perform well, some configuration parameters should be adjusted from t
|
||||
of 10% to 20%, as long as the dense matrices can fit on the device.
|
||||
|
||||
Broadphase
|
||||
While MuJoCo handles broadphase culling out of the box, MJX requires additional parameters. For an approximate version of
|
||||
broadphase, use the experimental custom numeric parameters
|
||||
``max_contact_points`` and ``max_geom_pairs``. ``max_contact_points`` caps the number of contact points
|
||||
sent to the solver for each condim type. ``max_geom_pairs`` caps the total number of geom-pairs sent to
|
||||
respective collision functions for each geom-type pair. As an example, the
|
||||
`shadow hand <https://github.com/google-deepmind/mujoco/tree/main/mjx/mujoco/mjx/test_data/shadow_hand>`__
|
||||
environment makes use of these parameters.
|
||||
While MuJoCo handles broadphase culling out of the box, MJX requires additional parameters. For an approximate version
|
||||
of broadphase, use the experimental custom numeric parameters ``max_contact_points`` and ``max_geom_pairs``.
|
||||
``max_contact_points`` caps the number of contact points sent to the solver for each condim type. ``max_geom_pairs``
|
||||
caps the total number of geom-pairs sent to respective collision functions for each geom-type pair. As an example, the
|
||||
`shadow hand <https://github.com/google-deepmind/mujoco/tree/main/mjx/mujoco/mjx/test_data/shadow_hand>`__ environment
|
||||
makes use of these parameters.
|
||||
|
||||
GPU performance
|
||||
---------------
|
||||
|
||||
@@ -293,6 +293,7 @@ The plugins in the `sensor/ <https://github.com/google-deepmind/mujoco/tree/main
|
||||
custom sensors. Currently the sole sensor plugin is the touch grid sensor, see the `README
|
||||
<https://github.com/google-deepmind/mujoco/blob/main/plugin/sensor/README.md>`__ for details.
|
||||
|
||||
.. _exSDF:
|
||||
|
||||
sdf
|
||||
"""
|
||||
|
||||
@@ -64,8 +64,9 @@ typedef enum mjtDisableBit_ { // disable default feature bitflags
|
||||
mjDSBL_MIDPHASE = 1<<13, // mid-phase collision filtering
|
||||
mjDSBL_EULERDAMP = 1<<14, // implicit integration of joint damping in Euler integrator
|
||||
mjDSBL_AUTORESET = 1<<15, // automatic reset when numerical issues are detected
|
||||
mjDSBL_NATIVECCD = 1<<16, // native convex collision detection
|
||||
|
||||
mjNDISABLE = 16 // number of disable flags
|
||||
mjNDISABLE = 17 // number of disable flags
|
||||
} mjtDisableBit;
|
||||
|
||||
|
||||
@@ -77,9 +78,8 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
|
||||
// experimental features:
|
||||
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
|
||||
mjENBL_ISLAND = 1<<5, // constraint island discovery
|
||||
mjENBL_NATIVECCD = 1<<6, // native convex collision detection
|
||||
|
||||
mjNENABLE = 7 // number of enable flags
|
||||
mjNENABLE = 6 // number of enable flags
|
||||
} mjtEnableBit;
|
||||
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ def _collide(
|
||||
mujoco.mj_resetDataKeyframe(m, d, keyframe)
|
||||
dx = mjx.put_data(m, d)
|
||||
|
||||
m.opt.enableflags |= mujoco.mjtEnableBit.mjENBL_NATIVECCD
|
||||
mujoco.mj_step(m, d)
|
||||
collision_jit_fn = jax.jit(mjx.collision)
|
||||
kinematics_jit_fn = jax.jit(mjx.kinematics)
|
||||
|
||||
@@ -938,7 +938,7 @@ Euler integrator, semi-implicit in velocity.
|
||||
self.assertEqual(mujoco.mjtEnableBit.mjENBL_OVERRIDE, 1 << 0)
|
||||
self.assertEqual(mujoco.mjtEnableBit.mjENBL_ENERGY, 1 << 1)
|
||||
self.assertEqual(mujoco.mjtEnableBit.mjENBL_FWDINV, 1 << 2)
|
||||
self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 7)
|
||||
self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 6)
|
||||
self.assertEqual(mujoco.mjtGeom.mjGEOM_PLANE, 0)
|
||||
self.assertEqual(mujoco.mjtGeom.mjGEOM_HFIELD, 1)
|
||||
self.assertEqual(mujoco.mjtGeom.mjGEOM_SPHERE, 2)
|
||||
|
||||
@@ -43,7 +43,8 @@ ENUMS: Mapping[str, EnumDecl] = dict([
|
||||
('mjDSBL_MIDPHASE', 8192),
|
||||
('mjDSBL_EULERDAMP', 16384),
|
||||
('mjDSBL_AUTORESET', 32768),
|
||||
('mjNDISABLE', 16),
|
||||
('mjDSBL_NATIVECCD', 65536),
|
||||
('mjNDISABLE', 17),
|
||||
]),
|
||||
)),
|
||||
('mjtEnableBit',
|
||||
@@ -57,8 +58,7 @@ ENUMS: Mapping[str, EnumDecl] = dict([
|
||||
('mjENBL_INVDISCRETE', 8),
|
||||
('mjENBL_MULTICCD', 16),
|
||||
('mjENBL_ISLAND', 32),
|
||||
('mjENBL_NATIVECCD', 64),
|
||||
('mjNENABLE', 7),
|
||||
('mjNENABLE', 6),
|
||||
]),
|
||||
)),
|
||||
('mjtJoint',
|
||||
|
||||
@@ -44,8 +44,7 @@ class EnumsTest(absltest.TestCase):
|
||||
('mjENBL_INVDISCRETE', 1<<3),
|
||||
('mjENBL_MULTICCD', 1<<4),
|
||||
('mjENBL_ISLAND', 1<<5),
|
||||
('mjENBL_NATIVECCD', 1<<6),
|
||||
('mjNENABLE', 7)))
|
||||
('mjNENABLE', 6)))
|
||||
|
||||
# values mostly increment by one with occasional overrides
|
||||
def test_mjtGeom(self): # pylint: disable=invalid-name
|
||||
|
||||
@@ -33,38 +33,38 @@
|
||||
// call libccd or nativeccd to recover penetration info
|
||||
static int mjc_penetration(const mjModel* m, mjCCDObj* obj1, mjCCDObj* obj2,
|
||||
const ccd_t* ccd, ccd_real_t* depth, ccd_vec3_t* dir, ccd_vec3_t* pos) {
|
||||
if (mjENABLED(mjENBL_NATIVECCD)) {
|
||||
mjCCDConfig config;
|
||||
mjCCDStatus status;
|
||||
|
||||
// set config
|
||||
config.max_iterations = ccd->max_iterations,
|
||||
config.tolerance = ccd->mpr_tolerance,
|
||||
config.max_contacts = 1;
|
||||
config.dist_cutoff = 0; // no geom distances needed
|
||||
|
||||
mjtNum dist = mjc_ccd(&config, &status, obj1, obj2);
|
||||
if (dist < 0) {
|
||||
if (depth) *depth = -dist;
|
||||
if (dir) {
|
||||
mju_sub3(dir->v, status.x1, status.x2);
|
||||
mju_normalize3(dir->v);
|
||||
}
|
||||
if (pos) {
|
||||
pos->v[0] = 0.5 * (status.x1[0] + status.x2[0]);
|
||||
pos->v[1] = 0.5 * (status.x1[1] + status.x2[1]);
|
||||
pos->v[2] = 0.5 * (status.x1[2] + status.x2[2]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (depth) *depth = 0;
|
||||
if (dir) mju_zero3(dir->v);
|
||||
if (pos) mju_zero3(dir->v);
|
||||
return 1;
|
||||
// fallback to MPR
|
||||
if (mjDISABLED(mjDSBL_NATIVECCD)) {
|
||||
return ccdMPRPenetration(obj1, obj2, ccd, depth, dir, pos);
|
||||
}
|
||||
|
||||
// fallback to MPR
|
||||
return ccdMPRPenetration(obj1, obj2, ccd, depth, dir, pos);
|
||||
mjCCDConfig config;
|
||||
mjCCDStatus status;
|
||||
|
||||
// set config
|
||||
config.max_iterations = ccd->max_iterations,
|
||||
config.tolerance = ccd->mpr_tolerance,
|
||||
config.max_contacts = 1;
|
||||
config.dist_cutoff = 0; // no geom distances needed
|
||||
|
||||
mjtNum dist = mjc_ccd(&config, &status, obj1, obj2);
|
||||
if (dist < 0) {
|
||||
if (depth) *depth = -dist;
|
||||
if (dir) {
|
||||
mju_sub3(dir->v, status.x1, status.x2);
|
||||
mju_normalize3(dir->v);
|
||||
}
|
||||
if (pos) {
|
||||
pos->v[0] = 0.5 * (status.x1[0] + status.x2[0]);
|
||||
pos->v[1] = 0.5 * (status.x1[1] + status.x2[1]);
|
||||
pos->v[2] = 0.5 * (status.x1[2] + status.x2[2]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (depth) *depth = 0;
|
||||
if (dir) mju_zero3(dir->v);
|
||||
if (pos) mju_zero3(dir->v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -791,7 +791,7 @@ static void mjc_initCCD(ccd_t* ccd, const mjModel* m) {
|
||||
// find convex-convex collision
|
||||
static int mjc_CCDIteration(const mjModel* m, const mjData* d, mjCCDObj* obj1, mjCCDObj* obj2,
|
||||
mjContact* con, int max_contacts, mjtNum margin) {
|
||||
if (mjENABLED(mjENBL_NATIVECCD)) {
|
||||
if (!mjDISABLED(mjDSBL_NATIVECCD)) {
|
||||
mjCCDConfig config;
|
||||
mjCCDStatus status;
|
||||
|
||||
@@ -928,7 +928,7 @@ int mjc_Convex(const mjModel* m, const mjData* d,
|
||||
int ncon = mjc_CCDIteration(m, d, &obj1, &obj2, con, max_contacts, margin);
|
||||
|
||||
// nativeccd supports multi Box-Box collision directly
|
||||
if (mjENABLED(mjENBL_NATIVECCD) && singlePass(&obj1, &obj2)) {
|
||||
if (!mjDISABLED(mjDSBL_NATIVECCD) && singlePass(&obj1, &obj2)) {
|
||||
return ncon;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,8 @@ const char* mjDISABLESTRING[mjNDISABLE] = {
|
||||
"Sensor",
|
||||
"Midphase",
|
||||
"Eulerdamp",
|
||||
"AutoReset"
|
||||
"AutoReset",
|
||||
"NativeCCD"
|
||||
};
|
||||
|
||||
|
||||
@@ -72,8 +73,7 @@ const char* mjENABLESTRING[mjNENABLE] = {
|
||||
"Fwdinv",
|
||||
"InvDiscrete",
|
||||
"MultiCCD",
|
||||
"Island",
|
||||
"NativeCCD"
|
||||
"Island"
|
||||
};
|
||||
|
||||
|
||||
@@ -1425,7 +1425,7 @@ mjtNum mj_geomDistance(const mjModel* m, const mjData* d, int geom1, int geom2,
|
||||
}
|
||||
|
||||
// use nativecdd if flag is enabled
|
||||
if (mjENABLED(mjENBL_NATIVECCD)) {
|
||||
if (!mjDISABLED(mjDSBL_NATIVECCD)) {
|
||||
if (func == mjc_Convex || func == mjc_BoxBox) {
|
||||
return mj_geomDistanceCCD(m, d, g1, g2, distmax, fromto);
|
||||
}
|
||||
|
||||
@@ -1118,6 +1118,7 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) {
|
||||
READDSBL("midphase", mjDSBL_MIDPHASE)
|
||||
READDSBL("eulerdamp", mjDSBL_EULERDAMP)
|
||||
READDSBL("autoreset", mjDSBL_AUTORESET)
|
||||
READDSBL("nativeccd", mjDSBL_NATIVECCD)
|
||||
#undef READDSBL
|
||||
|
||||
#define READENBL(NAME, MASK) \
|
||||
@@ -1131,7 +1132,6 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) {
|
||||
READENBL("invdiscrete", mjENBL_INVDISCRETE)
|
||||
READENBL("multiccd", mjENBL_MULTICCD)
|
||||
READENBL("island", mjENBL_ISLAND)
|
||||
READENBL("nativeccd", mjENBL_NATIVECCD)
|
||||
#undef READENBL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1028,6 +1028,7 @@ void mjXWriter::Option(XMLElement* root) {
|
||||
WRITEDSBL("midphase", mjDSBL_MIDPHASE)
|
||||
WRITEDSBL("eulerdamp", mjDSBL_EULERDAMP)
|
||||
WRITEDSBL("autoreset", mjDSBL_AUTORESET)
|
||||
WRITEDSBL("nativeccd", mjDSBL_NATIVECCD)
|
||||
#undef WRITEDSBL
|
||||
|
||||
#define WRITEENBL(NAME, MASK) \
|
||||
@@ -1039,7 +1040,6 @@ void mjXWriter::Option(XMLElement* root) {
|
||||
WRITEENBL("invdiscrete", mjENBL_INVDISCRETE)
|
||||
WRITEENBL("multiccd", mjENBL_MULTICCD)
|
||||
WRITEENBL("island", mjENBL_ISLAND)
|
||||
WRITEENBL("nativeccd", mjENBL_NATIVECCD)
|
||||
#undef WRITEENBL
|
||||
}
|
||||
|
||||
|
||||
@@ -42,11 +42,11 @@ static const char kMixedPath[] =
|
||||
|
||||
class TestHarness {
|
||||
public:
|
||||
TestHarness(const char* xml_path, std::string label, int enable_flags = 0) {
|
||||
TestHarness(const char* xml_path, std::string label, int disable_flags = 0) {
|
||||
// Fail test if there are any mujoco errors
|
||||
MujocoErrorTestGuard guard;
|
||||
model_ = LoadModelFromPath(xml_path);
|
||||
model_->opt.enableflags |= enable_flags;
|
||||
model_->opt.disableflags |= disable_flags;
|
||||
data_ = mj_makeData(model_);
|
||||
for (int i=0; i < kNumWarmupSteps; i++) {
|
||||
mj_step(model_, data_);
|
||||
@@ -100,43 +100,43 @@ class TestHarness {
|
||||
|
||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
BM_BoxMesh_NativeCCD(benchmark::State& state) {
|
||||
static TestHarness harness(kBoxMeshPath, "boxmesh.xml (nativeccd)",
|
||||
mjENBL_NATIVECCD);
|
||||
static TestHarness harness(kBoxMeshPath, "boxmesh.xml (nativeccd)");
|
||||
harness.RunBenchmark(state);
|
||||
}
|
||||
BENCHMARK(BM_BoxMesh_NativeCCD);
|
||||
|
||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
BM_BoxMesh_LibCCD(benchmark::State& state) {
|
||||
static TestHarness harness(kBoxMeshPath, "boxmesh.xml (libccd)");
|
||||
static TestHarness harness(kBoxMeshPath, "boxmesh.xml (libccd)",
|
||||
mjDSBL_NATIVECCD);
|
||||
harness.RunBenchmark(state);
|
||||
}
|
||||
BENCHMARK(BM_BoxMesh_LibCCD);
|
||||
|
||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
BM_Ellipsoid_NativeCCD(benchmark::State& state) {
|
||||
static TestHarness harness(kEllipsoidPath, "ellipsoid.xml (nativeccd)",
|
||||
mjENBL_NATIVECCD);
|
||||
static TestHarness harness(kEllipsoidPath, "ellipsoid.xml (nativeccd)");
|
||||
harness.RunBenchmark(state);
|
||||
}
|
||||
BENCHMARK(BM_Ellipsoid_NativeCCD);
|
||||
|
||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL
|
||||
BM_Ellipsoid_LibCCD(benchmark::State& state) {
|
||||
static TestHarness harness(kEllipsoidPath, "ellipsoid.xml (libccd)");
|
||||
static TestHarness harness(kEllipsoidPath, "ellipsoid.xml (libccd)",
|
||||
mjDSBL_NATIVECCD);
|
||||
harness.RunBenchmark(state);
|
||||
}
|
||||
BENCHMARK(BM_Ellipsoid_LibCCD);
|
||||
|
||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_Mixed_NativeCCD(benchmark::State& state) {
|
||||
static TestHarness harness(kMixedPath, "mixed.xml (nativeccd)",
|
||||
mjENBL_NATIVECCD);
|
||||
static TestHarness harness(kMixedPath, "mixed.xml (nativeccd)");
|
||||
harness.RunBenchmark(state);
|
||||
}
|
||||
BENCHMARK(BM_Mixed_NativeCCD);
|
||||
|
||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_Mixed_LibCCD(benchmark::State& state) {
|
||||
static TestHarness harness(kMixedPath, "mixed.xml (libccd)");
|
||||
static TestHarness harness(kMixedPath, "mixed.xml (libccd)",
|
||||
mjDSBL_NATIVECCD);
|
||||
harness.RunBenchmark(state);
|
||||
}
|
||||
BENCHMARK(BM_Mixed_LibCCD);
|
||||
|
||||
@@ -160,7 +160,8 @@ public enum mjtDisableBit : int{
|
||||
mjDSBL_MIDPHASE = 8192,
|
||||
mjDSBL_EULERDAMP = 16384,
|
||||
mjDSBL_AUTORESET = 32768,
|
||||
mjNDISABLE = 16,
|
||||
mjDSBL_NATIVECCD = 65536,
|
||||
mjNDISABLE = 17,
|
||||
}
|
||||
public enum mjtEnableBit : int{
|
||||
mjENBL_OVERRIDE = 1,
|
||||
@@ -169,8 +170,7 @@ public enum mjtEnableBit : int{
|
||||
mjENBL_INVDISCRETE = 8,
|
||||
mjENBL_MULTICCD = 16,
|
||||
mjENBL_ISLAND = 32,
|
||||
mjENBL_NATIVECCD = 64,
|
||||
mjNENABLE = 7,
|
||||
mjNENABLE = 6,
|
||||
}
|
||||
public enum mjtJoint : int{
|
||||
mjJNT_FREE = 0,
|
||||
|
||||
Reference in New Issue
Block a user