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` :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>`. 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: 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) :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. **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) :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. **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) :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. 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 place at (0, 0, 1) and the mesh is a 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. discrete cone. If radius is positive, the mesh is a truncated discrete cone.
**nvert**: integer >= 3: The number vertices in the polygon. **nvert**: integer >= 3: The number vertices in the polygon.
|br| **radius**: real in [0, 1]: The radius of the top face. |br| **radius**: real in [0, 1]: The radius of the top face.
:at-val:`supersphere` (resolution, e, n) .. image:: images/XMLreference/ss.png
A generalization of a sphere, also known as a superellipsoid (we use "supersphere" since semiaxis rescaling is :width: 23%
performed by the :ref:`scale<asset-mesh-scale>` attribute). If the **n** and **e** parameters are both 1, the :align: right
shape is a sphere. See `here <https://en.wikipedia.org/wiki/Superellipsoid>`__ for the definition of superspheres. :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| **e**: real >= 0: The "east-west" exponent.
|br| **n**: real >= 0: The "north-south" 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) :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 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 both 1, the shape is a torus. See `here <https://en.wikipedia.org/wiki/Supertoroid>`__ for more details. Note that
the definition of supertori. 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| **radius**: real in (0, 1]: The minor radius of the torus.
|br| **s**: real > 0: The "squareness" of major sections. |br| **s**: real > 0: The "squareness" of minor sections.
|br| **t**: 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) :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. **res_phi**: integer >= 0: The vertical resolution of the slice.
|br| **res_theta**: integer >= 0: The horizontal 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, 180]: The horizontal field of view (degrees).
|br| **fov_phi**: real in (0, 90): The vertical field of view (latitude) in 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. |br| **gamma**: real in [0, 1]: Foveal deformation of the discretization.
:at-val:`plate` (res_x, res_y) :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. **res_x**: integer > 0: The horizontal resolution of the plate.
|br| **res_y**: integer > 0: The vertical 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 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. 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 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 ``mjx.Data``. Some fields are no longer publicly available due to differences in the
underlying implementations of this data structure. underlying implementations of this data structure.
General General
^^^^^^^ ^^^^^^^
+14 -15
View File
@@ -1603,9 +1603,6 @@ native pipeline
.. _coDistance: .. _coDistance:
Geom distance
^^^^^^^^^^^^^
.. image:: ../images/computation/ccd_light.gif .. image:: ../images/computation/ccd_light.gif
:width: 25% :width: 25%
:align: right :align: right
@@ -1616,28 +1613,30 @@ Geom distance
:align: right :align: right
:class: only-dark :class: only-dark
Geom distance
^^^^^^^^^^^^^
The narrow-phase collision functions described :ref:`above<coChecking>` drive the :ref:`mj_geomDistance` function and 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 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 (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. contrast, the GJK-based native pipeline (bottom), computes the correct values at all distances.
.. _coDecomposition:
Convex decomposition 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 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 (which can be primitive shapes or meshes) and attach them to the same body. The other exception to this rule (besides
is automatically-decomposed into prisms 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 Open source mesh-decomposition tools like the `CoACD library <https://github.com/SarahWeiii/CoACD>`__ can be used
`CoACD library <https://github.com/SarahWeiii/CoACD>`__ can be used outside MuJoCo to automate this process. Finally, outside MuJoCo to automate this process. Finally, all built-in collision functions can be replaced with custom
all built-in collision functions can be replaced with custom callbacks. This can be used to incorporate a callbacks. This can be used to incorporate a general-purpose "triangle soup" collision detector for example. However we
general-purpose "triangle soup" collision detector for example. However we do not recommend such an approach. do not recommend such an approach. Pre-processing the geometry and representing it as a union of convex geoms takes some
Pre-processing the geometry and representing it as a union of convex geoms takes some work, but it pays off at runtime work, but it pays off at runtime and yields both faster and more stable simulation.
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.
.. _Pipeline: .. _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_site = parent.attach(child, site=site, prefix='child-')
worldframe_in_frame = parent.attach(child, frame=frame, prefix='child-') worldframe_in_frame = parent.attach(child, frame=frame, prefix='child-')
.. _PyEditConvenience:
Convenience methods 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 = 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. 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: .. _PyMJCF:
Relationship to ``PyMJCF`` and ``bind`` Relationship to ``PyMJCF`` and ``bind``
+200 -19
View File
@@ -1,26 +1,207 @@
<mujoco model="makemesh"> <mujoco model="makemesh">
<statistic meansize="1"/>
<visual>
<global offheight="2000" offwidth="2000"/>
</visual>
<asset> <asset>
<mesh name="sphere" builtin="sphere" params="2" scale=".8 .8 .8"/> <texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
<mesh name="hemisphere" builtin="hemisphere" params="4" scale=".8 .8 .8"/> <material name="grid" texture="grid" texrepeat=".5 .5" texuniform="true" reflectance=".2"/>
<mesh name="supersphere" builtin="supersphere" params="50 2 1" scale=".8 .8 .8"/> </asset>
<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"/> <default>
<mesh name="prism3" builtin="cone" params="3 1" scale=".3 .3 .3"/> <geom type="mesh"/>
<mesh name="prism5" builtin="cone" params="5 1" scale=".3 .3 .1"/> <camera xyaxes="1 0 0 0 2.7 1" fovy="27"/>
<mesh name="cone6" builtin="cone" params="6 0" scale=".3 .3 .7"/>
<mesh name="cone4" builtin="cone" params="4 .5" scale=".3 .3 .3"/> <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> </asset>
<worldbody> <worldbody>
<light pos="0 0 10"/> <geom name="floor" size="26 6 .05" type="plane" material="grid"/>
<geom mesh="sphere" type="mesh" pos="-3 0 0"/>
<geom mesh="hemisphere" type="mesh" pos="-1 0 0"/> <light pos="-21 1 10"/>
<geom mesh="supersphere" type="mesh" pos="2 0 2"/> <camera pos="-21 -5 15"/>
<geom mesh="toroid" type="mesh" pos="-1 0 2"/> <geom pos="-23 3 1" mesh="s0" class="s"/>
<geom mesh="wedge" type="mesh" euler="90 -90 0"/> <geom pos="-21 1 1" mesh="s1" class="s"/>
<geom mesh="prism5" type="mesh" pos="2 0 0" euler="90 0 0"/> <geom pos="-19 -1 1" mesh="s2" class="s"/>
<geom mesh="prism3" type="mesh" pos="3 0 0"/> <site pos="-23 2 0" name="0"/>
<geom mesh="cone6" type="mesh" pos="4 0 0" euler="90 0 0"/> <site pos="-21 0 0" name="1"/>
<geom mesh="cone4" type="mesh" pos="5 0 0" /> <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> </worldbody>
</mujoco> </mujoco>