Finalize built-in mesh example model and documentation

PiperOrigin-RevId: 791227350
Change-Id: Ibdcdb8a4ee5b3f78c9ae93e1db2a9a2f9d55a80c
This commit is contained in:
Yuval Tassa
2025-08-05 08:31:46 -07:00
committed by Copybara-Service
parent 2f4375dda3
commit fde479736e
11 changed files with 283 additions and 55 deletions
+54 -19
View File
@@ -1327,57 +1327,92 @@ The full list of processing steps applied by the compiler to each mesh is as fol
:at:`builtin`: :at-val:`string, optional`
The mesh is generated by the compiler from a set of parameters specified in :ref:`params<asset-mesh-params>`.
When saved to XML, meshes produced this way are converted to explicit vertices.
When saved to XML, meshes produced this way are converted to explicit vertices. The Python bindings include
:ref:`convenience methods <PyEditConvenience>` for generating these meshes.
The available built-in types, their parameters and semantics are:
.. image:: images/XMLreference/s.png
:width: 23%
:align: right
:target: https://github.com/google-deepmind/mujoco/blob/main/test/user/testdata/makemesh.xml
:at-val:`sphere` (subdivision)
Repeated subdivisions :math:`s` of a unit icosahedron. Has :math:`2 + 10 \cdot 4^s` vertices.
Repeated subdivisions of a unit icosahedron ("icosphere"). For :math:`s` subdivisions, this mesh
has :math:`V = 2 + 10 \cdot 4^s` vertices and :math:`F = 20 \cdot 4^s` faces.
**subdivision**: integer in [0-4]: The number of subdivisions to apply to icosahedron faces.
.. image:: images/XMLreference/h.png
:width: 23%
:align: right
:target: https://github.com/google-deepmind/mujoco/blob/main/test/user/testdata/makemesh.xml
:at-val:`hemisphere` (subdivision)
Repeated subdivisions :math:`s` of a square-based pyramid. Has :math:`2+2(s+1)(s+2)` vertices.
Repeated subdivisions of a square-based pyramid. For :math:`s` subdivisions, this mesh
has :math:`V = 2 + 2(s+1)(s+2)` vertices and :math:`F = 4(s+1)(s+2)` faces.
**subdivision**: integer in [0-10]: The number of subdivisions to apply to the pyramid.
.. image:: images/XMLreference/c.png
:width: 23%
:align: right
:target: https://github.com/google-deepmind/mujoco/blob/main/test/user/testdata/makemesh.xml
:at-val:`cone` (nvert, radius)
The convex hull of a regular unit polygon at z = -1 and a unit polygon with the given radiusat z = 1.
If radius is 1, the mesh a prism. If radius is 0, only a single vertex is place at (0, 0, 1) and the mesh is a
The convex hull of a regular unit polygon at z = -1 and a unit polygon with the given radius at z = 1.
If radius is 1, the mesh a prism. If radius is 0, only a single vertex is placed at (0, 0, 1) and the mesh is a
discrete cone. If radius is positive, the mesh is a truncated discrete cone.
**nvert**: integer >= 3: The number vertices in the polygon.
|br| **radius**: real in [0, 1]: The radius of the top face.
:at-val:`supersphere` (resolution, e, n)
A generalization of a sphere, also known as a superellipsoid (we use "supersphere" since semiaxis rescaling is
performed by the :ref:`scale<asset-mesh-scale>` attribute). If the **n** and **e** parameters are both 1, the
shape is a sphere. See `here <https://en.wikipedia.org/wiki/Superellipsoid>`__ for the definition of superspheres.
.. image:: images/XMLreference/ss.png
:width: 23%
:align: right
:target: https://github.com/google-deepmind/mujoco/blob/main/test/user/testdata/makemesh.xml
**resolution** integer >= 4: The discretization of both major and minor radii.
:at-val:`supersphere` (resolution, e, n)
A generalization of a sphere, also known as a superellipsoid (we use 'supersphere' since semiaxis rescaling is
performed by the :ref:`scale<asset-mesh-scale>` attribute). If the **n** and **e** parameters are both 1, the
shape is a sphere. See `here <https://en.wikipedia.org/wiki/Superellipsoid>`__ for more details.
**resolution** integer >= 3: Longitude and latitude discretization.
|br| **e**: real >= 0: The "east-west" exponent.
|br| **n**: real >= 0: The "north-south" exponent.
.. image:: images/XMLreference/st.png
:width: 23%
:align: right
:target: https://github.com/google-deepmind/mujoco/blob/main/test/user/testdata/makemesh.xml
:at-val:`supertorus` (resolution, radius, s, t)
A generalization of a torus with major radius of 1 and given minor radius. If the **s** and **t** parameters are
both 1, the shape is a torus. See `here <https://en.wikipedia.org/wiki/Supertoroid>`__ for details regarding
the definition of supertori.
both 1, the shape is a torus. See `here <https://en.wikipedia.org/wiki/Supertoroid>`__ for more details. Note that
this shape is inherently non-convex, and the :ref:`standard caveats<coDecomposition>` about mesh collisions apply.
**resolution** integer >= 4: The discretization of both major and minor radii.
**resolution** integer >= 3: Discretization of both circumfrences.
|br| **radius**: real in (0, 1]: The minor radius of the torus.
|br| **s**: real > 0: The "squareness" of major sections.
|br| **t**: real > 0: The "squareness" of minor sections.
|br| **s**: real > 0: The "squareness" of minor sections.
|br| **t**: real > 0: The "squareness" of major sections.
.. image:: images/XMLreference/w.png
:width: 23%
:align: right
:target: https://github.com/google-deepmind/mujoco/blob/main/test/user/testdata/makemesh.xml
:at-val:`wedge` (res_phi, res_theta, fov_phi, fov_theta, gamma)
A slice of a unit spherical shell in spherical coordinates.
A slice of a unit spherical shell in spherical coordinates. This mesh is designed to be used by the :ref:`tactile
sensor<sensor-tactile>`, which reports data at the vertices.
**res_phi**: integer >= 0: The vertical resolution of the slice.
|br| **res_theta**: integer >= 0: The horizontal resolution of the slice.
|br| **fov_phi**: real in (0, 180]: The horizontal field of view (longitude) in degrees.
|br| **fov_phi**: real in (0, 90): The vertical field of view (latitude) in degrees.
|br| **fov_phi**: real in (0, 180]: The horizontal field of view (degrees).
|br| **fov_phi**: real in (0, 90): The vertical field of view (degrees).
|br| **gamma**: real in [0, 1]: Foveal deformation of the discretization.
:at-val:`plate` (res_x, res_y)
A rectangular plate with resolution in each dimension.
A rectangular plate with given resolution in each dimension. This mesh is designed to be used by the :ref:`tactile
sensor<sensor-tactile>`, which reports data at the vertices.
**res_x**: integer > 0: The horizontal resolution of the plate.
|br| **res_y**: integer > 0: The vertical resolution of the plate.
+2 -2
View File
@@ -55,8 +55,8 @@ Version 3.3.4 (July 8, 2025)
function :ref:`mjs_setName` which allows checking for naming collisions at set-time rather than compile-time, for
earlier catching of errors. Relatedly, the ``name`` attribute has been removed from all mjs elements.
4. For MJX, the ``mjx.Option`` dataclass now has private and public fields similar to ``mjx.Model`` and
``mjx.Data``. Some fields are no longer publicly available due to differences in the
underlying implementations of this data structure.
``mjx.Data``. Some fields are no longer publicly available due to differences in the
underlying implementations of this data structure.
General
^^^^^^^
+14 -15
View File
@@ -1603,9 +1603,6 @@ native pipeline
.. _coDistance:
Geom distance
^^^^^^^^^^^^^
.. image:: ../images/computation/ccd_light.gif
:width: 25%
:align: right
@@ -1616,28 +1613,30 @@ Geom distance
:align: right
:class: only-dark
Geom distance
^^^^^^^^^^^^^
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.
.. _coDecomposition:
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. A height-field is essentially a shape that
is automatically-decomposed into prisms
(which can be primitive shapes or meshes) and attach them to the same body. The other exception to this rule (besides
height fields) are :ref:`Signed Distance Functions<exSDF>` (see documentation therein), which in certain cases (e.g.,
`analytic SDFs <https://github.com/google-deepmind/mujoco/blob/main/plugin/sdf/README.md#gear>`__) can be efficient, but
have other requirements and limitations.
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 have other requirements and limitations.
Open source 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.
.. _Pipeline:
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

+13
View File
@@ -590,6 +590,8 @@ attaching. However, it is possible to override the default behavior by setting `
worldframe_in_site = parent.attach(child, site=site, prefix='child-')
worldframe_in_frame = parent.attach(child, frame=frame, prefix='child-')
.. _PyEditConvenience:
Convenience methods
-------------------
@@ -641,6 +643,17 @@ The ``MjSpec`` object can be serialized with all of its assets using the functio
can be either a path to a file or a file object. In order to load the spec from a zip file, use ``spec =
MjSpec.from_zip(file)``, where ``file`` is a path to a zip file or a zip file object.
Mesh creation
^^^^^^^^^^^^^
The :ref:`mjsMesh` object includes convenience methods for model creation with named attributes, corresponding to the
:ref:`mesh/builtin<asset-mesh-builtin>` semantics. See `specs_test.py
<https://github.com/google-deepmind/mujoco/blob/main/python/mujoco/specs_test.py>`__.
.. code-block:: python
mesh = spec.add_mesh(name='prism')
mesh.make_cone(nedge=5, radius=1)
.. _PyMJCF:
Relationship to ``PyMJCF`` and ``bind``
+200 -19
View File
@@ -1,26 +1,207 @@
<mujoco model="makemesh">
<statistic meansize="1"/>
<visual>
<global offheight="2000" offwidth="2000"/>
</visual>
<asset>
<mesh name="sphere" builtin="sphere" params="2" scale=".8 .8 .8"/>
<mesh name="hemisphere" builtin="hemisphere" params="4" scale=".8 .8 .8"/>
<mesh name="supersphere" builtin="supersphere" params="50 2 1" scale=".8 .8 .8"/>
<mesh name="toroid" builtin="supertorus" params="50 .5 .42 1.42" scale=".8 .8 .8"/>
<mesh name="wedge" builtin="wedge" params="10 10 60 60 0"/>
<mesh name="prism3" builtin="cone" params="3 1" scale=".3 .3 .3"/>
<mesh name="prism5" builtin="cone" params="5 1" scale=".3 .3 .1"/>
<mesh name="cone6" builtin="cone" params="6 0" scale=".3 .3 .7"/>
<mesh name="cone4" builtin="cone" params="4 .5" scale=".3 .3 .3"/>
<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=".5 .5" texuniform="true" reflectance=".2"/>
</asset>
<default>
<geom type="mesh"/>
<camera xyaxes="1 0 0 0 2.7 1" fovy="27"/>
<default class="s">
<geom euler="0 0 -40"/>
</default>
<default class="h">
<geom euler="-30 -50 20"/>
</default>
<default class="c">
<geom euler="-20 -20 40"/>
<mesh scale=".6 .6 .7"/>
</default>
<default class="ss">
<geom euler="-30 -40 0"/>
<mesh scale=".7 .7 .7"/>
</default>
<default class="st">
<geom euler="20 -30 0"/>
<mesh scale=".5 .5 .5"/>
</default>
<default class="w">
<geom euler="-135 -60 0"/>
<mesh scale=".7 .7 .7"/>
</default>
</default>
<asset>
<mesh name="s0" builtin="sphere" params="0"/>
<mesh name="s1" builtin="sphere" params="1"/>
<mesh name="s2" builtin="sphere" params="2"/>
<mesh name="h0" builtin="hemisphere" params="0"/>
<mesh name="h2" builtin="hemisphere" params="2"/>
<mesh name="h4" builtin="hemisphere" params="4"/>
<mesh name="c0" builtin="cone" params="3 1" class="c"/>
<mesh name="c1" builtin="cone" params="5 1" class="c"/>
<mesh name="c2" builtin="cone" params="7 1" class="c"/>
<mesh name="c3" builtin="cone" params="3 .5" class="c"/>
<mesh name="c4" builtin="cone" params="5 .5" class="c"/>
<mesh name="c5" builtin="cone" params="7 .5" class="c"/>
<mesh name="c6" builtin="cone" params="3 0" class="c"/>
<mesh name="c7" builtin="cone" params="5 0" class="c"/>
<mesh name="c8" builtin="cone" params="7 0" class="c"/>
<mesh name="ss0" builtin="supersphere" params="30 .4 .4" class="ss"/>
<mesh name="ss1" builtin="supersphere" params="30 .4 1" class="ss"/>
<mesh name="ss2" builtin="supersphere" params="30 .4 2" class="ss"/>
<mesh name="ss3" builtin="supersphere" params="30 1 .4" class="ss"/>
<mesh name="ss4" builtin="supersphere" params="30 1 1" class="ss"/>
<mesh name="ss5" builtin="supersphere" params="30 1 2" class="ss"/>
<mesh name="ss6" builtin="supersphere" params="30 2 .4" class="ss"/>
<mesh name="ss7" builtin="supersphere" params="30 2 1" class="ss"/>
<mesh name="ss8" builtin="supersphere" params="30 2 2" class="ss"/>
<mesh name="st0" builtin="supertorus" params="30 .5 .4 .4" class="st"/>
<mesh name="st1" builtin="supertorus" params="30 .5 .4 1" class="st"/>
<mesh name="st2" builtin="supertorus" params="30 .5 .4 2" class="st"/>
<mesh name="st3" builtin="supertorus" params="30 .5 1 .4" class="st"/>
<mesh name="st4" builtin="supertorus" params="30 .5 1 1" class="st"/>
<mesh name="st5" builtin="supertorus" params="30 .5 1 2" class="st"/>
<mesh name="st6" builtin="supertorus" params="30 .5 2 .4" class="st"/>
<mesh name="st7" builtin="supertorus" params="30 .5 2 1" class="st"/>
<mesh name="st8" builtin="supertorus" params="30 .5 2 2" class="st"/>
<mesh name="w0" builtin="wedge" params="30 30 45 20 0" class="w"/>
<mesh name="w1" builtin="wedge" params="30 30 45 45 0" class="w"/>
<mesh name="w2" builtin="wedge" params="30 30 45 90 0" class="w"/>
<mesh name="w3" builtin="wedge" params="30 30 90 20 0" class="w"/>
<mesh name="w4" builtin="wedge" params="30 30 90 45 0" class="w"/>
<mesh name="w5" builtin="wedge" params="30 30 90 90 0" class="w"/>
<mesh name="w6" builtin="wedge" params="30 30 180 20 0" class="w"/>
<mesh name="w7" builtin="wedge" params="30 30 180 45 0" class="w"/>
<mesh name="w8" builtin="wedge" params="30 30 180 90 0" class="w"/>
</asset>
<worldbody>
<light pos="0 0 10"/>
<geom mesh="sphere" type="mesh" pos="-3 0 0"/>
<geom mesh="hemisphere" type="mesh" pos="-1 0 0"/>
<geom mesh="supersphere" type="mesh" pos="2 0 2"/>
<geom mesh="toroid" type="mesh" pos="-1 0 2"/>
<geom mesh="wedge" type="mesh" euler="90 -90 0"/>
<geom mesh="prism5" type="mesh" pos="2 0 0" euler="90 0 0"/>
<geom mesh="prism3" type="mesh" pos="3 0 0"/>
<geom mesh="cone6" type="mesh" pos="4 0 0" euler="90 0 0"/>
<geom mesh="cone4" type="mesh" pos="5 0 0" />
<geom name="floor" size="26 6 .05" type="plane" material="grid"/>
<light pos="-21 1 10"/>
<camera pos="-21 -5 15"/>
<geom pos="-23 3 1" mesh="s0" class="s"/>
<geom pos="-21 1 1" mesh="s1" class="s"/>
<geom pos="-19 -1 1" mesh="s2" class="s"/>
<site pos="-23 2 0" name="0"/>
<site pos="-21 0 0" name="1"/>
<site pos="-19 -2 0" name="2"/>
<site pos="-22 -3 1" name="sphere"/>
<light pos="-13 1 10"/>
<camera pos="-13 -5 15"/>
<geom pos="-15 3 1" mesh="h0" class="h"/>
<geom pos="-13 1 1" mesh="h2" class="h"/>
<geom pos="-11 -1 1" mesh="h4" class="h"/>
<site pos="-15 2 0" name=" 0"/>
<site pos="-13 0 0" name=" 2"/>
<site pos="-11 -2 0" name=" 4"/>
<site pos="-14 -3 1" name="hemisphere"/>
<light pos="-5 1 10"/>
<camera pos="-5 -5 15"/>
<geom pos="-7 3 1" mesh="c0" class="c"/>
<geom pos="-5 3 1" mesh="c1" class="c"/>
<geom pos="-3 3 1" mesh="c2" class="c"/>
<geom pos="-7 1 1" mesh="c3" class="c"/>
<geom pos="-5 1 1" mesh="c4" class="c"/>
<geom pos="-3 1 1" mesh="c5" class="c"/>
<geom pos="-7 -1 1" mesh="c6" class="c"/>
<geom pos="-5 -1 1" mesh="c7" class="c"/>
<geom pos="-3 -1 1" mesh="c7" class="c"/>
<site pos="-7 2 0" name="3 1"/>
<site pos="-5 2 0" name="5 1"/>
<site pos="-3 2 0" name="7 1"/>
<site pos="-7 0 0" name="3 .5"/>
<site pos="-5 0 0" name="5 .5"/>
<site pos="-3 0 0" name="7 .5"/>
<site pos="-7 -2 0" name="3 0"/>
<site pos="-5 -2 0" name="5 0"/>
<site pos="-3 -2 0" name="7 0"/>
<site pos="-6 -3 1" name="cone"/>
<light pos="3 1 10"/>
<camera pos="3 -5 15"/>
<geom pos="1 3 1" mesh="ss0" class="ss"/>
<geom pos="3 3 1" mesh="ss1" class="ss"/>
<geom pos="5 3 1" mesh="ss2" class="ss"/>
<geom pos="1 1 1" mesh="ss3" class="ss"/>
<geom pos="3 1 1" mesh="ss4" class="ss"/>
<geom pos="5 1 1" mesh="ss5" class="ss"/>
<geom pos="1 -1 1" mesh="ss6" class="ss"/>
<geom pos="3 -1 1" mesh="ss7" class="ss"/>
<geom pos="5 -1 1" mesh="ss8" class="ss"/>
<site pos="1 2 0" name=".4 .4"/>
<site pos="3 2 0" name=".4 1"/>
<site pos="5 2 0" name=".4 2"/>
<site pos="1 0 0" name=" 1 .4"/>
<site pos="3 0 0" name=" 1 1"/>
<site pos="5 0 0" name=" 1 2"/>
<site pos="1 -2 0" name=" 2 .4"/>
<site pos="3 -2 0" name=" 2 1"/>
<site pos="5 -2 0" name=" 2 2"/>
<site pos="2 -3 1" name="supersphere"/>
<light pos="11 1 10"/>
<camera pos="11 -5 15"/>
<geom pos="9 3 1" mesh="st0" class="st"/>
<geom pos="11 3 1" mesh="st1" class="st"/>
<geom pos="13 3 1" mesh="st2" class="st"/>
<geom pos="9 1 1" mesh="st3" class="st"/>
<geom pos="11 1 1" mesh="st4" class="st"/>
<geom pos="13 1 1" mesh="st5" class="st"/>
<geom pos="9 -1 1" mesh="st6" class="st"/>
<geom pos="11 -1 1" mesh="st7" class="st"/>
<geom pos="13 -1 1" mesh="st8" class="st"/>
<site pos="9 2 0" name=" .4 .4"/>
<site pos="11 2 0" name=" .4 1"/>
<site pos="13 2 0" name=" .4 2"/>
<site pos="9 0 0" name=" 1 .4"/>
<site pos="11 0 0" name=" 1 1"/>
<site pos="13 0 0" name=" 1 2"/>
<site pos="9 -2 0" name=" 2 .4"/>
<site pos="11 -2 0" name=" 2 1"/>
<site pos="13 -2 0" name=" 2 2"/>
<site pos="10 -3 1" name="supertorus"/>
<light pos="19 1 10"/>
<camera pos="19 -5 15"/>
<geom pos="17 3 1" mesh="w0" class="w"/>
<geom pos="19 3 1" mesh="w1" class="w"/>
<geom pos="21 3 1" mesh="w2" class="w"/>
<geom pos="17 1 1" mesh="w3" class="w"/>
<geom pos="19 1 1" mesh="w4" class="w"/>
<geom pos="21 1 1" mesh="w5" class="w"/>
<geom pos="17 -1 1" mesh="w6" class="w"/>
<geom pos="19 -1 1" mesh="w7" class="w"/>
<geom pos="21 -1 1" mesh="w8" class="w"/>
<site pos="17 2 0" name="45 20"/>
<site pos="19 2 0" name="45 45"/>
<site pos="21 2 0" name="45 90"/>
<site pos="17 0 0" name="90 20"/>
<site pos="19 0 0" name="90 45"/>
<site pos="21 0 0" name="90 90"/>
<site pos="17 -2 0" name="180 20"/>
<site pos="19 -2 0" name="180 45"/>
<site pos="21 -2 0" name="180 90"/>
<site pos="18 -3 1" name="wedge"/>
</worldbody>
</mujoco>