merging with main mujoco repo

This commit is contained in:
Abhishek Joshi
2024-04-02 16:39:04 -04:00
136 changed files with 48702 additions and 2845 deletions
+49 -37
View File
@@ -2129,12 +2129,6 @@ from its default.
When this flag is enabled, :ref:`mj_inverse` will interpret ``qacc`` as having been computed from the difference of When this flag is enabled, :ref:`mj_inverse` will interpret ``qacc`` as having been computed from the difference of
two sequential velocities, and undo the above modification. two sequential velocities, and undo the above modification.
.. _option-flag-sensornoise:
:at:`sensornoise`: :at-val:`[disable, enable], "disable"`
This flag enables the simulation of sensor noise. When disabled (which is the default) noise is not added to
sensordata, even if the sensors specify non-zero noise amplitudes. When enabled, zero-mean Gaussian noise is added to
the underlying deterministic sensor data. Its standard deviation is determined by the noise parameter of each sensor.
.. _option-flag-multiccd: .. _option-flag-multiccd:
@@ -2354,24 +2348,6 @@ rotations as unit quaternions.
joint inertia in the model reference configuration. Note that the format is the same as the solref parameter of the joint inertia in the model reference configuration. Note that the format is the same as the solref parameter of the
constraint solver. constraint solver.
.. _body-joint-limited:
:at:`limited`: :at-val:`[false, true, auto], "auto"`
This attribute specifies if the joint has limits. It interacts with the range attribute below. If this attribute
is "false", joint limits are disabled. If this attribute is "true", joint limits are enabled. If this
attribute is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, joint limits will be enabled
if range is defined.
.. _body-joint-actuatorfrclimited:
:at:`actuatorfrclimited`: :at-val:`[false, true, auto], "auto"`
This attribute specifies whether actuator forces acting on the joint should be clamped. See :ref:`CForceRange` for
details. It is available only for scalar joints (hinge and slider) and ignored for ball and free joints. |br| This
attribute interacts with the actuatorfrcrange attribute below. If this attribute is "false", actuator force
clamping is disabled. If it is "true", actuator force clamping is enabled. If this attribute is "auto", and
:at:`autolimits` is set in :ref:`compiler <compiler>`, actuator force clamping will be enabled if actuatorfrcrange
is defined.
.. _body-joint-solreflimit: .. _body-joint-solreflimit:
.. _body-joint-solimplimit: .. _body-joint-solimplimit:
@@ -2400,16 +2376,44 @@ rotations as unit quaternions.
joints, the limit is imposed on the angle of rotation (relative to the reference configuration) regardless of the joints, the limit is imposed on the angle of rotation (relative to the reference configuration) regardless of the
axis of rotation. Only the second range parameter is used for ball joints; the first range parameter should be set to axis of rotation. Only the second range parameter is used for ball joints; the first range parameter should be set to
0. See the :ref:`Limit <coLimit>` section in the Computation chapter for more information. 0. See the :ref:`Limit <coLimit>` section in the Computation chapter for more information.
|br| Setting this attribute without specifying :at:`limited` is an error, unless :at:`autolimits` is set in |br| Setting this attribute without specifying :at:`limited` is an error if :at:`autolimits` is "false" in
:ref:`compiler <compiler>`. :ref:`compiler <compiler>`.
.. _body-joint-limited:
:at:`limited`: :at-val:`[false, true, auto], "auto"`
This attribute specifies if the joint has limits. It interacts with the range attribute below. If this attribute
is "false", joint limits are disabled. If this attribute is "true", joint limits are enabled. If this
attribute is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, joint limits will be enabled
if range is defined.
.. _body-joint-actuatorfrcrange: .. _body-joint-actuatorfrcrange:
:at:`actuatorfrcrange`: :at-val:`real(2), "0 0"` :at:`actuatorfrcrange`: :at-val:`real(2), "0 0"`
Range for clamping total actuator forces acting on this joint. See :ref:`CForceRange` for details. It is available Range for clamping total actuator forces acting on this joint. See :ref:`CForceRange` for details. It is available
only for scalar joints (hinge and slider) and ignored for ball and free joints. |br| The compiler expects the first only for scalar joints (hinge and slider) and ignored for ball and free joints. |br| The compiler expects the first
value to be smaller than the second value. |br| Setting this attribute without specifying :at:`actuatorfrclimited` value to be smaller than the second value. |br| Setting this attribute without specifying :at:`actuatorfrclimited`
is an error, unless :at:`compiler-autolimits` is set. is an error if :at:`compiler-autolimits` is "false".
.. _body-joint-actuatorfrclimited:
:at:`actuatorfrclimited`: :at-val:`[false, true, auto], "auto"`
This attribute specifies whether actuator forces acting on the joint should be clamped. See :ref:`CForceRange` for
details. It is available only for scalar joints (hinge and slider) and ignored for ball and free joints. |br| This
attribute interacts with the actuatorfrcrange attribute below. If this attribute is "false", actuator force
clamping is disabled. If it is "true", actuator force clamping is enabled. If this attribute is "auto", and
:at:`autolimits` is set in :ref:`compiler <compiler>`, actuator force clamping will be enabled if
:at:`actuatorfrcrange` is defined.
.. _body-joint-actuatorgravcomp:
:at:`actuatorgravcomp`: :at-val:`[false, true], "false"`
If this flag is enabled, gravity compensation applied to this joint is added to actuator forces
(``mjData.qfrc_actuator``) rather than passive forces (``mjData.qfrc_passive``). Notionally, this means that gravity
compensation is the result of a control system rather than natural buoyancy. In practice, enabling this flag is
useful when joint-level actuator force clamping is used. In this case, the total actuation force applied on a joint,
including gravity compensation, is guaranteed to not exceeed the specified limits. See :ref:`CForceRange` and
:ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` for more details on this type of force limit.
.. _body-joint-margin: .. _body-joint-margin:
@@ -3808,8 +3812,12 @@ saving the XML:
in MuJoCo can be used as a rigid geom attached to a single body. In contrast, the flex generated here corresponds to in MuJoCo can be used as a rigid geom attached to a single body. In contrast, the flex generated here corresponds to
a soft mesh with the same initial shape, where each vertex is a separate moving body (unless pinned). a soft mesh with the same initial shape, where each vertex is a separate moving body (unless pinned).
**gmsh** is similar to mesh, but it loads a `GMSH file <https://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format>`__ .. _gmsh-file-docs:
in format 4.1 (ascii or binary). The file extension can be anything; the parser recognizes the format by examining
**gmsh** is similar to mesh, but it loads a GMSH file in
`format 4.1 <https://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format>`__
and `format 2.2 <https://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format-version-2-_0028Legacy_0029>`__
(ascii or binary). The file extension can be anything; the parser recognizes the format by examining
the file header. This is a very rich file format, allowing all kinds of elements with different dimensionality and the file header. This is a very rich file format, allowing all kinds of elements with different dimensionality and
topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes and topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes and
assumes that the nodes are specified in a single block. Only the Nodes and Elements sections of the GMHS file are assumes that the nodes are specified in a single block. Only the Nodes and Elements sections of the GMHS file are
@@ -3817,7 +3825,7 @@ saving the XML:
GMSH file contains meshes that are not supported by MuJoCo. :at:`dim` is automatically set to the dimensionality GMSH file contains meshes that are not supported by MuJoCo. :at:`dim` is automatically set to the dimensionality
specified in the GMSH file. Presently this is the only mechanism to load a large tetrahedral mesh in MuJoCo and specified in the GMSH file. Presently this is the only mechanism to load a large tetrahedral mesh in MuJoCo and
generate a corresponding soft entity. If such a mesh is available in a different file format, use the freely generate a corresponding soft entity. If such a mesh is available in a different file format, use the freely
available `GMSH software <https://gmsh.info/>`__ to convert it to GMSH 4.1. available `GMSH software <https://gmsh.info/>`__ to convert it to GMSH in one of the supported versions.
**direct** allows the user to specify the point and element data of the flexcomp directly in the XML. Note that **direct** allows the user to specify the point and element data of the flexcomp directly in the XML. Note that
flexcomp will still generate moving bodies automatically, as well as automate other settings; so it still provides flexcomp will still generate moving bodies automatically, as well as automate other settings; so it still provides
@@ -3873,7 +3881,7 @@ saving the XML:
:at:`file`: :at-val:`string, optional` :at:`file`: :at-val:`string, optional`
The name of the file from which a **mesh** or a **gmsh** is loaded. For mesh, the file extentsion is used to The name of the file from which a **mesh** or a **gmsh** is loaded. For mesh, the file extentsion is used to
determine the file format. Supported formats are the same as in :ref:`mesh assets<asset-mesh>`. For gmsh, the file is determine the file format. Supported formats are the same as in :ref:`mesh assets<asset-mesh>`. For gmsh, the file is
expected to be in GMSH format 4.1, ascii or binary. expected to be in GMSH format 4.1 or 2.2, ascii or binary, see :ref:`here<gmsh-file-docs>`.
.. _body-flexcomp-rigid: .. _body-flexcomp-rigid:
@@ -5092,14 +5100,14 @@ specify them independently.
:at:`ctrlrange`: :at-val:`real(2), "0 0"` :at:`ctrlrange`: :at-val:`real(2), "0 0"`
Range for clamping the control input. The first value must be smaller than the second value. Range for clamping the control input. The first value must be smaller than the second value.
|br| Setting this attribute without specifying :at:`ctrllimited` is an error, unless :at:`autolimits` is set in |br| Setting this attribute without specifying :at:`ctrllimited` is an error if :at:`autolimits` is "false" in
:ref:`compiler <compiler>`. :ref:`compiler <compiler>`.
.. _actuator-general-forcerange: .. _actuator-general-forcerange:
:at:`forcerange`: :at-val:`real(2), "0 0"` :at:`forcerange`: :at-val:`real(2), "0 0"`
Range for clamping the force output. The first value must be no greater than the second value. Range for clamping the force output. The first value must be no greater than the second value.
|br| Setting this attribute without specifying :at:`forcelimited` is an error, unless :at:`autolimits` is set in |br| Setting this attribute without specifying :at:`forcelimited` is an error if :at:`autolimits` is "false" in
:ref:`compiler <compiler>`. :ref:`compiler <compiler>`.
.. _actuator-general-actrange: .. _actuator-general-actrange:
@@ -5107,7 +5115,7 @@ specify them independently.
:at:`actrange`: :at-val:`real(2), "0 0"` :at:`actrange`: :at-val:`real(2), "0 0"`
Range for clamping the activation state. The first value must be no greater than the second value. Range for clamping the activation state. The first value must be no greater than the second value.
See the :ref:`Activation clamping <CActRange>` section for more details. See the :ref:`Activation clamping <CActRange>` section for more details.
|br| Setting this attribute without specifying :at:`actlimited` is an error, unless :at:`autolimits` is set in |br| Setting this attribute without specifying :at:`actlimited` is an error if :at:`autolimits` is "false" in
:ref:`compiler <compiler>`. :ref:`compiler <compiler>`.
.. _actuator-general-lengthrange: .. _actuator-general-lengthrange:
@@ -6485,10 +6493,12 @@ arms determined by the transmission). This sensor can be attached to any actuato
:el-prefix:`sensor/` |-| **jointactuatorfrc** (*) :el-prefix:`sensor/` |-| **jointactuatorfrc** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This element creates an actuator force sensor, measured at a joint. The quantity being sensed is the This element creates an actuator force sensor, measured at a joint. The quantity being sensed is the generalized force
generalized force contributed by all actuators to a single scalar joint (hinge or slider). This type of sensor is contributed by all actuators to a single scalar joint (hinge or slider). If the joint's
important when multiple actuators act on a single joint or when a single actuator act on multiple joints. See :ref:`actuatorgravcomp<body-joint-actuatorgravcomp>` attribute is "true", this sensor will also measure contributions by
:ref:`CForceRange` for details. gravity compensation forces (which are added directly to the joint and would *not* register in the
:ref:`actuatorfrc<sensor-actuatorfrc>`) sensor. This type of sensor is important when multiple actuators act on a single
joint or when a single actuator act on multiple joints. See :ref:`CForceRange` for details.
.. _sensor-jointactuatorfrc-name: .. _sensor-jointactuatorfrc-name:
@@ -7382,6 +7392,8 @@ if omitted.
.. _default-joint-actuatorfrclimited: .. _default-joint-actuatorfrclimited:
.. _default-joint-actuatorgravcomp:
.. _default-joint-solreflimit: .. _default-joint-solreflimit:
.. _default-joint-solimplimit: .. _default-joint-solimplimit:
+7 -7
View File
@@ -247,9 +247,9 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`sensor<option-flag-sensor>` | :ref:`midphase<option-flag-midphase>` | :ref:`eulerdamp<option-flag-eulerdamp>` | :ref:`override<option-flag-override>` | | | | | | :ref:`sensor<option-flag-sensor>` | :ref:`midphase<option-flag-midphase>` | :ref:`eulerdamp<option-flag-eulerdamp>` | :ref:`override<option-flag-override>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`energy<option-flag-energy>` | :ref:`fwdinv<option-flag-fwdinv>` | :ref:`invdiscrete<option-flag-invdiscrete>` | :ref:`sensornoise<option-flag-sensornoise>` | | | | | | :ref:`energy<option-flag-energy>` | :ref:`fwdinv<option-flag-fwdinv>` | :ref:`invdiscrete<option-flag-invdiscrete>` | :ref:`multiccd<option-flag-multiccd>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`multiccd<option-flag-multiccd>` | :ref:`island<option-flag-island>` | | | | | | | | :ref:`island<option-flag-island>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mujoco |br| |L| | | .. table:: | | mujoco |br| |L| | | .. table:: |
@@ -286,9 +286,9 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`solimpfriction<body-joint-solimpfriction>` | :ref:`stiffness<body-joint-stiffness>` | :ref:`range<body-joint-range>` | :ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` | | | | | | :ref:`solimpfriction<body-joint-solimpfriction>` | :ref:`stiffness<body-joint-stiffness>` | :ref:`range<body-joint-range>` | :ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`margin<body-joint-margin>` | :ref:`ref<body-joint-ref>` | :ref:`springref<body-joint-springref>` | :ref:`armature<body-joint-armature>` | | | | | | :ref:`actuatorgravcomp<body-joint-actuatorgravcomp>` | :ref:`margin<body-joint-margin>` | :ref:`ref<body-joint-ref>` | :ref:`springref<body-joint-springref>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`damping<body-joint-damping>` | :ref:`frictionloss<body-joint-frictionloss>` | :ref:`user<body-joint-user>` | | | | | | | :ref:`armature<body-joint-armature>` | :ref:`damping<body-joint-damping>` | :ref:`frictionloss<body-joint-frictionloss>` | :ref:`user<body-joint-user>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_| body |br| |_| |L| | | .. table:: | | |_| body |br| |_| |L| | | .. table:: |
@@ -1320,11 +1320,11 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`solimplimit<default-joint-solimplimit>` | :ref:`solreffriction<default-joint-solreffriction>` | :ref:`solimpfriction<default-joint-solimpfriction>` | :ref:`stiffness<default-joint-stiffness>` | | | | | | :ref:`solimplimit<default-joint-solimplimit>` | :ref:`solreffriction<default-joint-solreffriction>` | :ref:`solimpfriction<default-joint-solimpfriction>` | :ref:`stiffness<default-joint-stiffness>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`range<default-joint-range>` | :ref:`actuatorfrcrange<default-joint-actuatorfrcrange>` | :ref:`margin<default-joint-margin>` | :ref:`ref<default-joint-ref>` | | | | | | :ref:`range<default-joint-range>` | :ref:`actuatorfrcrange<default-joint-actuatorfrcrange>` | :ref:`actuatorgravcomp<default-joint-actuatorgravcomp>` | :ref:`margin<default-joint-margin>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`springref<default-joint-springref>` | :ref:`armature<default-joint-armature>` | :ref:`damping<default-joint-damping>` | :ref:`frictionloss<default-joint-frictionloss>` | | | | | | :ref:`ref<default-joint-ref>` | :ref:`springref<default-joint-springref>` | :ref:`armature<default-joint-armature>` | :ref:`damping<default-joint-damping>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`user<default-joint-user>` | | | | | | | | | :ref:`frictionloss<default-joint-frictionloss>` | :ref:`user<default-joint-user>` | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_| default |br| |_| |L| | | .. table:: | | |_| default |br| |_| |L| | | .. table:: |
+52 -12
View File
@@ -5,14 +5,62 @@ Changelog
Upcoming version (not yet released) Upcoming version (not yet released)
----------------------------------- -----------------------------------
General
^^^^^^^
.. admonition:: Breaking API changes
:class: attention
1. Removed the ability to natively add noise to sensors. Note that the ``mjModel.sensor_noise`` field and
:ref:`corresponding attribute<CSensor>` are kept and now function as a convenient location for the user to save
standard-deviation information for their own use. This feature was removed because:
- There was no mechanism to seed the randon noise generator.
- It was not thread-safe, even if seeding would have been provided, sampling on multiple threads would lead to
non-reproducible results.
- This feature was seen as overreach by the engine. Adding noise should be the user's responsibility.
- We are not aware of anyone who was actually using the feature.
**Migration:** Add noise to sensor values yourself.
2. Added the :ref:`actuatorgravcomp<body-joint-actuatorgravcomp>` joint attribute. When enabled, gravity compensation
forces on the joint are treated as applied by actuators. See attribute documentation for more details. The example
model
`refsite.xml <https://github.com/google-deepmind/mujoco/blob/main/test/engine/testdata/actuation/refsite.xml>`__,
which demostrates Cartesian actuation of an arm, has been updated to use this attribute.
3. Added support for gmsh format 2.2, as generated by e.g. `fTetwild <https://github.com/wildmeshing/fTetWild>`__.
MJX MJX
^^^ ^^^
4. Improved performance of SAT for convex collisions.
5. Fixed bug for sphere/capsule-convex deep penetration.
6. Fixed bug where ``mjx.Data`` produced by ``mjx.put_data`` had different treedef than ``mjx.make_data``.
7. Throw an error for margin/gap for convex mesh collisions, since they are not supported.
Simulate
^^^^^^^^
8. Fixed bug in order of enable flag strings. Before this change, using the simulate UI to toggle the
:ref:`invdiscrete<option-flag-invdiscrete>` or the (now removed) ``sensornoise`` flags would actually toggle the
other flag.
Python bindings
^^^^^^^^^^^^^^^
.. youtube:: xHDS0n5DpqM
:align: right
:width: 240px
9. Added the ``mujoco.minimize`` Python module for nonlinear least-squares, designed for System Identification (sysID).
The sysID tutorial is work in progress, but a pedagogical colab notebook with examples, including Inverse
Kinematics, is available here: |ls_colab|
|br| The video on the right shows example clips from the tutorial.
.. |ls_colab| image:: https://colab.research.google.com/assets/colab-badge.svg
:target: https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/python/least_squares.ipynb
1. Improved performance of SAT for convex collisions.
2. Fixed bug for sphere/capsule-convex deep penetration.
Version 3.1.3 (March 5th, 2024) Version 3.1.3 (March 5th, 2024)
----------------------------------- -------------------------------
General General
^^^^^^^ ^^^^^^^
@@ -31,7 +79,6 @@ General
MJX MJX
^^^ ^^^
4. Improved performance of getting and putting device data. 4. Improved performance of getting and putting device data.
- Use ``tobytes()`` for numpy array serialization, which is orders of magnitude faster than converting to tuples. - Use ``tobytes()`` for numpy array serialization, which is orders of magnitude faster than converting to tuples.
@@ -50,16 +97,9 @@ Python bindings
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
11. Fixed incorrect data types in the bindings for the ``geom``, ``vert``, ``elem``, and ``flex`` array members 11. Fixed incorrect data types in the bindings for the ``geom``, ``vert``, ``elem``, and ``flex`` array members
of the ``mjContact`` struct, and all array members of the ``mjrContext`` struct. of the ``mjContact`` struct, and all array members of the ``mjrContext`` struct.
12. Added the ``mujoco.minimize`` Python module for nonlinear least-squares, designed for System Identification (sysID).
The sysID tutorial is work in progress, but a pedagogical colab notebook with examples, including Inverse
Kinematics, is available here: |ls_colab|
.. |ls_colab| image:: https://colab.research.google.com/assets/colab-badge.svg
:target: https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/python/least_squares.ipynb
Version 3.1.2 (February 05, 2024) Version 3.1.2 (February 05, 2024)
----------------------------------- ---------------------------------
General General
^^^^^^^ ^^^^^^^
+2 -4
View File
@@ -85,8 +85,7 @@ Ellipsoid model
:figwidth: 50% :figwidth: 50%
:align: right :align: right
The flight-capable Drosophila Melanogaster model in this figure will be described in a The flight-capable Drosophila Melanogaster model in this figure is described in :cite:t:`Vaxenburg2024`.
forthcoming publication.
In this section we describe and derive a stateless model of the forces exerted onto a moving rigid body by the In this section we describe and derive a stateless model of the forces exerted onto a moving rigid body by the
@@ -94,7 +93,6 @@ surrounding fluid, based on an ellipsoidal approximation of geom shape. This mod
different types of fluid forces than the inertia-based model of the previous section. The motivating use-case for this different types of fluid forces than the inertia-based model of the previous section. The motivating use-case for this
model is insect flight, see figure on the right. model is insect flight, see figure on the right.
Summary Summary
~~~~~~~ ~~~~~~~
@@ -426,7 +424,7 @@ increasing Reynolds numbers, and a single reference area :math:`A_D` may not be
drag for highly irregular or slender bodies. For example, experimental fits are derived from problems ranging from drag for highly irregular or slender bodies. For example, experimental fits are derived from problems ranging from
falling playing cards :cite:p:`wang2004,andersen2005a,andersen2005b` to particle transport :cite:p:`loth2008, falling playing cards :cite:p:`wang2004,andersen2005a,andersen2005b` to particle transport :cite:p:`loth2008,
bagheri2016`. See screen capture of the bagheri2016`. See screen capture of the
`cards.xml <https://github.com/deepmind/mujoco/blob/main/model/card/cards.xml>`__ model on the right. `cards.xml <https://github.com/deepmind/mujoco/blob/main/model/cards/cards.xml>`__ model on the right.
We derive a formula for :math:`\mathbf{f}_\text{D}` based on two surfaces :math:`A^\text{proj}_\mathbf{v}` and We derive a formula for :math:`\mathbf{f}_\text{D}` based on two surfaces :math:`A^\text{proj}_\mathbf{v}` and
:math:`A_\text{max}`. The first, :math:`A^\text{proj}_\mathbf{v}`, is the cylindrical projection of the body onto a :math:`A_\text{max}`. The first, :math:`A^\text{proj}_\mathbf{v}`, is the cylindrical projection of the body onto a
+7 -7
View File
@@ -426,12 +426,11 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
mjENBL_ENERGY = 1<<1, // energy computation mjENBL_ENERGY = 1<<1, // energy computation
mjENBL_FWDINV = 1<<2, // record solver statistics mjENBL_FWDINV = 1<<2, // record solver statistics
mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics
mjENBL_SENSORNOISE = 1<<4, // add noise to sensor data
// experimental features: // experimental features:
mjENBL_MULTICCD = 1<<5, // multi-point convex collision detection mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
mjENBL_ISLAND = 1<<6, // constraint island discovery mjENBL_ISLAND = 1<<5, // constraint island discovery
mjNENABLE = 7 // number of enable flags mjNENABLE = 6 // number of enable flags
} mjtEnableBit; } mjtEnableBit;
typedef enum mjtJoint_ { // type of degree of freedom typedef enum mjtJoint_ { // type of degree of freedom
mjJNT_FREE = 0, // global position and orientation (quat) (7) mjJNT_FREE = 0, // global position and orientation (quat) (7)
@@ -926,9 +925,9 @@ struct mjModel_ {
int nemax; // number of potential equality-constraint rows int nemax; // number of potential equality-constraint rows
int njmax; // number of available rows in constraint Jacobian int njmax; // number of available rows in constraint Jacobian
int nconmax; // number of potential contacts in contact list int nconmax; // number of potential contacts in contact list
int nuserdata; // number of extra fields in mjData int nuserdata; // number of mjtNums reserved for the user
int nsensordata; // number of fields in sensor data vector int nsensordata; // number of mjtNums in sensor data vector
int npluginstate; // number of fields in plugin state vector int npluginstate; // number of mjtNums in plugin state vector
size_t narena; // number of bytes in the mjData arena (inclusive of stack) size_t narena; // number of bytes in the mjData arena (inclusive of stack)
size_t nbuffer; // number of bytes in buffer size_t nbuffer; // number of bytes in buffer
@@ -993,6 +992,7 @@ struct mjModel_ {
int* jnt_group; // group for visibility (njnt x 1) int* jnt_group; // group for visibility (njnt x 1)
mjtByte* jnt_limited; // does joint have limits (njnt x 1) mjtByte* jnt_limited; // does joint have limits (njnt x 1)
mjtByte* jnt_actfrclimited; // does joint have actuator force limits (njnt x 1) mjtByte* jnt_actfrclimited; // does joint have actuator force limits (njnt x 1)
mjtByte* jnt_actgravcomp; // is gravcomp force applied via actuators (njnt x 1)
mjtNum* jnt_solref; // constraint solver reference: limit (njnt x mjNREF) mjtNum* jnt_solref; // constraint solver reference: limit (njnt x mjNREF)
mjtNum* jnt_solimp; // constraint solver impedance: limit (njnt x mjNIMP) mjtNum* jnt_solimp; // constraint solver impedance: limit (njnt x mjNIMP)
mjtNum* jnt_pos; // local anchor position (njnt x 3) mjtNum* jnt_pos; // local anchor position (njnt x 3)
+13 -12
View File
@@ -215,6 +215,14 @@ The following features are **in development** and coming soon:
* - Category * - Category
- Feature - Feature
* - :ref:`Geom <mjtGeom>`
- ``SDF``, ``HFIELD``, ``ELLIPSOID``, ``CYLINDER``
* - :ref:`Condim <coContact>`
- 1, 4, 6
* - :ref:`Constraint <mjtConstraint>`
- :ref:`Frictionloss <coFriction>`, ``CONTACT_FRICTIONLESS``, ``CONTACT_ELLIPTIC``, ``FRICTION_DOF``
* - :ref:`Integrator <mjtIntegrator>`
- ``IMPLICIT``, ``IMPLICITFAST``
* - Dynamics * - Dynamics
- :ref:`Inverse <mj_inverse>` - :ref:`Inverse <mj_inverse>`
* - :ref:`Transmission <mjtTrn>` * - :ref:`Transmission <mjtTrn>`
@@ -227,16 +235,8 @@ The following features are **in development** and coming soon:
- ``MUSCLE`` - ``MUSCLE``
* - :ref:`Tendon Wrapping <mjtWrap>` * - :ref:`Tendon Wrapping <mjtWrap>`
- ``NONE``, ``JOINT``, ``PULLEY``, ``SITE``, ``SPHERE``, ``CYLINDER`` - ``NONE``, ``JOINT``, ``PULLEY``, ``SITE``, ``SPHERE``, ``CYLINDER``
* - :ref:`Geom <mjtGeom>`
- ``HFIELD``, ``ELLIPSOID``, ``CYLINDER``
* - :ref:`Constraint <mjtConstraint>`
- :ref:`Frictionloss <coFriction>`, ``CONTACT_FRICTIONLESS``, ``CONTACT_ELLIPTIC``, ``FRICTION_DOF``
* - :ref:`Integrator <mjtIntegrator>`
- ``IMPLICIT``, ``IMPLICITFAST``
* - :ref:`Cone <mjtCone>` * - :ref:`Cone <mjtCone>`
- ``ELLIPTIC`` - ``ELLIPTIC``
* - :ref:`Condim <coContact>`
- 1, 4, 6
* - Fluid Model * - Fluid Model
- :ref:`flEllipsoid` - :ref:`flEllipsoid`
* - :ref:`Tendons <tendon>` * - :ref:`Tendons <tendon>`
@@ -258,6 +258,8 @@ The following features are **unsupported**:
* - Category * - Category
- Feature - Feature
* - :ref:`margin<body-geom-margin>` and :ref:`gap<body-geom-gap>`
- Unimplemented for collisions with ``Mesh`` :ref:`Geom <mjtGeom>`.
* - :ref:`Transmission <mjtTrn>` * - :ref:`Transmission <mjtTrn>`
- ``TRN_JOINTINPARENT``, ``TRN_SLIDERCRANK``, ``TRN_BODY`` - ``TRN_JOINTINPARENT``, ``TRN_SLIDERCRANK``, ``TRN_BODY``
* - :ref:`Actuator Dynamics <mjtDyn>` * - :ref:`Actuator Dynamics <mjtDyn>`
@@ -270,8 +272,6 @@ The following features are **unsupported**:
- ``PGS`` - ``PGS``
* - :ref:`Sensors <mjtSensor>` * - :ref:`Sensors <mjtSensor>`
- ``PLUGIN``, ``USER`` - ``PLUGIN``, ``USER``
* - :ref:`Geom <mjtGeom>`
- ``SDF``
.. _MjxSharpBits: .. _MjxSharpBits:
@@ -299,8 +299,9 @@ Collisions between large meshes
SAT works well for smaller meshes but suffers in both runtime and memory for larger meshes. SAT works well for smaller meshes but suffers in both runtime and memory for larger meshes.
For For
collisions with convex meshes, the convex decompositon of the mesh should have collisions with convex meshes and primitives, the convex decompositon of the mesh should have
roughly **200 vertices or less** for reasonable performance. roughly **200 vertices or less** for reasonable performance. For convex-convex collisions,
the convex mesh should have roughly **fewer than 32 vertices**.
With careful With careful
tuning, MJX can simulate scenes with mesh collisions -- see the MJX tuning, MJX can simulate scenes with mesh collisions -- see the MJX
`shadow hand <https://github.com/google-deepmind/mujoco/tree/main/mjx/mujoco/mjx/benchmark/model/shadow_hand>`__ `shadow hand <https://github.com/google-deepmind/mujoco/tree/main/mjx/mujoco/mjx/benchmark/model/shadow_hand>`__
+8 -4
View File
@@ -421,7 +421,7 @@ and the damping ratio is ignored. Equivalently, in the direct format, the :math:
impedance is constant, then the penetration depth at rest is impedance is constant, then the penetration depth at rest is
.. math:: .. math::
r = \au \cdot (1 - d) \cdot \text{stiffness} r = \frac{\au (1 - d)}{\text{stiffness}}
.. tip:: .. tip::
In the positive-value default format, the :math:`\text{timeconst}` parameter controls constraint **softness**. In the positive-value default format, the :math:`\text{timeconst}` parameter controls constraint **softness**.
@@ -431,6 +431,9 @@ and the damping ratio is ignored. Equivalently, in the direct format, the :math:
The negative-value "direct" format is more flexible, for example allowing for perfectly elastic collisions The negative-value "direct" format is more flexible, for example allowing for perfectly elastic collisions
(:math:`\text{damping} = 0`). It is the recommended format for system identification. (:math:`\text{damping} = 0`). It is the recommended format for system identification.
A :math:`\text{dampratio}` of 1 in the positive-value format is equivalent to
:math:`\text{damping} = 2 \sqrt{ \text{stiffness} }` in the direct format.
.. _CContact: .. _CContact:
Contact parameters Contact parameters
@@ -1057,9 +1060,10 @@ Here we describe the XML attributes common to all sensor types, so as to avoid r
:at:`name`: :at-val:`string, optional` :at:`name`: :at-val:`string, optional`
Name of the sensor. Name of the sensor.
:at:`noise`: :at-val:`real, "0"` :at:`noise`: :at-val:`real, "0"`
The standard deviation of zero-mean Gaussian noise added to the sensor output, when the :at:`sensornoise` The standard deviation of the noise model of this sensor. In versions prior to 3.1.4, this would lead to noise being
attribute of :ref:`flag <option-flag>` is enabled. Sensor noise respects the sensor data type: added to the sensors. In release 3.1.4 this feature was removed, see :doc:`3.1.4 changelog <changelog>` for a
quaternions and unit vectors remain normalized, non-negative quantities remain non-negative. detailed justification. As of subsequent versions, this attrbute serves as a convenient location for saving standard
deviation information for later use.
:at:`cutoff`: :at-val:`real, "0"` :at:`cutoff`: :at-val:`real, "0"`
When this value is positive, it limits the absolute value of the sensor output. It is also used to normalize the When this value is positive, it limits the absolute value of the sensor output. It is also used to normalize the
sensor output in the sensor data plots in :ref:`simulate.cc <saSimulate>`. sensor output in the sensor data plots in :ref:`simulate.cc <saSimulate>`.
+11
View File
@@ -88,3 +88,14 @@
year={2015}, year={2015},
publisher={Nature Publishing Group} publisher={Nature Publishing Group}
} }
@article {Vaxenburg2024,
author = {Roman Vaxenburg and Igor Siwanowicz and Josh Merel and Alice A Robie and Carmen Morrow and Guido Novati and Zinovia Stefanidi and Gwyneth M Card and Michael B Reiser and Matthew M Botvinick and Kristin M Branson and Yuval Tassa and Srinivas C Turaga},
title = {Whole-body simulation of realistic fruit fly locomotion with deep reinforcement learning},
elocation-id = {2024.03.11.584515},
year = {2024},
doi = {10.1101/2024.03.11.584515},
publisher = {Cold Spring Harbor Laboratory},
journal = {bioRxiv}
}
+7 -7
View File
@@ -74,12 +74,11 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
mjENBL_ENERGY = 1<<1, // energy computation mjENBL_ENERGY = 1<<1, // energy computation
mjENBL_FWDINV = 1<<2, // record solver statistics mjENBL_FWDINV = 1<<2, // record solver statistics
mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics
mjENBL_SENSORNOISE = 1<<4, // add noise to sensor data
// experimental features: // experimental features:
mjENBL_MULTICCD = 1<<5, // multi-point convex collision detection mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
mjENBL_ISLAND = 1<<6, // constraint island discovery mjENBL_ISLAND = 1<<5, // constraint island discovery
mjNENABLE = 7 // number of enable flags mjNENABLE = 6 // number of enable flags
} mjtEnableBit; } mjtEnableBit;
@@ -641,9 +640,9 @@ struct mjModel_ {
int nemax; // number of potential equality-constraint rows int nemax; // number of potential equality-constraint rows
int njmax; // number of available rows in constraint Jacobian int njmax; // number of available rows in constraint Jacobian
int nconmax; // number of potential contacts in contact list int nconmax; // number of potential contacts in contact list
int nuserdata; // number of extra fields in mjData int nuserdata; // number of mjtNums reserved for the user
int nsensordata; // number of fields in sensor data vector int nsensordata; // number of mjtNums in sensor data vector
int npluginstate; // number of fields in plugin state vector int npluginstate; // number of mjtNums in plugin state vector
size_t narena; // number of bytes in the mjData arena (inclusive of stack) size_t narena; // number of bytes in the mjData arena (inclusive of stack)
size_t nbuffer; // number of bytes in buffer size_t nbuffer; // number of bytes in buffer
@@ -708,6 +707,7 @@ struct mjModel_ {
int* jnt_group; // group for visibility (njnt x 1) int* jnt_group; // group for visibility (njnt x 1)
mjtByte* jnt_limited; // does joint have limits (njnt x 1) mjtByte* jnt_limited; // does joint have limits (njnt x 1)
mjtByte* jnt_actfrclimited; // does joint have actuator force limits (njnt x 1) mjtByte* jnt_actfrclimited; // does joint have actuator force limits (njnt x 1)
mjtByte* jnt_actgravcomp; // is gravcomp force applied via actuators (njnt x 1)
mjtNum* jnt_solref; // constraint solver reference: limit (njnt x mjNREF) mjtNum* jnt_solref; // constraint solver reference: limit (njnt x mjNREF)
mjtNum* jnt_solimp; // constraint solver impedance: limit (njnt x mjNIMP) mjtNum* jnt_solimp; // constraint solver impedance: limit (njnt x mjNIMP)
mjtNum* jnt_pos; // local anchor position (njnt x 3) mjtNum* jnt_pos; // local anchor position (njnt x 3)
+1
View File
@@ -215,6 +215,7 @@
XMJV( int, jnt_group, njnt, 1 ) \ XMJV( int, jnt_group, njnt, 1 ) \
X ( mjtByte, jnt_limited, njnt, 1 ) \ X ( mjtByte, jnt_limited, njnt, 1 ) \
X ( mjtByte, jnt_actfrclimited, njnt, 1 ) \ X ( mjtByte, jnt_actfrclimited, njnt, 1 ) \
X ( mjtByte, jnt_actgravcomp, njnt, 1 ) \
X ( mjtNum, jnt_solref, njnt, mjNREF ) \ X ( mjtNum, jnt_solref, njnt, mjNREF ) \
X ( mjtNum, jnt_solimp, njnt, mjNIMP ) \ X ( mjtNum, jnt_solimp, njnt, mjNIMP ) \
X ( mjtNum, jnt_pos, njnt, 3 ) \ X ( mjtNum, jnt_pos, njnt, 3 ) \
+3 -4
View File
@@ -54,10 +54,9 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjENBL_ENERGY', 2), ('mjENBL_ENERGY', 2),
('mjENBL_FWDINV', 4), ('mjENBL_FWDINV', 4),
('mjENBL_INVDISCRETE', 8), ('mjENBL_INVDISCRETE', 8),
('mjENBL_SENSORNOISE', 16), ('mjENBL_MULTICCD', 16),
('mjENBL_MULTICCD', 32), ('mjENBL_ISLAND', 32),
('mjENBL_ISLAND', 64), ('mjNENABLE', 6),
('mjNENABLE', 7),
]), ]),
)), )),
('mjtJoint', ('mjtJoint',
+3 -4
View File
@@ -42,10 +42,9 @@ class EnumsTest(absltest.TestCase):
('mjENBL_ENERGY', 1<<1), ('mjENBL_ENERGY', 1<<1),
('mjENBL_FWDINV', 1<<2), ('mjENBL_FWDINV', 1<<2),
('mjENBL_INVDISCRETE', 1<<3), ('mjENBL_INVDISCRETE', 1<<3),
('mjENBL_SENSORNOISE', 1<<4), ('mjENBL_MULTICCD', 1<<4),
('mjENBL_MULTICCD', 1<<5), ('mjENBL_ISLAND', 1<<5),
('mjENBL_ISLAND', 1<<6), ('mjNENABLE', 6)))
('mjNENABLE', 7)))
# values mostly increment by one with occasional overrides # values mostly increment by one with occasional overrides
def test_mjtGeom(self): # pylint: disable=invalid-name def test_mjtGeom(self): # pylint: disable=invalid-name
+10 -3
View File
@@ -1218,17 +1218,17 @@ STRUCTS: Mapping[str, StructDecl] = dict([
StructFieldDecl( StructFieldDecl(
name='nuserdata', name='nuserdata',
type=ValueType(name='int'), type=ValueType(name='int'),
doc='number of extra fields in mjData', doc='number of mjtNums reserved for the user',
), ),
StructFieldDecl( StructFieldDecl(
name='nsensordata', name='nsensordata',
type=ValueType(name='int'), type=ValueType(name='int'),
doc='number of fields in sensor data vector', doc='number of mjtNums in sensor data vector',
), ),
StructFieldDecl( StructFieldDecl(
name='npluginstate', name='npluginstate',
type=ValueType(name='int'), type=ValueType(name='int'),
doc='number of fields in plugin state vector', doc='number of mjtNums in plugin state vector',
), ),
StructFieldDecl( StructFieldDecl(
name='narena', name='narena',
@@ -1556,6 +1556,13 @@ STRUCTS: Mapping[str, StructDecl] = dict([
), ),
doc='does joint have actuator force limits (njnt x 1)', doc='does joint have actuator force limits (njnt x 1)',
), ),
StructFieldDecl(
name='jnt_actgravcomp',
type=PointerType(
inner_type=ValueType(name='mjtByte'),
),
doc='is gravcomp force applied via actuators (njnt x 1)',
),
StructFieldDecl( StructFieldDecl(
name='jnt_solref', name='jnt_solref',
type=PointerType( type=PointerType(
+2
View File
@@ -16,6 +16,7 @@
# pylint:disable=g-importing-member # pylint:disable=g-importing-member
from mujoco.mjx._src.collision_driver import collision from mujoco.mjx._src.collision_driver import collision
from mujoco.mjx._src.collision_driver import get_params
from mujoco.mjx._src.collision_driver import ncon from mujoco.mjx._src.collision_driver import ncon
from mujoco.mjx._src.constraint import count_constraints from mujoco.mjx._src.constraint import count_constraints
from mujoco.mjx._src.constraint import make_constraint from mujoco.mjx._src.constraint import make_constraint
@@ -48,4 +49,5 @@ from mujoco.mjx._src.solver import solve
from mujoco.mjx._src.support import full_m from mujoco.mjx._src.support import full_m
from mujoco.mjx._src.support import is_sparse from mujoco.mjx._src.support import is_sparse
from mujoco.mjx._src.support import mul_m from mujoco.mjx._src.support import mul_m
from mujoco.mjx._src.test_util import benchmark
from mujoco.mjx._src.types import * from mujoco.mjx._src.types import *
+3 -3
View File
@@ -50,10 +50,10 @@ class GeomInfo(PyTreeNode):
size: jax.Array size: jax.Array
face: Optional[jax.Array] = None face: Optional[jax.Array] = None
vert: Optional[jax.Array] = None vert: Optional[jax.Array] = None
edge: Optional[jax.Array] = None edge_dir: Optional[jax.Array] = None
facenorm: Optional[jax.Array] = None facenorm: Optional[jax.Array] = None
face_edge: Optional[jax.Array] = None edge: Optional[jax.Array] = None
face_edge_normal: Optional[jax.Array] = None edge_face_normal: Optional[jax.Array] = None
class SolverParams(PyTreeNode): class SolverParams(PyTreeNode):
+142 -130
View File
@@ -215,46 +215,47 @@ def sphere_convex(sphere: GeomInfo, convex: GeomInfo) -> Contact:
return jp.dot(pos - faces[0], normal) return jp.dot(pos - faces[0], normal)
support = get_support(faces, normals) support = get_support(faces, normals)
has_separating_axis = jp.any(support >= 0)
# Pick the face with minimal penetration as long as it has support. # Pick the face with the best separating axis.
support = jp.where(support >= 0, -1e12, support)
best_idx = support.argmax() best_idx = support.argmax()
face = faces[best_idx] face = faces[best_idx]
normal = normals[best_idx] face_normal = normals[best_idx]
# Get closest point between the polygon face and the sphere center point. # Get closest point between the polygon face and the sphere center point.
# Project the sphere center point onto poly plane. If it's inside polygon # Project the sphere center point onto poly plane. If it's inside polygon
# edge normals, then we're done. # side planes, then we're done.
pt = _project_pt_onto_plane(sphere_pos, face[0], normal) pt = _project_pt_onto_plane(sphere_pos, face[0], face_normal)
edge_p0 = jp.roll(face, 1, axis=0) edge_p0 = jp.roll(face, 1, axis=0)
edge_p1 = face edge_p1 = face
edge_normals = jax.vmap(jp.cross, in_axes=[0, None])( side_normals = jax.vmap(jp.cross, in_axes=[0, None])(
edge_p1 - edge_p0, edge_p1 - edge_p0,
normal, face_normal,
) )
edge_dist = jax.vmap( edge_dist = jax.vmap(
lambda plane_pt, plane_norm: (pt - plane_pt).dot(plane_norm) lambda plane_pt, plane_norm: (pt - plane_pt).dot(plane_norm)
)(edge_p0, edge_normals) )(edge_p0, side_normals)
inside = jp.all(edge_dist <= 0) # lte to handle degenerate edges pt_on_face = jp.all(edge_dist <= 0) # lte to handle degenerate edges
# If the point is outside edge normals, project onto the closest edge plane # If the point is outside side planes, project onto the closest side plane
# that the point is in front of. # that the point is in front of.
degenerate_edge = jp.all(edge_normals == 0, axis=1) degenerate_edge = jp.all(side_normals == 0, axis=1)
behind = edge_dist < 0.0 behind = edge_dist < 0.0
edge_dist = jp.where(degenerate_edge | behind, 1e12, edge_dist) edge_dist = jp.where(degenerate_edge | behind, 1e12, edge_dist)
idx = edge_dist.argmin() idx = edge_dist.argmin()
edge_pt = math.closest_segment_point(edge_p0[idx], edge_p1[idx], pt) edge_pt = math.closest_segment_point(edge_p0[idx], edge_p1[idx], pt)
pt = jp.where(pt_on_face, pt, edge_pt)
pt = jp.where(inside, pt, edge_pt)
# Get the normal, dist, and contact position. # Get the normal, dist, and contact position.
n, d = math.normalize_with_norm(pt - sphere_pos) pt_normal, d = math.normalize_with_norm(pt - sphere_pos)
n = jp.where(inside | (d < 1e-6), normal, n)
# Ensure normal points towards convex centroid. # Ensure normal points towards convex centroid.
n *= jp.where(jp.dot(pt, n) < 0, 1, -1) inside = jp.dot(pt, pt_normal) > 0
sign = jp.where(inside, -1, 1)
n = jp.where(pt_on_face | (d < 1e-6), -face_normal, sign * pt_normal)
d *= sign
spt = sphere_pos + n * sphere.size[0] spt = sphere_pos + n * sphere.size[0]
dist = d - sphere.size[0] dist = jp.where(has_separating_axis, 1.0, d - sphere.size[0])
pos = (pt + spt) * 0.5 pos = (pt + spt) * 0.5
# Go back to world frame. # Go back to world frame.
@@ -292,8 +293,7 @@ def capsule_convex(cap: GeomInfo, convex: GeomInfo) -> Contact:
support = get_support(faces, normals) support = get_support(faces, normals)
has_support = jp.all(support < 0) has_support = jp.all(support < 0)
# Pick the face with minimal penetration as long as it has support. # Pick the face with minimal penetration.
support = jp.where(support >= 0, -1e12, support)
best_idx = support.argmax() best_idx = support.argmax()
face = faces[best_idx] face = faces[best_idx]
normal = normals[best_idx] normal = normals[best_idx]
@@ -302,12 +302,12 @@ def capsule_convex(cap: GeomInfo, convex: GeomInfo) -> Contact:
# the face. # the face.
edge_p0 = jp.roll(face, 1, axis=0) edge_p0 = jp.roll(face, 1, axis=0)
edge_p1 = face edge_p1 = face
edge_normals = jax.vmap(jp.cross, in_axes=[0, None])( side_planes = jax.vmap(jp.cross, in_axes=[0, None])(
edge_p1 - edge_p0, edge_p1 - edge_p0,
normal, normal,
) )
cap_pts_clipped, mask = _clip_edge_to_planes( cap_pts_clipped, mask = _clip_edge_to_planes(
cap_pts[0], cap_pts[1], edge_p0, edge_normals cap_pts[0], cap_pts[1], edge_p0, side_planes
) )
cap_pts_clipped = cap_pts_clipped - normal * cap.size[0] cap_pts_clipped = cap_pts_clipped - normal * cap.size[0]
face_pts = jax.vmap(_project_pt_onto_plane, in_axes=[0, None, None])( face_pts = jax.vmap(_project_pt_onto_plane, in_axes=[0, None, None])(
@@ -316,33 +316,65 @@ def capsule_convex(cap: GeomInfo, convex: GeomInfo) -> Contact:
# Create variables for the face contact. # Create variables for the face contact.
pos = (cap_pts_clipped + face_pts) * 0.5 pos = (cap_pts_clipped + face_pts) * 0.5
contact_normal = -jp.stack([normal] * 2, 0) contact_normal = -jp.stack([normal] * 2, 0)
penetration = jp.where( face_penetration = jp.where(
mask & has_support, jp.dot(face_pts - cap_pts_clipped, normal), -1 mask & has_support, jp.dot(face_pts - cap_pts_clipped, normal), -1
) )
# Get a potential edge contact. # Pick a potential shallow edge contact.
edge_closest, cap_closest, t_a, t_b = jax.vmap( def get_edge_axis(edge):
math.closest_segment_to_segment_points_w_barycentric, edge_closest_pt, cap_closest_pt = math.closest_segment_to_segment_points(
in_axes=[0, 0, None, None], edge[0], edge[1], cap_pts[0], cap_pts[1]
)(edge_p0, edge_p1, cap_pts[0], cap_pts[1]) )
e_idx = ((edge_closest - cap_closest) ** 2).sum(axis=1).argmin() edge_dir = edge_closest_pt - cap_closest_pt
cap_closest_pt, edge_closest_pt = cap_closest[e_idx], edge_closest[e_idx] degenerate_edge_dir = jp.sum(jp.square(edge_dir)) < 1e-6
edge_dist = math.norm(cap_closest_pt - edge_closest_pt) edge_axis, edge_dist = math.normalize_with_norm(edge_dir)
t_a, t_b = t_a[e_idx], t_b[e_idx] return (
in_segment = ((t_a > 0) & (t_a < 1)) | ((t_b > 0) & (t_b < 1)) edge_dist,
# Ensure edge_axis points towards the convex centroid. edge_axis,
edge_axis = jp.cross(edge_p0[e_idx] - edge_p1[e_idx], axis) degenerate_edge_dir,
sign = jp.where(jp.dot(edge_closest_pt, edge_axis) < 0, 1, -1) edge_closest_pt,
edge_axis *= sign cap_closest_pt,
degenerate_edge_axis = (edge_axis**2).sum() < 1e-6 )
edge_axis = math.normalize(edge_axis)
edge = jp.take(convex.vert, convex.edge, axis=0)
edge_face_normal = convex.edge_face_normal # pytype: disable=attribute-error
res = jax.vmap(get_edge_axis)(edge.reshape(-1, 2, 3))
e_idx = jp.abs(res[0]).argmin()
(
edge_dist,
edge_axis,
degenerate_edge_dir,
edge_closest_pt,
cap_closest_pt,
) = jax.tree_map(lambda x, i=e_idx: jp.take(x, i, axis=0), res)
edge_face_normals = edge_face_normal[e_idx]
edge_voronoi_front = ((edge_face_normals @ edge_axis) < 0).all()
shallow = ~degenerate_edge_dir & edge_voronoi_front
edge_penetration = jp.where(shallow, cap.size[0] - edge_dist, -1)
# Determine edge contact position. # Determine edge contact position.
edge_pos = ( edge_pos = (
edge_closest_pt + (cap_closest_pt + edge_axis * cap.size[0]) edge_closest_pt + (cap_closest_pt + edge_axis * cap.size[0])
) * 0.5 ) * 0.5
edge_penetration = cap.size[0] - edge_dist edge_dir_parallel_to_face = (
has_edge_contact = (edge_penetration > 0) & in_segment & ~degenerate_edge_axis jp.abs(edge_axis.dot(normal)) > 0.99
) & ~degenerate_edge_dir
min_face_penetration = face_penetration.min()
has_edge_contact = (
(edge_penetration > 0)
# prefer edge contact if the edge is smaller than face penetration
& jp.where(
min_face_penetration > 0,
edge_penetration < min_face_penetration,
True,
)
# prefer face contact if the edge axis is parallel to the face normal
& ~edge_dir_parallel_to_face
# make sure we have a shallow contact
& edge_voronoi_front
)
# Get the contact info. # Get the contact info.
pos = jp.where(has_edge_contact, pos.at[0].set(edge_pos), pos) pos = jp.where(has_edge_contact, pos.at[0].set(edge_pos), pos)
@@ -355,7 +387,7 @@ def capsule_convex(cap: GeomInfo, convex: GeomInfo) -> Contact:
n = n @ convex.mat.T n = n @ convex.mat.T
dist = -jp.where( dist = -jp.where(
has_edge_contact, penetration.at[0].set(edge_penetration), penetration has_edge_contact, jp.array([edge_penetration, -1]), face_penetration
) )
frame = jax.vmap(math.make_frame)(n) frame = jax.vmap(math.make_frame)(n)
return dist, pos, frame return dist, pos, frame
@@ -598,8 +630,9 @@ def _sat_bruteforce(
We return both the edge and face contacts. Valid contacts can be checked with We return both the edge and face contacts. Valid contacts can be checked with
dist < 0. Resulting edge contacts should be preferred over face contacts. dist < 0. Resulting edge contacts should be preferred over face contacts.
This method checks all unique edge-pairs and is thus costly to run over large This method checks all separating axes via a brute force support function, and
meshes, but is more performant for smaller meshes (boxes, tetrahedra, etc.). is thus costly to run over large meshes, but is more performant for smaller
meshes (boxes, tetrahedra, etc.).
Args: Args:
faces_a: Faces for hull A. faces_a: Faces for hull A.
@@ -699,7 +732,7 @@ def _arcs_intersect(
return (cba * dba < 0) & (adc * bdc < 0) & (cba * bdc > 0) return (cba * dba < 0) & (adc * bdc < 0) & (cba * bdc > 0)
def _sat_approx( def _sat_gaussmap(
centroid_a: jax.Array, centroid_a: jax.Array,
faces_a: jax.Array, faces_a: jax.Array,
faces_b: jax.Array, faces_b: jax.Array,
@@ -707,23 +740,16 @@ def _sat_approx(
vertices_b: jax.Array, vertices_b: jax.Array,
normals_a: jax.Array, normals_a: jax.Array,
normals_b: jax.Array, normals_b: jax.Array,
face_edges_a: jax.Array, edges_a: jax.Array,
face_edges_b: jax.Array, edges_b: jax.Array,
face_edge_normals_a: jax.Array, edge_face_normals_a: jax.Array,
face_edge_normals_b: jax.Array, edge_face_normals_b: jax.Array,
) -> Tuple[jax.Array, jax.Array, jax.Array]: ) -> Tuple[jax.Array, jax.Array, jax.Array]:
"""Runs the Separating Axis Test for a pair of hulls. """Runs the Separating Axis Test for a pair of hulls.
Runs the separating axis test for all faces. After obtaining a reference Runs the separating axis test for all faces. Tests edge separating axes via
and incident face, tests edge separating axes via edge intersections edge intersections on gauss maps for all edge pairs. h/t to Dirk Gregorius
on gauss maps. for the implementation details and gauss map trick.
Certain meshes can have nearly parallel coplanar faces that are not merged.
Thus reference/incident faces can be non-overlapping, and face contacts will
not get generated. Since we only check edge separating axes on
reference/incident faces, the correct edge separating axes may also be
missing. We mitigate this issue by checking nearly coplanar anti-parallel
reference/incident faces for support, hence why this method is "approximate".
Args: Args:
centroid_a: Centroid of hull A. centroid_a: Centroid of hull A.
@@ -733,10 +759,10 @@ def _sat_approx(
vertices_b: Vertices for hull B. vertices_b: Vertices for hull B.
normals_a: Normal vectors for hull A faces. normals_a: Normal vectors for hull A faces.
normals_b: Normal vectors for hull B faces. normals_b: Normal vectors for hull B faces.
face_edges_a: Edges for faces in hull A. edges_a: Edges for hull A.
face_edges_b: Edges for faces in hull B. edges_b: Edges for hull B.
face_edge_normals_a: Edge normals for faces in hull A. edge_face_normals_a: Face normals for edges in hull A.
face_edge_normals_b: Edge normals for faces in hull B. edge_face_normals_b: Face normals for edges in hull B.
Returns: Returns:
tuple of dist, pos, and normal tuple of dist, pos, and normal
@@ -784,75 +810,61 @@ def _sat_approx(
-best_axis, -best_axis,
) )
# Handle edge separating axes by checking edge pairs on the reference and # Handle edge separating axes by checking all edge pairs.
# incident faces. In principle, the correct edge-edge separating axis can be a_idx = jp.tile(jp.arange(edges_a.shape[0]), reps=edges_b.shape[0])
# created from edge pairs on the reference and incident faces. b_idx = jp.repeat(
# first get the edge directions and face edge normals jp.arange(edges_b.shape[0]), repeats=edges_a.shape[0], axis=0
face_edges_a = face_edges_a[face_a_idx] )
v_norm = jax.vmap(math.normalize) normal_a_1 = edge_face_normals_a[a_idx, 0]
face_edges_dir_a = v_norm(face_edges_a[:, 0] - face_edges_a[:, 1]) normal_a_2 = edge_face_normals_a[a_idx, 1]
face_edges_b = face_edges_b[face_b_idx] normal_b_1 = edge_face_normals_b[b_idx, 0]
face_edges_dir_b = v_norm(face_edges_b[:, 0] - face_edges_b[:, 1]) normal_b_2 = edge_face_normals_b[b_idx, 1]
face_edge_normals_a = face_edge_normals_a[face_a_idx] is_minkowski_face = jax.vmap(_arcs_intersect)(
face_edge_normals_b = face_edge_normals_b[face_b_idx] normal_a_1, normal_a_2, -normal_b_1, -normal_b_2
# scatter to all edge pairs
edge_idx_a = jp.repeat(
jp.arange(face_edges_a.shape[0]), face_edges_b.shape[0]
) )
edge_idx_b = jp.tile(jp.arange(face_edges_b.shape[0]), face_edges_a.shape[0])
face_edges_dir_a = face_edges_dir_a[edge_idx_a]
face_edges_dir_b = face_edges_dir_b[edge_idx_b]
face_edges_pt_a = face_edges_a[:, 0][edge_idx_a]
face_edges_pt_b = face_edges_b[:, 0][edge_idx_b]
face_edge_normals_a = face_edge_normals_a[edge_idx_a]
face_edge_normals_b = face_edge_normals_b[edge_idx_b]
@jax.vmap # get distances
edge_a_dir = jax.vmap(math.normalize)(edges_a[:, 0] - edges_a[:, 1])[a_idx]
edge_b_dir = jax.vmap(math.normalize)(edges_b[:, 0] - edges_b[:, 1])[b_idx]
edges_a, edges_b = edges_a[a_idx], edges_b[b_idx]
edge_a_pt, edge_a_pt_2 = edges_a[:, 0], edges_a[:, 1]
edge_b_pt, edge_b_pt_2 = edges_b[:, 0], edges_b[:, 1]
def get_normals(a_dir, a_pt, b_dir): def get_normals(a_dir, a_pt, b_dir):
edge_axis = math.normalize(jp.cross(a_dir, b_dir)) edge_axis = jp.cross(a_dir, b_dir)
degenerate_edge_axis = jp.sum(edge_axis**2) < 1e-6
edge_axis = math.normalize(edge_axis)
# correct normal to point from a to b, object b is at the origin # correct normal to point from a to b, object b is at the origin
sign = jp.where(jp.dot(edge_axis, a_pt - centroid_a) > 0.0, 1.0, -1.0) sign = jp.where(jp.dot(edge_axis, a_pt - centroid_a) > 0.0, 1.0, -1.0)
return edge_axis * sign return edge_axis * sign, degenerate_edge_axis
edge_axes = get_normals(face_edges_dir_a, face_edges_pt_a, face_edges_dir_b) edge_axes, degenerate_edge_axes = jax.vmap(get_normals)(
edge_dist = jax.vmap(jp.dot)(edge_axes, face_edges_pt_b - face_edges_pt_a) edge_a_dir, edge_a_pt, edge_b_dir)
# handle degenerate axes edge_dist = jax.vmap(jp.dot)(edge_axes, edge_b_pt - edge_a_pt)
edge_dist = jp.where((edge_axes**2).sum(axis=1) < 1e-6, 1e6, edge_dist) # handle degenerate axis
# ensure edges create a minkowski face by testing intersection on gauss maps edge_dist = jp.where(degenerate_edge_axes, -jp.inf, edge_dist)
is_minkowski_face = jax.vmap(_arcs_intersect)( # ensure edges create minkowski face
face_edge_normals_a[:, 0], edge_dist = jp.where(is_minkowski_face, edge_dist, -jp.inf)
face_edge_normals_a[:, 1],
-face_edge_normals_b[:, 0],
-face_edge_normals_b[:, 1],
)
edge_dist = jp.where(is_minkowski_face, edge_dist, 1e6)
edge_dist = jp.where(edge_dist > 0, -1e6, edge_dist)
best_edge_idx = edge_dist.argmax() best_edge_idx = edge_dist.argmax()
best_edge_dist = edge_dist[best_edge_idx] best_edge_dist = edge_dist[best_edge_idx]
# prefer edge over face contacts as long as we have a valid edge contact is_edge_contact = jp.where(
is_edge_contact = (best_edge_dist > dist.min() + 1e-6) & (best_edge_dist < 0) dist.max() < 0, best_edge_dist > dist.max() - 1e-6,
(best_edge_dist < 0) & ~jp.isinf(best_edge_dist)
)
is_edge_contact = is_edge_contact & ~is_face_separating
normal = jp.where(is_edge_contact, edge_axes[best_edge_idx], normal) normal = jp.where(is_edge_contact, edge_axes[best_edge_idx], normal)
dist = jp.where(is_edge_contact, jp.array([best_edge_dist, 1, 1, 1]), dist) dist = jp.where(
is_edge_contact,
# A failure mode occurs if faces are very narrow and nearly parallel jp.array([best_edge_dist, 1, 1, 1]),
# (i.e. faces did not get merged properly as coplanar faces). The face dist,
# contacts will be empty since the reference/incident faces may not overlap.
# An edge-edge separating axis will not be found, since the reference and
# incident faces will also not overlap or necessarily create a minkowski face.
# Thus, we approximate the contact for anti-parallel faces with support.
anti_parallel = incident_face_norm.dot(ref_face_norm) < -0.97
dist = dist.at[0].set(
jp.where(
anti_parallel
& ~is_face_separating
& (dist > 0).all()
& ~is_edge_contact,
-support[best_idx],
dist[0],
)
) )
a_closest, b_closest = math.closest_segment_to_segment_points(
edge_a_pt[best_edge_idx], edge_a_pt_2[best_edge_idx],
edge_b_pt[best_edge_idx], edge_b_pt_2[best_edge_idx])
pos = jp.where(
is_edge_contact,
jp.tile(0.5 * (a_closest + b_closest), (4, 1)), pos)
return dist, pos, normal return dist, pos, normal
@@ -892,15 +904,15 @@ def convex_convex(c1: GeomInfo, c2: GeomInfo) -> Contact:
unique_edges1 = jp.take(vertices1, c1.edge, axis=0) unique_edges1 = jp.take(vertices1, c1.edge, axis=0)
unique_edges2 = jp.take(vertices2, c2.edge, axis=0) unique_edges2 = jp.take(vertices2, c2.edge, axis=0)
face_edges1 = jp.take(vertices1, c1.face_edge, axis=0) edges1 = jp.take(vertices1, c1.edge, axis=0)
face_edges2 = jp.take(vertices2, c2.face_edge, axis=0) edges2 = jp.take(vertices2, c2.edge, axis=0)
face_edge_normals1 = c1.face_edge_normal @ to_local_mat.T edge_face_normals1 = c1.edge_face_normal @ to_local_mat.T
face_edge_normals2 = c2.face_edge_normal edge_face_normals2 = c2.edge_face_normal
enable_bruteforce = ( enable_bruteforce = (
unique_edges1.shape[0] * unique_edges2.shape[0] unique_edges1.shape[0] * unique_edges2.shape[0]
< face_edges1[0].shape[0] * face_edges2[0].shape[0] < edges1[0].shape[0] * edges2[0].shape[0]
) )
if enable_bruteforce: if enable_bruteforce:
dist, pos, normal = _sat_bruteforce( dist, pos, normal = _sat_bruteforce(
@@ -914,7 +926,7 @@ def convex_convex(c1: GeomInfo, c2: GeomInfo) -> Contact:
unique_edges2, unique_edges2,
) )
else: else:
dist, pos, normal = _sat_approx( dist, pos, normal = _sat_gaussmap(
to_local_pos, to_local_pos,
faces1, faces1,
faces2, faces2,
@@ -922,10 +934,10 @@ def convex_convex(c1: GeomInfo, c2: GeomInfo) -> Contact:
vertices2, vertices2,
normals1, normals1,
normals2, normals2,
face_edges1, edges1,
face_edges2, edges2,
face_edge_normals1, edge_face_normals1,
face_edge_normals2, edge_face_normals2,
) )
# Go back to world frame. # Go back to world frame.
+36 -26
View File
@@ -14,7 +14,7 @@
# ============================================================================== # ==============================================================================
"""Collide geometries.""" """Collide geometries."""
from typing import Callable, Dict, Optional, Sequence, Tuple, Union from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union
import jax import jax
from jax import numpy as jp from jax import numpy as jp
@@ -33,6 +33,7 @@ from mujoco.mjx._src.collision_convex import plane_convex
from mujoco.mjx._src.collision_convex import sphere_convex from mujoco.mjx._src.collision_convex import sphere_convex
from mujoco.mjx._src.collision_primitive import capsule_capsule from mujoco.mjx._src.collision_primitive import capsule_capsule
from mujoco.mjx._src.collision_primitive import plane_capsule from mujoco.mjx._src.collision_primitive import plane_capsule
from mujoco.mjx._src.collision_primitive import plane_ellipsoid
from mujoco.mjx._src.collision_primitive import plane_sphere from mujoco.mjx._src.collision_primitive import plane_sphere
from mujoco.mjx._src.collision_primitive import sphere_capsule from mujoco.mjx._src.collision_primitive import sphere_capsule
from mujoco.mjx._src.collision_primitive import sphere_sphere from mujoco.mjx._src.collision_primitive import sphere_sphere
@@ -48,6 +49,7 @@ _COLLISION_FUNC = {
(GeomType.PLANE, GeomType.SPHERE): plane_sphere, (GeomType.PLANE, GeomType.SPHERE): plane_sphere,
(GeomType.PLANE, GeomType.CAPSULE): plane_capsule, (GeomType.PLANE, GeomType.CAPSULE): plane_capsule,
(GeomType.PLANE, GeomType.BOX): plane_convex, (GeomType.PLANE, GeomType.BOX): plane_convex,
(GeomType.PLANE, GeomType.ELLIPSOID): plane_ellipsoid,
(GeomType.PLANE, GeomType.MESH): plane_convex, (GeomType.PLANE, GeomType.MESH): plane_convex,
(GeomType.SPHERE, GeomType.SPHERE): sphere_sphere, (GeomType.SPHERE, GeomType.SPHERE): sphere_sphere,
(GeomType.SPHERE, GeomType.CAPSULE): sphere_capsule, (GeomType.SPHERE, GeomType.CAPSULE): sphere_capsule,
@@ -187,6 +189,31 @@ def _dynamic_params(
return SolverParams(friction, solref, solreffriction, solimp, margin, gap) return SolverParams(friction, solref, solreffriction, solimp, margin, gap)
def get_params(
m: Union[Model, mujoco.MjModel], candidates: Sequence[Candidate]
) -> Tuple[List[int], List[int], SolverParams]:
"""Gets solver params for a list of collision candidates."""
# group sol params by different candidate types
typ_cands = {}
for c in candidates:
typ = (c.ipair > -1, c.geomp > -1)
typ_cands.setdefault(typ, []).append(c)
geom1, geom2, params = [], [], []
for (pair, priority), candidates in typ_cands.items():
geom1.extend([c.geom1 for c in candidates])
geom2.extend([c.geom2 for c in candidates])
if pair:
params.append(_pair_params(m, candidates))
elif priority:
params.append(_priority_params(m, candidates))
else:
params.append(_dynamic_params(m, candidates))
params = jax.tree_map(lambda *x: jp.concatenate(x), *params)
return geom1, geom2, params
def _pair_info( def _pair_info(
m: Model, d: Data, geom1: Sequence[int], geom2: Sequence[int] m: Model, d: Data, geom1: Sequence[int], geom2: Sequence[int]
) -> Tuple[GeomInfo, GeomInfo, Sequence[Dict[str, Optional[int]]]]: ) -> Tuple[GeomInfo, GeomInfo, Sequence[Dict[str, Optional[int]]]]:
@@ -205,20 +232,20 @@ def _pair_info(
info = info.replace( info = info.replace(
face=jp.stack([m.geom_convex_face[i] for i in geom]), face=jp.stack([m.geom_convex_face[i] for i in geom]),
vert=jp.stack([m.geom_convex_vert[i] for i in geom]), vert=jp.stack([m.geom_convex_vert[i] for i in geom]),
edge=jp.stack([m.geom_convex_edge_dir[i] for i in geom]), edge_dir=jp.stack([m.geom_convex_edge_dir[i] for i in geom]),
facenorm=jp.stack([m.geom_convex_facenormal[i] for i in geom]), facenorm=jp.stack([m.geom_convex_facenormal[i] for i in geom]),
face_edge_normal=jp.stack( edge=jp.stack([m.geom_convex_edge[i] for i in geom]),
[m.geom_convex_face_edge_normal[i] for i in geom] edge_face_normal=jp.stack(
[m.geom_convex_edge_face_normal[i] for i in geom]
), ),
face_edge=jp.stack([m.geom_convex_face_edge[i] for i in geom]),
) )
in_axes = in_axes.replace( in_axes = in_axes.replace(
face=0, face=0,
vert=0, vert=0,
edge=0, edge_dir=0,
facenorm=0, facenorm=0,
face_edge=0, edge=0,
face_edge_normal=0, edge_face_normal=0,
) )
return info, in_axes return info, in_axes
@@ -276,24 +303,7 @@ def _collide_geoms(
if not fn: if not fn:
return Contact.zero() return Contact.zero()
# group sol params by different candidate types geom1, geom2, params = get_params(m, candidates)
typ_cands = {}
for c in candidates:
typ = (c.ipair > -1, c.geomp > -1)
typ_cands.setdefault(typ, []).append(c)
geom1, geom2, params = [], [], []
for (pair, priority), candidates in typ_cands.items():
geom1.extend([c.geom1 for c in candidates])
geom2.extend([c.geom2 for c in candidates])
if pair:
params.append(_pair_params(m, candidates))
elif priority:
params.append(_priority_params(m, candidates))
else:
params.append(_dynamic_params(m, candidates))
params = jax.tree_map(lambda *x: jp.concatenate(x), *params)
g1, g2, in_axes = _pair_info(m, d, geom1, geom2) g1, g2, in_axes = _pair_info(m, d, geom1, geom2)
# Run a crude version of broadphase. # Run a crude version of broadphase.
+163 -23
View File
@@ -132,37 +132,93 @@ class SphereCollisionTest(parameterized.TestCase):
</mujoco> </mujoco>
""" """
def test_sphere_convex(self): def test_sphere_convex_face(self):
d, dx = _collide(self._SPHERE_CONVEX) # no contact
xml = self._SPHERE_CONVEX.replace(
'<body pos="0.52 0 0.52">', '<body pos="0.55 0 0.5">'
)
d, dx = _collide(xml)
self.assertEmpty(d.contact.dist)
self.assertGreater(dx.contact.dist, 0)
# face contact
xml = self._SPHERE_CONVEX.replace(
'<body pos="0.52 0 0.52">', '<body pos="0.51 0 0.25">'
)
d, dx = _collide(xml)
for field in dataclasses.fields(Contact): for field in dataclasses.fields(Contact):
_assert_attr_eq(dx.contact, d.contact, field.name, 'sphere_convex', 1e-4) _assert_attr_eq(dx.contact, d.contact, field.name, 'face', 1e-4)
# test deep penetration # deep face contact
xml = self._SPHERE_CONVEX.replace(
'<body pos="0.52 0 0.52">', '<body pos="0.48 0 0.47">'
)
d, dx = _collide(xml)
self.assertTrue((dx.contact.dist < 0).all())
self.assertTrue((d.contact.dist < 0).all())
np.testing.assert_allclose(dx.contact.dist, [-0.07], atol=1e-5)
np.testing.assert_array_almost_equal(dx.contact.pos, d.contact.pos)
np.testing.assert_array_almost_equal(
dx.contact.frame, d.contact.frame.reshape((-1, 3, 3))
)
def test_sphere_convex_edge(self):
# edge contact
d, dx = _collide(self._SPHERE_CONVEX)
for field in dataclasses.fields(Contact):
_assert_attr_eq(dx.contact, d.contact, field.name, 'edge', 1e-4)
# deep edge penetration
xml = self._SPHERE_CONVEX.replace( xml = self._SPHERE_CONVEX.replace(
'<body pos="0.52 0 0.52">', '<body pos="0.49 0 0.49">' '<body pos="0.52 0 0.52">', '<body pos="0.49 0 0.49">'
) )
d, dx = _collide(xml) d, dx = _collide(xml)
self.assertTrue((dx.contact.dist < 0).all()) self.assertTrue((dx.contact.dist < 0).all())
self.assertTrue((d.contact.dist < 0).all()) self.assertTrue((d.contact.dist < 0).all())
np.testing.assert_allclose(dx.contact.dist, [-0.06], atol=1e-5)
np.testing.assert_array_almost_equal(dx.contact.pos, d.contact.pos) np.testing.assert_array_almost_equal(dx.contact.pos, d.contact.pos)
np.testing.assert_array_almost_equal( np.testing.assert_array_almost_equal(
dx.contact.frame, d.contact.frame.reshape((-1, 3, 3)) dx.contact.frame, d.contact.frame.reshape((-1, 3, 3))
) )
# test sphere center on vertex # vertex contact
xml = self._SPHERE_CONVEX.replace(
'<body pos="0.52 0 0.52">', '<body pos="0.5 0.52 0.51">'
)
d, dx = _collide(xml)
for field in dataclasses.fields(Contact):
_assert_attr_eq(dx.contact, d.contact, field.name, 'vertex', 1e-4)
# sphere center on vertex
xml = self._SPHERE_CONVEX.replace( xml = self._SPHERE_CONVEX.replace(
'<body pos="0.52 0 0.52">', '<body pos="0.5 0 0.5">' '<body pos="0.52 0 0.52">', '<body pos="0.5 0 0.5">'
) )
d, dx = _collide(xml) d, dx = _collide(xml)
for field in dataclasses.fields(Contact):
_assert_attr_eq(dx.contact, d.contact, field.name, 'vertex_center', 1e-4)
self.assertTrue((dx.contact.dist < 0).all())
self.assertTrue((d.contact.dist < 0).all()) class EllipsoidCollisionTest(parameterized.TestCase):
np.testing.assert_array_almost_equal(dx.contact.pos, d.contact.pos)
np.testing.assert_array_almost_equal( _ELLIPSOID_PLANE = """
dx.contact.frame, d.contact.frame.reshape((-1, 3, 3)) <mujoco>
) <worldbody>
<geom name="floor" size="0 0 .05" type="plane"/>
<body pos="0 0 0.03" euler="45 0 0">
<freejoint/>
<geom size=".15 .03 .05" type="ellipsoid"/>
</body>
</worldbody>
</mujoco>
"""
def test_plane_ellipsoid(self):
"""Tests ellipsoid plane contact."""
d, dx = _collide(self._ELLIPSOID_PLANE)
self.assertLess(dx.contact.dist[0], 0)
for field in dataclasses.fields(Contact):
_assert_attr_eq(
dx.contact, d.contact, field.name, 'ellipsoid-plane', 1e-5)
class CapsuleCollisionTest(parameterized.TestCase): class CapsuleCollisionTest(parameterized.TestCase):
@@ -248,8 +304,8 @@ class CapsuleCollisionTest(parameterized.TestCase):
</mujoco> </mujoco>
""" """
def test_capsule_convex(self): def test_capsule_convex_face(self):
"""Tests a capsule-convex collision for a face contact.""" """Tests face contact."""
d, dx = _collide(self._CAP_BOX) d, dx = _collide(self._CAP_BOX)
# sort positions for comparison # sort positions for comparison
@@ -263,7 +319,8 @@ class CapsuleCollisionTest(parameterized.TestCase):
for field in dataclasses.fields(Contact): for field in dataclasses.fields(Contact):
_assert_attr_eq(dx.contact, d.contact, field.name, 'capsule_convex', 1e-4) _assert_attr_eq(dx.contact, d.contact, field.name, 'capsule_convex', 1e-4)
# test deep face penetration def test_capsule_convex_face_deep(self):
"""Tests deep face penetration."""
xml = self._CAP_BOX.replace('<body pos="0 0 0.54">', '<body pos="0 0 0.4">') xml = self._CAP_BOX.replace('<body pos="0 0 0.54">', '<body pos="0 0 0.4">')
_, dx = _collide(xml) _, dx = _collide(xml)
@@ -294,7 +351,7 @@ class CapsuleCollisionTest(parameterized.TestCase):
""" """
def test_capsule_convex_edge(self): def test_capsule_convex_edge(self):
"""Tests a capsule-convex collision for an edge contact.""" """Tests edge contact."""
d, dx = _collide(self._CAP_EDGE_BOX) d, dx = _collide(self._CAP_EDGE_BOX)
c = dx.contact c = dx.contact
@@ -305,17 +362,62 @@ class CapsuleCollisionTest(parameterized.TestCase):
for field in dataclasses.fields(Contact): for field in dataclasses.fields(Contact):
_assert_attr_eq(c, d.contact, field.name, 'capsule_convex_edge', 1e-4) _assert_attr_eq(c, d.contact, field.name, 'capsule_convex_edge', 1e-4)
# test deep edge penetration def test_capsule_convex_edge_deep(self):
"""Tests deep edge penetration."""
xml = self._CAP_EDGE_BOX.replace( xml = self._CAP_EDGE_BOX.replace(
'<body pos="0.5 0 0.55"', '<body pos="0.5 0 0.48"' '<body pos="0.5 0 0.55"', '<body pos="0.5 0 0.42"'
) )
_, dx = _collide(xml) _, dx = _collide(xml)
np.testing.assert_array_equal(dx.contact.dist < 0, np.array([True, False])) np.testing.assert_array_equal(dx.contact.dist < 0, np.array([True, False]))
np.testing.assert_array_almost_equal(dx.contact.dist[0], np.array([-0.13]))
np.testing.assert_array_almost_equal( np.testing.assert_array_almost_equal(
dx.contact.pos[0], np.array([0.483, 0, 0.471]), decimal=3 dx.contact.pos[0], np.array([0.5, 0, 0.435]), decimal=3
) )
np.testing.assert_array_almost_equal( np.testing.assert_array_almost_equal(
dx.contact.frame[0, 0], np.array([-0.5, 0, -0.866]), decimal=3 dx.contact.frame[0, 0], np.array([0, 0, -1]), decimal=3
)
def test_capsule_convex_edge_shallow_tip(self):
"""Tests shallow edge penetration on the tip of the capsule."""
# the capsule sphere is inside the edge voronoi region, so there is an
# edge contact
xml = self._CAP_EDGE_BOX.replace(
'<geom fromto="-0.6 0 0 0.6 0 0" size="0.05"',
'<geom fromto="0.6 0 0.6 -0.05 0 0" size="0.1"',
)
xml = xml.replace('<body pos="0.5 0 0.55"', '<body pos="0.58 0 0.55"')
d, dx = _collide(xml)
c = dx.contact
self.assertEqual(c.pos.shape[0], 2)
self.assertGreater(c.dist[1], 0)
# extract the contact point with penetration
c = jax.tree_map(lambda x: jp.take(x, 0, axis=0)[None], dx.contact)
for field in dataclasses.fields(Contact):
_assert_attr_eq(c, d.contact, field.name, 'edge_shallow_tip1', 1e-4)
np.testing.assert_array_almost_equal(
dx.contact.frame[0][0, :3], np.array([-0.43952, 0.0, -0.898233])
)
# the capsule sphere is outside the edge voronoi region, so there is a
# face contact
xml = self._CAP_EDGE_BOX.replace(
'<geom fromto="-0.6 0 0 0.6 0 0" size="0.05"',
'<geom fromto="-0.6 0 0.6 -0.05 0 0" size="0.1"',
)
xml = xml.replace('<body pos="0.5 0 0.55"', '<body pos="0.5 0 0.52"')
d, dx = _collide(xml)
c = dx.contact
self.assertEqual(c.pos.shape[0], 2)
self.assertGreater(c.dist[1], 0)
# extract the contact point with penetration
c = jax.tree_map(lambda x: jp.take(x, 0, axis=0)[None], dx.contact)
for field in dataclasses.fields(Contact):
_assert_attr_eq(c, d.contact, field.name, 'edge_shallow_tip2', 1e-4)
np.testing.assert_array_almost_equal(
dx.contact.frame[0][0, :3], np.array([0.0, 0.0, -1.0])
) )
@@ -448,7 +550,7 @@ class ConvexTest(absltest.TestCase):
""" """
def test_convex_convex(self): def test_convex_convex(self):
"""Tests generic convex-convex collision via _sat_approx.""" """Tests generic convex-convex collision via _sat_gaussmap."""
directory = epath.resource_path('mujoco.mjx') directory = epath.resource_path('mujoco.mjx')
assets = { assets = {
'meshes/dodecahedron.stl': ( 'meshes/dodecahedron.stl': (
@@ -463,6 +565,44 @@ class ConvexTest(absltest.TestCase):
np.testing.assert_array_less(0, c.dist[1:]) np.testing.assert_array_less(0, c.dist[1:])
np.testing.assert_array_almost_equal(c.frame[0, 0], np.array([0, 0, 1])) np.testing.assert_array_almost_equal(c.frame[0, 0], np.array([0, 0, 1]))
_CONVEX_CONVEX_THIN = """
<mujoco>
<asset>
<mesh name="poly"
vertex="0.3 0 0 0 0.5 0 -0.3 0 0 0 -0.5 0 0 -1 1 0 1 1"
face="0 1 5 0 5 4 0 4 3 3 4 2 2 4 5 1 2 5 0 2 1 0 3 2"/>
</asset>
<worldbody>
<body pos="0.0 2.0 0.35" euler="0 0 90">
<freejoint/>
<geom size="0.2 0.2 0.2" type="mesh" mesh="poly"/>
</body>
<body pos="0.0 2.0 2.281" euler="180 0 0">
<freejoint/>
<geom size="0.2 0.2 0.2" type="mesh" mesh="poly"/>
</body>
</worldbody>
</mujoco>
"""
def test_convex_convex_edge(self):
"""Tests convex-convex collisions with edge contact via _sat_gaussmap."""
_, dx = _collide(self._CONVEX_CONVEX_THIN)
c = dx.contact
# Only one contact point for an edge contact.
self.assertLess(c.dist[0], 0)
np.testing.assert_array_less(0, c.dist[1:])
np.testing.assert_array_almost_equal(c.frame[0, 0], np.array([0, 0, 1]))
np.testing.assert_array_almost_equal(
c.pos[0], np.array([0, 2, 1.3155]), decimal=5)
_, dx = _collide(
self._CONVEX_CONVEX_THIN.replace(
'pos="0.0 2.0 0.35"', 'pos="0.0 2.0 0"'))
c = dx.contact
self.assertTrue((c.dist > 0).all())
class BodyPairFilterTest(absltest.TestCase): class BodyPairFilterTest(absltest.TestCase):
"""Tests that certain body pairs get filtered.""" """Tests that certain body pairs get filtered."""
@@ -568,11 +708,11 @@ class NconTest(parameterized.TestCase):
m.numeric_data[m.numeric_adr[i]] = -1 m.numeric_data[m.numeric_adr[i]] = -1
ncon = collision_driver.ncon(m) ncon = collision_driver.ncon(m)
self.assertEqual(ncon, 307) self.assertEqual(ncon, 98)
mx = mjx.put_model(m) mx = mjx.put_model(m)
ncon = collision_driver.ncon(mx) ncon = collision_driver.ncon(mx)
self.assertEqual(ncon, 307) self.assertEqual(ncon, 98)
class TopKContactTest(absltest.TestCase): class TopKContactTest(absltest.TestCase):
@@ -65,6 +65,19 @@ def plane_capsule(plane: GeomInfo, cap: GeomInfo) -> Contact:
return jax.tree_map(lambda *x: jp.concatenate(x), *contacts) return jax.tree_map(lambda *x: jp.concatenate(x), *contacts)
def plane_ellipsoid(plane: GeomInfo, ellipsoid: GeomInfo) -> Contact:
"""Calculates one contact between an ellipsoid and a plane."""
n = plane.mat[:, 2]
size = ellipsoid.size
sphere_support = -math.normalize((ellipsoid.mat.T @ n) * size)
pos = ellipsoid.pos + ellipsoid.mat @ (sphere_support * size)
dist = jp.dot(n, pos - plane.pos)
pos = pos - n * dist * 0.5
return jax.tree_map(
lambda x: jp.expand_dims(x, axis=0), (dist, pos, math.make_frame(n))
)
def _sphere_sphere( def _sphere_sphere(
pos1: jax.Array, radius1: jax.Array, pos2: jax.Array, radius2: jax.Array pos1: jax.Array, radius1: jax.Array, pos2: jax.Array, radius2: jax.Array
) -> Contact: ) -> Contact:
@@ -121,6 +134,7 @@ def capsule_capsule(cap1: GeomInfo, cap2: GeomInfo) -> Contact:
# store ncon as function attributes # store ncon as function attributes
plane_sphere.ncon = 1 plane_sphere.ncon = 1
plane_capsule.ncon = 2 plane_capsule.ncon = 2
plane_ellipsoid.ncon = 1
sphere_sphere.ncon = 1 sphere_sphere.ncon = 1
sphere_capsule.ncon = 1 sphere_capsule.ncon = 1
capsule_capsule.ncon = 1 capsule_capsule.ncon = 1
+7 -2
View File
@@ -138,8 +138,7 @@ def _validate(m: mujoco.MjModel):
raise NotImplementedError('Tendons are not supported.') raise NotImplementedError('Tendons are not supported.')
# check collision geom types # check collision geom types
candidate_set = collision_driver.collision_candidates(m) for (g1, g2, *_), c in collision_driver.collision_candidates(m).items():
for g1, g2, *_ in candidate_set:
g1, g2 = mujoco.mjtGeom(g1), mujoco.mjtGeom(g2) g1, g2 = mujoco.mjtGeom(g1), mujoco.mjtGeom(g2)
if g1 == mujoco.mjtGeom.mjGEOM_PLANE and g2 in ( if g1 == mujoco.mjtGeom.mjGEOM_PLANE and g2 in (
mujoco.mjtGeom.mjGEOM_PLANE, mujoco.mjtGeom.mjGEOM_PLANE,
@@ -149,6 +148,12 @@ def _validate(m: mujoco.MjModel):
continue continue
if collision_driver.get_collision_fn((g1, g2)) is None: if collision_driver.get_collision_fn((g1, g2)) is None:
raise NotImplementedError(f'({g1}, {g2}) collisions not implemented.') raise NotImplementedError(f'({g1}, {g2}) collisions not implemented.')
*_, params = collision_driver.get_params(m, c)
margin_gap = not np.allclose(np.concatenate([params.margin, params.gap]), 0)
if mujoco.mjtGeom.mjGEOM_MESH in (g1, g2) and margin_gap:
raise NotImplementedError(
f'Margin and gap not implemented for ({g1}, {g2})'
)
# TODO(erikfrey): warn for high solver iterations, nefc, etc. # TODO(erikfrey): warn for high solver iterations, nefc, etc.
+13 -3
View File
@@ -91,10 +91,16 @@ def put_model(m: mujoco.MjModel, device=None) -> types.Model:
raise NotImplementedError('only condim=3 is supported') raise NotImplementedError('only condim=3 is supported')
# check collision geom types # check collision geom types
for g1, g2, *_ in collision_driver.collision_candidates(m): for (g1, g2, *_), c in collision_driver.collision_candidates(m).items():
if collision_driver.get_collision_fn((g1, g2)) is None:
g1, g2 = mujoco.mjtGeom(g1), mujoco.mjtGeom(g2) g1, g2 = mujoco.mjtGeom(g1), mujoco.mjtGeom(g2)
if collision_driver.get_collision_fn((g1, g2)) is None:
raise NotImplementedError(f'({g1}, {g2}) has no collision function') raise NotImplementedError(f'({g1}, {g2}) has no collision function')
*_, params = collision_driver.get_params(m, c)
margin_gap = not np.allclose(np.concatenate([params.margin, params.gap]), 0)
if mujoco.mjtGeom.mjGEOM_MESH in (g1, g2) and margin_gap:
raise NotImplementedError(
f'Margin and gap not implemented for ({g1}, {g2})'
)
for enum_field, enum_type, mj_type in ( for enum_field, enum_type, mj_type in (
(m.actuator_biastype, types.BiasType, mujoco.mjtBias), (m.actuator_biastype, types.BiasType, mujoco.mjtBias),
@@ -172,7 +178,7 @@ def make_data(m: Union[types.Model, mujoco.MjModel]) -> types.Data:
ctrl=zero_nu, ctrl=zero_nu,
qfrc_applied=zero_nv, qfrc_applied=zero_nv,
xfrc_applied=zero_nbody_6, xfrc_applied=zero_nbody_6,
eq_active=jp.zeros(m.neq, dtype=int), eq_active=jp.zeros(m.neq, dtype=jp.uint8),
qacc=zero_nv, qacc=zero_nv,
act_dot=zero_na, act_dot=zero_na,
xpos=zero_nbody_3, xpos=zero_nbody_3,
@@ -233,6 +239,7 @@ def _get_contact(
ncon = cx.dist.shape[0] ncon = cx.dist.shape[0]
c.efc_address[:] = np.arange(efc_start, efc_start + ncon * 4, 4)[con_id] c.efc_address[:] = np.arange(efc_start, efc_start + ncon * 4, 4)[con_id]
c.dim[:] = 3
def get_data( def get_data(
@@ -374,6 +381,9 @@ def put_data(m: mujoco.MjModel, d: mujoco.MjData, device=None) -> types.Data:
for fname in ('xmat', 'ximat', 'geom_xmat', 'site_xmat', 'cam_xmat'): for fname in ('xmat', 'ximat', 'geom_xmat', 'site_xmat', 'cam_xmat'):
fields[fname] = fields[fname].reshape((-1, 3, 3)) fields[fname] = fields[fname].reshape((-1, 3, 3))
# MJX does not support islanding, so only transfer the first solver_niter
fields['solver_niter'] = fields['solver_niter'][0]
# pad efc fields: MuJoCo efc arrays are sparse for inactive constraints. # pad efc fields: MuJoCo efc arrays are sparse for inactive constraints.
# efc_J is also optionally column-sparse (typically for large nv). MJX is # efc_J is also optionally column-sparse (typically for large nv). MJX is
# neither: it contains zeros for inactive constraints, and efc_J is always # neither: it contains zeros for inactive constraints, and efc_J is always
+34
View File
@@ -209,6 +209,25 @@ class ModelIOTest(parameterized.TestCase):
</worldbody> </worldbody>
</mujoco>""")) </mujoco>"""))
def test_margin_gap_mesh_not_implemented(self):
with self.assertRaises(NotImplementedError):
mjx.put_model(mujoco.MjModel.from_xml_string("""
<mujoco>
<asset>
<mesh name="box" vertex="-1 -1 -1 1 -1 -1 1 1 -1 1 1 1 1 -1 1 -1 1 -1 -1 1 1 -1 -1 1" scale="1 1 1"/>
</asset>
<worldbody>
<body>
<freejoint/>
<geom type="mesh" mesh="box" margin="0.3"/>
</body>
<body>
<freejoint/>
<geom size="0.05"/>
</body>
</worldbody>
</mujoco>"""))
class DataIOTest(parameterized.TestCase): class DataIOTest(parameterized.TestCase):
"""IO tests for mjx.Data.""" """IO tests for mjx.Data."""
@@ -434,5 +453,20 @@ class DataIOTest(parameterized.TestCase):
self.assertEqual(d_2.contact.frame.shape, (1, 9)) self.assertEqual(d_2.contact.frame.shape, (1, 9))
np.testing.assert_allclose(d_2.contact.frame, d.contact.frame) np.testing.assert_allclose(d_2.contact.frame, d.contact.frame)
def test_make_matches_put(self):
"""Test that make_data produces a pytree that matches put_data."""
m = mujoco.MjModel.from_xml_string(_MULTIPLE_CONSTRAINTS)
d = mujoco.MjData(m)
mujoco.mj_step(m, d, 2)
dx = mjx.put_data(m, d)
step_fn = lambda d: d.replace(time=d.time + 1)
step_fn_jit = jax.jit(step_fn).lower(dx).compile()
# placing an MjData onto device should yield the same treedef mjx.Data as
# calling make_data. they should be interchangeable for jax functions:
step_fn_jit(mjx.make_data(m))
if __name__ == '__main__': if __name__ == '__main__':
absltest.main() absltest.main()
+3 -15
View File
@@ -331,9 +331,9 @@ def closest_segment_point_and_dist(
return closest, dist return closest, dist
def closest_segment_to_segment_points_w_barycentric( def closest_segment_to_segment_points(
a0: jax.Array, a1: jax.Array, b0: jax.Array, b1: jax.Array a0: jax.Array, a1: jax.Array, b0: jax.Array, b1: jax.Array
) -> Tuple[jax.Array, jax.Array, jax.Array, jax.Array]: ) -> Tuple[jax.Array, jax.Array]:
"""Returns closest points between two line segments.""" """Returns closest points between two line segments."""
# Gets the closest segment points by first finding the closest points # Gets the closest segment points by first finding the closest points
# between two lines. Points are then clipped to be on the line segments # between two lines. Points are then clipped to be on the line segments
@@ -364,10 +364,6 @@ def closest_segment_to_segment_points_w_barycentric(
t_a = jp.clip(orig_t_a, -half_len_a, half_len_a) t_a = jp.clip(orig_t_a, -half_len_a, half_len_a)
t_b = jp.clip(orig_t_b, -half_len_b, half_len_b) t_b = jp.clip(orig_t_b, -half_len_b, half_len_b)
# reparametrize t_a, t_b
t_a_01 = (orig_t_a + half_len_a) / jp.maximum(len_a, 1e-6)
t_b_01 = (orig_t_b + half_len_b) / jp.maximum(len_b, 1e-6)
best_a = a_mid + dir_a * t_a best_a = a_mid + dir_a * t_a
best_b = b_mid + dir_b * t_b best_b = b_mid + dir_b * t_b
@@ -381,12 +377,4 @@ def closest_segment_to_segment_points_w_barycentric(
best_a = jp.where(d1 < d2, new_a, best_a) best_a = jp.where(d1 < d2, new_a, best_a)
best_b = jp.where(d1 < d2, best_b, new_b) best_b = jp.where(d1 < d2, best_b, new_b)
return best_a, best_b, t_a_01, t_b_01 return best_a, best_b
def closest_segment_to_segment_points(
a0: jax.Array, a1: jax.Array, b0: jax.Array, b1: jax.Array
) -> Tuple[jax.Array, jax.Array]:
"""Returns closest points between two line segments."""
a, b, *_ = closest_segment_to_segment_points_w_barycentric(a0, a1, b0, b1)
return a, b
+10 -19
View File
@@ -49,8 +49,8 @@ _DERIVED_ARGS = [
'geom_convex_vert', 'geom_convex_vert',
'geom_convex_edge_dir', 'geom_convex_edge_dir',
'geom_convex_facenormal', 'geom_convex_facenormal',
'geom_convex_face_edge', 'geom_convex_edge',
'geom_convex_face_edge_normal', 'geom_convex_edge_face_normal',
] ]
DERIVED = {(Model, d) for d in _DERIVED_ARGS} DERIVED = {(Model, d) for d in _DERIVED_ARGS}
@@ -114,7 +114,7 @@ def _get_unique_edge_dir(vert: np.ndarray, face: np.ndarray) -> np.ndarray:
return edges[unique_edge_idx] return edges[unique_edge_idx]
def _get_face_edge_normals( def _get_edge_normals(
face: np.ndarray, face_norm: np.ndarray face: np.ndarray, face_norm: np.ndarray
) -> Tuple[np.ndarray, np.ndarray]: ) -> Tuple[np.ndarray, np.ndarray]:
"""Returns face edges and face edge normals.""" """Returns face edges and face edge normals."""
@@ -133,7 +133,7 @@ def _get_face_edge_normals(
continue continue
edge_map_list[tuple(face_edge_flat[i])].append(edge_face_norm[i]) edge_map_list[tuple(face_edge_flat[i])].append(edge_face_norm[i])
edge_map = {} edges, edge_face_normals = [], []
for k, v in edge_map_list.items(): for k, v in edge_map_list.items():
v = np.array(v) v = np.array(v)
if len(v) > 2: if len(v) > 2:
@@ -145,19 +145,10 @@ def _get_face_edge_normals(
# and face vertices were down sampled. In either case, we ignore these # and face vertices were down sampled. In either case, we ignore these
# edges. # edges.
continue continue
edge_map[k] = v edges.append(k)
edge_face_normals.append(v)
# for each face, list the edge normals return np.array(edges), np.array(edge_face_normals)
face_edge_normal = []
for face_idx in range(face_edge.shape[0]):
normals = []
for edge in face_edge[face_idx]:
k = tuple(edge)
normals.append(edge_map.get(k, np.zeros((2, 3))))
face_edge_normal.append(np.array(normals))
face_edge_normal = np.array(face_edge_normal)
return face_edge, face_edge_normal
def _convex_hull_2d(points: np.ndarray, normal: np.ndarray) -> np.ndarray: def _convex_hull_2d(points: np.ndarray, normal: np.ndarray) -> np.ndarray:
@@ -297,15 +288,15 @@ def _geom_mesh_kwargs(
vert = np.array(tm_convex.vertices) vert = np.array(tm_convex.vertices)
face = _merge_coplanar(tm_convex, mesh_info) face = _merge_coplanar(tm_convex, mesh_info)
facenormal = _get_face_norm(vert, face) facenormal = _get_face_norm(vert, face)
face_edge, face_edge_normal = _get_face_edge_normals(face, facenormal) edge, edge_face_normal = _get_edge_normals(face, facenormal)
return { return {
'geom_convex_face': vert[face], 'geom_convex_face': vert[face],
'geom_convex_face_vert_idx': face, 'geom_convex_face_vert_idx': face,
'geom_convex_vert': vert, 'geom_convex_vert': vert,
'geom_convex_edge_dir': _get_unique_edge_dir(vert, face), 'geom_convex_edge_dir': _get_unique_edge_dir(vert, face),
'geom_convex_facenormal': facenormal, 'geom_convex_facenormal': facenormal,
'geom_convex_face_edge': face_edge, 'geom_convex_edge': edge,
'geom_convex_face_edge_normal': face_edge_normal, 'geom_convex_edge_face_normal': edge_face_normal,
} }
+4 -13
View File
@@ -80,7 +80,7 @@ class GeomMeshKwargsTest(absltest.TestCase):
self.assertEqual(h['geom_convex_facenormal'].shape, (5, 3)) self.assertEqual(h['geom_convex_facenormal'].shape, (5, 3))
# face edges # face edges
edges = np.concatenate(h['geom_convex_face_edge']) edges = h['geom_convex_edge']
edges = np.vectorize(map_.get)(edges) edges = np.vectorize(map_.get)(edges)
mask = edges[:, 0] != edges[:, 1] mask = edges[:, 0] != edges[:, 1]
edges = edges[mask] edges = edges[mask]
@@ -92,27 +92,18 @@ class GeomMeshKwargsTest(absltest.TestCase):
edges, edges,
np.array([ np.array([
[0, 2], [0, 2],
[0, 2],
[0, 3],
[0, 3], [0, 3],
[0, 4], [0, 4],
[0, 4],
[1, 2],
[1, 2], [1, 2],
[1, 3], [1, 3],
[1, 3],
[1, 4],
[1, 4], [1, 4],
[2, 4], [2, 4],
[2, 4],
[3, 4],
[3, 4], [3, 4],
]), ]),
) )
# face edge normals # face edge normals
edge_normal = h['geom_convex_face_edge_normal'] edge_normal = h['geom_convex_edge_face_normal']
edge_normal = np.concatenate(edge_normal)
edge_normal = edge_normal[mask] edge_normal = edge_normal[mask]
edge_normal = np.take_along_axis( edge_normal = np.take_along_axis(
edge_normal, sort_col_idx[..., None], axis=1 edge_normal, sort_col_idx[..., None], axis=1
@@ -120,8 +111,8 @@ class GeomMeshKwargsTest(absltest.TestCase):
edge_normal = edge_normal[sort_row_idx] edge_normal = edge_normal[sort_row_idx]
edge_normal_02 = np.array([[0.4472136, -0.0, 0.89442719], [-1.0, 0.0, 0.0]]) edge_normal_02 = np.array([[0.4472136, -0.0, 0.89442719], [-1.0, 0.0, 0.0]])
np.testing.assert_array_almost_equal( np.testing.assert_array_almost_equal(
edge_normal[:2], edge_normal[:1],
np.array([edge_normal_02, edge_normal_02]), np.array([edge_normal_02]),
) )
-1
View File
@@ -13,7 +13,6 @@
# limitations under the License. # limitations under the License.
# ============================================================================== # ==============================================================================
"""Engine support functions.""" """Engine support functions."""
from typing import Optional, Tuple, Union from typing import Optional, Tuple, Union
import jax import jax
+82
View File
@@ -14,14 +14,96 @@
# ============================================================================== # ==============================================================================
"""Utilities for testing.""" """Utilities for testing."""
import os
import sys import sys
import time
from typing import Dict, Tuple from typing import Dict, Tuple
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from etils import epath from etils import epath
import jax
import mujoco import mujoco
# pylint: disable=g-importing-member
from mujoco.mjx._src import forward
from mujoco.mjx._src import io
# pylint: enable=g-importing-member
import numpy as np import numpy as np
def _measure(fn, *args) -> Tuple[float, float]:
"""Reports jit time and op time for a function."""
beg = time.perf_counter()
compiled_fn = fn.lower(*args).compile()
end = time.perf_counter()
jit_time = end - beg
beg = time.perf_counter()
result = compiled_fn(*args)
jax.block_until_ready(result)
end = time.perf_counter()
run_time = end - beg
return jit_time, run_time
def benchmark(
m: mujoco.MjModel,
nstep: int = 1000,
batch_size: int = 1024,
unroll_steps: int = 1,
solver: str = 'cg',
iterations: int = 1,
ls_iterations: int = 4,
) -> Tuple[float, float, int]:
"""Benchmark a model."""
xla_flags = os.environ.get('XLA_FLAGS', '')
xla_flags += ' --xla_gpu_triton_gemm_any=True'
os.environ['XLA_FLAGS'] = xla_flags
m.opt.solver = {
'cg': mujoco.mjtSolver.mjSOL_CG,
'newton': mujoco.mjtSolver.mjSOL_NEWTON,
}[solver.lower()]
m.opt.iterations = iterations
m.opt.ls_iterations = ls_iterations
m = io.put_model(m)
@jax.pmap
def init(key):
key = jax.random.split(key, batch_size // jax.device_count())
@jax.vmap
def random_init(key):
d = io.make_data(m)
qvel = 0.01 * jax.random.normal(key, shape=(m.nv,))
d = d.replace(qvel=qvel)
return d
return random_init(key)
key = jax.random.split(jax.random.key(0), jax.device_count())
d = init(key)
jax.block_until_ready(d)
@jax.pmap
def unroll(d):
@jax.vmap
def step(d, _):
d = forward.step(m, d)
return d, None
d, _ = jax.lax.scan(step, d, None, length=nstep, unroll=unroll_steps)
return d
jit_time, run_time = _measure(unroll, d)
steps = nstep * batch_size
return jit_time, run_time, steps
_ACTUATOR_TYPES = ['motor', 'velocity', 'position', 'general', 'intvelocity'] _ACTUATOR_TYPES = ['motor', 'velocity', 'position', 'general', 'intvelocity']
_DYN_TYPES = ['none', 'integrator', 'filter', 'filterexact'] _DYN_TYPES = ['none', 'integrator', 'filter', 'filterexact']
_DYN_PRMS = ['0.189', '2.1'] _DYN_PRMS = ['0.189', '2.1']
+2 -2
View File
@@ -543,8 +543,8 @@ class Model(PyTreeNode):
geom_convex_vert: List[Optional[jax.Array]] geom_convex_vert: List[Optional[jax.Array]]
geom_convex_edge_dir: List[Optional[jax.Array]] geom_convex_edge_dir: List[Optional[jax.Array]]
geom_convex_facenormal: List[Optional[jax.Array]] geom_convex_facenormal: List[Optional[jax.Array]]
geom_convex_face_edge: List[Optional[jax.Array]] geom_convex_edge: List[Optional[jax.Array]]
geom_convex_face_edge_normal: List[Optional[jax.Array]] geom_convex_edge_face_normal: List[Optional[jax.Array]]
pair_solref: jax.Array pair_solref: jax.Array
pair_solreffriction: jax.Array pair_solreffriction: jax.Array
pair_solimp: jax.Array pair_solimp: jax.Array
@@ -0,0 +1,150 @@
<mujoco model="01 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="4" name="max_contact_points"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<default class="body">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="0"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,255 @@
<mujoco model="02 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="8" name="max_contact_points"/>
<numeric data="8" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="5"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="3"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,359 @@
<mujoco model="03 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="12" name="max_contact_points"/>
<numeric data="12" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="13"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="11"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="7"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,463 @@
<mujoco model="04 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="16" name="max_contact_points"/>
<numeric data="16" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="29"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="27"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="23"/>
</default>
<default class="body4">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="16" conaffinity="15"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="4a_torso" pos="-1 2 1.5" childclass="body4">
<camera name="4a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="4a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="4a_root"/>
<geom name="4a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="4a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="4a_head" pos="0 0 .19">
<geom name="4a_head" type="sphere" size=".09"/>
<camera name="4a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="4a_lower_waist" pos="-.01 0 -.26">
<geom name="4a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="4a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="4a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="4a_pelvis" pos="0 0 -.165">
<joint name="4a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="4a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="4a_right_thigh" pos="0 -.1 -.04">
<joint name="4a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="4a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="4a_right_shin" pos="0 .01 -.403">
<joint name="4a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_right_foot" pos="0 0 -.39">
<joint name="4a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="4a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="4a_left_thigh" pos="0 .1 -.04">
<joint name="4a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="4a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="4a_left_shin" pos="0 -.01 -.403">
<joint name="4a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_left_foot" pos="0 0 -.39">
<joint name="4a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="4a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="4a_right_upper_arm" pos="0 -.17 .06">
<joint name="4a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="4a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="4a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="4a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="4a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="4a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="4a_right_hand" pos=".18 .18 .18">
<geom name="4a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="4a_left_upper_arm" pos="0 .17 .06">
<joint name="4a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="4a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="4a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="4a_left_lower_arm" pos=".18 .18 -.18">
<joint name="4a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="4a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="4a_left_hand" pos=".18 -.18 .18">
<geom name="4a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="4a_abdomen_y"/>
<motor gear="40" joint="4a_abdomen_z"/>
<motor gear="40" joint="4a_abdomen_x"/>
<motor gear="40" joint="4a_right_hip_x"/>
<motor gear="40" joint="4a_right_hip_z"/>
<motor gear="120" joint="4a_right_hip_y"/>
<motor gear="80" joint="4a_right_knee"/>
<motor gear="20" joint="4a_right_ankle_x"/>
<motor gear="20" joint="4a_right_ankle_y"/>
<motor gear="40" joint="4a_left_hip_x"/>
<motor gear="40" joint="4a_left_hip_z"/>
<motor gear="120" joint="4a_left_hip_y"/>
<motor gear="80" joint="4a_left_knee"/>
<motor gear="20" joint="4a_left_ankle_x"/>
<motor gear="20" joint="4a_left_ankle_y"/>
<motor gear="20" joint="4a_right_shoulder1"/>
<motor gear="20" joint="4a_right_shoulder2"/>
<motor gear="40" joint="4a_right_elbow"/>
<motor gear="20" joint="4a_left_shoulder1"/>
<motor gear="20" joint="4a_left_shoulder2"/>
<motor gear="40" joint="4a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,567 @@
<mujoco model="05 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="20" name="max_contact_points"/>
<numeric data="20" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="61"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="59"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="55"/>
</default>
<default class="body4">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="16" conaffinity="47"/>
</default>
<default class="body5">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="32" conaffinity="31"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="4a_torso" pos="-1 2 1.5" childclass="body4">
<camera name="4a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="4a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="4a_root"/>
<geom name="4a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="4a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="4a_head" pos="0 0 .19">
<geom name="4a_head" type="sphere" size=".09"/>
<camera name="4a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="4a_lower_waist" pos="-.01 0 -.26">
<geom name="4a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="4a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="4a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="4a_pelvis" pos="0 0 -.165">
<joint name="4a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="4a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="4a_right_thigh" pos="0 -.1 -.04">
<joint name="4a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="4a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="4a_right_shin" pos="0 .01 -.403">
<joint name="4a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_right_foot" pos="0 0 -.39">
<joint name="4a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="4a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="4a_left_thigh" pos="0 .1 -.04">
<joint name="4a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="4a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="4a_left_shin" pos="0 -.01 -.403">
<joint name="4a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_left_foot" pos="0 0 -.39">
<joint name="4a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="4a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="4a_right_upper_arm" pos="0 -.17 .06">
<joint name="4a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="4a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="4a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="4a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="4a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="4a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="4a_right_hand" pos=".18 .18 .18">
<geom name="4a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="4a_left_upper_arm" pos="0 .17 .06">
<joint name="4a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="4a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="4a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="4a_left_lower_arm" pos=".18 .18 -.18">
<joint name="4a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="4a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="4a_left_hand" pos=".18 -.18 .18">
<geom name="4a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="5a_torso" pos="-1 -2 1.5" childclass="body5">
<camera name="5a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="5a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="5a_root"/>
<geom name="5a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="5a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="5a_head" pos="0 0 .19">
<geom name="5a_head" type="sphere" size=".09"/>
<camera name="5a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="5a_lower_waist" pos="-.01 0 -.26">
<geom name="5a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="5a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="5a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="5a_pelvis" pos="0 0 -.165">
<joint name="5a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="5a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="5a_right_thigh" pos="0 -.1 -.04">
<joint name="5a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="5a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="5a_right_shin" pos="0 .01 -.403">
<joint name="5a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_right_foot" pos="0 0 -.39">
<joint name="5a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="5a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="5a_left_thigh" pos="0 .1 -.04">
<joint name="5a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="5a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="5a_left_shin" pos="0 -.01 -.403">
<joint name="5a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_left_foot" pos="0 0 -.39">
<joint name="5a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="5a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="5a_right_upper_arm" pos="0 -.17 .06">
<joint name="5a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="5a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="5a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="5a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="5a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="5a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="5a_right_hand" pos=".18 .18 .18">
<geom name="5a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="5a_left_upper_arm" pos="0 .17 .06">
<joint name="5a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="5a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="5a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="5a_left_lower_arm" pos=".18 .18 -.18">
<joint name="5a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="5a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="5a_left_hand" pos=".18 -.18 .18">
<geom name="5a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="4a_abdomen_y"/>
<motor gear="40" joint="4a_abdomen_z"/>
<motor gear="40" joint="4a_abdomen_x"/>
<motor gear="40" joint="4a_right_hip_x"/>
<motor gear="40" joint="4a_right_hip_z"/>
<motor gear="120" joint="4a_right_hip_y"/>
<motor gear="80" joint="4a_right_knee"/>
<motor gear="20" joint="4a_right_ankle_x"/>
<motor gear="20" joint="4a_right_ankle_y"/>
<motor gear="40" joint="4a_left_hip_x"/>
<motor gear="40" joint="4a_left_hip_z"/>
<motor gear="120" joint="4a_left_hip_y"/>
<motor gear="80" joint="4a_left_knee"/>
<motor gear="20" joint="4a_left_ankle_x"/>
<motor gear="20" joint="4a_left_ankle_y"/>
<motor gear="20" joint="4a_right_shoulder1"/>
<motor gear="20" joint="4a_right_shoulder2"/>
<motor gear="40" joint="4a_right_elbow"/>
<motor gear="20" joint="4a_left_shoulder1"/>
<motor gear="20" joint="4a_left_shoulder2"/>
<motor gear="40" joint="4a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="5a_abdomen_y"/>
<motor gear="40" joint="5a_abdomen_z"/>
<motor gear="40" joint="5a_abdomen_x"/>
<motor gear="40" joint="5a_right_hip_x"/>
<motor gear="40" joint="5a_right_hip_z"/>
<motor gear="120" joint="5a_right_hip_y"/>
<motor gear="80" joint="5a_right_knee"/>
<motor gear="20" joint="5a_right_ankle_x"/>
<motor gear="20" joint="5a_right_ankle_y"/>
<motor gear="40" joint="5a_left_hip_x"/>
<motor gear="40" joint="5a_left_hip_z"/>
<motor gear="120" joint="5a_left_hip_y"/>
<motor gear="80" joint="5a_left_knee"/>
<motor gear="20" joint="5a_left_ankle_x"/>
<motor gear="20" joint="5a_left_ankle_y"/>
<motor gear="20" joint="5a_right_shoulder1"/>
<motor gear="20" joint="5a_right_shoulder2"/>
<motor gear="40" joint="5a_right_elbow"/>
<motor gear="20" joint="5a_left_shoulder1"/>
<motor gear="20" joint="5a_left_shoulder2"/>
<motor gear="40" joint="5a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,671 @@
<mujoco model="06 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="24" name="max_contact_points"/>
<numeric data="24" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="125"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="123"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="119"/>
</default>
<default class="body4">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="16" conaffinity="111"/>
</default>
<default class="body5">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="32" conaffinity="95"/>
</default>
<default class="body6">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="64" conaffinity="63"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="4a_torso" pos="-1 2 1.5" childclass="body4">
<camera name="4a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="4a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="4a_root"/>
<geom name="4a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="4a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="4a_head" pos="0 0 .19">
<geom name="4a_head" type="sphere" size=".09"/>
<camera name="4a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="4a_lower_waist" pos="-.01 0 -.26">
<geom name="4a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="4a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="4a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="4a_pelvis" pos="0 0 -.165">
<joint name="4a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="4a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="4a_right_thigh" pos="0 -.1 -.04">
<joint name="4a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="4a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="4a_right_shin" pos="0 .01 -.403">
<joint name="4a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_right_foot" pos="0 0 -.39">
<joint name="4a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="4a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="4a_left_thigh" pos="0 .1 -.04">
<joint name="4a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="4a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="4a_left_shin" pos="0 -.01 -.403">
<joint name="4a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_left_foot" pos="0 0 -.39">
<joint name="4a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="4a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="4a_right_upper_arm" pos="0 -.17 .06">
<joint name="4a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="4a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="4a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="4a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="4a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="4a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="4a_right_hand" pos=".18 .18 .18">
<geom name="4a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="4a_left_upper_arm" pos="0 .17 .06">
<joint name="4a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="4a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="4a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="4a_left_lower_arm" pos=".18 .18 -.18">
<joint name="4a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="4a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="4a_left_hand" pos=".18 -.18 .18">
<geom name="4a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="5a_torso" pos="-1 -2 1.5" childclass="body5">
<camera name="5a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="5a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="5a_root"/>
<geom name="5a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="5a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="5a_head" pos="0 0 .19">
<geom name="5a_head" type="sphere" size=".09"/>
<camera name="5a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="5a_lower_waist" pos="-.01 0 -.26">
<geom name="5a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="5a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="5a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="5a_pelvis" pos="0 0 -.165">
<joint name="5a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="5a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="5a_right_thigh" pos="0 -.1 -.04">
<joint name="5a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="5a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="5a_right_shin" pos="0 .01 -.403">
<joint name="5a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_right_foot" pos="0 0 -.39">
<joint name="5a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="5a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="5a_left_thigh" pos="0 .1 -.04">
<joint name="5a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="5a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="5a_left_shin" pos="0 -.01 -.403">
<joint name="5a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_left_foot" pos="0 0 -.39">
<joint name="5a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="5a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="5a_right_upper_arm" pos="0 -.17 .06">
<joint name="5a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="5a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="5a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="5a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="5a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="5a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="5a_right_hand" pos=".18 .18 .18">
<geom name="5a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="5a_left_upper_arm" pos="0 .17 .06">
<joint name="5a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="5a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="5a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="5a_left_lower_arm" pos=".18 .18 -.18">
<joint name="5a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="5a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="5a_left_hand" pos=".18 -.18 .18">
<geom name="5a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="6a_torso" pos="-1 3 1.5" childclass="body6">
<camera name="6a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="6a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="6a_root"/>
<geom name="6a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="6a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="6a_head" pos="0 0 .19">
<geom name="6a_head" type="sphere" size=".09"/>
<camera name="6a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="6a_lower_waist" pos="-.01 0 -.26">
<geom name="6a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="6a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="6a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="6a_pelvis" pos="0 0 -.165">
<joint name="6a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="6a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="6a_right_thigh" pos="0 -.1 -.04">
<joint name="6a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="6a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="6a_right_shin" pos="0 .01 -.403">
<joint name="6a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_right_foot" pos="0 0 -.39">
<joint name="6a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="6a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="6a_left_thigh" pos="0 .1 -.04">
<joint name="6a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="6a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="6a_left_shin" pos="0 -.01 -.403">
<joint name="6a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_left_foot" pos="0 0 -.39">
<joint name="6a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="6a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="6a_right_upper_arm" pos="0 -.17 .06">
<joint name="6a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="6a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="6a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="6a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="6a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="6a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="6a_right_hand" pos=".18 .18 .18">
<geom name="6a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="6a_left_upper_arm" pos="0 .17 .06">
<joint name="6a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="6a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="6a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="6a_left_lower_arm" pos=".18 .18 -.18">
<joint name="6a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="6a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="6a_left_hand" pos=".18 -.18 .18">
<geom name="6a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="4a_abdomen_y"/>
<motor gear="40" joint="4a_abdomen_z"/>
<motor gear="40" joint="4a_abdomen_x"/>
<motor gear="40" joint="4a_right_hip_x"/>
<motor gear="40" joint="4a_right_hip_z"/>
<motor gear="120" joint="4a_right_hip_y"/>
<motor gear="80" joint="4a_right_knee"/>
<motor gear="20" joint="4a_right_ankle_x"/>
<motor gear="20" joint="4a_right_ankle_y"/>
<motor gear="40" joint="4a_left_hip_x"/>
<motor gear="40" joint="4a_left_hip_z"/>
<motor gear="120" joint="4a_left_hip_y"/>
<motor gear="80" joint="4a_left_knee"/>
<motor gear="20" joint="4a_left_ankle_x"/>
<motor gear="20" joint="4a_left_ankle_y"/>
<motor gear="20" joint="4a_right_shoulder1"/>
<motor gear="20" joint="4a_right_shoulder2"/>
<motor gear="40" joint="4a_right_elbow"/>
<motor gear="20" joint="4a_left_shoulder1"/>
<motor gear="20" joint="4a_left_shoulder2"/>
<motor gear="40" joint="4a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="5a_abdomen_y"/>
<motor gear="40" joint="5a_abdomen_z"/>
<motor gear="40" joint="5a_abdomen_x"/>
<motor gear="40" joint="5a_right_hip_x"/>
<motor gear="40" joint="5a_right_hip_z"/>
<motor gear="120" joint="5a_right_hip_y"/>
<motor gear="80" joint="5a_right_knee"/>
<motor gear="20" joint="5a_right_ankle_x"/>
<motor gear="20" joint="5a_right_ankle_y"/>
<motor gear="40" joint="5a_left_hip_x"/>
<motor gear="40" joint="5a_left_hip_z"/>
<motor gear="120" joint="5a_left_hip_y"/>
<motor gear="80" joint="5a_left_knee"/>
<motor gear="20" joint="5a_left_ankle_x"/>
<motor gear="20" joint="5a_left_ankle_y"/>
<motor gear="20" joint="5a_right_shoulder1"/>
<motor gear="20" joint="5a_right_shoulder2"/>
<motor gear="40" joint="5a_right_elbow"/>
<motor gear="20" joint="5a_left_shoulder1"/>
<motor gear="20" joint="5a_left_shoulder2"/>
<motor gear="40" joint="5a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="6a_abdomen_y"/>
<motor gear="40" joint="6a_abdomen_z"/>
<motor gear="40" joint="6a_abdomen_x"/>
<motor gear="40" joint="6a_right_hip_x"/>
<motor gear="40" joint="6a_right_hip_z"/>
<motor gear="120" joint="6a_right_hip_y"/>
<motor gear="80" joint="6a_right_knee"/>
<motor gear="20" joint="6a_right_ankle_x"/>
<motor gear="20" joint="6a_right_ankle_y"/>
<motor gear="40" joint="6a_left_hip_x"/>
<motor gear="40" joint="6a_left_hip_z"/>
<motor gear="120" joint="6a_left_hip_y"/>
<motor gear="80" joint="6a_left_knee"/>
<motor gear="20" joint="6a_left_ankle_x"/>
<motor gear="20" joint="6a_left_ankle_y"/>
<motor gear="20" joint="6a_right_shoulder1"/>
<motor gear="20" joint="6a_right_shoulder2"/>
<motor gear="40" joint="6a_right_elbow"/>
<motor gear="20" joint="6a_left_shoulder1"/>
<motor gear="20" joint="6a_left_shoulder2"/>
<motor gear="40" joint="6a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,775 @@
<mujoco model="07 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="28" name="max_contact_points"/>
<numeric data="28" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="253"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="251"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="247"/>
</default>
<default class="body4">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="16" conaffinity="239"/>
</default>
<default class="body5">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="32" conaffinity="223"/>
</default>
<default class="body6">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="64" conaffinity="191"/>
</default>
<default class="body7">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="128" conaffinity="127"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="4a_torso" pos="-1 2 1.5" childclass="body4">
<camera name="4a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="4a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="4a_root"/>
<geom name="4a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="4a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="4a_head" pos="0 0 .19">
<geom name="4a_head" type="sphere" size=".09"/>
<camera name="4a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="4a_lower_waist" pos="-.01 0 -.26">
<geom name="4a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="4a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="4a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="4a_pelvis" pos="0 0 -.165">
<joint name="4a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="4a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="4a_right_thigh" pos="0 -.1 -.04">
<joint name="4a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="4a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="4a_right_shin" pos="0 .01 -.403">
<joint name="4a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_right_foot" pos="0 0 -.39">
<joint name="4a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="4a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="4a_left_thigh" pos="0 .1 -.04">
<joint name="4a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="4a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="4a_left_shin" pos="0 -.01 -.403">
<joint name="4a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_left_foot" pos="0 0 -.39">
<joint name="4a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="4a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="4a_right_upper_arm" pos="0 -.17 .06">
<joint name="4a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="4a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="4a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="4a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="4a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="4a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="4a_right_hand" pos=".18 .18 .18">
<geom name="4a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="4a_left_upper_arm" pos="0 .17 .06">
<joint name="4a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="4a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="4a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="4a_left_lower_arm" pos=".18 .18 -.18">
<joint name="4a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="4a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="4a_left_hand" pos=".18 -.18 .18">
<geom name="4a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="5a_torso" pos="-1 -2 1.5" childclass="body5">
<camera name="5a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="5a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="5a_root"/>
<geom name="5a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="5a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="5a_head" pos="0 0 .19">
<geom name="5a_head" type="sphere" size=".09"/>
<camera name="5a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="5a_lower_waist" pos="-.01 0 -.26">
<geom name="5a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="5a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="5a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="5a_pelvis" pos="0 0 -.165">
<joint name="5a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="5a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="5a_right_thigh" pos="0 -.1 -.04">
<joint name="5a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="5a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="5a_right_shin" pos="0 .01 -.403">
<joint name="5a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_right_foot" pos="0 0 -.39">
<joint name="5a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="5a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="5a_left_thigh" pos="0 .1 -.04">
<joint name="5a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="5a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="5a_left_shin" pos="0 -.01 -.403">
<joint name="5a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_left_foot" pos="0 0 -.39">
<joint name="5a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="5a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="5a_right_upper_arm" pos="0 -.17 .06">
<joint name="5a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="5a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="5a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="5a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="5a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="5a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="5a_right_hand" pos=".18 .18 .18">
<geom name="5a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="5a_left_upper_arm" pos="0 .17 .06">
<joint name="5a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="5a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="5a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="5a_left_lower_arm" pos=".18 .18 -.18">
<joint name="5a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="5a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="5a_left_hand" pos=".18 -.18 .18">
<geom name="5a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="6a_torso" pos="-1 3 1.5" childclass="body6">
<camera name="6a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="6a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="6a_root"/>
<geom name="6a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="6a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="6a_head" pos="0 0 .19">
<geom name="6a_head" type="sphere" size=".09"/>
<camera name="6a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="6a_lower_waist" pos="-.01 0 -.26">
<geom name="6a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="6a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="6a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="6a_pelvis" pos="0 0 -.165">
<joint name="6a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="6a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="6a_right_thigh" pos="0 -.1 -.04">
<joint name="6a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="6a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="6a_right_shin" pos="0 .01 -.403">
<joint name="6a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_right_foot" pos="0 0 -.39">
<joint name="6a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="6a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="6a_left_thigh" pos="0 .1 -.04">
<joint name="6a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="6a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="6a_left_shin" pos="0 -.01 -.403">
<joint name="6a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_left_foot" pos="0 0 -.39">
<joint name="6a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="6a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="6a_right_upper_arm" pos="0 -.17 .06">
<joint name="6a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="6a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="6a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="6a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="6a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="6a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="6a_right_hand" pos=".18 .18 .18">
<geom name="6a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="6a_left_upper_arm" pos="0 .17 .06">
<joint name="6a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="6a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="6a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="6a_left_lower_arm" pos=".18 .18 -.18">
<joint name="6a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="6a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="6a_left_hand" pos=".18 -.18 .18">
<geom name="6a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="7a_torso" pos="-1 -3 1.5" childclass="body7">
<camera name="7a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="7a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="7a_root"/>
<geom name="7a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="7a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="7a_head" pos="0 0 .19">
<geom name="7a_head" type="sphere" size=".09"/>
<camera name="7a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="7a_lower_waist" pos="-.01 0 -.26">
<geom name="7a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="7a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="7a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="7a_pelvis" pos="0 0 -.165">
<joint name="7a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="7a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="7a_right_thigh" pos="0 -.1 -.04">
<joint name="7a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="7a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="7a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="7a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="7a_right_shin" pos="0 .01 -.403">
<joint name="7a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="7a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="7a_right_foot" pos="0 0 -.39">
<joint name="7a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="7a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="7a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="7a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="7a_left_thigh" pos="0 .1 -.04">
<joint name="7a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="7a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="7a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="7a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="7a_left_shin" pos="0 -.01 -.403">
<joint name="7a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="7a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="7a_left_foot" pos="0 0 -.39">
<joint name="7a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="7a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="7a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="7a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="7a_right_upper_arm" pos="0 -.17 .06">
<joint name="7a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="7a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="7a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="7a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="7a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="7a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="7a_right_hand" pos=".18 .18 .18">
<geom name="7a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="7a_left_upper_arm" pos="0 .17 .06">
<joint name="7a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="7a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="7a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="7a_left_lower_arm" pos=".18 .18 -.18">
<joint name="7a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="7a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="7a_left_hand" pos=".18 -.18 .18">
<geom name="7a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="4a_abdomen_y"/>
<motor gear="40" joint="4a_abdomen_z"/>
<motor gear="40" joint="4a_abdomen_x"/>
<motor gear="40" joint="4a_right_hip_x"/>
<motor gear="40" joint="4a_right_hip_z"/>
<motor gear="120" joint="4a_right_hip_y"/>
<motor gear="80" joint="4a_right_knee"/>
<motor gear="20" joint="4a_right_ankle_x"/>
<motor gear="20" joint="4a_right_ankle_y"/>
<motor gear="40" joint="4a_left_hip_x"/>
<motor gear="40" joint="4a_left_hip_z"/>
<motor gear="120" joint="4a_left_hip_y"/>
<motor gear="80" joint="4a_left_knee"/>
<motor gear="20" joint="4a_left_ankle_x"/>
<motor gear="20" joint="4a_left_ankle_y"/>
<motor gear="20" joint="4a_right_shoulder1"/>
<motor gear="20" joint="4a_right_shoulder2"/>
<motor gear="40" joint="4a_right_elbow"/>
<motor gear="20" joint="4a_left_shoulder1"/>
<motor gear="20" joint="4a_left_shoulder2"/>
<motor gear="40" joint="4a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="5a_abdomen_y"/>
<motor gear="40" joint="5a_abdomen_z"/>
<motor gear="40" joint="5a_abdomen_x"/>
<motor gear="40" joint="5a_right_hip_x"/>
<motor gear="40" joint="5a_right_hip_z"/>
<motor gear="120" joint="5a_right_hip_y"/>
<motor gear="80" joint="5a_right_knee"/>
<motor gear="20" joint="5a_right_ankle_x"/>
<motor gear="20" joint="5a_right_ankle_y"/>
<motor gear="40" joint="5a_left_hip_x"/>
<motor gear="40" joint="5a_left_hip_z"/>
<motor gear="120" joint="5a_left_hip_y"/>
<motor gear="80" joint="5a_left_knee"/>
<motor gear="20" joint="5a_left_ankle_x"/>
<motor gear="20" joint="5a_left_ankle_y"/>
<motor gear="20" joint="5a_right_shoulder1"/>
<motor gear="20" joint="5a_right_shoulder2"/>
<motor gear="40" joint="5a_right_elbow"/>
<motor gear="20" joint="5a_left_shoulder1"/>
<motor gear="20" joint="5a_left_shoulder2"/>
<motor gear="40" joint="5a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="6a_abdomen_y"/>
<motor gear="40" joint="6a_abdomen_z"/>
<motor gear="40" joint="6a_abdomen_x"/>
<motor gear="40" joint="6a_right_hip_x"/>
<motor gear="40" joint="6a_right_hip_z"/>
<motor gear="120" joint="6a_right_hip_y"/>
<motor gear="80" joint="6a_right_knee"/>
<motor gear="20" joint="6a_right_ankle_x"/>
<motor gear="20" joint="6a_right_ankle_y"/>
<motor gear="40" joint="6a_left_hip_x"/>
<motor gear="40" joint="6a_left_hip_z"/>
<motor gear="120" joint="6a_left_hip_y"/>
<motor gear="80" joint="6a_left_knee"/>
<motor gear="20" joint="6a_left_ankle_x"/>
<motor gear="20" joint="6a_left_ankle_y"/>
<motor gear="20" joint="6a_right_shoulder1"/>
<motor gear="20" joint="6a_right_shoulder2"/>
<motor gear="40" joint="6a_right_elbow"/>
<motor gear="20" joint="6a_left_shoulder1"/>
<motor gear="20" joint="6a_left_shoulder2"/>
<motor gear="40" joint="6a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="7a_abdomen_y"/>
<motor gear="40" joint="7a_abdomen_z"/>
<motor gear="40" joint="7a_abdomen_x"/>
<motor gear="40" joint="7a_right_hip_x"/>
<motor gear="40" joint="7a_right_hip_z"/>
<motor gear="120" joint="7a_right_hip_y"/>
<motor gear="80" joint="7a_right_knee"/>
<motor gear="20" joint="7a_right_ankle_x"/>
<motor gear="20" joint="7a_right_ankle_y"/>
<motor gear="40" joint="7a_left_hip_x"/>
<motor gear="40" joint="7a_left_hip_z"/>
<motor gear="120" joint="7a_left_hip_y"/>
<motor gear="80" joint="7a_left_knee"/>
<motor gear="20" joint="7a_left_ankle_x"/>
<motor gear="20" joint="7a_left_ankle_y"/>
<motor gear="20" joint="7a_right_shoulder1"/>
<motor gear="20" joint="7a_right_shoulder2"/>
<motor gear="40" joint="7a_right_elbow"/>
<motor gear="20" joint="7a_left_shoulder1"/>
<motor gear="20" joint="7a_left_shoulder2"/>
<motor gear="40" joint="7a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,879 @@
<mujoco model="08 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="32" name="max_contact_points"/>
<numeric data="32" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="509"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="507"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="503"/>
</default>
<default class="body4">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="16" conaffinity="495"/>
</default>
<default class="body5">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="32" conaffinity="479"/>
</default>
<default class="body6">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="64" conaffinity="447"/>
</default>
<default class="body7">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="128" conaffinity="383"/>
</default>
<default class="body8">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="256" conaffinity="255"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="4a_torso" pos="-1 2 1.5" childclass="body4">
<camera name="4a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="4a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="4a_root"/>
<geom name="4a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="4a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="4a_head" pos="0 0 .19">
<geom name="4a_head" type="sphere" size=".09"/>
<camera name="4a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="4a_lower_waist" pos="-.01 0 -.26">
<geom name="4a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="4a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="4a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="4a_pelvis" pos="0 0 -.165">
<joint name="4a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="4a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="4a_right_thigh" pos="0 -.1 -.04">
<joint name="4a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="4a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="4a_right_shin" pos="0 .01 -.403">
<joint name="4a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_right_foot" pos="0 0 -.39">
<joint name="4a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="4a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="4a_left_thigh" pos="0 .1 -.04">
<joint name="4a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="4a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="4a_left_shin" pos="0 -.01 -.403">
<joint name="4a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_left_foot" pos="0 0 -.39">
<joint name="4a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="4a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="4a_right_upper_arm" pos="0 -.17 .06">
<joint name="4a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="4a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="4a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="4a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="4a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="4a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="4a_right_hand" pos=".18 .18 .18">
<geom name="4a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="4a_left_upper_arm" pos="0 .17 .06">
<joint name="4a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="4a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="4a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="4a_left_lower_arm" pos=".18 .18 -.18">
<joint name="4a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="4a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="4a_left_hand" pos=".18 -.18 .18">
<geom name="4a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="5a_torso" pos="-1 -2 1.5" childclass="body5">
<camera name="5a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="5a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="5a_root"/>
<geom name="5a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="5a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="5a_head" pos="0 0 .19">
<geom name="5a_head" type="sphere" size=".09"/>
<camera name="5a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="5a_lower_waist" pos="-.01 0 -.26">
<geom name="5a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="5a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="5a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="5a_pelvis" pos="0 0 -.165">
<joint name="5a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="5a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="5a_right_thigh" pos="0 -.1 -.04">
<joint name="5a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="5a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="5a_right_shin" pos="0 .01 -.403">
<joint name="5a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_right_foot" pos="0 0 -.39">
<joint name="5a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="5a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="5a_left_thigh" pos="0 .1 -.04">
<joint name="5a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="5a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="5a_left_shin" pos="0 -.01 -.403">
<joint name="5a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_left_foot" pos="0 0 -.39">
<joint name="5a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="5a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="5a_right_upper_arm" pos="0 -.17 .06">
<joint name="5a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="5a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="5a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="5a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="5a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="5a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="5a_right_hand" pos=".18 .18 .18">
<geom name="5a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="5a_left_upper_arm" pos="0 .17 .06">
<joint name="5a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="5a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="5a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="5a_left_lower_arm" pos=".18 .18 -.18">
<joint name="5a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="5a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="5a_left_hand" pos=".18 -.18 .18">
<geom name="5a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="6a_torso" pos="-1 3 1.5" childclass="body6">
<camera name="6a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="6a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="6a_root"/>
<geom name="6a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="6a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="6a_head" pos="0 0 .19">
<geom name="6a_head" type="sphere" size=".09"/>
<camera name="6a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="6a_lower_waist" pos="-.01 0 -.26">
<geom name="6a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="6a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="6a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="6a_pelvis" pos="0 0 -.165">
<joint name="6a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="6a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="6a_right_thigh" pos="0 -.1 -.04">
<joint name="6a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="6a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="6a_right_shin" pos="0 .01 -.403">
<joint name="6a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_right_foot" pos="0 0 -.39">
<joint name="6a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="6a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="6a_left_thigh" pos="0 .1 -.04">
<joint name="6a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="6a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="6a_left_shin" pos="0 -.01 -.403">
<joint name="6a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_left_foot" pos="0 0 -.39">
<joint name="6a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="6a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="6a_right_upper_arm" pos="0 -.17 .06">
<joint name="6a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="6a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="6a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="6a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="6a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="6a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="6a_right_hand" pos=".18 .18 .18">
<geom name="6a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="6a_left_upper_arm" pos="0 .17 .06">
<joint name="6a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="6a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="6a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="6a_left_lower_arm" pos=".18 .18 -.18">
<joint name="6a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="6a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="6a_left_hand" pos=".18 -.18 .18">
<geom name="6a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="7a_torso" pos="-1 -3 1.5" childclass="body7">
<camera name="7a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="7a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="7a_root"/>
<geom name="7a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="7a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="7a_head" pos="0 0 .19">
<geom name="7a_head" type="sphere" size=".09"/>
<camera name="7a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="7a_lower_waist" pos="-.01 0 -.26">
<geom name="7a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="7a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="7a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="7a_pelvis" pos="0 0 -.165">
<joint name="7a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="7a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="7a_right_thigh" pos="0 -.1 -.04">
<joint name="7a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="7a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="7a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="7a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="7a_right_shin" pos="0 .01 -.403">
<joint name="7a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="7a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="7a_right_foot" pos="0 0 -.39">
<joint name="7a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="7a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="7a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="7a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="7a_left_thigh" pos="0 .1 -.04">
<joint name="7a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="7a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="7a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="7a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="7a_left_shin" pos="0 -.01 -.403">
<joint name="7a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="7a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="7a_left_foot" pos="0 0 -.39">
<joint name="7a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="7a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="7a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="7a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="7a_right_upper_arm" pos="0 -.17 .06">
<joint name="7a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="7a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="7a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="7a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="7a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="7a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="7a_right_hand" pos=".18 .18 .18">
<geom name="7a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="7a_left_upper_arm" pos="0 .17 .06">
<joint name="7a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="7a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="7a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="7a_left_lower_arm" pos=".18 .18 -.18">
<joint name="7a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="7a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="7a_left_hand" pos=".18 -.18 .18">
<geom name="7a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="8a_torso" pos="-1 4 1.5" childclass="body8">
<camera name="8a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="8a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="8a_root"/>
<geom name="8a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="8a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="8a_head" pos="0 0 .19">
<geom name="8a_head" type="sphere" size=".09"/>
<camera name="8a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="8a_lower_waist" pos="-.01 0 -.26">
<geom name="8a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="8a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="8a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="8a_pelvis" pos="0 0 -.165">
<joint name="8a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="8a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="8a_right_thigh" pos="0 -.1 -.04">
<joint name="8a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="8a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="8a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="8a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="8a_right_shin" pos="0 .01 -.403">
<joint name="8a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="8a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="8a_right_foot" pos="0 0 -.39">
<joint name="8a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="8a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="8a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="8a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="8a_left_thigh" pos="0 .1 -.04">
<joint name="8a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="8a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="8a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="8a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="8a_left_shin" pos="0 -.01 -.403">
<joint name="8a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="8a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="8a_left_foot" pos="0 0 -.39">
<joint name="8a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="8a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="8a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="8a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="8a_right_upper_arm" pos="0 -.17 .06">
<joint name="8a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="8a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="8a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="8a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="8a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="8a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="8a_right_hand" pos=".18 .18 .18">
<geom name="8a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="8a_left_upper_arm" pos="0 .17 .06">
<joint name="8a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="8a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="8a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="8a_left_lower_arm" pos=".18 .18 -.18">
<joint name="8a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="8a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="8a_left_hand" pos=".18 -.18 .18">
<geom name="8a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="4a_abdomen_y"/>
<motor gear="40" joint="4a_abdomen_z"/>
<motor gear="40" joint="4a_abdomen_x"/>
<motor gear="40" joint="4a_right_hip_x"/>
<motor gear="40" joint="4a_right_hip_z"/>
<motor gear="120" joint="4a_right_hip_y"/>
<motor gear="80" joint="4a_right_knee"/>
<motor gear="20" joint="4a_right_ankle_x"/>
<motor gear="20" joint="4a_right_ankle_y"/>
<motor gear="40" joint="4a_left_hip_x"/>
<motor gear="40" joint="4a_left_hip_z"/>
<motor gear="120" joint="4a_left_hip_y"/>
<motor gear="80" joint="4a_left_knee"/>
<motor gear="20" joint="4a_left_ankle_x"/>
<motor gear="20" joint="4a_left_ankle_y"/>
<motor gear="20" joint="4a_right_shoulder1"/>
<motor gear="20" joint="4a_right_shoulder2"/>
<motor gear="40" joint="4a_right_elbow"/>
<motor gear="20" joint="4a_left_shoulder1"/>
<motor gear="20" joint="4a_left_shoulder2"/>
<motor gear="40" joint="4a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="5a_abdomen_y"/>
<motor gear="40" joint="5a_abdomen_z"/>
<motor gear="40" joint="5a_abdomen_x"/>
<motor gear="40" joint="5a_right_hip_x"/>
<motor gear="40" joint="5a_right_hip_z"/>
<motor gear="120" joint="5a_right_hip_y"/>
<motor gear="80" joint="5a_right_knee"/>
<motor gear="20" joint="5a_right_ankle_x"/>
<motor gear="20" joint="5a_right_ankle_y"/>
<motor gear="40" joint="5a_left_hip_x"/>
<motor gear="40" joint="5a_left_hip_z"/>
<motor gear="120" joint="5a_left_hip_y"/>
<motor gear="80" joint="5a_left_knee"/>
<motor gear="20" joint="5a_left_ankle_x"/>
<motor gear="20" joint="5a_left_ankle_y"/>
<motor gear="20" joint="5a_right_shoulder1"/>
<motor gear="20" joint="5a_right_shoulder2"/>
<motor gear="40" joint="5a_right_elbow"/>
<motor gear="20" joint="5a_left_shoulder1"/>
<motor gear="20" joint="5a_left_shoulder2"/>
<motor gear="40" joint="5a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="6a_abdomen_y"/>
<motor gear="40" joint="6a_abdomen_z"/>
<motor gear="40" joint="6a_abdomen_x"/>
<motor gear="40" joint="6a_right_hip_x"/>
<motor gear="40" joint="6a_right_hip_z"/>
<motor gear="120" joint="6a_right_hip_y"/>
<motor gear="80" joint="6a_right_knee"/>
<motor gear="20" joint="6a_right_ankle_x"/>
<motor gear="20" joint="6a_right_ankle_y"/>
<motor gear="40" joint="6a_left_hip_x"/>
<motor gear="40" joint="6a_left_hip_z"/>
<motor gear="120" joint="6a_left_hip_y"/>
<motor gear="80" joint="6a_left_knee"/>
<motor gear="20" joint="6a_left_ankle_x"/>
<motor gear="20" joint="6a_left_ankle_y"/>
<motor gear="20" joint="6a_right_shoulder1"/>
<motor gear="20" joint="6a_right_shoulder2"/>
<motor gear="40" joint="6a_right_elbow"/>
<motor gear="20" joint="6a_left_shoulder1"/>
<motor gear="20" joint="6a_left_shoulder2"/>
<motor gear="40" joint="6a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="7a_abdomen_y"/>
<motor gear="40" joint="7a_abdomen_z"/>
<motor gear="40" joint="7a_abdomen_x"/>
<motor gear="40" joint="7a_right_hip_x"/>
<motor gear="40" joint="7a_right_hip_z"/>
<motor gear="120" joint="7a_right_hip_y"/>
<motor gear="80" joint="7a_right_knee"/>
<motor gear="20" joint="7a_right_ankle_x"/>
<motor gear="20" joint="7a_right_ankle_y"/>
<motor gear="40" joint="7a_left_hip_x"/>
<motor gear="40" joint="7a_left_hip_z"/>
<motor gear="120" joint="7a_left_hip_y"/>
<motor gear="80" joint="7a_left_knee"/>
<motor gear="20" joint="7a_left_ankle_x"/>
<motor gear="20" joint="7a_left_ankle_y"/>
<motor gear="20" joint="7a_right_shoulder1"/>
<motor gear="20" joint="7a_right_shoulder2"/>
<motor gear="40" joint="7a_right_elbow"/>
<motor gear="20" joint="7a_left_shoulder1"/>
<motor gear="20" joint="7a_left_shoulder2"/>
<motor gear="40" joint="7a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="8a_abdomen_y"/>
<motor gear="40" joint="8a_abdomen_z"/>
<motor gear="40" joint="8a_abdomen_x"/>
<motor gear="40" joint="8a_right_hip_x"/>
<motor gear="40" joint="8a_right_hip_z"/>
<motor gear="120" joint="8a_right_hip_y"/>
<motor gear="80" joint="8a_right_knee"/>
<motor gear="20" joint="8a_right_ankle_x"/>
<motor gear="20" joint="8a_right_ankle_y"/>
<motor gear="40" joint="8a_left_hip_x"/>
<motor gear="40" joint="8a_left_hip_z"/>
<motor gear="120" joint="8a_left_hip_y"/>
<motor gear="80" joint="8a_left_knee"/>
<motor gear="20" joint="8a_left_ankle_x"/>
<motor gear="20" joint="8a_left_ankle_y"/>
<motor gear="20" joint="8a_right_shoulder1"/>
<motor gear="20" joint="8a_right_shoulder2"/>
<motor gear="40" joint="8a_right_elbow"/>
<motor gear="20" joint="8a_left_shoulder1"/>
<motor gear="20" joint="8a_left_shoulder2"/>
<motor gear="40" joint="8a_left_elbow"/>
</actuator>
</mujoco>
@@ -0,0 +1,983 @@
<mujoco model="09 Humanoids">
<option timestep="0.005" solver="Newton" iterations="1" ls_iterations="4">
<flag eulerdamp="disable"/>
</option>
<custom>
<numeric data="36" name="max_contact_points"/>
<numeric data="36" name="max_geom_pairs"/>
</custom>
<size memory="100M"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128"
rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1" random="0.01"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<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="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="big_joint">
<joint damping="5" stiffness="10"/>
<default class="big_stiff_joint">
<joint stiffness="20"/>
</default>
</default>
<default class="body1">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="2" conaffinity="1021"/>
</default>
<default class="body2">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="4" conaffinity="1019"/>
</default>
<default class="body3">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="8" conaffinity="1015"/>
</default>
<default class="body4">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="16" conaffinity="1007"/>
</default>
<default class="body5">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="32" conaffinity="991"/>
</default>
<default class="body6">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="64" conaffinity="959"/>
</default>
<default class="body7">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="128" conaffinity="895"/>
</default>
<default class="body8">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="256" conaffinity="767"/>
</default>
<default class="body9">
<geom type="capsule" condim="3" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" contype="512" conaffinity="511"/>
</default>
</default>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<quality shadowsize="4096"/>
<global offwidth="800" offheight="800"/>
</visual>
<worldbody>
<geom size="10 10 .05" type="plane" material="grid" condim="3"/>
<light dir=".2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="-2 -10 4" cutoff="35"/>
<light dir="-.2 1 -.4" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="2 -10 4" cutoff="35"/>
<body name="1a_torso" pos="-1 0 1.5" childclass="body1">
<camera name="1a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="1a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="1a_root"/>
<geom name="1a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="1a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="1a_head" pos="0 0 .19">
<geom name="1a_head" type="sphere" size=".09"/>
<camera name="1a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="1a_lower_waist" pos="-.01 0 -.26">
<geom name="1a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="1a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="1a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="1a_pelvis" pos="0 0 -.165">
<joint name="1a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="1a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="1a_right_thigh" pos="0 -.1 -.04">
<joint name="1a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="1a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="1a_right_shin" pos="0 .01 -.403">
<joint name="1a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_right_foot" pos="0 0 -.39">
<joint name="1a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="1a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="1a_left_thigh" pos="0 .1 -.04">
<joint name="1a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="1a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="1a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="1a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="1a_left_shin" pos="0 -.01 -.403">
<joint name="1a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="1a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="1a_left_foot" pos="0 0 -.39">
<joint name="1a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="1a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="1a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="1a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="1a_right_upper_arm" pos="0 -.17 .06">
<joint name="1a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="1a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="1a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="1a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="1a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="1a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="1a_right_hand" pos=".18 .18 .18">
<geom name="1a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="1a_left_upper_arm" pos="0 .17 .06">
<joint name="1a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="1a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="1a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="1a_left_lower_arm" pos=".18 .18 -.18">
<joint name="1a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="1a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="1a_left_hand" pos=".18 -.18 .18">
<geom name="1a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="2a_torso" pos="-1 1 1.5" childclass="body2">
<camera name="2a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="2a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="2a_root"/>
<geom name="2a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="2a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="2a_head" pos="0 0 .19">
<geom name="2a_head" type="sphere" size=".09"/>
<camera name="2a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="2a_lower_waist" pos="-.01 0 -.26">
<geom name="2a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="2a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="2a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="2a_pelvis" pos="0 0 -.165">
<joint name="2a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="2a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="2a_right_thigh" pos="0 -.1 -.04">
<joint name="2a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="2a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="2a_right_shin" pos="0 .01 -.403">
<joint name="2a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_right_foot" pos="0 0 -.39">
<joint name="2a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="2a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="2a_left_thigh" pos="0 .1 -.04">
<joint name="2a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="2a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="2a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="2a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="2a_left_shin" pos="0 -.01 -.403">
<joint name="2a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="2a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="2a_left_foot" pos="0 0 -.39">
<joint name="2a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="2a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="2a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="2a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="2a_right_upper_arm" pos="0 -.17 .06">
<joint name="2a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="2a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="2a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="2a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="2a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="2a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="2a_right_hand" pos=".18 .18 .18">
<geom name="2a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="2a_left_upper_arm" pos="0 .17 .06">
<joint name="2a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="2a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="2a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="2a_left_lower_arm" pos=".18 .18 -.18">
<joint name="2a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="2a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="2a_left_hand" pos=".18 -.18 .18">
<geom name="2a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="3a_torso" pos="-1 -1 1.5" childclass="body3">
<camera name="3a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="3a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="3a_root"/>
<geom name="3a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="3a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="3a_head" pos="0 0 .19">
<geom name="3a_head" type="sphere" size=".09"/>
<camera name="3a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="3a_lower_waist" pos="-.01 0 -.26">
<geom name="3a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="3a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="3a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="3a_pelvis" pos="0 0 -.165">
<joint name="3a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="3a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="3a_right_thigh" pos="0 -.1 -.04">
<joint name="3a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="3a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="3a_right_shin" pos="0 .01 -.403">
<joint name="3a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_right_foot" pos="0 0 -.39">
<joint name="3a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="3a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="3a_left_thigh" pos="0 .1 -.04">
<joint name="3a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="3a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="3a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="3a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="3a_left_shin" pos="0 -.01 -.403">
<joint name="3a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="3a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="3a_left_foot" pos="0 0 -.39">
<joint name="3a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="3a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="3a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="3a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="3a_right_upper_arm" pos="0 -.17 .06">
<joint name="3a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="3a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="3a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="3a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="3a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="3a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="3a_right_hand" pos=".18 .18 .18">
<geom name="3a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="3a_left_upper_arm" pos="0 .17 .06">
<joint name="3a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="3a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="3a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="3a_left_lower_arm" pos=".18 .18 -.18">
<joint name="3a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="3a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="3a_left_hand" pos=".18 -.18 .18">
<geom name="3a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="4a_torso" pos="-1 2 1.5" childclass="body4">
<camera name="4a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="4a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="4a_root"/>
<geom name="4a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="4a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="4a_head" pos="0 0 .19">
<geom name="4a_head" type="sphere" size=".09"/>
<camera name="4a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="4a_lower_waist" pos="-.01 0 -.26">
<geom name="4a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="4a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="4a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="4a_pelvis" pos="0 0 -.165">
<joint name="4a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="4a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="4a_right_thigh" pos="0 -.1 -.04">
<joint name="4a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="4a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="4a_right_shin" pos="0 .01 -.403">
<joint name="4a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_right_foot" pos="0 0 -.39">
<joint name="4a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="4a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="4a_left_thigh" pos="0 .1 -.04">
<joint name="4a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="4a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="4a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="4a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="4a_left_shin" pos="0 -.01 -.403">
<joint name="4a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="4a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="4a_left_foot" pos="0 0 -.39">
<joint name="4a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="4a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="4a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="4a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="4a_right_upper_arm" pos="0 -.17 .06">
<joint name="4a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="4a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="4a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="4a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="4a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="4a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="4a_right_hand" pos=".18 .18 .18">
<geom name="4a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="4a_left_upper_arm" pos="0 .17 .06">
<joint name="4a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="4a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="4a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="4a_left_lower_arm" pos=".18 .18 -.18">
<joint name="4a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="4a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="4a_left_hand" pos=".18 -.18 .18">
<geom name="4a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="5a_torso" pos="-1 -2 1.5" childclass="body5">
<camera name="5a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="5a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="5a_root"/>
<geom name="5a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="5a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="5a_head" pos="0 0 .19">
<geom name="5a_head" type="sphere" size=".09"/>
<camera name="5a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="5a_lower_waist" pos="-.01 0 -.26">
<geom name="5a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="5a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="5a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="5a_pelvis" pos="0 0 -.165">
<joint name="5a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="5a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="5a_right_thigh" pos="0 -.1 -.04">
<joint name="5a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="5a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="5a_right_shin" pos="0 .01 -.403">
<joint name="5a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_right_foot" pos="0 0 -.39">
<joint name="5a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="5a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="5a_left_thigh" pos="0 .1 -.04">
<joint name="5a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="5a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="5a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="5a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="5a_left_shin" pos="0 -.01 -.403">
<joint name="5a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="5a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="5a_left_foot" pos="0 0 -.39">
<joint name="5a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="5a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="5a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="5a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="5a_right_upper_arm" pos="0 -.17 .06">
<joint name="5a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="5a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="5a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="5a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="5a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="5a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="5a_right_hand" pos=".18 .18 .18">
<geom name="5a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="5a_left_upper_arm" pos="0 .17 .06">
<joint name="5a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="5a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="5a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="5a_left_lower_arm" pos=".18 .18 -.18">
<joint name="5a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="5a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="5a_left_hand" pos=".18 -.18 .18">
<geom name="5a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="6a_torso" pos="-1 3 1.5" childclass="body6">
<camera name="6a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="6a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="6a_root"/>
<geom name="6a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="6a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="6a_head" pos="0 0 .19">
<geom name="6a_head" type="sphere" size=".09"/>
<camera name="6a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="6a_lower_waist" pos="-.01 0 -.26">
<geom name="6a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="6a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="6a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="6a_pelvis" pos="0 0 -.165">
<joint name="6a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="6a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="6a_right_thigh" pos="0 -.1 -.04">
<joint name="6a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="6a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="6a_right_shin" pos="0 .01 -.403">
<joint name="6a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_right_foot" pos="0 0 -.39">
<joint name="6a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="6a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="6a_left_thigh" pos="0 .1 -.04">
<joint name="6a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="6a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="6a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="6a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="6a_left_shin" pos="0 -.01 -.403">
<joint name="6a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="6a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="6a_left_foot" pos="0 0 -.39">
<joint name="6a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="6a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="6a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="6a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="6a_right_upper_arm" pos="0 -.17 .06">
<joint name="6a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="6a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="6a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="6a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="6a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="6a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="6a_right_hand" pos=".18 .18 .18">
<geom name="6a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="6a_left_upper_arm" pos="0 .17 .06">
<joint name="6a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="6a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="6a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="6a_left_lower_arm" pos=".18 .18 -.18">
<joint name="6a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="6a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="6a_left_hand" pos=".18 -.18 .18">
<geom name="6a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="7a_torso" pos="-1 -3 1.5" childclass="body7">
<camera name="7a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="7a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="7a_root"/>
<geom name="7a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="7a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="7a_head" pos="0 0 .19">
<geom name="7a_head" type="sphere" size=".09"/>
<camera name="7a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="7a_lower_waist" pos="-.01 0 -.26">
<geom name="7a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="7a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="7a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="7a_pelvis" pos="0 0 -.165">
<joint name="7a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="7a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="7a_right_thigh" pos="0 -.1 -.04">
<joint name="7a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="7a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="7a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="7a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="7a_right_shin" pos="0 .01 -.403">
<joint name="7a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="7a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="7a_right_foot" pos="0 0 -.39">
<joint name="7a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="7a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="7a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="7a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="7a_left_thigh" pos="0 .1 -.04">
<joint name="7a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="7a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="7a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="7a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="7a_left_shin" pos="0 -.01 -.403">
<joint name="7a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="7a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="7a_left_foot" pos="0 0 -.39">
<joint name="7a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="7a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="7a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="7a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="7a_right_upper_arm" pos="0 -.17 .06">
<joint name="7a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="7a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="7a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="7a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="7a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="7a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="7a_right_hand" pos=".18 .18 .18">
<geom name="7a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="7a_left_upper_arm" pos="0 .17 .06">
<joint name="7a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="7a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="7a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="7a_left_lower_arm" pos=".18 .18 -.18">
<joint name="7a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="7a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="7a_left_hand" pos=".18 -.18 .18">
<geom name="7a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="8a_torso" pos="-1 4 1.5" childclass="body8">
<camera name="8a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="8a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="8a_root"/>
<geom name="8a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="8a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="8a_head" pos="0 0 .19">
<geom name="8a_head" type="sphere" size=".09"/>
<camera name="8a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="8a_lower_waist" pos="-.01 0 -.26">
<geom name="8a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="8a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="8a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="8a_pelvis" pos="0 0 -.165">
<joint name="8a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="8a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="8a_right_thigh" pos="0 -.1 -.04">
<joint name="8a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="8a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="8a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="8a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="8a_right_shin" pos="0 .01 -.403">
<joint name="8a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="8a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="8a_right_foot" pos="0 0 -.39">
<joint name="8a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="8a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="8a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="8a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="8a_left_thigh" pos="0 .1 -.04">
<joint name="8a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="8a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="8a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="8a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="8a_left_shin" pos="0 -.01 -.403">
<joint name="8a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="8a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="8a_left_foot" pos="0 0 -.39">
<joint name="8a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="8a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="8a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="8a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="8a_right_upper_arm" pos="0 -.17 .06">
<joint name="8a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="8a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="8a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="8a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="8a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="8a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="8a_right_hand" pos=".18 .18 .18">
<geom name="8a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="8a_left_upper_arm" pos="0 .17 .06">
<joint name="8a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="8a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="8a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="8a_left_lower_arm" pos=".18 .18 -.18">
<joint name="8a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="8a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="8a_left_hand" pos=".18 -.18 .18">
<geom name="8a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
<body name="9a_torso" pos="-1 -4 1.5" childclass="body9">
<camera name="9a_back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="9a_side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="9a_root"/>
<geom name="9a_torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="9a_upper_waist" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="9a_head" pos="0 0 .19">
<geom name="9a_head" type="sphere" size=".09"/>
<camera name="9a_egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="9a_lower_waist" pos="-.01 0 -.26">
<geom name="9a_lower_waist" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="9a_abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="big_stiff_joint"/>
<joint name="9a_abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="big_joint"/>
<body name="9a_pelvis" pos="0 0 -.165">
<joint name="9a_abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="big_joint"/>
<geom name="9a_butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="9a_right_thigh" pos="0 -.1 -.04">
<joint name="9a_right_hip_x" axis="1 0 0" range="-25 5" class="big_joint"/>
<joint name="9a_right_hip_z" axis="0 0 1" range="-60 35" class="big_joint"/>
<joint name="9a_right_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="9a_right_thigh" fromto="0 0 0 0 .01 -.34" size=".06"/>
<body name="9a_right_shin" pos="0 .01 -.403">
<joint name="9a_right_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="9a_right_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="9a_right_foot" pos="0 0 -.39">
<joint name="9a_right_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="9a_right_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="9a_right_right_foot" fromto="-.07 -.02 0 .14 -.04 0" size=".027"/>
<geom name="9a_left_right_foot" fromto="-.07 0 0 .14 .02 0" size=".027"/>
</body>
</body>
</body>
<body name="9a_left_thigh" pos="0 .1 -.04">
<joint name="9a_left_hip_x" axis="-1 0 0" range="-25 5" class="big_joint"/>
<joint name="9a_left_hip_z" axis="0 0 -1" range="-60 35" class="big_joint"/>
<joint name="9a_left_hip_y" axis="0 1 0" range="-110 20" class="big_stiff_joint"/>
<geom name="9a_left_thigh" fromto="0 0 0 0 -.01 -.34" size=".06"/>
<body name="9a_left_shin" pos="0 -.01 -.403">
<joint name="9a_left_knee" pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
<geom name="9a_left_shin" fromto="0 0 0 0 0 -.3" size=".049"/>
<body name="9a_left_foot" pos="0 0 -.39">
<joint name="9a_left_ankle_y" pos="0 0 .08" axis="0 1 0" range="-50 50" stiffness="6"/>
<joint name="9a_left_ankle_x" pos="0 0 .04" axis="1 0 .5" range="-50 50" stiffness="3"/>
<geom name="9a_left_left_foot" fromto="-.07 .02 0 .14 .04 0" size=".027"/>
<geom name="9a_right_left_foot" fromto="-.07 0 0 .14 -.02 0" size=".027"/>
</body>
</body>
</body>
</body>
</body>
<body name="9a_right_upper_arm" pos="0 -.17 .06">
<joint name="9a_right_shoulder1" axis="2 1 1" range="-85 60"/>
<joint name="9a_right_shoulder2" axis="0 -1 1" range="-85 60"/>
<geom name="9a_right_upper_arm" fromto="0 0 0 .16 -.16 -.16" size=".04 .16"/>
<body name="9a_right_lower_arm" pos=".18 -.18 -.18">
<joint name="9a_right_elbow" axis="0 -1 1" range="-90 50" stiffness="0"/>
<geom name="9a_right_lower_arm" fromto=".01 .01 .01 .17 .17 .17" size=".031"/>
<body name="9a_right_hand" pos=".18 .18 .18">
<geom name="9a_right_hand" type="sphere" size=".04" zaxis="1 1 1"/>
</body>
</body>
</body>
<body name="9a_left_upper_arm" pos="0 .17 .06">
<joint name="9a_left_shoulder1" axis="2 -1 1" range="-60 85"/>
<joint name="9a_left_shoulder2" axis="0 1 1" range="-60 85"/>
<geom name="9a_left_upper_arm" fromto="0 0 0 .16 .16 -.16" size=".04 .16"/>
<body name="9a_left_lower_arm" pos=".18 .18 -.18">
<joint name="9a_left_elbow" axis="0 -1 -1" range="-90 50" stiffness="0"/>
<geom name="9a_left_lower_arm" fromto=".01 -.01 .01 .17 -.17 .17" size=".031"/>
<body name="9a_left_hand" pos=".18 -.18 .18">
<geom name="9a_left_hand" type="sphere" size=".04" zaxis="1 -1 1"/>
</body>
</body>
</body>
</body>
</worldbody>
<actuator>
<motor gear="40" joint="1a_abdomen_y"/>
<motor gear="40" joint="1a_abdomen_z"/>
<motor gear="40" joint="1a_abdomen_x"/>
<motor gear="40" joint="1a_right_hip_x"/>
<motor gear="40" joint="1a_right_hip_z"/>
<motor gear="120" joint="1a_right_hip_y"/>
<motor gear="80" joint="1a_right_knee"/>
<motor gear="20" joint="1a_right_ankle_x"/>
<motor gear="20" joint="1a_right_ankle_y"/>
<motor gear="40" joint="1a_left_hip_x"/>
<motor gear="40" joint="1a_left_hip_z"/>
<motor gear="120" joint="1a_left_hip_y"/>
<motor gear="80" joint="1a_left_knee"/>
<motor gear="20" joint="1a_left_ankle_x"/>
<motor gear="20" joint="1a_left_ankle_y"/>
<motor gear="20" joint="1a_right_shoulder1"/>
<motor gear="20" joint="1a_right_shoulder2"/>
<motor gear="40" joint="1a_right_elbow"/>
<motor gear="20" joint="1a_left_shoulder1"/>
<motor gear="20" joint="1a_left_shoulder2"/>
<motor gear="40" joint="1a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="2a_abdomen_y"/>
<motor gear="40" joint="2a_abdomen_z"/>
<motor gear="40" joint="2a_abdomen_x"/>
<motor gear="40" joint="2a_right_hip_x"/>
<motor gear="40" joint="2a_right_hip_z"/>
<motor gear="120" joint="2a_right_hip_y"/>
<motor gear="80" joint="2a_right_knee"/>
<motor gear="20" joint="2a_right_ankle_x"/>
<motor gear="20" joint="2a_right_ankle_y"/>
<motor gear="40" joint="2a_left_hip_x"/>
<motor gear="40" joint="2a_left_hip_z"/>
<motor gear="120" joint="2a_left_hip_y"/>
<motor gear="80" joint="2a_left_knee"/>
<motor gear="20" joint="2a_left_ankle_x"/>
<motor gear="20" joint="2a_left_ankle_y"/>
<motor gear="20" joint="2a_right_shoulder1"/>
<motor gear="20" joint="2a_right_shoulder2"/>
<motor gear="40" joint="2a_right_elbow"/>
<motor gear="20" joint="2a_left_shoulder1"/>
<motor gear="20" joint="2a_left_shoulder2"/>
<motor gear="40" joint="2a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="3a_abdomen_y"/>
<motor gear="40" joint="3a_abdomen_z"/>
<motor gear="40" joint="3a_abdomen_x"/>
<motor gear="40" joint="3a_right_hip_x"/>
<motor gear="40" joint="3a_right_hip_z"/>
<motor gear="120" joint="3a_right_hip_y"/>
<motor gear="80" joint="3a_right_knee"/>
<motor gear="20" joint="3a_right_ankle_x"/>
<motor gear="20" joint="3a_right_ankle_y"/>
<motor gear="40" joint="3a_left_hip_x"/>
<motor gear="40" joint="3a_left_hip_z"/>
<motor gear="120" joint="3a_left_hip_y"/>
<motor gear="80" joint="3a_left_knee"/>
<motor gear="20" joint="3a_left_ankle_x"/>
<motor gear="20" joint="3a_left_ankle_y"/>
<motor gear="20" joint="3a_right_shoulder1"/>
<motor gear="20" joint="3a_right_shoulder2"/>
<motor gear="40" joint="3a_right_elbow"/>
<motor gear="20" joint="3a_left_shoulder1"/>
<motor gear="20" joint="3a_left_shoulder2"/>
<motor gear="40" joint="3a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="4a_abdomen_y"/>
<motor gear="40" joint="4a_abdomen_z"/>
<motor gear="40" joint="4a_abdomen_x"/>
<motor gear="40" joint="4a_right_hip_x"/>
<motor gear="40" joint="4a_right_hip_z"/>
<motor gear="120" joint="4a_right_hip_y"/>
<motor gear="80" joint="4a_right_knee"/>
<motor gear="20" joint="4a_right_ankle_x"/>
<motor gear="20" joint="4a_right_ankle_y"/>
<motor gear="40" joint="4a_left_hip_x"/>
<motor gear="40" joint="4a_left_hip_z"/>
<motor gear="120" joint="4a_left_hip_y"/>
<motor gear="80" joint="4a_left_knee"/>
<motor gear="20" joint="4a_left_ankle_x"/>
<motor gear="20" joint="4a_left_ankle_y"/>
<motor gear="20" joint="4a_right_shoulder1"/>
<motor gear="20" joint="4a_right_shoulder2"/>
<motor gear="40" joint="4a_right_elbow"/>
<motor gear="20" joint="4a_left_shoulder1"/>
<motor gear="20" joint="4a_left_shoulder2"/>
<motor gear="40" joint="4a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="5a_abdomen_y"/>
<motor gear="40" joint="5a_abdomen_z"/>
<motor gear="40" joint="5a_abdomen_x"/>
<motor gear="40" joint="5a_right_hip_x"/>
<motor gear="40" joint="5a_right_hip_z"/>
<motor gear="120" joint="5a_right_hip_y"/>
<motor gear="80" joint="5a_right_knee"/>
<motor gear="20" joint="5a_right_ankle_x"/>
<motor gear="20" joint="5a_right_ankle_y"/>
<motor gear="40" joint="5a_left_hip_x"/>
<motor gear="40" joint="5a_left_hip_z"/>
<motor gear="120" joint="5a_left_hip_y"/>
<motor gear="80" joint="5a_left_knee"/>
<motor gear="20" joint="5a_left_ankle_x"/>
<motor gear="20" joint="5a_left_ankle_y"/>
<motor gear="20" joint="5a_right_shoulder1"/>
<motor gear="20" joint="5a_right_shoulder2"/>
<motor gear="40" joint="5a_right_elbow"/>
<motor gear="20" joint="5a_left_shoulder1"/>
<motor gear="20" joint="5a_left_shoulder2"/>
<motor gear="40" joint="5a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="6a_abdomen_y"/>
<motor gear="40" joint="6a_abdomen_z"/>
<motor gear="40" joint="6a_abdomen_x"/>
<motor gear="40" joint="6a_right_hip_x"/>
<motor gear="40" joint="6a_right_hip_z"/>
<motor gear="120" joint="6a_right_hip_y"/>
<motor gear="80" joint="6a_right_knee"/>
<motor gear="20" joint="6a_right_ankle_x"/>
<motor gear="20" joint="6a_right_ankle_y"/>
<motor gear="40" joint="6a_left_hip_x"/>
<motor gear="40" joint="6a_left_hip_z"/>
<motor gear="120" joint="6a_left_hip_y"/>
<motor gear="80" joint="6a_left_knee"/>
<motor gear="20" joint="6a_left_ankle_x"/>
<motor gear="20" joint="6a_left_ankle_y"/>
<motor gear="20" joint="6a_right_shoulder1"/>
<motor gear="20" joint="6a_right_shoulder2"/>
<motor gear="40" joint="6a_right_elbow"/>
<motor gear="20" joint="6a_left_shoulder1"/>
<motor gear="20" joint="6a_left_shoulder2"/>
<motor gear="40" joint="6a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="7a_abdomen_y"/>
<motor gear="40" joint="7a_abdomen_z"/>
<motor gear="40" joint="7a_abdomen_x"/>
<motor gear="40" joint="7a_right_hip_x"/>
<motor gear="40" joint="7a_right_hip_z"/>
<motor gear="120" joint="7a_right_hip_y"/>
<motor gear="80" joint="7a_right_knee"/>
<motor gear="20" joint="7a_right_ankle_x"/>
<motor gear="20" joint="7a_right_ankle_y"/>
<motor gear="40" joint="7a_left_hip_x"/>
<motor gear="40" joint="7a_left_hip_z"/>
<motor gear="120" joint="7a_left_hip_y"/>
<motor gear="80" joint="7a_left_knee"/>
<motor gear="20" joint="7a_left_ankle_x"/>
<motor gear="20" joint="7a_left_ankle_y"/>
<motor gear="20" joint="7a_right_shoulder1"/>
<motor gear="20" joint="7a_right_shoulder2"/>
<motor gear="40" joint="7a_right_elbow"/>
<motor gear="20" joint="7a_left_shoulder1"/>
<motor gear="20" joint="7a_left_shoulder2"/>
<motor gear="40" joint="7a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="8a_abdomen_y"/>
<motor gear="40" joint="8a_abdomen_z"/>
<motor gear="40" joint="8a_abdomen_x"/>
<motor gear="40" joint="8a_right_hip_x"/>
<motor gear="40" joint="8a_right_hip_z"/>
<motor gear="120" joint="8a_right_hip_y"/>
<motor gear="80" joint="8a_right_knee"/>
<motor gear="20" joint="8a_right_ankle_x"/>
<motor gear="20" joint="8a_right_ankle_y"/>
<motor gear="40" joint="8a_left_hip_x"/>
<motor gear="40" joint="8a_left_hip_z"/>
<motor gear="120" joint="8a_left_hip_y"/>
<motor gear="80" joint="8a_left_knee"/>
<motor gear="20" joint="8a_left_ankle_x"/>
<motor gear="20" joint="8a_left_ankle_y"/>
<motor gear="20" joint="8a_right_shoulder1"/>
<motor gear="20" joint="8a_right_shoulder2"/>
<motor gear="40" joint="8a_right_elbow"/>
<motor gear="20" joint="8a_left_shoulder1"/>
<motor gear="20" joint="8a_left_shoulder2"/>
<motor gear="40" joint="8a_left_elbow"/>
</actuator>
<actuator>
<motor gear="40" joint="9a_abdomen_y"/>
<motor gear="40" joint="9a_abdomen_z"/>
<motor gear="40" joint="9a_abdomen_x"/>
<motor gear="40" joint="9a_right_hip_x"/>
<motor gear="40" joint="9a_right_hip_z"/>
<motor gear="120" joint="9a_right_hip_y"/>
<motor gear="80" joint="9a_right_knee"/>
<motor gear="20" joint="9a_right_ankle_x"/>
<motor gear="20" joint="9a_right_ankle_y"/>
<motor gear="40" joint="9a_left_hip_x"/>
<motor gear="40" joint="9a_left_hip_z"/>
<motor gear="120" joint="9a_left_hip_y"/>
<motor gear="80" joint="9a_left_knee"/>
<motor gear="20" joint="9a_left_ankle_x"/>
<motor gear="20" joint="9a_left_ankle_y"/>
<motor gear="20" joint="9a_right_shoulder1"/>
<motor gear="20" joint="9a_right_shoulder2"/>
<motor gear="40" joint="9a_right_elbow"/>
<motor gear="20" joint="9a_left_shoulder1"/>
<motor gear="20" joint="9a_left_shoulder2"/>
<motor gear="40" joint="9a_left_elbow"/>
</actuator>
</mujoco>
File diff suppressed because it is too large Load Diff
@@ -156,7 +156,7 @@
diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/> diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/>
<joint name="rh_FFJ1" class="middle_distal"/> <joint name="rh_FFJ1" class="middle_distal"/>
<geom class="plastic_visual" mesh="f_distal_pst"/> <geom class="plastic_visual" mesh="f_distal_pst"/>
<geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214"/> <geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214" contype="0" conaffinity="2"/>
</body> </body>
</body> </body>
</body> </body>
@@ -181,7 +181,7 @@
diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/> diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/>
<joint name="rh_MFJ1" class="middle_distal"/> <joint name="rh_MFJ1" class="middle_distal"/>
<geom class="plastic_visual" mesh="f_distal_pst"/> <geom class="plastic_visual" mesh="f_distal_pst"/>
<geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214"/> <geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214" contype="0" conaffinity="2"/>
</body> </body>
</body> </body>
</body> </body>
@@ -206,7 +206,7 @@
diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/> diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/>
<joint name="rh_RFJ1" class="middle_distal"/> <joint name="rh_RFJ1" class="middle_distal"/>
<geom class="plastic_visual" mesh="f_distal_pst"/> <geom class="plastic_visual" mesh="f_distal_pst"/>
<geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214"/> <geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214" contype="0" conaffinity="2"/>
</body> </body>
</body> </body>
</body> </body>
@@ -236,7 +236,7 @@
diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/> diaginertia="1.28092e-06 1.12092e-06 5.3e-07"/>
<joint name="rh_LFJ1" class="middle_distal"/> <joint name="rh_LFJ1" class="middle_distal"/>
<geom class="plastic_visual" mesh="f_distal_pst"/> <geom class="plastic_visual" mesh="f_distal_pst"/>
<geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214"/> <geom class="plastic_collision" type="mesh" mesh="f_distal_pst_214" contype="0" conaffinity="2"/>
</body> </body>
</body> </body>
</body> </body>
@@ -266,7 +266,7 @@
diaginertia="2.37794e-06 2.27794e-06 1e-06"/> diaginertia="2.37794e-06 2.27794e-06 1e-06"/>
<joint name="rh_THJ1" class="thdistal"/> <joint name="rh_THJ1" class="thdistal"/>
<geom class="plastic_visual" mesh="th_distal_pst"/> <geom class="plastic_visual" mesh="th_distal_pst"/>
<geom class="plastic_collision" type="mesh" mesh="th_distal_pst_190"/> <geom class="plastic_collision" type="mesh" mesh="th_distal_pst_190" contype="0" conaffinity="2"/>
</body> </body>
</body> </body>
</body> </body>
+41 -84
View File
@@ -14,110 +14,67 @@
# ============================================================================== # ==============================================================================
"""Run benchmarks on various devices.""" """Run benchmarks on various devices."""
import os from typing import Sequence
import time
from typing import Sequence, Tuple
from absl import app from absl import app
from absl import flags from absl import flags
from etils import epath from etils import epath
import jax
import mujoco import mujoco
from mujoco import mjx from mujoco import mjx
FLAGS = flags.FLAGS _MJCF = flags.DEFINE_string('mjcf', None, 'path to model', required=True)
_BASE_PATH = flags.DEFINE_string(
flags.DEFINE_string('mjcf', None, 'path to model', required=True) 'base_path', None, 'base path, defaults to mujoco.mjx resource path'
flags.DEFINE_integer('nstep', 1000, 'number of steps per rollout') )
flags.DEFINE_integer('batch_size', 1024, 'number of parallel rollouts') _NSTEP = flags.DEFINE_integer('nstep', 1000, 'number of steps per rollout')
flags.DEFINE_integer('unroll', 1, 'loop unroll length') _BATCH_SIZE = flags.DEFINE_integer(
flags.DEFINE_enum('solver', 'cg', ['cg', 'newton'], 'constraint solver') 'batch_size', 1024, 'number of parallel rollouts'
flags.DEFINE_integer('iterations', 1, 'number of solver iterations') )
flags.DEFINE_integer('ls_iterations', 4, 'number of linesearch iterations') _UNROLL = flags.DEFINE_integer('unroll', 1, 'loop unroll length')
flags.DEFINE_enum('output', 'text', ['text', 'tsv'], 'format to print results') _SOLVER = flags.DEFINE_enum(
'solver', 'cg', ['cg', 'newton'], 'constraint solver'
)
def _measure(fn, *args) -> Tuple[float, float]: _ITERATIONS = flags.DEFINE_integer(
"""Reports jit time and op time for a function.""" 'iterations', 1, 'number of solver iterations'
)
beg = time.perf_counter() _LS_ITERATIONS = flags.DEFINE_integer(
compiled_fn = fn.lower(*args).compile() 'ls_iterations', 4, 'number of linesearch iterations'
end = time.perf_counter() )
jit_time = end - beg _OUTPUT = flags.DEFINE_enum(
'output', 'text', ['text', 'tsv'], 'format to print results'
beg = time.perf_counter() )
result = compiled_fn(*args)
jax.block_until_ready(result)
end = time.perf_counter()
run_time = end - beg
return jit_time, run_time
def _main(argv: Sequence[str]): def _main(argv: Sequence[str]):
"""Benchmark a model.""" """Runs testpeed function."""
base_path = _BASE_PATH.value or epath.resource_path('mujoco.mjx')
xla_flags = os.environ.get('XLA_FLAGS', '') f = base_path / 'test_data' / _MJCF.value
xla_flags += ' --xla_gpu_triton_gemm_any=True'
os.environ['XLA_FLAGS'] = xla_flags
f = epath.resource_path('mujoco.mjx') / 'test_data' / FLAGS.mjcf
m = mujoco.MjModel.from_xml_path(f.as_posix()) m = mujoco.MjModel.from_xml_path(f.as_posix())
m.opt.solver = {
'cg': mujoco.mjtSolver.mjSOL_CG,
'newton': mujoco.mjtSolver.mjSOL_NEWTON,
}[FLAGS.solver.lower()]
m.opt.iterations = FLAGS.iterations
m.opt.ls_iterations = FLAGS.ls_iterations
m = mjx.put_model(m)
if FLAGS.output == 'text': print(f'Rolling out {_NSTEP.value} steps at dt = {m.opt.timestep:.3f}...')
print(f"Rolling out {FLAGS.nstep} steps at dt = {m.opt.timestep:.3f}...") jit_time, run_time, steps = mjx.benchmark(
m,
_NSTEP.value,
_BATCH_SIZE.value,
_UNROLL.value,
_SOLVER.value,
_ITERATIONS.value,
_LS_ITERATIONS.value,
)
@jax.pmap name = argv[0]
def init(key): if _OUTPUT.value == 'text':
key = jax.random.split(key, FLAGS.batch_size // jax.device_count())
@jax.vmap
def random_init(key):
d = mjx.make_data(m)
qvel = 0.01 * jax.random.normal(key, shape=(m.nv,))
d = d.replace(qvel=qvel)
return d
return random_init(key)
key = jax.random.split(jax.random.key(0), jax.device_count())
d = init(key)
jax.block_until_ready(d)
@jax.pmap
def unroll(d):
@jax.vmap
def step(d, _):
d = mjx.step(m, d)
return d, None
d, _ = jax.lax.scan(step, d, None, length=FLAGS.nstep, unroll=FLAGS.unroll)
return d
jit_time, run_time = _measure(unroll, d)
steps = FLAGS.nstep * FLAGS.batch_size
if FLAGS.output == 'text':
print(f""" print(f"""
Summary for {FLAGS.batch_size} parallel rollouts Summary for {_BATCH_SIZE.value} parallel rollouts
Total JIT time: {jit_time:.2f} s Total JIT time: {jit_time:.2f} s
Total simulation time: {run_time:.2f} s Total simulation time: {run_time:.2f} s
Total steps per second: { steps / run_time:.0f} Total steps per second: { steps / run_time:.0f}
Total realtime factor: { steps * m.opt.timestep / run_time:.2f} x Total realtime factor: { steps * m.opt.timestep / run_time:.2f} x
Total time per step: { 1e6 * run_time / steps:.2f} µs""") Total time per step: { 1e6 * run_time / steps:.2f} µs""")
elif FLAGS.output == 'tsv': elif _OUTPUT.value == 'tsv':
name = argv[0].split('/')[-1].replace('testspeed_', '') name = name.split('/')[-1].replace('testspeed_', '')
print(f"{name}\tjit: {jit_time:.2f}s\tsteps/second: {steps / run_time:.0f}") print(f'{name}\tjit: {jit_time:.2f}s\tsteps/second: {steps / run_time:.0f}')
def main(): def main():
+1 -1
View File
@@ -367,7 +367,7 @@
"rng = jax.random.split(rng, 4096)\n", "rng = jax.random.split(rng, 4096)\n",
"batch = jax.vmap(lambda rng: mjx_data.replace(qpos=jax.random.uniform(rng, (1,))))(rng)\n", "batch = jax.vmap(lambda rng: mjx_data.replace(qpos=jax.random.uniform(rng, (1,))))(rng)\n",
"\n", "\n",
"jit_step = jax.vmap(mjx.step, in_axes=(None, 0))\n", "jit_step = jax.jit(jax.vmap(mjx.step, in_axes=(None, 0)))\n",
"batch = jit_step(mjx_model, batch)\n", "batch = jit_step(mjx_model, batch)\n",
"\n", "\n",
"print(batch.qpos)" "print(batch.qpos)"
+2 -2
View File
@@ -234,10 +234,10 @@
"$$\n", "$$\n",
"\\begin{aligned}\n", "\\begin{aligned}\n",
"x^* &= \\arg \\min_x f(x)\\\\\n", "x^* &= \\arg \\min_x f(x)\\\\\n",
"\\textrm{s.t.} &\\quad l \\succcurlyeq x \\succcurlyeq u\n", "\\textrm{s.t.} &\\quad l \\preccurlyeq x \\preccurlyeq u\n",
"\\end{aligned}\n", "\\end{aligned}\n",
"$$\n", "$$\n",
"Where $l$ and $u$ are respectively lower and upper bound vectors and the inequalities $l \\succcurlyeq x \\succcurlyeq u$ are read elementwise. Solving for the minimizing $\\delta x$ is now a bit more involved than solving a linear system, and the optimization method is now referred to as [Sequential Quadratic Programming](https://en.wikipedia.org/wiki/Sequential_quadratic_programming) (SQP). Fortunately MuJoCo has an efficient box-constrained QP solver: the [mju_boxQP](https://mujoco.readthedocs.io/en/latest/APIreference/APIfunctions.html#mju-boxqp) function." "Where $l$ and $u$ are respectively lower and upper bound vectors and the inequalities $l \\preccurlyeq x \\preccurlyeq u$ are read elementwise. Solving for the minimizing $\\delta x$ is now a bit more involved than solving a linear system, and the optimization method is now referred to as [Sequential Quadratic Programming](https://en.wikipedia.org/wiki/Sequential_quadratic_programming) (SQP). Fortunately MuJoCo has an efficient box-constrained QP solver: the [mju_boxQP](https://mujoco.readthedocs.io/en/latest/APIreference/APIfunctions.html#mju-boxqp) function."
] ]
}, },
{ {
+4 -4
View File
@@ -623,7 +623,7 @@ class MuJoCoBindingsTest(parameterized.TestCase):
self.assertEqual(struct, struct2) self.assertEqual(struct, struct2)
self.assertNotEqual(struct, 3) self.assertNotEqual(struct, 3)
self.assertNotEqual(struct, None) self.assertIsNotNone(struct)
# mutable structs shouldn't declare __hash__ # mutable structs shouldn't declare __hash__
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
@@ -705,7 +705,8 @@ class MuJoCoBindingsTest(parameterized.TestCase):
# Check that the output argument must have the correct dtype. # Check that the output argument must have the correct dtype.
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
mujoco.mju_rotVecQuat(vec, quat, res=np.zeros(3, int)) res = np.zeros(3, np.int32)
mujoco.mju_rotVecQuat(res, vec, quat)
def test_getsetstate(self): # pylint: disable=invalid-name def test_getsetstate(self): # pylint: disable=invalid-name
mujoco.mj_step(self.model, self.data) mujoco.mj_step(self.model, self.data)
@@ -850,8 +851,7 @@ Euler integrator, semi-implicit in velocity.
self.assertEqual(mujoco.mjtEnableBit.mjENBL_OVERRIDE, 1<<0) self.assertEqual(mujoco.mjtEnableBit.mjENBL_OVERRIDE, 1<<0)
self.assertEqual(mujoco.mjtEnableBit.mjENBL_ENERGY, 1<<1) self.assertEqual(mujoco.mjtEnableBit.mjENBL_ENERGY, 1<<1)
self.assertEqual(mujoco.mjtEnableBit.mjENBL_FWDINV, 1<<2) self.assertEqual(mujoco.mjtEnableBit.mjENBL_FWDINV, 1<<2)
self.assertEqual(mujoco.mjtEnableBit.mjENBL_SENSORNOISE, 1<<4) self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 6)
self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 7)
self.assertEqual(mujoco.mjtGeom.mjGEOM_PLANE, 0) self.assertEqual(mujoco.mjtGeom.mjGEOM_PLANE, 0)
self.assertEqual(mujoco.mjtGeom.mjGEOM_HFIELD, 1) self.assertEqual(mujoco.mjtGeom.mjGEOM_HFIELD, 1)
self.assertEqual(mujoco.mjtGeom.mjGEOM_SPHERE, 2) self.assertEqual(mujoco.mjtGeom.mjGEOM_SPHERE, 2)
+71
View File
@@ -0,0 +1,71 @@
#usda 1.0
(
defaultPrim = "World"
doc = """Generated from Composed Stage of root layer
"""
endTimeCode = 1
startTimeCode = 0
timeCodesPerSecond = 24
upAxis = "Z"
)
def Xform "World"
{
def Xform "Light_Xform_0"
{
double3 xformOp:translate
uniform token[] xformOpOrder = ["xformOp:translate"]
def SphereLight "Light_0"
{
bool inputs:normalize = 1
float inputs:radius = 0.3
bool treatAsPoint = 0
}
}
def Xform "CubeMesh_Xform_white_box"
{
matrix4d xformOp:transform.timeSamples = {
0: ( (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 0), (0, 0, 0, 1) ),
}
uniform token[] xformOpOrder = ["xformOp:transform"]
def Mesh "CubeMesh_white_box" (
apiSchemas = ["MaterialBindingAPI"]
)
{
int[] faceVertexCounts = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
int[] faceVertexIndices = [4, 7, 5, 4, 6, 7, 0, 2, 4, 2, 6, 4, 0, 1, 2, 1, 3, 2, 1, 5, 7, 1, 7, 3, 2, 3, 7, 2, 7, 6, 0, 4, 1, 1, 4, 5]
rel material:binding = </World/_materials/Material_white_box>
point3f[] points = [(-1, -1, -1), (1, -1, -1), (-1, -1, 1), (1, -1, 1), (-1, 1, -1), (1, 1, -1), (-1, 1, 1), (1, 1, 1)]
texCoord2f[] primvars:UVMap = [] (
interpolation = "faceVarying"
)
int[] primvars:UVMap:indices = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35]
uniform token subdivisionScheme = "none"
token visibility.timeSamples = {
0: "inherited",
}
}
}
def "_materials"
{
def Material "Material_white_box"
{
token outputs:surface.connect = </World/_materials/Material_white_box/Principled_BSDF.outputs:surface>
def Shader "Principled_BSDF"
{
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor = (1, 1, 1)
float inputs:metallic = 0.5
float inputs:opacity = 1
float inputs:roughness = 0.5
token outputs:surface
}
}
}
}
+14 -126
View File
@@ -15,6 +15,7 @@
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
import mujoco import mujoco
import mujoco.usd.utils
import numpy as np import numpy as np
# TODO: b/288149332 - Remove once USD Python Binding works well with pytype. # TODO: b/288149332 - Remove once USD Python Binding works well with pytype.
@@ -38,7 +39,7 @@ class USDMesh:
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
dataid: int, dataid: int,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
self.stage = stage self.stage = stage
@@ -236,7 +237,7 @@ class USDPrimitiveMesh:
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
self.stage = stage self.stage = stage
@@ -245,7 +246,10 @@ class USDPrimitiveMesh:
self.rgba = rgba self.rgba = rgba
self.texture_file = texture_file self.texture_file = texture_file
self.usd_prim = Usd.Prim()
self.usd_mesh = UsdGeom.Mesh()
self.prim_mesh = None self.prim_mesh = None
self.transform_op = Gf.Matrix4d(1.)
def _set_refinement_properties(self): def _set_refinement_properties(self):
self.usd_prim.GetAttribute("subdivisionScheme").Set("none") self.usd_prim.GetAttribute("subdivisionScheme").Set("none")
@@ -374,119 +378,6 @@ class USDPrimitiveMesh:
self.usd_prim.GetAttribute("visibility").Set("invisible", frame) self.usd_prim.GetAttribute("visibility").Set("invisible", frame)
class USDPrimitive:
def __init__(
self,
stage: Usd.Stage,
geom: mujoco.MjvGeom,
obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1),
texture_file: Optional[str] = None,
):
self.stage = stage
self.geom = geom
self.obj_name = obj_name
self.rgba = rgba
self.texture_file = texture_file
def _set_refinement_properties(self):
self.usd_prim.GetAttribute("subdivisionScheme").Set("none")
def _attach_material(self):
mtl_path = Sdf.Path(f"/World/_materials/Material_{self.obj_name}")
mtl = UsdShade.Material.Define(self.stage, mtl_path)
if self.texture_file:
bsdf_shader = UsdShade.Shader.Define(
self.stage, mtl_path.AppendPath("Principled_BSDF")
)
image_shader = UsdShade.Shader.Define(
self.stage, mtl_path.AppendPath("Image_Texture")
)
uvmap_shader = UsdShade.Shader.Define(
self.stage, mtl_path.AppendPath("uvmap")
)
# settings the bsdf shader attributes
bsdf_shader.CreateIdAttr("UsdPreviewSurface")
bsdf_shader.CreateInput(
"diffuseColor", Sdf.ValueTypeNames.Color3f
).ConnectToSource(image_shader.ConnectableAPI(), "rgb")
bsdf_shader.CreateInput("opacity", Sdf.ValueTypeNames.Float).Set(
float(self.rgba[-1])
)
bsdf_shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set(
self.geom.shininess
)
bsdf_shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set(
1.0 - self.geom.shininess
)
mtl.CreateSurfaceOutput().ConnectToSource(
bsdf_shader.ConnectableAPI(), "surface"
)
self.usd_primitive_shape.GetPrim().ApplyAPI(UsdShade.MaterialBindingAPI)
UsdShade.MaterialBindingAPI(self.usd_primitive_shape).Bind(mtl)
# setting the image texture attributes
image_shader.CreateIdAttr("UsdUVTexture")
image_shader.CreateInput("file", Sdf.ValueTypeNames.Asset).Set(
self.texture_file
)
image_shader.CreateInput(
"sourceColorSpace", Sdf.ValueTypeNames.Token
).Set("sRGB")
image_shader.CreateInput("st", Sdf.ValueTypeNames.Float2).ConnectToSource(
uvmap_shader.ConnectableAPI(), "result"
)
image_shader.CreateOutput("rgb", Sdf.ValueTypeNames.Float3)
# setting uvmap shader attributes
uvmap_shader.CreateIdAttr("UsdPrimvarReader_float2")
uvmap_shader.CreateInput("varname", Sdf.ValueTypeNames.Token).Set("UVMap")
uvmap_shader.CreateOutput("results", Sdf.ValueTypeNames.Float2)
else:
bsdf_shader = UsdShade.Shader.Define(
self.stage, mtl_path.AppendPath("Principled_BSDF")
)
# settings the bsdf shader attributes
bsdf_shader.CreateIdAttr("UsdPreviewSurface")
bsdf_shader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).Set(
tuple(self.rgba[:3])
)
bsdf_shader.CreateInput("opacity", Sdf.ValueTypeNames.Float).Set(
float(self.rgba[-1])
)
bsdf_shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set(
self.geom.shininess
)
bsdf_shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set(
1.0 - self.geom.shininess
)
mtl.CreateSurfaceOutput().ConnectToSource(
bsdf_shader.ConnectableAPI(), "surface"
)
self.usd_primitive_shape.GetPrim().ApplyAPI(UsdShade.MaterialBindingAPI)
UsdShade.MaterialBindingAPI(self.usd_primitive_shape).Bind(mtl)
def update(self, pos: np.ndarray, mat: np.ndarray, visible: bool, frame: int):
transformation_mat = mujoco.usd.utils.create_transform_matrix(
rotation_matrix=mat, translation_vector=pos
).T
self.transform_op.Set(Gf.Matrix4d(transformation_mat.tolist()), frame)
self.update_visibility(visible, frame)
def update_visibility(self, visible: bool, frame: int):
if visible:
self.usd_prim.GetAttribute("visibility").Set("inherited", frame)
else:
self.usd_prim.GetAttribute("visibility").Set("invisible", frame)
class USDCapsule(USDPrimitive): class USDCapsule(USDPrimitive):
def __init__( def __init__(
@@ -494,7 +385,7 @@ class USDCapsule(USDPrimitive):
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
@@ -514,7 +405,7 @@ class USDCapsule(USDPrimitive):
self._set_size_attributes() self._set_size_attributes()
self._attach_material() self._attach_material()
self._set_refinement_properties() # self._set_refinement_properties()
def _set_size_attributes(self): def _set_size_attributes(self):
self.usd_primitive_shape.GetRadiusAttr().Set(float(self.geom.size[0])) self.usd_primitive_shape.GetRadiusAttr().Set(float(self.geom.size[0]))
@@ -530,7 +421,7 @@ class USDEllipsoid(USDPrimitive):
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
@@ -550,7 +441,7 @@ class USDEllipsoid(USDPrimitive):
self._set_size_attributes() self._set_size_attributes()
self._attach_material() self._attach_material()
self._set_refinement_properties() # self._set_refinement_properties()
def _set_size_attributes(self): def _set_size_attributes(self):
self.scale_op.Set(Gf.Vec3d(self.geom.size.tolist())) self.scale_op.Set(Gf.Vec3d(self.geom.size.tolist()))
@@ -563,7 +454,7 @@ class USDCubeMesh(USDPrimitiveMesh):
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
@@ -579,8 +470,6 @@ class USDCubeMesh(USDPrimitiveMesh):
width=self.geom.size[0] * 2, width=self.geom.size[0] * 2,
height=self.geom.size[1] * 2, height=self.geom.size[1] * 2,
depth=self.geom.size[2] * 2, depth=self.geom.size[2] * 2,
create_uv_map=True,
map_texture_to_each_face=True,
) )
self.prim_mesh.translate(-self.prim_mesh.get_center()) self.prim_mesh.translate(-self.prim_mesh.get_center())
@@ -617,7 +506,7 @@ class USDSphereMesh(USDPrimitiveMesh):
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
@@ -667,7 +556,7 @@ class USDCylinderMesh(USDPrimitiveMesh):
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
@@ -719,7 +608,7 @@ class USDPlaneMesh(USDPrimitiveMesh):
stage: Usd.Stage, stage: Usd.Stage,
geom: mujoco.MjvGeom, geom: mujoco.MjvGeom,
obj_name: str, obj_name: str,
rgba: Tuple[int, ...] = (1, 1, 1, 1), rgba: np.ndarray = np.array([1, 1, 1, 1]),
texture_file: Optional[str] = None, texture_file: Optional[str] = None,
): ):
@@ -814,7 +703,6 @@ class USDDomeLight:
self.usd_light.GetNormalizeAttr().Set(True) self.usd_light.GetNormalizeAttr().Set(True)
def update(self, intensity: int, color: np.ndarray, frame: int): def update(self, intensity: int, color: np.ndarray, frame: int):
self.usd_light.GetIntensityAttr().Set(intensity) self.usd_light.GetIntensityAttr().Set(intensity)
self.usd_light.GetExposureAttr().Set(0.0) self.usd_light.GetExposureAttr().Set(0.0)
self.usd_light.GetColorAttr().Set(Gf.Vec3d(color.tolist())) self.usd_light.GetColorAttr().Set(Gf.Vec3d(color.tolist()))
+1 -1
View File
@@ -14,6 +14,6 @@ if __name__ == "__main__":
exp.update_scene(d) exp.update_scene(d)
exp.save_scene(filetype="usd") exp.save_scene(filetype="usda")
+22 -16
View File
@@ -15,6 +15,7 @@
import os import os
import mujoco import mujoco
import mujoco.usd.component as component_module
import numpy as np import numpy as np
import scipy import scipy
import termcolor import termcolor
@@ -235,7 +236,7 @@ class USDExporter:
# handles meshes in scene # handles meshes in scene
if geom.type == mujoco.mjtGeom.mjGEOM_MESH: if geom.type == mujoco.mjtGeom.mjGEOM_MESH:
usd_geom = mujoco.usd.component.USDMesh( usd_geom = component_module.USDMesh(
stage=self.stage, stage=self.stage,
model=self.model, model=self.model,
geom=geom, geom=geom,
@@ -245,7 +246,7 @@ class USDExporter:
texture_file=texture_file, texture_file=texture_file,
) )
elif geom.type == mujoco.mjtGeom.mjGEOM_PLANE: elif geom.type == mujoco.mjtGeom.mjGEOM_PLANE:
usd_geom = mujoco.usd.component.USDPlaneMesh( usd_geom = component_module.USDPlaneMesh(
stage=self.stage, stage=self.stage,
geom=geom, geom=geom,
obj_name=geom_name, obj_name=geom_name,
@@ -253,7 +254,7 @@ class USDExporter:
texture_file=texture_file, texture_file=texture_file,
) )
elif geom.type == mujoco.mjtGeom.mjGEOM_SPHERE: elif geom.type == mujoco.mjtGeom.mjGEOM_SPHERE:
usd_geom = mujoco.usd.component.USDSphereMesh( usd_geom = component_module.USDSphereMesh(
stage=self.stage, stage=self.stage,
geom=geom, geom=geom,
obj_name=geom_name, obj_name=geom_name,
@@ -261,7 +262,7 @@ class USDExporter:
texture_file=texture_file, texture_file=texture_file,
) )
elif geom.type == mujoco.mjtGeom.mjGEOM_CAPSULE: elif geom.type == mujoco.mjtGeom.mjGEOM_CAPSULE:
usd_geom = mujoco.usd.component.USDCapsule( usd_geom = component_module.USDCapsule(
stage=self.stage, stage=self.stage,
geom=geom, geom=geom,
obj_name=geom_name, obj_name=geom_name,
@@ -269,7 +270,7 @@ class USDExporter:
texture_file=texture_file, texture_file=texture_file,
) )
elif geom.type == mujoco.mjtGeom.mjGEOM_ELLIPSOID: elif geom.type == mujoco.mjtGeom.mjGEOM_ELLIPSOID:
usd_geom = mujoco.usd.component.USDEllipsoid( usd_geom = component_module.USDEllipsoid(
stage=self.stage, stage=self.stage,
geom=geom, geom=geom,
obj_name=geom_name, obj_name=geom_name,
@@ -277,7 +278,7 @@ class USDExporter:
texture_file=texture_file, texture_file=texture_file,
) )
elif geom.type == mujoco.mjtGeom.mjGEOM_CYLINDER: elif geom.type == mujoco.mjtGeom.mjGEOM_CYLINDER:
usd_geom = mujoco.usd.component.USDCylinderMesh( usd_geom = component_module.USDCylinderMesh(
stage=self.stage, stage=self.stage,
geom=geom, geom=geom,
obj_name=geom_name, obj_name=geom_name,
@@ -285,7 +286,7 @@ class USDExporter:
texture_file=texture_file, texture_file=texture_file,
) )
elif geom.type == mujoco.mjtGeom.mjGEOM_BOX: elif geom.type == mujoco.mjtGeom.mjGEOM_BOX:
usd_geom = mujoco.usd.component.USDCubeMesh( usd_geom = component_module.USDCubeMesh(
stage=self.stage, stage=self.stage,
geom=geom, geom=geom,
obj_name=geom_name, obj_name=geom_name,
@@ -331,7 +332,8 @@ class USDExporter:
for i in range(self.scene.nlight): for i in range(self.scene.nlight):
light = self.scene.lights[i] light = self.scene.lights[i]
if not np.allclose(light.pos, [0, 0, 0]): if not np.allclose(light.pos, [0, 0, 0]):
self.usd_lights.append(mujoco.usd.component.USDSphereLight(stage=self.stage, obj_name=i)) self.usd_lights.append
(component_module.USDSphereLight(stage=self.stage, obj_name=str(i)))
else: else:
self.usd_lights.append(None) self.usd_lights.append(None)
@@ -342,7 +344,7 @@ class USDExporter:
if np.allclose(light.pos, [0, 0, 0]): if np.allclose(light.pos, [0, 0, 0]):
continue continue
if self.usd_lights[i] is None: if i >= len(self.usd_lights) or self.usd_lights[i] is None:
continue continue
self.usd_lights[i].update( self.usd_lights[i].update(
@@ -356,7 +358,8 @@ class USDExporter:
self.usd_cameras = [] self.usd_cameras = []
if self.camera_names is not None: if self.camera_names is not None:
for name in self.camera_names: for name in self.camera_names:
self.usd_cameras.append(mujoco.usd.USDCamera(stage=self.stage, obj_name=name)) self.usd_cameras.append(
component_module.USDCamera(stage=self.stage, obj_name=name))
def _update_cameras( def _update_cameras(
self, self,
@@ -372,7 +375,8 @@ class USDExporter:
data, scene_option=scene_option, camera=camera_name data, scene_option=scene_option, camera=camera_name
) )
avg_camera = mujoco.mjv_averageCamera(self.scene.camera[0], self.scene.camera[1]) avg_camera = mujoco.mjv_averageCamera(
self.scene.camera[0], self.scene.camera[1])
forward = avg_camera.forward forward = avg_camera.forward
up = avg_camera.up up = avg_camera.up
@@ -396,11 +400,12 @@ class USDExporter:
): ):
if light_type == "sphere": if light_type == "sphere":
new_light = mujoco.usd.component.USDSphereLight(stage=self.stage, obj_name=obj_name, radius=radius) new_light = component_module.USDSphereLight(stage=self.stage, obj_name=str(objid), radius=radius)
new_light.update(pos=pos, intensity=intensity, color=color, frame=0) new_light.update(pos=np.array(pos), intensity=intensity, color=color, frame=0)
elif light_type == "dome": elif light_type == "dome":
new_light = mujoco.usd.component.USDDomeLight(stage=self.stage, obj_name=obj_name) new_light = component_module.USDDomeLight(
stage=self.stage, obj_name=str(objid))
new_light.update(intensity=intensity, color=color, frame=0) new_light.update(intensity=intensity, color=color, frame=0)
@@ -410,11 +415,12 @@ class USDExporter:
rotation_xyz: List[float], rotation_xyz: List[float],
obj_name: Optional[str] = "camera_1", obj_name: Optional[str] = "camera_1",
): ):
new_camera = mujoco.usd.component.USDCamera(stage=self.stage, obj_name=obj_name) new_camera = component_module.USDCamera(
stage=self.stage, obj_name=str(objid))
r = scipy.spatial.transform.Rotation.from_euler( r = scipy.spatial.transform.Rotation.from_euler(
"xyz", rotation_xyz, degrees=True) "xyz", rotation_xyz, degrees=True)
new_camera.update(cam_pos=pos, cam_mat=r.as_matrix(), frame=0) new_camera.update(cam_pos=np.array(pos), cam_mat=r.as_matrix(), frame=0)
def save_scene(self, filetype: str = "usd"): def save_scene(self, filetype: str = "usd"):
self.stage.SetEndTimeCode(self.frame_count) self.stage.SetEndTimeCode(self.frame_count)
+70
View File
@@ -0,0 +1,70 @@
# Copyright 2024 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for the MuJoCo USD Exporter."""
import logging
import os
import mujoco
from absl.testing import absltest
from etils import epath
# Open3D and USD are not fully supported on all MuJoCo architectures.
# pylint: disable=python.style(g-import-not-at-top)
execute_test = True
try:
from mujoco.usd import exporter as exporter_module
from pxr import Usd
except ImportError:
logging.warning('Skipping test due to missing import')
execute_test = False
# pylint: enable=python.style(g-import-not-at-top)
class ExporterTest(absltest.TestCase):
def test_usd_export(self):
if not execute_test:
return
output_dir = os.getenv('TEST_UNDECLARED_OUTPUTS_DIR')
xml = """
<mujoco>
<worldbody>
<camera name="closeup" pos="0 -6 0" xyaxes="1 0 0 0 1 100"/>
<geom name="white_box" type="box" size="1 1 1" rgba="1 1 1 1"/>
</worldbody>
</mujoco>
"""
model = mujoco.MjModel.from_xml_string(xml)
data = mujoco.MjData(model)
exporter = exporter_module.USDExporter(
model,
output_directory_name="mujoco_usdpkg",
output_directory_root=output_dir,
)
exporter.update_scene(data)
exporter.save_scene("export.usda")
with open(os.path.join(
output_dir, "mujoco_usdpkg/frames", "frame_1_.export.usda"), "r") as f:
golden_path = os.path.join(
epath.resource_path("mujoco"), "testdata", "usd_golden.usda")
with open(golden_path, "r") as golden_file:
self.assertEqual(f.read(), golden_file.read())
if __name__ == "__main__":
absltest.main()
View File
+6
View File
@@ -169,6 +169,9 @@ def _file_loader(path: str) -> _LoaderWithPathType:
"""Loads an MJCF model from file path.""" """Loads an MJCF model from file path."""
def load(path=path) -> Tuple[mujoco.MjModel, mujoco.MjData, str]: def load(path=path) -> Tuple[mujoco.MjModel, mujoco.MjData, str]:
if len(path) >= 4 and path[-4:] == '.mjb':
m = mujoco.MjModel.from_binary_path(path)
else:
m = mujoco.MjModel.from_xml_path(path) m = mujoco.MjModel.from_xml_path(path)
d = mujoco.MjData(m) d = mujoco.MjData(m)
return m, d, path return m, d, path
@@ -199,6 +202,9 @@ def _reload(
path = load_tuple[2] if len(load_tuple) == 3 else '' path = load_tuple[2] if len(load_tuple) == 3 else ''
simulate.load(m, d, path) simulate.load(m, d, path)
# Make sure any load_error message is cleared
simulate.load_error = ''
if notify_loaded: if notify_loaded:
notify_loaded() notify_loaded()
+4 -4
View File
@@ -638,7 +638,7 @@ int mjc_BoxBox(const mjModel* M, const mjData* D, mjContact* con, int g1, int g2
mju_sub3(tmp1, pos1, pos2); mju_sub3(tmp1, pos1, pos2);
mju_rotVecMatT(pos12, tmp1, mat2); mju_rotVecMatT(pos12, tmp1, mat2);
mju_mulMatTMat(rot, mat1, mat2, 3, 3, 3); mju_mulMatTMat3(rot, mat1, mat2);
mju_transpose(rott, rot, 3, 3); mju_transpose(rott, rot, 3, 3);
for (i = 0; i < 9; i++) for (i = 0; i < 9; i++)
@@ -804,7 +804,7 @@ int mjc_BoxBox(const mjModel* M, const mjData* D, mjContact* con, int g1, int g2
} }
if (q2) { if (q2) {
mju_mulMatMatT(r, rotmore, rot, 3, 3, 3); mju_mulMatMatT3(r, rotmore, rot);
// mju_rotVecMat(p,pos12,rotmore); // mju_rotVecMat(p,pos12,rotmore);
// mju_rotVecMat(tmp1,size2,rotmore); // mju_rotVecMat(tmp1,size2,rotmore);
@@ -956,7 +956,7 @@ int mjc_BoxBox(const mjModel* M, const mjData* D, mjContact* con, int g1, int g2
} }
mju_mulMatMatT(r, q2 ? mat2 : mat1, rotmore, 3, 3, 3); mju_mulMatMatT3(r, q2 ? mat2 : mat1, rotmore);
mju_copy3(p, q2 ? pos2 : pos1); mju_copy3(p, q2 ? pos2 : pos1);
tmp2[0] = (q2 ? -1 : 1) * r[2]; tmp2[0] = (q2 ? -1 : 1) * r[2];
@@ -1319,7 +1319,7 @@ edgeedge:
} }
} }
mju_mulMatMatT(r, mat1, rotmore, 3, 3, 3); mju_mulMatMatT3(r, mat1, rotmore);
mju_rotVecMat(tmp1, rnorm, r); mju_rotVecMat(tmp1, rnorm, r);
+2 -2
View File
@@ -318,7 +318,7 @@ static void mju_rotateFrame(const mjtNum origin[3], const mjtNum rot[9],
mjtNum mat[9], vec[3], rel[3]; mjtNum mat[9], vec[3], rel[3];
// rotate frame: xmat = rot*xmat // rotate frame: xmat = rot*xmat
mju_mulMatMat(mat, rot, xmat, 3, 3, 3); mju_mulMatMat3(mat, rot, xmat);
mju_copy(xmat, mat, 9); mju_copy(xmat, mat, 9);
// vector to rotation origin: rel = origin - xpos // vector to rotation origin: rel = origin - xpos
@@ -682,7 +682,7 @@ int mjc_ConvexHField(const mjModel* m, const mjData* d,
} }
// express geom2 mat in heightfield frame // express geom2 mat in heightfield frame
mju_mulMatTMat(mat, mat1, mat2, 3, 3, 3); mju_mulMatTMat3(mat, mat1, mat2);
//------------------------------------- AABB computation, box-box test //------------------------------------- AABB computation, box-box test
+12 -3
View File
@@ -140,9 +140,18 @@ static void geomGradient(mjtNum gradient[3], const mjModel* m, const mjData* d,
b[2] = a[2] / size[2]; b[2] = a[2] / size[2];
mjtNum k0 = mju_norm3(a); mjtNum k0 = mju_norm3(a);
mjtNum k1 = mju_norm3(b); mjtNum k1 = mju_norm3(b);
gradient[0] = a[0]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[0]/(k1*k1); mjtNum invK0 = 1. / k0;
gradient[1] = a[1]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[1]/(k1*k1); mjtNum invK1 = 1. / k1;
gradient[2] = a[2]*(2.*k0 - 1.) / k1 + k0*(k0 - 1.) * b[2]/(k1*k1); mjtNum gk0[3] = {b[0]*invK0, b[1]*invK0, b[2]*invK0};
mjtNum gk1[3] = {b[0]*invK1/(size[0]*size[0]),
b[1]*invK1/(size[1]*size[1]),
b[2]*invK1/(size[2]*size[2])};
mjtNum df_dk0 = (2.*k0 - 1.) * invK1;
mjtNum df_dk1 = k0*(k0 - 1.) * invK1 * invK1;
gradient[0] = gk0[0]*df_dk0 - gk1[0]*df_dk1;
gradient[1] = gk0[1]*df_dk0 - gk1[1]*df_dk1;
gradient[2] = gk0[2]*df_dk0 - gk1[2]*df_dk1;
mju_normalize3(gradient);
break; break;
case mjGEOM_CYLINDER: case mjGEOM_CYLINDER:
c = mju_sqrt(x[0]*x[0]+x[1]*x[1]); c = mju_sqrt(x[0]*x[0]+x[1]*x[1]);
+1 -1
View File
@@ -251,7 +251,7 @@ void mjd_subQuat(const mjtNum qa[4], const mjtNum qb[4], mjtNum Da[9], mjtNum Db
// add term linear in K * K // add term linear in K * K
mjtNum KK[9]; mjtNum KK[9];
mju_mulMatMat(KK, K, K, 3, 3, 3); mju_mulMatMat3(KK, K, K);
mjtNum coef = 1.0 - (half_angle < 6e-8 ? 1.0 : half_angle / mju_tan(half_angle)); mjtNum coef = 1.0 - (half_angle < 6e-8 ? 1.0 : half_angle / mju_tan(half_angle));
mju_addToScl(Da_tmp, KK, coef, 9); mju_addToScl(Da_tmp, KK, coef, 9);
+53 -26
View File
@@ -243,6 +243,19 @@ static mjtNum nextActivation(const mjModel* m, const mjData* d,
// clamp vector to range
static void clampVec(mjtNum* vec, const mjtNum* range, const mjtByte* limited, int n,
const int* index) {
for (int i=0; i < n; i++) {
int j = index ? index[i] : i;
if (limited[i]) {
vec[j] = mju_clip(vec[j], range[2*i], range[2*i + 1]);
}
}
}
// (qpos, qvel, ctrl, act) => (qfrc_actuator, actuator_force, act_dot) // (qpos, qvel, ctrl, act) => (qfrc_actuator, actuator_force, act_dot)
void mj_fwdActuation(const mjModel* m, mjData* d) { void mj_fwdActuation(const mjModel* m, mjData* d) {
TM_START; TM_START;
@@ -262,18 +275,9 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
// local, clamped copy of ctrl // local, clamped copy of ctrl
mj_markStack(d); mj_markStack(d);
mjtNum *ctrl = mj_stackAllocNum(d, nu); mjtNum *ctrl = mj_stackAllocNum(d, nu);
if (mjDISABLED(mjDSBL_CLAMPCTRL)) {
mju_copy(ctrl, d->ctrl, nu); mju_copy(ctrl, d->ctrl, nu);
} else { if (!mjDISABLED(mjDSBL_CLAMPCTRL)) {
for (int i=0; i < nu; i++) { clampVec(ctrl, m->actuator_ctrlrange, m->actuator_ctrllimited, nu, NULL);
// clamp ctrl
if (m->actuator_ctrllimited[i]) {
mjtNum *ctrlrange = m->actuator_ctrlrange + 2*i;
ctrl[i] = mju_clip(d->ctrl[i], ctrlrange[0], ctrlrange[1]);
} else {
ctrl[i] = d->ctrl[i];
}
}
} }
// check controls, set all to 0 if any are bad // check controls, set all to 0 if any are bad
@@ -459,25 +463,47 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
} }
// clamp actuator_force // clamp actuator_force
for (int i=0; i < nu; i++) { clampVec(force, m->actuator_forcerange, m->actuator_forcelimited, nu, NULL);
if (m->actuator_forcelimited[i]) {
mjtNum *forcerange = m->actuator_forcerange + 2*i;
force[i] = mju_clip(force[i], forcerange[0], forcerange[1]);
}
}
// qfrc_actuator = moment' * force // qfrc_actuator = moment' * force
mju_mulMatTVec(d->qfrc_actuator, moment, force, nu, nv); mju_mulMatTVec(d->qfrc_actuator, moment, force, nu, nv);
// clamp qfrc_actuator // actuator-level gravity compensation
if (!mjDISABLED(mjDSBL_GRAVITY) && mju_norm3(m->opt.gravity)) {
int njnt = m->njnt; int njnt = m->njnt;
for (int i=0; i < njnt; i++) { for (int i=0; i < njnt; i++) {
if (m->jnt_actfrclimited[i]) { // skip if gravcomp added as passive force
mjtNum *forcerange = m->jnt_actfrcrange + 2*i; if (!m->jnt_actgravcomp[i]) {
mjtNum *qfrc = d->qfrc_actuator + m->jnt_dofadr[i]; continue;
qfrc[0] = mju_clip(qfrc[0], forcerange[0], forcerange[1]); }
// get number of dofs for this joint
int dofnum;
switch (m->jnt_type[i]) {
case mjJNT_HINGE:
case mjJNT_SLIDE:
dofnum = 1;
break;
case mjJNT_BALL:
dofnum = 3;
break;
case mjJNT_FREE:
dofnum = 6;
break;
}
// add gravcomp force
int dofadr = m->jnt_dofadr[i];
for (int j=0; j < dofnum; j++) {
d->qfrc_actuator[dofadr+j] += d->qfrc_gravcomp[dofadr+j];
} }
} }
}
// clamp qfrc_actuator to joint-level actuator force limits
clampVec(d->qfrc_actuator, m->jnt_actfrcrange, m->jnt_actfrclimited, m->njnt, m->jnt_dofadr);
mj_freeStack(d); mj_freeStack(d);
TM_END(mjTIMER_ACTUATION); TM_END(mjTIMER_ACTUATION);
@@ -489,13 +515,13 @@ void mj_fwdActuation(const mjModel* m, mjData* d) {
void mj_fwdAcceleration(const mjModel* m, mjData* d) { void mj_fwdAcceleration(const mjModel* m, mjData* d) {
int nv = m->nv; int nv = m->nv;
// qforce = sum of all non-constraint forces // qfrc_smooth = sum of all non-constraint forces
mju_sub(d->qfrc_smooth, d->qfrc_passive, d->qfrc_bias, nv); // qfrc_bias is negative mju_sub(d->qfrc_smooth, d->qfrc_passive, d->qfrc_bias, nv); // qfrc_bias is negative
mju_addTo(d->qfrc_smooth, d->qfrc_applied, nv); mju_addTo(d->qfrc_smooth, d->qfrc_applied, nv);
mju_addTo(d->qfrc_smooth, d->qfrc_actuator, nv); mju_addTo(d->qfrc_smooth, d->qfrc_actuator, nv);
mj_xfrcAccumulate(m, d, d->qfrc_smooth); mj_xfrcAccumulate(m, d, d->qfrc_smooth);
// qacc_smooth = M \ qfr_smooth // qacc_smooth = M \ qfrc_smooth
mj_solveM(m, d, d->qacc_smooth, d->qfrc_smooth, 1); mj_solveM(m, d, d->qacc_smooth, d->qfrc_smooth, 1);
} }
@@ -706,9 +732,10 @@ void mj_fwdConstraint(const mjModel* m, mjData* d) {
// advance state and time given activation derivatives, acceleration, and optional velocity // advance state and time given activation derivatives, acceleration, and optional velocity
static void mj_advance(const mjModel* m, mjData* d, static void mj_advance(const mjModel* m, mjData* d,
const mjtNum* act_dot, const mjtNum* qacc, const mjtNum* qvel) { const mjtNum* act_dot, const mjtNum* qacc, const mjtNum* qvel) {
// advance activations and clamp // advance activations
if (m->na && !mjDISABLED(mjDSBL_ACTUATION)) { if (m->na && !mjDISABLED(mjDSBL_ACTUATION)) {
for (int i=0; i < m->nu; i++) { int nu = m->nu;
for (int i=0; i < nu; i++) {
int actadr = m->actuator_actadr[i]; int actadr = m->actuator_actadr[i];
int actadr_end = actadr + m->actuator_actnum[i]; int actadr_end = actadr + m->actuator_actnum[i];
for (int j=actadr; j < actadr_end; j++) { for (int j=actadr; j < actadr_end; j++) {
+32 -1
View File
@@ -255,8 +255,39 @@ void mj_passive(const mjModel* m, mjData* d) {
// add passive forces into qfrc_passive // add passive forces into qfrc_passive
mju_add(d->qfrc_passive, d->qfrc_spring, d->qfrc_damper, nv); mju_add(d->qfrc_passive, d->qfrc_spring, d->qfrc_damper, nv);
if (has_gravcomp) mju_addTo(d->qfrc_passive, d->qfrc_gravcomp, nv);
if (has_fluid) mju_addTo(d->qfrc_passive, d->qfrc_fluid, nv); if (has_fluid) mju_addTo(d->qfrc_passive, d->qfrc_fluid, nv);
if (has_gravcomp) {
int njnt = m->njnt;
for (int i=0; i < njnt; i++) {
// skip if gravcomp added via actuators
if (m->jnt_actgravcomp[i]) {
continue;
}
// get number of dofs for this joint
int dofnum;
switch (m->jnt_type[i]) {
case mjJNT_HINGE:
case mjJNT_SLIDE:
dofnum = 1;
break;
case mjJNT_BALL:
dofnum = 3;
break;
case mjJNT_FREE:
dofnum = 6;
break;
}
// add gravcomp force
int dofadr = m->jnt_dofadr[i];
for (int j=0; j < dofnum; j++) {
d->qfrc_passive[dofadr+j] += d->qfrc_gravcomp[dofadr+j];
}
}
}
// user callback: add custom passive forces // user callback: add custom passive forces
if (mjcb_passive) { if (mjcb_passive) {
+9 -8
View File
@@ -361,14 +361,6 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
} }
if (m->nbody) fprintf(fp, "\n"); if (m->nbody) fprintf(fp, "\n");
// BVHs
for (int i=0; i < m->nbvh; i++) {
fprintf(fp, "\nBVH %d:\n", i);
object_class = &m->nbvh;
MJMODEL_POINTERS
}
if (m->nbvh) fprintf(fp, "\n");
// joints // joints
for (int i=0; i < m->njnt; i++) { for (int i=0; i < m->njnt; i++) {
fprintf(fp, "\nJOINT %d:\n", i); fprintf(fp, "\nJOINT %d:\n", i);
@@ -732,6 +724,15 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
#undef X #undef X
// BVHs
fprintf(fp, "BVH:\n");
fprintf(fp, " %-8s%-8s%-8s%-10s%-s\n","id", "depth", "nodeid", "child[0]" ,"child[1]");
for (int i=0; i < m->nbvh; i++) {
fprintf(fp, " %-8d%-8d% -8d% -10d% -d\n",
i, m->bvh_depth[i], m->bvh_nodeid[i], m->bvh_child[2*i], m->bvh_child[2*i+1]);
}
fprintf(fp, "\n");
if (filename) { if (filename) {
fclose(fp); fclose(fp);
} }
+14 -17
View File
@@ -34,6 +34,7 @@
#include <mujoco/mjplugin.h> #include <mujoco/mjplugin.h>
#include "engine/engine_plugin.h" #include "engine/engine_plugin.h"
#include "engine/engine_util_errmem.h" #include "engine/engine_util_errmem.h"
#include "engine/engine_util_misc.h"
// internal helper for mju_fileToMemory (closes fp automatically) // internal helper for mju_fileToMemory (closes fp automatically)
static void* _fileToMemory(FILE* fp, const char* filename, size_t* filesize); static void* _fileToMemory(FILE* fp, const char* filename, size_t* filesize);
@@ -113,10 +114,8 @@ mjResource* mju_openResource(const char* name, char* error, size_t error_sz) {
memcpy(&spec->mtime, &file_stat.st_mtime, sizeof(time_t)); memcpy(&spec->mtime, &file_stat.st_mtime, sizeof(time_t));
} else { } else {
memset(&spec->mtime, 0, sizeof(time_t)); memset(&spec->mtime, 0, sizeof(time_t));
resource->timestamp[0] = '\0';
} }
strftime(resource->timestamp, 512, "%Y-%m-%d-%H:%M:%S", mju_encodeBase64(resource->timestamp, (uint8_t*) &spec->mtime, sizeof(time_t));
localtime(&(spec->mtime)));
return resource; return resource;
} }
@@ -199,19 +198,6 @@ void mju_getResourceDir(mjResource* resource, const char** dir, int* ndir) {
// modified callback for OS filesystem
static int mju_isModifiedFile(const char* name, const file_spec* spec) {
if (spec != NULL) {
struct stat file_stat;
if (stat(name, &file_stat) == 0) {
return difftime(spec->mtime, file_stat.st_mtime) < 0;
}
}
return 1; // modified (default)
}
// return 0 if the resource's timestamp matches the provided timestamp // return 0 if the resource's timestamp matches the provided timestamp
// return > 0 if the the resource is younger than the given timestamp // return > 0 if the the resource is younger than the given timestamp
// return < 0 if the resource is older than the given timestamp // return < 0 if the resource is older than the given timestamp
@@ -224,7 +210,18 @@ int mju_isModifiedResource(const mjResource* resource, const char* timestamp) {
return 1; // default (modified) return 1; // default (modified)
} }
return mju_isModifiedFile(resource->name, (file_spec*) resource->data); // fallback to OS filesystem
if (mju_isValidBase64(timestamp) != sizeof(time_t)) {
return 1; // error (assume modified)
}
time_t time1, time2;
mju_decodeBase64((uint8_t*) &time1, timestamp);
time2 = ((file_spec*) resource->data)->mtime;
double diff = difftime(time2, time1);
if (diff < 0) return -1;
if (diff > 0) return 1;
return 0;
} }
+1 -85
View File
@@ -32,78 +32,9 @@
#include "engine/engine_util_spatial.h" #include "engine/engine_util_spatial.h"
//-------------------------------- utility --------------------------------------------------------- //-------------------------------- utility ---------------------------------------------------------
// add sensor noise after each stage
static void add_noise(const mjModel* m, mjData* d, mjtStage stage) {
int adr, dim;
mjtNum rnd[4], noise, quat[4], res[4];
// process sensors matching stage and having positive noise
for (int i=0; i < m->nsensor; i++) {
if (m->sensor_needstage[i] == stage && m->sensor_noise[i] > 0) {
// get sensor info
adr = m->sensor_adr[i];
dim = m->sensor_dim[i];
noise = m->sensor_noise[i];
// real or positive: add noise directly, with clamp for positive
if (m->sensor_datatype[i] == mjDATATYPE_REAL ||
m->sensor_datatype[i] == mjDATATYPE_POSITIVE) {
for (int j=0; j < dim; j++) {
// get random numbers; use only the first one
rnd[0] = mju_standardNormal(rnd+1);
// positive
if (m->sensor_datatype[i] == mjDATATYPE_POSITIVE) {
// add noise only if positive, keep it positive
if (d->sensordata[adr+j] > 0) {
d->sensordata[adr+j] = mju_max(0, d->sensordata[adr+j]+rnd[0]*noise);
}
}
// real
else {
d->sensordata[adr+j] += rnd[0]*noise;
}
}
}
// axis or quat: rotate around random axis by random angle
else {
// get four random numbers
rnd[0] = mju_standardNormal(rnd+1);
rnd[2] = mju_standardNormal(rnd+3);
// scale angle, normalize axis, make quaternion
rnd[0] *= noise;
mju_normalize3(rnd+1);
mju_axisAngle2Quat(quat, rnd+1, rnd[0]);
// axis
if (m->sensor_datatype[i] == mjDATATYPE_AXIS) {
// apply quaternion rotation to axis, assign
mju_rotVecQuat(res, d->sensordata+adr, quat);
mju_copy3(d->sensordata+adr, res);
}
// quaternion
else if (m->sensor_datatype[i] == mjDATATYPE_QUATERNION) {
// apply quaternion rotation to quaternion, assign
mju_mulQuat(d->sensordata+adr, d->sensordata+adr, quat);
}
// unknown datatype
else {
mjERROR("unknown datatype in sensor %d", i);
}
}
}
}
}
// apply cutoff after each stage // apply cutoff after each stage
static void apply_cutoff(const mjModel* m, mjData* d, mjtStage stage) { static void apply_cutoff(const mjModel* m, mjData* d, mjtStage stage) {
// process sensors matching stage and having positive cutoff // process sensors matching stage and having positive cutoff
@@ -442,11 +373,6 @@ void mj_sensorPos(const mjModel* m, mjData* d) {
mjcb_sensor(m, d, mjSTAGE_POS); mjcb_sensor(m, d, mjSTAGE_POS);
} }
// add noise if enabled
if (mjENABLED(mjENBL_SENSORNOISE)) {
add_noise(m, d, mjSTAGE_POS);
}
// compute plugin sensor values // compute plugin sensor values
if (m->nplugin) { if (m->nplugin) {
const int nslot = mjp_pluginCount(); const int nslot = mjp_pluginCount();
@@ -623,11 +549,6 @@ void mj_sensorVel(const mjModel* m, mjData* d) {
mjcb_sensor(m, d, mjSTAGE_VEL); mjcb_sensor(m, d, mjSTAGE_VEL);
} }
// add noise if enabled
if (mjENABLED(mjENBL_SENSORNOISE)) {
add_noise(m, d, mjSTAGE_VEL);
}
// trigger computation of plugins // trigger computation of plugins
if (m->nplugin) { if (m->nplugin) {
const int nslot = mjp_pluginCount(); const int nslot = mjp_pluginCount();
@@ -839,11 +760,6 @@ void mj_sensorAcc(const mjModel* m, mjData* d) {
mjcb_sensor(m, d, mjSTAGE_ACC); mjcb_sensor(m, d, mjSTAGE_ACC);
} }
// add noise if enabled
if (mjENABLED(mjENBL_SENSORNOISE)) {
add_noise(m, d, mjSTAGE_ACC);
}
// trigger computation of plugins // trigger computation of plugins
if (m->nplugin) { if (m->nplugin) {
const int nslot = mjp_pluginCount(); const int nslot = mjp_pluginCount();
+5 -6
View File
@@ -66,7 +66,6 @@ const char* mjENABLESTRING[mjNENABLE] = {
"Override", "Override",
"Energy", "Energy",
"Fwdinv", "Fwdinv",
"Sensornoise",
"InvDiscrete", "InvDiscrete",
"MultiCCD", "MultiCCD",
"Island" "Island"
@@ -815,8 +814,8 @@ void mj_angmomMat(const mjModel* m, mjData* d, mjtNum* mat, int body) {
// term1 = body angular momentum about self COM in world frame // term1 = body angular momentum about self COM in world frame
mjtNum tmp1[9], tmp2[9]; mjtNum tmp1[9], tmp2[9];
mju_mulMatMat(tmp1, ximat, inertia, 3, 3, 3); // tmp1 = ximat * inertia mju_mulMatMat3(tmp1, ximat, inertia); // tmp1 = ximat * inertia
mju_mulMatMatT(tmp2, tmp1, ximat, 3, 3, 3); // tmp2 = ximat * inertia * ximat^T mju_mulMatMatT3(tmp2, tmp1, ximat); // tmp2 = ximat * inertia * ximat^T
mju_mulMatMat(term1, tmp2, jacr, 3, 3, nv); // term1 = ximat * inertia * ximat^T * jacr mju_mulMatMat(term1, tmp2, jacr, 3, 3, nv); // term1 = ximat * inertia * ximat^T * jacr
// location of body COM w.r.t subtree COM // location of body COM w.r.t subtree COM
@@ -1050,11 +1049,11 @@ static int _getnumadr(const mjModel* m, mjtObj type, int** padr, int* mapadr) {
} }
// get string hash, see http://www.cse.yorku.ca/~oz/hash.html // get string hash, see http://www.cse.yorku.ca/~oz/hash.html
uint64_t mj_hashdjb2(const char* s, uint64_t n) { uint64_t mj_hashString(const char* s, uint64_t n) {
uint64_t h = 5381; uint64_t h = 5381;
int c; int c;
while ((c = *s++)) { while ((c = *s++)) {
h = ((h << 5) + h) + c; h = ((h << 5) + h) ^ c;
} }
return h % n; return h % n;
} }
@@ -1070,7 +1069,7 @@ int mj_name2id(const mjModel* m, int type, const char* name) {
// search // search
if (num) { // look up at hash address if (num) { // look up at hash address
uint64_t hash = mj_hashdjb2(name, num); uint64_t hash = mj_hashString(name, num);
uint64_t i = hash; uint64_t i = hash;
do { do {
+1 -1
View File
@@ -114,7 +114,7 @@ MJAPI void mj_angmomMat(const mjModel* m, mjData* d, mjtNum* mat, int body);
//-------------------------- name functions -------------------------------------------------------- //-------------------------- name functions --------------------------------------------------------
// get string hash, see http://www.cse.yorku.ca/~oz/hash.html // get string hash, see http://www.cse.yorku.ca/~oz/hash.html
uint64_t mj_hashdjb2(const char* s, uint64_t n); uint64_t mj_hashString(const char* s, uint64_t n);
// get id of object with the specified mjtObj type and name, returns -1 if id not found // get id of object with the specified mjtObj type and name, returns -1 if id not found
MJAPI int mj_name2id(const mjModel* m, int type, const char* name); MJAPI int mj_name2id(const mjModel* m, int type, const char* name);
+45
View File
@@ -180,6 +180,51 @@ void mju_rotVecMatT(mjtNum res[3], const mjtNum vec[3], const mjtNum mat[9]) {
// multiply 3x3 matrices,
void mju_mulMatMat3(mjtNum res[9], const mjtNum a[9], const mjtNum b[9]) {
res[0] = a[0]*b[0] + a[1]*b[3] + a[2]*b[6];
res[1] = a[0]*b[1] + a[1]*b[4] + a[2]*b[7];
res[2] = a[0]*b[2] + a[1]*b[5] + a[2]*b[8];
res[3] = a[3]*b[0] + a[4]*b[3] + a[5]*b[6];
res[4] = a[3]*b[1] + a[4]*b[4] + a[5]*b[7];
res[5] = a[3]*b[2] + a[4]*b[5] + a[5]*b[8];
res[6] = a[6]*b[0] + a[7]*b[3] + a[8]*b[6];
res[7] = a[6]*b[1] + a[7]*b[4] + a[8]*b[7];
res[8] = a[6]*b[2] + a[7]*b[5] + a[8]*b[8];
}
// multiply 3x3 matrices, first argument transposed
void mju_mulMatTMat3(mjtNum res[9], const mjtNum a[9], const mjtNum b[9]) {
res[0] = a[0]*b[0] + a[3]*b[3] + a[6]*b[6];
res[1] = a[0]*b[1] + a[3]*b[4] + a[6]*b[7];
res[2] = a[0]*b[2] + a[3]*b[5] + a[6]*b[8];
res[3] = a[1]*b[0] + a[4]*b[3] + a[7]*b[6];
res[4] = a[1]*b[1] + a[4]*b[4] + a[7]*b[7];
res[5] = a[1]*b[2] + a[4]*b[5] + a[7]*b[8];
res[6] = a[2]*b[0] + a[5]*b[3] + a[8]*b[6];
res[7] = a[2]*b[1] + a[5]*b[4] + a[8]*b[7];
res[8] = a[2]*b[2] + a[5]*b[5] + a[8]*b[8];
}
// multiply 3x3 matrices, second argument transposed
void mju_mulMatMatT3(mjtNum res[9], const mjtNum a[9], const mjtNum b[9]) {
res[0] = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
res[1] = a[0]*b[3] + a[1]*b[4] + a[2]*b[5];
res[2] = a[0]*b[6] + a[1]*b[7] + a[2]*b[8];
res[3] = a[3]*b[0] + a[4]*b[1] + a[5]*b[2];
res[4] = a[3]*b[3] + a[4]*b[4] + a[5]*b[5];
res[5] = a[3]*b[6] + a[4]*b[7] + a[5]*b[8];
res[6] = a[6]*b[0] + a[7]*b[1] + a[8]*b[2];
res[7] = a[6]*b[3] + a[7]*b[4] + a[8]*b[5];
res[8] = a[6]*b[6] + a[7]*b[7] + a[8]*b[8];
}
//------------------------------ 4D vector and matrix-vector operations ---------------------------- //------------------------------ 4D vector and matrix-vector operations ----------------------------
// res = 0 // res = 0
+8
View File
@@ -109,6 +109,14 @@ MJAPI void mju_rotVecMat(mjtNum res[3], const mjtNum vec[3], const mjtNum mat[9]
// multiply vector by transposed 3D rotation matrix // multiply vector by transposed 3D rotation matrix
MJAPI void mju_rotVecMatT(mjtNum res[3], const mjtNum vec[3], const mjtNum mat[9]); MJAPI void mju_rotVecMatT(mjtNum res[3], const mjtNum vec[3], const mjtNum mat[9]);
// multiply 3x3 matrices
MJAPI void mju_mulMatMat3(mjtNum res[9], const mjtNum mat1[9], const mjtNum mat2[9]);
// multiply 3x3 matrices, first argument transposed
MJAPI void mju_mulMatTMat3(mjtNum res[9], const mjtNum a[9], const mjtNum b[9]);
// multiply 3x3 matrices, second argument transposed
MJAPI void mju_mulMatMatT3(mjtNum res[9], const mjtNum mat1[9], const mjtNum mat2[9]);
//------------------------------ 4D/quaternion operations ------------------------------------------ //------------------------------ 4D/quaternion operations ------------------------------------------
+1 -1
View File
@@ -639,7 +639,7 @@ static uint32_t _decode(char ch) {
// returns number of chars written in buf: 4 * [(ndata + 2) / 3] + 1 // returns number of chars written in buf: 4 * [(ndata + 2) / 3] + 1
size_t mju_encodeBase64(char* buf, const uint8_t* data, size_t ndata) { size_t mju_encodeBase64(char* buf, const uint8_t* data, size_t ndata) {
static const char *table = static const char *table =
"ABCDEFGHIJKLMNOPQRSTUBWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int i = 0, j = 0; int i = 0, j = 0;
+2 -2
View File
@@ -721,8 +721,8 @@ int mju_eig3(mjtNum eigval[3], mjtNum eigvec[9], mjtNum quat[4], const mjtNum ma
for (iter=0; iter < 500; iter++) { for (iter=0; iter < 500; iter++) {
// make quaternion matrix eigvec, compute D = eigvec'*mat*eigvec // make quaternion matrix eigvec, compute D = eigvec'*mat*eigvec
mju_quat2Mat(eigvec, quat); mju_quat2Mat(eigvec, quat);
mju_mulMatTMat(tmp, eigvec, mat, 3, 3, 3); mju_mulMatTMat3(tmp, eigvec, mat);
mju_mulMatMat(D, tmp, eigvec, 3, 3, 3); mju_mulMatMat3(D, tmp, eigvec);
// assign eigenvalues // assign eigenvalues
eigval[0] = D[0]; eigval[0] = D[0];
+24 -1
View File
@@ -347,6 +347,29 @@ static void vfs_getdir_callback(mjResource* resource, const char** dir, int* ndi
} }
// modified callback for the VFS resource provider
// return > 0 if modified and 0 if unmodified
static int vfs_modified_callback(const mjResource* resource, const char* timestamp) {
uint64_t filestamp;
if (mju_isValidBase64(timestamp) > sizeof(uint64_t)) {
return 2; // error (assume modified)
}
mju_decodeBase64((uint8_t*) &filestamp, timestamp);
if (!filestamp) return 3; // no hash (assume modified)
if (resource) {
const mjVFS* vfs = (const mjVFS*) resource->data;
int i = mj_findFileVFS(vfs, resource->name);
if (i < 0) return 4; // missing file (assume modified)
if (!vfs->filestamp[i]) return 5; // missing filestamp (assume modified)
if (vfs->filestamp[i] == filestamp) {
return 0; // unmodified
}
}
return 1; // modified
}
// open VFS resource // open VFS resource
mjResource* mju_openVfsResource(const char* name, const mjVFS* vfs) { mjResource* mju_openVfsResource(const char* name, const mjVFS* vfs) {
@@ -362,7 +385,7 @@ mjResource* mju_openVfsResource(const char* name, const mjVFS* vfs) {
.read = &vfs_read_callback, .read = &vfs_read_callback,
.close = &vfs_close_callback, .close = &vfs_close_callback,
.getdir = &vfs_getdir_callback, .getdir = &vfs_getdir_callback,
.modified = NULL .modified = &vfs_modified_callback,
}; };
// create resource // create resource
+2
View File
@@ -15,6 +15,8 @@
set(MUJOCO_USER_SRCS set(MUJOCO_USER_SRCS
user_api.cc user_api.cc
user_api.h user_api.h
user_cache.cc
user_cache.h
user_composite.cc user_composite.cc
user_composite.h user_composite.h
user_flexcomp.cc user_flexcomp.cc
+204 -136
View File
@@ -13,80 +13,121 @@
// limitations under the License. // limitations under the License.
#include "user/user_api.h" #include "user/user_api.h"
#include <cstddef>
#include <functional> #include <functional>
#include <map> #include <map>
#include <new>
#include <string> #include <string>
#include <string_view>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "user/user_model.h" #include "user/user_model.h"
#include "user/user_objects.h" #include "user/user_objects.h"
#include "user/user_cache.h"
#include "xml/xml_util.h" #include "xml/xml_util.h"
// prepend prefix
template <typename T>
static T& operator+(std::string_view prefix, T& base) {
base.prefix = std::string(prefix);
return base;
}
// append suffix
template <typename T>
static T& operator+(T& base, std::string_view suffix) {
base.suffix = std::string(suffix);
return base;
}
// create model // create model
mjSpec* mjm_createSpec() { mjSpec* mjs_createSpec() {
mjCModel* modelC = new mjCModel; mjCModel* modelC = new mjCModel;
return &modelC->spec; return &modelC->spec;
} }
// copy model
mjSpec* mjs_copySpec(const mjSpec* s) {
mjCModel* modelC = new mjCModel(*static_cast<mjCModel*>(s->element));
return &modelC->spec;
}
// copy back model // copy back model
void mjm_copyBack(mjSpec* s, const mjModel* m) { void mjs_copyBack(mjSpec* s, const mjModel* m) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
modelC->CopyBack(m); modelC->CopyBack(m);
} }
// compile model // compile model
mjModel* mjm_compile(mjSpec* s, const mjVFS* vfs) { mjModel* mjs_compile(mjSpec* s, const mjVFS* vfs) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
return modelC->Compile(vfs); return modelC->Compile(vfs);
} }
// attach body to a frame of the parent
int mjs_attachBody(mjsFrame* parent, const mjsBody* child,
const char* prefix, const char* suffix) {
mjCFrame* frame_parent = static_cast<mjCFrame*>(parent->element);
mjCBody* child_body = static_cast<mjCBody*>(child->element);
*frame_parent += std::string(prefix) + *child_body + std::string(suffix);
return 0;
}
// get error message from model // get error message from model
const char* mjm_getError(mjSpec* s) { const char* mjs_getError(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
return modelC->GetError().message; return modelC->GetError().message;
} }
// check if model has warnings // check if model has warnings
int mjm_isWarning(mjSpec* s) { int mjs_isWarning(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
return modelC->GetError().warning; return modelC->GetError().warning;
} }
// delete model // delete model
void mjm_deleteSpec(mjSpec* s) { void mjs_deleteSpec(mjSpec* s) {
mjCModel* model = reinterpret_cast<mjCModel*>(s->element); mjCModel* model = static_cast<mjCModel*>(s->element);
delete model; delete model;
} }
// add child body to body, return child spec // add child body to body, return child spec
mjmBody* mjm_addBody(mjmBody* bodyspec, mjmDefault* defspec) { mjsBody* mjs_addBody(mjsBody* bodyspec, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element)->AddBody(def); mjCBody* body = static_cast<mjCBody*>(bodyspec->element)->AddBody(def);
return &body->spec; return &body->spec;
} }
// add site to body, return site spec // add site to body, return site spec
mjmSite* mjm_addSite(mjmBody* bodyspec, mjmDefault* defspec) { mjsSite* mjs_addSite(mjsBody* bodyspec, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCSite* site = body->AddSite(def); mjCSite* site = body->AddSite(def);
return &site->spec; return &site->spec;
} }
@@ -94,9 +135,9 @@ mjmSite* mjm_addSite(mjmBody* bodyspec, mjmDefault* defspec) {
// add joint to body // add joint to body
mjmJoint* mjm_addJoint(mjmBody* bodyspec, mjmDefault* defspec) { mjsJoint* mjs_addJoint(mjsBody* bodyspec, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCJoint* joint = body->AddJoint(def); mjCJoint* joint = body->AddJoint(def);
return &joint->spec; return &joint->spec;
} }
@@ -104,8 +145,8 @@ mjmJoint* mjm_addJoint(mjmBody* bodyspec, mjmDefault* defspec) {
// add free joint to body // add free joint to body
mjmJoint* mjm_addFreeJoint(mjmBody* bodyspec) { mjsJoint* mjs_addFreeJoint(mjsBody* bodyspec) {
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCJoint* joint = body->AddFreeJoint(); mjCJoint* joint = body->AddFreeJoint();
return &joint->spec; return &joint->spec;
} }
@@ -113,9 +154,9 @@ mjmJoint* mjm_addFreeJoint(mjmBody* bodyspec) {
// add geom to body // add geom to body
mjmGeom* mjm_addGeom(mjmBody* bodyspec, mjmDefault* defspec) { mjsGeom* mjs_addGeom(mjsBody* bodyspec, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCGeom* geom = body->AddGeom(def); mjCGeom* geom = body->AddGeom(def);
return &geom->spec; return &geom->spec;
} }
@@ -123,9 +164,9 @@ mjmGeom* mjm_addGeom(mjmBody* bodyspec, mjmDefault* defspec) {
// add camera to body // add camera to body
mjmCamera* mjm_addCamera(mjmBody* bodyspec, mjmDefault* defspec) { mjsCamera* mjs_addCamera(mjsBody* bodyspec, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCCamera* camera = body->AddCamera(def); mjCCamera* camera = body->AddCamera(def);
return &camera->spec; return &camera->spec;
} }
@@ -133,9 +174,9 @@ mjmCamera* mjm_addCamera(mjmBody* bodyspec, mjmDefault* defspec) {
// add light to body // add light to body
mjmLight* mjm_addLight(mjmBody* bodyspec, mjmDefault* defspec) { mjsLight* mjs_addLight(mjsBody* bodyspec, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCLight* light = body->AddLight(def); mjCLight* light = body->AddLight(def);
return &light->spec; return &light->spec;
} }
@@ -143,8 +184,8 @@ mjmLight* mjm_addLight(mjmBody* bodyspec, mjmDefault* defspec) {
// add flex to model // add flex to model
mjmFlex* mjm_addFlex(mjSpec* s) { mjsFlex* mjs_addFlex(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCFlex* flex = modelC->AddFlex(); mjCFlex* flex = modelC->AddFlex();
return &flex->spec; return &flex->spec;
} }
@@ -152,22 +193,23 @@ mjmFlex* mjm_addFlex(mjSpec* s) {
// add frame to body // add frame to body
mjmFrame* mjm_addFrame(mjmBody* bodyspec, mjmFrame* parentframe) { mjsFrame* mjs_addFrame(mjsBody* bodyspec, mjsFrame* parentframe) {
mjCFrame* parentframeC = 0; mjCFrame* parentframeC = 0;
if (parentframe) { if (parentframe) {
parentframeC = reinterpret_cast<mjCFrame*>(parentframe->element); parentframeC = static_cast<mjCFrame*>(parentframe->element);
} }
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCFrame* frameC = body->AddFrame(parentframeC); mjCFrame* frameC = body->AddFrame(parentframeC);
frameC->SetParent(body);
return &frameC->spec; return &frameC->spec;
} }
// add mesh to model // add mesh to model
mjmMesh* mjm_addMesh(mjSpec* s, mjmDefault* defspec) { mjsMesh* mjs_addMesh(mjSpec* s, mjsDefault* defspec) {
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCMesh* mesh = modelC->AddMesh(def); mjCMesh* mesh = modelC->AddMesh(def);
return &mesh->spec; return &mesh->spec;
} }
@@ -175,8 +217,8 @@ mjmMesh* mjm_addMesh(mjSpec* s, mjmDefault* defspec) {
// add height field to model // add height field to model
mjmHField* mjm_addHField(mjSpec* s) { mjsHField* mjs_addHField(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCHField* heightField = modelC->AddHField(); mjCHField* heightField = modelC->AddHField();
return &heightField->spec; return &heightField->spec;
} }
@@ -184,8 +226,8 @@ mjmHField* mjm_addHField(mjSpec* s) {
// add skin to model // add skin to model
mjmSkin* mjm_addSkin(mjSpec* s) { mjsSkin* mjs_addSkin(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCSkin* skin = modelC->AddSkin(); mjCSkin* skin = modelC->AddSkin();
return &skin->spec; return &skin->spec;
} }
@@ -193,8 +235,8 @@ mjmSkin* mjm_addSkin(mjSpec* s) {
// add texture to model // add texture to model
mjmTexture* mjm_addTexture(mjSpec* s) { mjsTexture* mjs_addTexture(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCTexture* texture = modelC->AddTexture(); mjCTexture* texture = modelC->AddTexture();
return &texture->spec; return &texture->spec;
} }
@@ -202,9 +244,9 @@ mjmTexture* mjm_addTexture(mjSpec* s) {
// add material to model // add material to model
mjmMaterial* mjm_addMaterial(mjSpec* s, mjmDefault* defspec) { mjsMaterial* mjs_addMaterial(mjSpec* s, mjsDefault* defspec) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCMaterial* material = modelC->AddMaterial(def); mjCMaterial* material = modelC->AddMaterial(def);
return &material->spec; return &material->spec;
} }
@@ -212,9 +254,9 @@ mjmMaterial* mjm_addMaterial(mjSpec* s, mjmDefault* defspec) {
// add pair to model // add pair to model
mjmPair* mjm_addPair(mjSpec* s, mjmDefault* defspec) { mjsPair* mjs_addPair(mjSpec* s, mjsDefault* defspec) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCPair* pair = modelC->AddPair(def); mjCPair* pair = modelC->AddPair(def);
return &pair->spec; return &pair->spec;
} }
@@ -222,8 +264,8 @@ mjmPair* mjm_addPair(mjSpec* s, mjmDefault* defspec) {
// add pair exclusion to model // add pair exclusion to model
mjmExclude* mjm_addExclude(mjSpec* s) { mjsExclude* mjs_addExclude(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCBodyPair* bodypair = modelC->AddExclude(); mjCBodyPair* bodypair = modelC->AddExclude();
return &bodypair->spec; return &bodypair->spec;
} }
@@ -231,9 +273,9 @@ mjmExclude* mjm_addExclude(mjSpec* s) {
// add equality to model // add equality to model
mjmEquality* mjm_addEquality(mjSpec* s, mjmDefault* defspec) { mjsEquality* mjs_addEquality(mjSpec* s, mjsDefault* defspec) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCEquality* equality = modelC->AddEquality(def); mjCEquality* equality = modelC->AddEquality(def);
return &equality->spec; return &equality->spec;
} }
@@ -241,9 +283,9 @@ mjmEquality* mjm_addEquality(mjSpec* s, mjmDefault* defspec) {
// add tendon to model // add tendon to model
mjmTendon* mjm_addTendon(mjSpec* s, mjmDefault* defspec) { mjsTendon* mjs_addTendon(mjSpec* s, mjsDefault* defspec) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCTendon* tendon = modelC->AddTendon(def); mjCTendon* tendon = modelC->AddTendon(def);
return &tendon->spec; return &tendon->spec;
} }
@@ -251,8 +293,8 @@ mjmTendon* mjm_addTendon(mjSpec* s, mjmDefault* defspec) {
// wrap site using tendon // wrap site using tendon
MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendonspec, const char* name) { MJAPI mjsWrap* mjs_wrapSite(mjsTendon* tendonspec, const char* name) {
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element); mjCTendon* tendon = static_cast<mjCTendon*>(tendonspec->element);
tendon->WrapSite(name); tendon->WrapSite(name);
return &tendon->path.back()->spec; return &tendon->path.back()->spec;
} }
@@ -260,8 +302,8 @@ MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendonspec, const char* name) {
// wrap geom using tendon // wrap geom using tendon
mjmWrap* mjm_wrapGeom(mjmTendon* tendonspec, const char* name, const char* sidesite) { mjsWrap* mjs_wrapGeom(mjsTendon* tendonspec, const char* name, const char* sidesite) {
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element); mjCTendon* tendon = static_cast<mjCTendon*>(tendonspec->element);
tendon->WrapGeom(name, sidesite); tendon->WrapGeom(name, sidesite);
return &tendon->path.back()->spec; return &tendon->path.back()->spec;
} }
@@ -269,8 +311,8 @@ mjmWrap* mjm_wrapGeom(mjmTendon* tendonspec, const char* name, const char* sides
// wrap joint using tendon // wrap joint using tendon
mjmWrap* mjm_wrapJoint(mjmTendon* tendonspec, const char* name, double coef) { mjsWrap* mjs_wrapJoint(mjsTendon* tendonspec, const char* name, double coef) {
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element); mjCTendon* tendon = static_cast<mjCTendon*>(tendonspec->element);
tendon->WrapJoint(name, coef); tendon->WrapJoint(name, coef);
return &tendon->path.back()->spec; return &tendon->path.back()->spec;
} }
@@ -278,8 +320,8 @@ mjmWrap* mjm_wrapJoint(mjmTendon* tendonspec, const char* name, double coef) {
// wrap pulley using tendon // wrap pulley using tendon
mjmWrap* mjm_wrapPulley(mjmTendon* tendonspec, double divisor) { mjsWrap* mjs_wrapPulley(mjsTendon* tendonspec, double divisor) {
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element); mjCTendon* tendon = static_cast<mjCTendon*>(tendonspec->element);
tendon->WrapPulley(divisor); tendon->WrapPulley(divisor);
return &tendon->path.back()->spec; return &tendon->path.back()->spec;
} }
@@ -287,9 +329,9 @@ mjmWrap* mjm_wrapPulley(mjmTendon* tendonspec, double divisor) {
// add actuator to model // add actuator to model
mjmActuator* mjm_addActuator(mjSpec* s, mjmDefault* defspec) { mjsActuator* mjs_addActuator(mjSpec* s, mjsDefault* defspec) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* def = defspec ? reinterpret_cast<mjCDef*>(defspec->element) : 0; mjCDef* def = defspec ? static_cast<mjCDef*>(defspec->element) : 0;
mjCActuator* actuator = modelC->AddActuator(def); mjCActuator* actuator = modelC->AddActuator(def);
return &actuator->spec; return &actuator->spec;
} }
@@ -297,8 +339,8 @@ mjmActuator* mjm_addActuator(mjSpec* s, mjmDefault* defspec) {
// add sensor to model // add sensor to model
mjmSensor* mjm_addSensor(mjSpec* s) { mjsSensor* mjs_addSensor(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCSensor* sensor = modelC->AddSensor(); mjCSensor* sensor = modelC->AddSensor();
return &sensor->spec; return &sensor->spec;
} }
@@ -306,8 +348,8 @@ mjmSensor* mjm_addSensor(mjSpec* s) {
// add numeric to model // add numeric to model
mjmNumeric* mjm_addNumeric(mjSpec* s) { mjsNumeric* mjs_addNumeric(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCNumeric* numeric = modelC->AddNumeric(); mjCNumeric* numeric = modelC->AddNumeric();
return &numeric->spec; return &numeric->spec;
} }
@@ -315,8 +357,8 @@ mjmNumeric* mjm_addNumeric(mjSpec* s) {
// add text to model // add text to model
mjmText* mjm_addText(mjSpec* s) { mjsText* mjs_addText(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCText* text = modelC->AddText(); mjCText* text = modelC->AddText();
return &text->spec; return &text->spec;
} }
@@ -324,8 +366,8 @@ mjmText* mjm_addText(mjSpec* s) {
// add tuple to model // add tuple to model
mjmTuple* mjm_addTuple(mjSpec* s) { mjsTuple* mjs_addTuple(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCTuple* tuple = modelC->AddTuple(); mjCTuple* tuple = modelC->AddTuple();
return &tuple->spec; return &tuple->spec;
} }
@@ -333,8 +375,8 @@ mjmTuple* mjm_addTuple(mjSpec* s) {
// add keyframe to model // add keyframe to model
mjmKey* mjm_addKey(mjSpec* s) { mjsKey* mjs_addKey(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCKey* key = modelC->AddKey(); mjCKey* key = modelC->AddKey();
return &key->spec; return &key->spec;
} }
@@ -342,18 +384,18 @@ mjmKey* mjm_addKey(mjSpec* s) {
// add plugin to model // add plugin to model
mjmPlugin* mjm_addPlugin(mjSpec* s) { mjsPlugin* mjs_addPlugin(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCPlugin* plugin = modelC->AddPlugin(); mjCPlugin* plugin = modelC->AddPlugin();
plugin->spec.instance = (mjElement)plugin; plugin->spec.instance = static_cast<mjElement*>(plugin);
return &plugin->spec; return &plugin->spec;
} }
// add default to model // add default to model
mjmDefault* mjm_addDefault(mjSpec* s, const char* classname, int parentid, int* id) { mjsDefault* mjs_addDefault(mjSpec* s, const char* classname, int parentid, int* id) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
*id = (int)modelC->defaults.size(); *id = (int)modelC->defaults.size();
mjCDef* def = modelC->AddDef(classname, parentid); mjCDef* def = modelC->AddDef(classname, parentid);
if (def) { if (def) {
@@ -366,22 +408,22 @@ mjmDefault* mjm_addDefault(mjSpec* s, const char* classname, int parentid, int*
// get objects // get objects
mjSpec* mjm_getSpec(mjmBody* body) { mjSpec* mjs_getSpec(mjsBody* body) {
return &(reinterpret_cast<mjCBody*>(body->element)->model->spec); return &(static_cast<mjCBody*>(body->element)->model->spec);
} }
// get default // get default
mjmDefault* mjm_getDefault(mjElement element) { mjsDefault* mjs_getDefault(mjElement* element) {
return &(reinterpret_cast<mjCBase*>(element)->def->spec); return &(static_cast<mjCBase*>(element)->def->spec);
} }
// Find default with given name in model. // Find default with given name in model.
mjmDefault* mjm_findDefault(mjSpec* s, const char* classname) { mjsDefault* mjs_findDefault(mjSpec* s, const char* classname) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* cdef = modelC->FindDef(classname); mjCDef* cdef = modelC->FindDef(classname);
if (!cdef) { if (!cdef) {
return nullptr; return nullptr;
@@ -392,8 +434,8 @@ mjmDefault* mjm_findDefault(mjSpec* s, const char* classname) {
// get default[0] from model // get default[0] from model
mjmDefault* mjm_getSpecDefault(mjSpec* s) { mjsDefault* mjs_getSpecDefault(mjSpec* s) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
mjCDef* def = modelC->defaults[0]; mjCDef* def = modelC->defaults[0];
if (!def) { if (!def) {
return nullptr; return nullptr;
@@ -404,70 +446,83 @@ mjmDefault* mjm_getSpecDefault(mjSpec* s) {
// find body in model by name // find body in model by name
mjmBody* mjm_findBody(mjSpec* s, const char* name) { mjsBody* mjs_findBody(mjSpec* s, const char* name) {
mjCModel* model = reinterpret_cast<mjCModel*>(s->element); mjCModel* model = static_cast<mjCModel*>(s->element);
mjCBase* body = model->FindObject(mjOBJ_BODY, std::string(name)); mjCBase* body = 0;
if (!body) { if (model->IsCompiled()) {
return 0; body = model->FindObject(mjOBJ_BODY, std::string(name)); // fast lookup
} else {
body = model->FindBody(model->GetWorld(), std::string(name)); // recursive search
} }
return &(static_cast<mjCBody*>(body)->spec); return body ? &(static_cast<mjCBody*>(body)->spec) : nullptr;
} }
// find child of a body by name // find child of a body by name
mjmBody* mjm_findChild(mjmBody* bodyspec, const char* name) { mjsBody* mjs_findChild(mjsBody* bodyspec, const char* name) {
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
mjCBase* child = body->FindObject(mjOBJ_BODY, std::string(name)); mjCBase* child = body->FindObject(mjOBJ_BODY, std::string(name));
if (!child) { return child ? &(static_cast<mjCBody*>(child)->spec) : nullptr;
return 0;
}
return &(static_cast<mjCBody*>(child)->spec);
} }
// find mesh by name // find mesh by name
mjmMesh* mjm_findMesh(mjSpec* s, const char* name) { mjsMesh* mjs_findMesh(mjSpec* s, const char* name) {
mjCModel* model = reinterpret_cast<mjCModel*>(s->element); mjCModel* model = static_cast<mjCModel*>(s->element);
mjCMesh* mesh = (mjCMesh*)model->FindObject(mjOBJ_MESH, std::string(name)); mjCMesh* mesh = (mjCMesh*)model->FindObject(mjOBJ_MESH, std::string(name));
if (!mesh) { return mesh ? &(static_cast<mjCMesh*>(mesh)->spec) : nullptr;
return nullptr;
} }
return &(static_cast<mjCMesh*>(mesh)->spec);
// find frame by name
mjsFrame* mjs_findFrame(mjSpec* s, const char* name) {
mjCModel* model = static_cast<mjCModel*>(s->element);
mjCFrame* frame = (mjCFrame*)model->FindFrame(model->GetWorld(), std::string(name));
return frame ? &(static_cast<mjCFrame*>(frame)->spec) : nullptr;
} }
// set frame // set frame
void mjm_setFrame(mjElement dest, mjmFrame* frame) { void mjs_setFrame(mjElement* dest, mjsFrame* frame) {
if (!frame) { if (!frame) {
return; return;
} }
mjCFrame* frameC = reinterpret_cast<mjCFrame*>(frame->element); mjCFrame* frameC = static_cast<mjCFrame*>(frame->element);
mjCBase* baseC = reinterpret_cast<mjCBase*>(dest); mjCBase* baseC = static_cast<mjCBase*>(dest);
baseC->SetFrame(frameC); baseC->SetFrame(frameC);
} }
// Resolve alternative orientations.
const char* mjs_resolveOrientation(double quat[4], mjtByte degree, const char* sequence,
const mjsOrientation* orientation) {
return ResolveOrientation(quat, degree, sequence, *orientation);
}
// get id // get id
int mjm_getId(mjElement element) { int mjs_getId(mjElement* element) {
return reinterpret_cast<mjCBase*>(element)->id; return static_cast<mjCBase*>(element)->id;
} }
// set default // set default
void mjm_setDefault(mjElement element, mjmDefault* defspec) { void mjs_setDefault(mjElement* element, mjsDefault* defspec) {
mjCBase* baseC = reinterpret_cast<mjCBase*>(element); mjCBase* baseC = static_cast<mjCBase*>(element);
baseC->def = reinterpret_cast<mjCDef*>(defspec->element); baseC->def = static_cast<mjCDef*>(defspec->element);
} }
// set string // set string
void mjm_setString(mjString dest, const char* text) { void mjs_setString(mjString dest, const char* text) {
std::string* str = reinterpret_cast<std::string*>(dest); std::string* str = reinterpret_cast<std::string*>(dest);
*str = std::string(text); *str = std::string(text);
} }
@@ -475,10 +530,10 @@ void mjm_setString(mjString dest, const char* text) {
// Set specific entry in destination string vector. // Set specific entry in destination string vector.
mjtByte mjm_setInStringVec(mjStringVec dest, int i, const char* text) { mjtByte mjs_setInStringVec(mjStringVec dest, int i, const char* text) {
std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest); std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest);
if (v->size() <= i) { if (v->size() <= i) {
mju_error("Requested index in mjm_setInStringVec is out of bounds"); mju_error("Requested index in mjs_setInStringVec is out of bounds");
return 0; return 0;
} }
v->at(i) = std::string(text); v->at(i) = std::string(text);
@@ -488,7 +543,7 @@ mjtByte mjm_setInStringVec(mjStringVec dest, int i, const char* text) {
// split text and copy into string array // split text and copy into string array
void mjm_setStringVec(mjStringVec dest, const char* text) { void mjs_setStringVec(mjStringVec dest, const char* text) {
std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest); std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest);
*v = mjXUtil::String2Vector<std::string>(text); *v = mjXUtil::String2Vector<std::string>(text);
} }
@@ -496,14 +551,14 @@ void mjm_setStringVec(mjStringVec dest, const char* text) {
// add text entry to destination string vector // add text entry to destination string vector
void mjm_appendString(mjStringVec dest, const char* text) { void mjs_appendString(mjStringVec dest, const char* text) {
std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest); std::vector<std::string>* v = reinterpret_cast<std::vector<std::string>*>(dest);
v->push_back(std::string(text)); v->push_back(std::string(text));
} }
// copy int array to vector // copy int array to vector
void mjm_setInt(mjIntVec dest, const int* array, int size) { void mjs_setInt(mjIntVec dest, const int* array, int size) {
std::vector<int>* v = reinterpret_cast<std::vector<int>*>(dest); std::vector<int>* v = reinterpret_cast<std::vector<int>*>(dest);
v->assign(size, 0.0); v->assign(size, 0.0);
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
@@ -514,7 +569,7 @@ void mjm_setInt(mjIntVec dest, const int* array, int size) {
// append int array to vector of arrays // append int array to vector of arrays
void mjm_appendIntVec(mjIntVecVec dest, const int* array, int size) { void mjs_appendIntVec(mjIntVecVec dest, const int* array, int size) {
std::vector<std::vector<int>>* v = reinterpret_cast<std::vector<std::vector<int>>*>(dest); std::vector<std::vector<int>>* v = reinterpret_cast<std::vector<std::vector<int>>*>(dest);
v->push_back(std::vector<int>(array, array + size)); v->push_back(std::vector<int>(array, array + size));
} }
@@ -522,7 +577,7 @@ void mjm_appendIntVec(mjIntVecVec dest, const int* array, int size) {
// copy float array to vector // copy float array to vector
void mjm_setFloat(mjFloatVec dest, const float* array, int size) { void mjs_setFloat(mjFloatVec dest, const float* array, int size) {
std::vector<float>* v = reinterpret_cast<std::vector<float>*>(dest); std::vector<float>* v = reinterpret_cast<std::vector<float>*>(dest);
v->assign(size, 0.0); v->assign(size, 0.0);
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
@@ -534,7 +589,7 @@ void mjm_setFloat(mjFloatVec dest, const float* array, int size) {
// append float array to vector of arrays // append float array to vector of arrays
void mjm_appendFloatVec(mjFloatVecVec dest, const float* array, int size) { void mjs_appendFloatVec(mjFloatVecVec dest, const float* array, int size) {
std::vector<std::vector<float>>* v = reinterpret_cast<std::vector<std::vector<float>>*>(dest); std::vector<std::vector<float>>* v = reinterpret_cast<std::vector<std::vector<float>>*>(dest);
v->push_back(std::vector<float>(array, array + size)); v->push_back(std::vector<float>(array, array + size));
} }
@@ -542,7 +597,7 @@ void mjm_appendFloatVec(mjFloatVecVec dest, const float* array, int size) {
// copy double array to vector // copy double array to vector
void mjm_setDouble(mjDoubleVec dest, const double* array, int size) { void mjs_setDouble(mjDoubleVec dest, const double* array, int size) {
std::vector<double>* v = reinterpret_cast<std::vector<double>*>(dest); std::vector<double>* v = reinterpret_cast<std::vector<double>*>(dest);
v->assign(size, 0.0); v->assign(size, 0.0);
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
@@ -553,7 +608,7 @@ void mjm_setDouble(mjDoubleVec dest, const double* array, int size) {
// get string // get string
const char* mjm_getString(const mjString source) { const char* mjs_getString(const mjString source) {
std::string* str = reinterpret_cast<std::string*>(source); std::string* str = reinterpret_cast<std::string*>(source);
if (!str) { if (!str) {
return nullptr; return nullptr;
@@ -564,7 +619,7 @@ const char* mjm_getString(const mjString source) {
// get double array // get double array
const double* mjm_getDouble(const mjDoubleVec source, int* size) { const double* mjs_getDouble(const mjDoubleVec source, int* size) {
std::vector<double>* v = reinterpret_cast<std::vector<double>*>(source); std::vector<double>* v = reinterpret_cast<std::vector<double>*>(source);
if (size) { if (size) {
*size = v->size(); *size = v->size();
@@ -575,8 +630,8 @@ const double* mjm_getDouble(const mjDoubleVec source, int* size) {
// set plugin attributes // set plugin attributes
void mjm_setPluginAttributes(mjmPlugin* plugin, void* attributes) { void mjs_setPluginAttributes(mjsPlugin* plugin, void* attributes) {
mjCPlugin* pluginC = reinterpret_cast<mjCPlugin*>(plugin->instance); mjCPlugin* pluginC = static_cast<mjCPlugin*>(plugin->instance);
std::map<std::string, std::string, std::less<>>* config_attribs = std::map<std::string, std::string, std::less<>>* config_attribs =
reinterpret_cast<std::map<std::string, std::string, std::less<>>*>(attributes); reinterpret_cast<std::map<std::string, std::string, std::less<>>*>(attributes);
pluginC->config_attribs = std::move(*config_attribs); pluginC->config_attribs = std::move(*config_attribs);
@@ -585,8 +640,8 @@ void mjm_setPluginAttributes(mjmPlugin* plugin, void* attributes) {
// Set active plugins. // Set active plugins.
void mjm_setActivePlugins(mjSpec* s, void* activeplugins) { void mjs_setActivePlugins(mjSpec* s, void* activeplugins) {
mjCModel* modelC = reinterpret_cast<mjCModel*>(s->element); mjCModel* modelC = static_cast<mjCModel*>(s->element);
std::vector<std::pair<const mjpPlugin*, int>>* active_plugins = std::vector<std::pair<const mjpPlugin*, int>>* active_plugins =
reinterpret_cast<std::vector<std::pair<const mjpPlugin*, int>>*>(activeplugins); reinterpret_cast<std::vector<std::pair<const mjpPlugin*, int>>*>(activeplugins);
modelC->active_plugins = std::move(*active_plugins); modelC->active_plugins = std::move(*active_plugins);
@@ -595,9 +650,22 @@ void mjm_setActivePlugins(mjSpec* s, void* activeplugins) {
// compute full inertia // compute full inertia
const char* mjm_setFullInertia(mjmBody* bodyspec, double quat[4], double inertia[3]) { const char* mjs_setFullInertia(mjsBody* bodyspec, double quat[4], double inertia[3]) {
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element); mjCBody* body = static_cast<mjCBody*>(bodyspec->element);
return body->FullInertia(quat, inertia); return body->FullInertia(quat, inertia);
} }
// -------------------------- GLOBAL ASSET CACHE -------------------------------
void mj_setCacheSize(mjCache cache, std::size_t size) {
mjCCache* ccache = reinterpret_cast<mjCCache*>(cache);
if (ccache) {
ccache->SetMaxSize(size);
}
}
mjCache mj_globalCache() {
return NULL; // currently disabled
}
+222 -190
View File
@@ -29,7 +29,6 @@ extern "C" {
//---------------------------------- handles to internal objects ----------------------------------- //---------------------------------- handles to internal objects -----------------------------------
typedef struct _mjElement* mjElement;
typedef struct _mjString* mjString; typedef struct _mjString* mjString;
typedef struct _mjStringVec* mjStringVec; typedef struct _mjStringVec* mjStringVec;
typedef struct _mjIntVec* mjIntVec; typedef struct _mjIntVec* mjIntVec;
@@ -77,10 +76,15 @@ typedef enum _mjtInertiaFromGeom {
} mjtInertiaFromGeom; } mjtInertiaFromGeom;
//---------------------------------- attribute structs (mjm) --------------------------------------- //---------------------------------- attribute structs (mjs) ---------------------------------------
typedef struct _mjElement { // element type, do not modify
mjtObj elemtype; // element type
} mjElement;
typedef struct _mjSpec { // model specification typedef struct _mjSpec { // model specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjStatistic stat; // statistics override (if defined) mjStatistic stat; // statistics override (if defined)
// compiler settings // compiler settings
@@ -135,40 +139,40 @@ typedef struct _mjSpec { // model specification
} mjSpec; } mjSpec;
typedef struct _mjmOrientation { // alternative orientation specifiers typedef struct _mjsOrientation { // alternative orientation specifiers
double axisangle[4]; // rotation axis and angle double axisangle[4]; // rotation axis and angle
double xyaxes[6]; // x and y axes double xyaxes[6]; // x and y axes
double zaxis[3]; // z axis (use minimal rotation) double zaxis[3]; // z axis (use minimal rotation)
double euler[3]; // euler angles double euler[3]; // euler angles
} mjmOrientation; } mjsOrientation;
typedef struct _mjmPlugin { // plugin specification typedef struct _mjsPlugin { // plugin specification
mjElement instance; // internal, do not modify mjElement* instance; // object type
mjString name; // name mjString name; // name
mjString instance_name; // instance name mjString instance_name; // instance name
int plugin_slot; // global registered slot number of the plugin int plugin_slot; // global registered slot number of the plugin
mjtByte active; // is the plugin active mjtByte active; // is the plugin active
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmPlugin; } mjsPlugin;
typedef struct _mjmBody { // body specification typedef struct _mjsBody { // body specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString childclass; // childclass name mjString childclass; // childclass name
// body frame // body frame
double pos[3]; // frame position double pos[3]; // frame position
double quat[4]; // frame orientation double quat[4]; // frame orientation
mjmOrientation alt; // frame alternative orientation mjsOrientation alt; // frame alternative orientation
// inertial frame // inertial frame
double mass; // mass double mass; // mass
double ipos[3]; // inertial frame position double ipos[3]; // inertial frame position
double iquat[4]; // inertial frame orientation double iquat[4]; // inertial frame orientation
double inertia[3]; // diagonal inertia (in i-frame) double inertia[3]; // diagonal inertia (in i-frame)
mjmOrientation ialt; // inertial frame alternative orientation mjsOrientation ialt; // inertial frame alternative orientation
double fullinertia[6]; // non-axis-aligned inertia matrix double fullinertia[6]; // non-axis-aligned inertia matrix
// other // other
@@ -176,24 +180,24 @@ typedef struct _mjmBody { // body specification
double gravcomp; // gravity compensation double gravcomp; // gravity compensation
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjtByte explicitinertial; // whether to save the body with explicit inertial clause mjtByte explicitinertial; // whether to save the body with explicit inertial clause
mjmPlugin plugin; // passive force plugin mjsPlugin plugin; // passive force plugin
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmBody; } mjsBody;
typedef struct _mjmFrame { // frame specification typedef struct _mjsFrame { // frame specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString childclass; // childclass name mjString childclass; // childclass name
double pos[3]; // position double pos[3]; // position
double quat[4]; // orientation double quat[4]; // orientation
mjmOrientation alt; // alternative orientation mjsOrientation alt; // alternative orientation
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmFrame; } mjsFrame;
typedef struct _mjmJoint { // joint specification typedef struct _mjsJoint { // joint specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjtJoint type; // joint type mjtJoint type; // joint type
@@ -226,14 +230,15 @@ typedef struct _mjmJoint { // joint specification
// other // other
int group; // group int group; // group
mjtByte actgravcomp; // is gravcomp force applied via actuators
double urdfeffort; // effort (urdf) double urdfeffort; // effort (urdf)
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmJoint; } mjsJoint;
typedef struct _mjmGeom { // geom specification typedef struct _mjsGeom { // geom specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // classname mjString classname; // classname
mjtGeom type; // geom type mjtGeom type; // geom type
@@ -241,7 +246,7 @@ typedef struct _mjmGeom { // geom specification
// frame, size // frame, size
double pos[3]; // position double pos[3]; // position
double quat[4]; // orientation double quat[4]; // orientation
mjmOrientation alt; // alternative orientation mjsOrientation alt; // alternative orientation
double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid
double size[3]; // type-specific size double size[3]; // type-specific size
@@ -276,20 +281,20 @@ typedef struct _mjmGeom { // geom specification
mjString meshname; // mesh attached to geom mjString meshname; // mesh attached to geom
double fitscale; // scale mesh uniformly double fitscale; // scale mesh uniformly
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjmPlugin plugin; // sdf plugin mjsPlugin plugin; // sdf plugin
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmGeom; } mjsGeom;
typedef struct _mjmSite { // site specification typedef struct _mjsSite { // site specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
// frame, size // frame, size
double pos[3]; // position double pos[3]; // position
double quat[4]; // orientation double quat[4]; // orientation
mjmOrientation alt; // alternative orientation mjsOrientation alt; // alternative orientation
double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid
double size[3]; // geom size double size[3]; // geom size
@@ -302,18 +307,18 @@ typedef struct _mjmSite { // site specification
// other // other
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmSite; } mjsSite;
typedef struct _mjmCamera { // camera specification typedef struct _mjsCamera { // camera specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
// extrinsics // extrinsics
double pos[3]; // position double pos[3]; // position
double quat[4]; // orientation double quat[4]; // orientation
mjmOrientation alt; // alternative orientation mjsOrientation alt; // alternative orientation
mjtCamLight mode; // tracking mode mjtCamLight mode; // tracking mode
mjString targetbody; // target body for tracking/targeting mjString targetbody; // target body for tracking/targeting
@@ -331,11 +336,11 @@ typedef struct _mjmCamera { // camera specification
// other // other
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmCamera; } mjsCamera;
typedef struct _mjmLight { // light specification typedef struct _mjsLight { // light specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
@@ -358,11 +363,11 @@ typedef struct _mjmLight { // light specification
// other // other
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmLight; } mjsLight;
typedef struct _mjmFlex { typedef struct _mjsFlex {
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
@@ -399,11 +404,11 @@ typedef struct _mjmFlex {
// other // other
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmFlex; } mjsFlex;
typedef struct _mjmMesh { // mesh specification typedef struct _mjsMesh { // mesh specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjString content_type; // content type of file mjString content_type; // content type of file
@@ -418,13 +423,13 @@ typedef struct _mjmMesh { // mesh specification
mjIntVec userface; // user vertex indices mjIntVec userface; // user vertex indices
mjIntVec userfacenormal; // user normal indices mjIntVec userfacenormal; // user normal indices
mjIntVec userfacetexcoord; // user texcoord indices mjIntVec userfacetexcoord; // user texcoord indices
mjmPlugin plugin; // sdf plugin mjsPlugin plugin; // sdf plugin
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmMesh; } mjsMesh;
typedef struct _mjmHField { // height field specification typedef struct _mjsHField { // height field specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString content_type; // content type of file mjString content_type; // content type of file
mjString file; // file: (nrow, ncol, [elevation data]) mjString file; // file: (nrow, ncol, [elevation data])
@@ -433,12 +438,12 @@ typedef struct _mjmHField { // height field specification
int ncol; // number of columns int ncol; // number of columns
mjFloatVec userdata; // user-provided elevation data mjFloatVec userdata; // user-provided elevation data
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmHField; } mjsHField;
typedef struct _mjmSkin { // skin specification typedef struct _mjsSkin { // skin specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjString file; // skin file mjString file; // skin file
@@ -461,11 +466,11 @@ typedef struct _mjmSkin { // skin specification
// other // other
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmSkin; } mjsSkin;
typedef struct _mjmTexture { // texture specification typedef struct _mjsTexture { // texture specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjtTexture type; // texture type mjtTexture type; // texture type
@@ -495,11 +500,11 @@ typedef struct _mjmTexture { // texture specification
// other // other
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmTexture; } mjsTexture;
typedef struct _mjmMaterial { // material specification typedef struct _mjsMaterial { // material specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjString texture; // name of texture (empty: none) mjString texture; // name of texture (empty: none)
@@ -511,11 +516,11 @@ typedef struct _mjmMaterial { // material specification
float reflectance; // reflectance float reflectance; // reflectance
float rgba[4]; // rgba float rgba[4]; // rgba
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmMaterial; } mjsMaterial;
typedef struct _mjmPair { typedef struct _mjsPair {
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjString geomname1; // name of geom 1 mjString geomname1; // name of geom 1
@@ -530,20 +535,20 @@ typedef struct _mjmPair {
double gap; // include in solver if dist<margin-gap double gap; // include in solver if dist<margin-gap
double friction[5]; // full contact friction double friction[5]; // full contact friction
mjString info; // message appended to errors mjString info; // message appended to errors
} mjmPair; } mjsPair;
typedef struct _mjmExclude { typedef struct _mjsExclude {
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString bodyname1; // name of geom 1 mjString bodyname1; // name of geom 1
mjString bodyname2; // name of geom 2 mjString bodyname2; // name of geom 2
mjString info; // message appended to errors mjString info; // message appended to errors
} mjmExclude; } mjsExclude;
typedef struct _mjmEquality { // equality specification typedef struct _mjsEquality { // equality specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
mjtEq type; // constraint type mjtEq type; // constraint type
@@ -554,11 +559,11 @@ typedef struct _mjmEquality { // equality specification
mjtNum solref[mjNREF]; // solver reference mjtNum solref[mjNREF]; // solver reference
mjtNum solimp[mjNIMP]; // solver impedance mjtNum solimp[mjNIMP]; // solver impedance
mjString info; // message appended to errors mjString info; // message appended to errors
} mjmEquality; } mjsEquality;
typedef struct _mjmTendon { // tendon specification typedef struct _mjsTendon { // tendon specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
@@ -586,17 +591,17 @@ typedef struct _mjmTendon { // tendon specification
// other // other
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjString info; // message appended to errors mjString info; // message appended to errors
} mjmTendon; } mjsTendon;
typedef struct _mjmWrap { // wrapping object specification typedef struct _mjsWrap { // wrapping object specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString info; // message appended to errors mjString info; // message appended to errors
} mjmWrap; } mjsWrap;
typedef struct _mjmActuator { // actuator specification typedef struct _mjsActuator { // actuator specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
@@ -634,13 +639,13 @@ typedef struct _mjmActuator { // actuator specification
// other // other
int group; // group int group; // group
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjmPlugin plugin; // actuator plugin mjsPlugin plugin; // actuator plugin
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmActuator; } mjsActuator;
typedef struct _mjmSensor { // sensor specfication typedef struct _mjsSensor { // sensor specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString classname; // class name mjString classname; // class name
@@ -662,40 +667,40 @@ typedef struct _mjmSensor { // sensor specfication
// other // other
mjDoubleVec userdata; // user data mjDoubleVec userdata; // user data
mjmPlugin plugin; // sensor plugin mjsPlugin plugin; // sensor plugin
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmSensor; } mjsSensor;
typedef struct _mjmNumeric { // custom numeric field specification typedef struct _mjsNumeric { // custom numeric field specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjDoubleVec data; // initialization data mjDoubleVec data; // initialization data
int size; // array size, can be bigger than data size int size; // array size, can be bigger than data size
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmNumeric; } mjsNumeric;
typedef struct _mjmText { // custom text specification typedef struct _mjsText { // custom text specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjString data; // text string mjString data; // text string
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmText; } mjsText;
typedef struct _mjmTuple { // tuple specification typedef struct _mjsTuple { // tuple specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
mjIntVec objtype; // object types mjIntVec objtype; // object types
mjStringVec objname; // object names mjStringVec objname; // object names
mjDoubleVec objprm; // object parameters mjDoubleVec objprm; // object parameters
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmTuple; } mjsTuple;
typedef struct _mjmKey { // keyframe specification typedef struct _mjsKey { // keyframe specification
mjElement element; // internal, do not modify mjElement* element; // object type
mjString name; // name mjString name; // name
double time; // time double time; // time
mjDoubleVec qpos; // qpos mjDoubleVec qpos; // qpos
@@ -705,283 +710,310 @@ typedef struct _mjmKey { // keyframe specification
mjDoubleVec mquat; // mocap quat mjDoubleVec mquat; // mocap quat
mjDoubleVec ctrl; // ctrl mjDoubleVec ctrl; // ctrl
mjString info; // message appended to compiler errors mjString info; // message appended to compiler errors
} mjmKey; } mjsKey;
typedef struct _mjmDefault { // default specification typedef struct _mjsDefault { // default specification
mjString name; // name mjString name; // name
mjElement element; // internal, do not modify mjElement* element; // object type
mjmJoint* joint; // joint defaults mjsJoint* joint; // joint defaults
mjmGeom* geom; // geom defaults mjsGeom* geom; // geom defaults
mjmSite* site; // site defaults mjsSite* site; // site defaults
mjmCamera* camera; // camera defaults mjsCamera* camera; // camera defaults
mjmLight* light; // light defaults mjsLight* light; // light defaults
mjmFlex* flex; // flex defaults mjsFlex* flex; // flex defaults
mjmMesh* mesh; // mesh defaults mjsMesh* mesh; // mesh defaults
mjmMaterial* material; // material defaults mjsMaterial* material; // material defaults
mjmPair* pair; // pair defaults mjsPair* pair; // pair defaults
mjmEquality* equality; // equality defaults mjsEquality* equality; // equality defaults
mjmTendon* tendon; // tendon defaults mjsTendon* tendon; // tendon defaults
mjmActuator* actuator; // actuator defaults mjsActuator* actuator; // actuator defaults
} mjmDefault; } mjsDefault;
//---------------------------------- API functions ------------------------------------------------- //---------------------------------- API functions -------------------------------------------------
// Create model. // Create model.
MJAPI mjSpec* mjm_createSpec(); MJAPI mjSpec* mjs_createSpec();
// Copy model.
MJAPI mjSpec* mjs_copySpec(const mjSpec* s);
// Copy back model. // Copy back model.
MJAPI void mjm_copyBack(mjSpec* s, const mjModel* m); MJAPI void mjs_copyBack(mjSpec* s, const mjModel* m);
// Compile model. // Compile model.
MJAPI mjModel* mjm_compile(mjSpec* s, const mjVFS* vfs); MJAPI mjModel* mjs_compile(mjSpec* s, const mjVFS* vfs);
// Attach child body to a frame of the parent, return 0 if success
MJAPI int mjs_attachBody(mjsFrame* parent, const mjsBody* child,
const char* prefix, const char* suffix);
// Get error message from model. // Get error message from model.
MJAPI const char* mjm_getError(mjSpec* s); MJAPI const char* mjs_getError(mjSpec* s);
// Return 1 if model has warnings. // Return 1 if model has warnings.
MJAPI int mjm_isWarning(mjSpec* s); MJAPI int mjs_isWarning(mjSpec* s);
// Delete model. // Delete model.
MJAPI void mjm_deleteSpec(mjSpec* s); MJAPI void mjs_deleteSpec(mjSpec* s);
// Add child body to body, return child spec. // Add child body to body, return child spec.
MJAPI mjmBody* mjm_addBody(mjmBody* body, mjmDefault* def); MJAPI mjsBody* mjs_addBody(mjsBody* body, mjsDefault* def);
// Add site to body, return site spec. // Add site to body, return site spec.
MJAPI mjmSite* mjm_addSite(mjmBody* body, mjmDefault* def); MJAPI mjsSite* mjs_addSite(mjsBody* body, mjsDefault* def);
// Add joint to body. // Add joint to body.
MJAPI mjmJoint* mjm_addJoint(mjmBody* body, mjmDefault* def); MJAPI mjsJoint* mjs_addJoint(mjsBody* body, mjsDefault* def);
// Add freejoint to body. // Add freejoint to body.
MJAPI mjmJoint* mjm_addFreeJoint(mjmBody* body); MJAPI mjsJoint* mjs_addFreeJoint(mjsBody* body);
// Add geom to body. // Add geom to body.
MJAPI mjmGeom* mjm_addGeom(mjmBody* body, mjmDefault* def); MJAPI mjsGeom* mjs_addGeom(mjsBody* body, mjsDefault* def);
// Add camera to body. // Add camera to body.
MJAPI mjmCamera* mjm_addCamera(mjmBody* body, mjmDefault* def); MJAPI mjsCamera* mjs_addCamera(mjsBody* body, mjsDefault* def);
// Add light to body. // Add light to body.
MJAPI mjmLight* mjm_addLight(mjmBody* body, mjmDefault* def); MJAPI mjsLight* mjs_addLight(mjsBody* body, mjsDefault* def);
// Add frame to body. // Add frame to body.
MJAPI mjmFrame* mjm_addFrame(mjmBody* body, mjmFrame* parentframe); MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe);
// Add flex to model. // Add flex to model.
MJAPI mjmFlex* mjm_addFlex(mjSpec* s); MJAPI mjsFlex* mjs_addFlex(mjSpec* s);
// Add mesh to model. // Add mesh to model.
MJAPI mjmMesh* mjm_addMesh(mjSpec* s, mjmDefault* def); MJAPI mjsMesh* mjs_addMesh(mjSpec* s, mjsDefault* def);
// Add height field to model. // Add height field to model.
MJAPI mjmHField* mjm_addHField(mjSpec* s); MJAPI mjsHField* mjs_addHField(mjSpec* s);
// Add skin to model. // Add skin to model.
MJAPI mjmSkin* mjm_addSkin(mjSpec* s); MJAPI mjsSkin* mjs_addSkin(mjSpec* s);
// Add texture to model. // Add texture to model.
MJAPI mjmTexture* mjm_addTexture(mjSpec* s); MJAPI mjsTexture* mjs_addTexture(mjSpec* s);
// Add material to model. // Add material to model.
MJAPI mjmMaterial* mjm_addMaterial(mjSpec* s, mjmDefault* def); MJAPI mjsMaterial* mjs_addMaterial(mjSpec* s, mjsDefault* def);
// Add pair to model. // Add pair to model.
MJAPI mjmPair* mjm_addPair(mjSpec* s, mjmDefault* def); MJAPI mjsPair* mjs_addPair(mjSpec* s, mjsDefault* def);
// Add excluded body pair to model. // Add excluded body pair to model.
MJAPI mjmExclude* mjm_addExclude(mjSpec* s); MJAPI mjsExclude* mjs_addExclude(mjSpec* s);
// Add equality to model. // Add equality to model.
MJAPI mjmEquality* mjm_addEquality(mjSpec* s, mjmDefault* def); MJAPI mjsEquality* mjs_addEquality(mjSpec* s, mjsDefault* def);
// Add tendon to model. // Add tendon to model.
MJAPI mjmTendon* mjm_addTendon(mjSpec* s, mjmDefault* def); MJAPI mjsTendon* mjs_addTendon(mjSpec* s, mjsDefault* def);
// Wrap site using tendon. // Wrap site using tendon.
MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendon, const char* name); MJAPI mjsWrap* mjs_wrapSite(mjsTendon* tendon, const char* name);
// Wrap geom using tendon. // Wrap geom using tendon.
MJAPI mjmWrap* mjm_wrapGeom(mjmTendon* tendon, const char* name, const char* sidesite); MJAPI mjsWrap* mjs_wrapGeom(mjsTendon* tendon, const char* name, const char* sidesite);
// Wrap joint using tendon. // Wrap joint using tendon.
MJAPI mjmWrap* mjm_wrapJoint(mjmTendon* tendon, const char* name, double coef); MJAPI mjsWrap* mjs_wrapJoint(mjsTendon* tendon, const char* name, double coef);
// Wrap pulley using tendon. // Wrap pulley using tendon.
MJAPI mjmWrap* mjm_wrapPulley(mjmTendon* tendon, double divisor); MJAPI mjsWrap* mjs_wrapPulley(mjsTendon* tendon, double divisor);
// Add actuator to model. // Add actuator to model.
MJAPI mjmActuator* mjm_addActuator(mjSpec* s, mjmDefault* def); MJAPI mjsActuator* mjs_addActuator(mjSpec* s, mjsDefault* def);
// Add sensor to model. // Add sensor to model.
MJAPI mjmSensor* mjm_addSensor(mjSpec* s); MJAPI mjsSensor* mjs_addSensor(mjSpec* s);
// Add numeric to model. // Add numeric to model.
MJAPI mjmNumeric* mjm_addNumeric(mjSpec* s); MJAPI mjsNumeric* mjs_addNumeric(mjSpec* s);
// Add text to model. // Add text to model.
MJAPI mjmText* mjm_addText(mjSpec* s); MJAPI mjsText* mjs_addText(mjSpec* s);
// Add tuple to model. // Add tuple to model.
MJAPI mjmTuple* mjm_addTuple(mjSpec* s); MJAPI mjsTuple* mjs_addTuple(mjSpec* s);
// Add keyframe to model. // Add keyframe to model.
MJAPI mjmKey* mjm_addKey(mjSpec* s); MJAPI mjsKey* mjs_addKey(mjSpec* s);
// Add plugin to model. // Add plugin to model.
MJAPI mjmPlugin* mjm_addPlugin(mjSpec* s); MJAPI mjsPlugin* mjs_addPlugin(mjSpec* s);
// Add default to model. // Add default to model.
MJAPI mjmDefault* mjm_addDefault(mjSpec* s, const char* classname, int parentid, int* id); MJAPI mjsDefault* mjs_addDefault(mjSpec* s, const char* classname, int parentid, int* id);
// Get model spec from body. // Get model spec from body.
MJAPI mjSpec* mjm_getSpec(mjmBody* body); MJAPI mjSpec* mjs_getSpec(mjsBody* body);
// Get default corresponding to an mjElement. // Get default corresponding to an mjElement.
MJAPI mjmDefault* mjm_getDefault(mjElement element); MJAPI mjsDefault* mjs_getDefault(mjElement* element);
// Find default in model by class name. // Find default in model by class name.
MJAPI mjmDefault* mjm_findDefault(mjSpec* s, const char* classname); MJAPI mjsDefault* mjs_findDefault(mjSpec* s, const char* classname);
// Get global default from model. // Get global default from model.
MJAPI mjmDefault* mjm_getSpecDefault(mjSpec* s); MJAPI mjsDefault* mjs_getSpecDefault(mjSpec* s);
// Find body in model by name. // Find body in model by name.
MJAPI mjmBody* mjm_findBody(mjSpec* s, const char* name); MJAPI mjsBody* mjs_findBody(mjSpec* s, const char* name);
// Find child body by name. // Find child body by name.
MJAPI mjmBody* mjm_findChild(mjmBody* body, const char* name); MJAPI mjsBody* mjs_findChild(mjsBody* body, const char* name);
// Find mesh by name. // Find mesh by name.
MJAPI mjmMesh* mjm_findMesh(mjSpec* s, const char* name); MJAPI mjsMesh* mjs_findMesh(mjSpec* s, const char* name);
// Find frame by name.
MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
// Get element id. // Get element id.
MJAPI int mjm_getId(mjElement element); MJAPI int mjs_getId(mjElement* element);
// Copy text to string. // Copy text to string.
MJAPI void mjm_setString(mjString dest, const char* text); MJAPI void mjs_setString(mjString dest, const char* text);
// Split text to entries and copy to string vector. // Split text to entries and copy to string vector.
MJAPI void mjm_setStringVec(mjStringVec dest, const char* text); MJAPI void mjs_setStringVec(mjStringVec dest, const char* text);
// Set entry in string vector. // Set entry in string vector.
MJAPI mjtByte mjm_setInStringVec(mjStringVec dest, int i, const char* text); MJAPI mjtByte mjs_setInStringVec(mjStringVec dest, int i, const char* text);
// Append text entry to string vector. // Append text entry to string vector.
MJAPI void mjm_appendString(mjStringVec dest, const char* text); MJAPI void mjs_appendString(mjStringVec dest, const char* text);
// Copy int array to vector. // Copy int array to vector.
MJAPI void mjm_setInt(mjIntVec dest, const int* array, int size); MJAPI void mjs_setInt(mjIntVec dest, const int* array, int size);
// Append int array to vector of arrays. // Append int array to vector of arrays.
MJAPI void mjm_appendIntVec(mjIntVecVec dest, const int* array, int size); MJAPI void mjs_appendIntVec(mjIntVecVec dest, const int* array, int size);
// Copy float array to vector. // Copy float array to vector.
MJAPI void mjm_setFloat(mjFloatVec dest, const float* array, int size); MJAPI void mjs_setFloat(mjFloatVec dest, const float* array, int size);
// Append float array to vector of arrays. // Append float array to vector of arrays.
MJAPI void mjm_appendFloatVec(mjFloatVecVec dest, const float* array, int size); MJAPI void mjs_appendFloatVec(mjFloatVecVec dest, const float* array, int size);
// Copy double array to vector. // Copy double array to vector.
MJAPI void mjm_setDouble(mjDoubleVec dest, const double* array, int size); MJAPI void mjs_setDouble(mjDoubleVec dest, const double* array, int size);
// Get string contents. // Get string contents.
MJAPI const char* mjm_getString(mjString source); MJAPI const char* mjs_getString(mjString source);
// Get double array contents and optionally its size. // Get double array contents and optionally its size.
MJAPI const double* mjm_getDouble(mjDoubleVec source, int* size); MJAPI const double* mjs_getDouble(mjDoubleVec source, int* size);
// Set plugin attributes. // Set plugin attributes.
MJAPI void mjm_setPluginAttributes(mjmPlugin* plugin, void* attributes); MJAPI void mjs_setPluginAttributes(mjsPlugin* plugin, void* attributes);
// Set active plugins. // Set active plugins.
MJAPI void mjm_setActivePlugins(mjSpec* s, void* activeplugins); MJAPI void mjs_setActivePlugins(mjSpec* s, void* activeplugins);
// Set default. // Set default.
MJAPI void mjm_setDefault(mjElement element, mjmDefault* def); MJAPI void mjs_setDefault(mjElement* element, mjsDefault* def);
// Set frame. // Set frame.
MJAPI void mjm_setFrame(mjElement dest, mjmFrame* frame); MJAPI void mjs_setFrame(mjElement* dest, mjsFrame* frame);
// Resolve alternative orientations to quat.
MJAPI const char* mjs_resolveOrientation(double quat[4], mjtByte degree, const char* sequence,
const mjsOrientation* orientation);
// Compute quat and inertia from body->fullinertia. // Compute quat and inertia from body->fullinertia.
MJAPI const char* mjm_setFullInertia(mjmBody* body, double quat[4], double inertia[3]); MJAPI const char* mjs_setFullInertia(mjsBody* body, double quat[4], double inertia[3]);
//---------------------------------- Initialization functions -------------------------------------- //---------------------------------- Initialization functions --------------------------------------
// Default model attributes. // Default model attributes.
MJAPI void mjm_defaultSpec(mjSpec& model); MJAPI void mjs_defaultSpec(mjSpec& model);
// Default orientation attributes.
MJAPI void mjs_defaultOrientation(mjsOrientation& orient);
// Default body attributes. // Default body attributes.
MJAPI void mjm_defaultBody(mjmBody& body); MJAPI void mjs_defaultBody(mjsBody& body);
// Default frame attributes. // Default frame attributes.
MJAPI void mjm_defaultFrame(mjmFrame& frame); MJAPI void mjs_defaultFrame(mjsFrame& frame);
// Default joint attributes. // Default joint attributes.
MJAPI void mjm_defaultJoint(mjmJoint& joint); MJAPI void mjs_defaultJoint(mjsJoint& joint);
// Default geom attributes. // Default geom attributes.
MJAPI void mjm_defaultGeom(mjmGeom& geom); MJAPI void mjs_defaultGeom(mjsGeom& geom);
// Default site attributes. // Default site attributes.
MJAPI void mjm_defaultSite(mjmSite& site); MJAPI void mjs_defaultSite(mjsSite& site);
// Default camera attributes. // Default camera attributes.
MJAPI void mjm_defaultCamera(mjmCamera& camera); MJAPI void mjs_defaultCamera(mjsCamera& camera);
// Default light attributes. // Default light attributes.
MJAPI void mjm_defaultLight(mjmLight& light); MJAPI void mjs_defaultLight(mjsLight& light);
// Default flex attributes. // Default flex attributes.
MJAPI void mjm_defaultFlex(mjmFlex& flex); MJAPI void mjs_defaultFlex(mjsFlex& flex);
// Default mesh attributes. // Default mesh attributes.
MJAPI void mjm_defaultMesh(mjmMesh& mesh); MJAPI void mjs_defaultMesh(mjsMesh& mesh);
// Default height field attributes. // Default height field attributes.
MJAPI void mjm_defaultHField(mjmHField& hfield); MJAPI void mjs_defaultHField(mjsHField& hfield);
// Default skin attributes. // Default skin attributes.
MJAPI void mjm_defaultSkin(mjmSkin& skin); MJAPI void mjs_defaultSkin(mjsSkin& skin);
// Default texture attributes. // Default texture attributes.
MJAPI void mjm_defaultTexture(mjmTexture& texture); MJAPI void mjs_defaultTexture(mjsTexture& texture);
// Default material attributes. // Default material attributes.
MJAPI void mjm_defaultMaterial(mjmMaterial& material); MJAPI void mjs_defaultMaterial(mjsMaterial& material);
// Default pair attributes. // Default pair attributes.
MJAPI void mjm_defaultPair(mjmPair& pair); MJAPI void mjs_defaultPair(mjsPair& pair);
// Default equality attributes. // Default equality attributes.
MJAPI void mjm_defaultEquality(mjmEquality& equality); MJAPI void mjs_defaultEquality(mjsEquality& equality);
// Default tendon attributes. // Default tendon attributes.
MJAPI void mjm_defaultTendon(mjmTendon& tendon); MJAPI void mjs_defaultTendon(mjsTendon& tendon);
// Default actuator attributes. // Default actuator attributes.
MJAPI void mjm_defaultActuator(mjmActuator& actuator); MJAPI void mjs_defaultActuator(mjsActuator& actuator);
// Default sensor attributes. // Default sensor attributes.
MJAPI void mjm_defaultSensor(mjmSensor& sensor); MJAPI void mjs_defaultSensor(mjsSensor& sensor);
// Default numeric attributes. // Default numeric attributes.
MJAPI void mjm_defaultNumeric(mjmNumeric& numeric); MJAPI void mjs_defaultNumeric(mjsNumeric& numeric);
// Default text attributes. // Default text attributes.
MJAPI void mjm_defaultText(mjmText& text); MJAPI void mjs_defaultText(mjsText& text);
// Default tuple attributes. // Default tuple attributes.
MJAPI void mjm_defaultTuple(mjmTuple& tuple); MJAPI void mjs_defaultTuple(mjsTuple& tuple);
// Default keyframe attributes. // Default keyframe attributes.
MJAPI void mjm_defaultKey(mjmKey& key); MJAPI void mjs_defaultKey(mjsKey& key);
// Default plugin attributes. // Default plugin attributes.
MJAPI void mjm_defaultPlugin(mjmPlugin& plugin); MJAPI void mjs_defaultPlugin(mjsPlugin& plugin);
//------------------------- Cache functions ------------------------------------
typedef struct _mjCache* mjCache;
// Set the size of the cache in bytes.
MJAPI void mj_setCacheSize(mjCache cache, size_t size);
// Get internal global cache context.
MJAPI mjCache mj_globalCache();
#ifdef __cplusplus #ifdef __cplusplus
} }
+2 -1
View File
@@ -39,7 +39,8 @@ template<typename T> std::size_t mjCAsset::Add(const std::string& name,
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data); const uint8_t* ptr = reinterpret_cast<const uint8_t*>(data);
mjCAssetData& block = it->second; mjCAssetData& block = it->second;
block.bytes = std::make_shared<uint8_t[]>(nbytes); block.bytes = std::shared_ptr<uint8_t>(new uint8_t[nbytes],
[](uint8_t *p) {delete [] p;});
std::copy(ptr, ptr + nbytes, block.bytes.get()); std::copy(ptr, ptr + nbytes, block.bytes.get());
block.nbytes = nbytes; block.nbytes = nbytes;
nbytes_ += nbytes; nbytes_ += nbytes;
+18 -17
View File
@@ -30,7 +30,7 @@
// data associated with an asset // data associated with an asset
struct mjCAssetData { struct mjCAssetData {
std::shared_ptr<uint8_t[]> bytes; // raw serialized bytes of cached data std::shared_ptr<uint8_t> bytes; // raw serialized bytes of cached data
std::size_t nbytes; // number of bytes stored std::size_t nbytes; // number of bytes stored
}; };
@@ -80,6 +80,11 @@ class mjCAsset {
return blocks_.find(name) != blocks_.end(); return blocks_.find(name) != blocks_.end();
} }
const std::string& Timestamp() const { return timestamp_; }
const std::string& Id() const { return id_; }
std::size_t InsertNum() const { return insert_num_; }
std::size_t AccessCount() const { return access_count_; }
private: private:
mjCAsset() = default; mjCAsset() = default;
@@ -105,10 +110,6 @@ class mjCAsset {
void SetTimestamp(std::string timestamp) { timestamp_ = timestamp; } void SetTimestamp(std::string timestamp) { timestamp_ = timestamp; }
// accessors // accessors
const std::string& Id() const { return id_; }
const std::string& Timestamp() const { return timestamp_; }
std::size_t InsertNum() const { return insert_num_; }
std::size_t AccessCount() const { return access_count_; }
std::size_t BytesCount() const { return nbytes_; } std::size_t BytesCount() const { return nbytes_; }
const std::unordered_map<std::string, mjCAssetData>& Blocks() const { const std::unordered_map<std::string, mjCAssetData>& Blocks() const {
return blocks_; return blocks_;
@@ -128,14 +129,23 @@ class mjCAsset {
std::set<std::string> references_; std::set<std::string> references_;
}; };
struct mjCAssetCompare {
bool operator()(const mjCAsset* e1, const mjCAsset* e2) const {
if (e1->AccessCount() != e2->AccessCount()) {
return e1->AccessCount() < e2->AccessCount();
}
return e1->InsertNum() < e2->InsertNum();
}
};
// the class container for a thread-safe asset cache // the class container for a thread-safe asset cache
class mjCCache { class mjCCache {
public: public:
explicit mjCCache(std::size_t size) : max_size_(size) {} explicit mjCCache(std::size_t size) : max_size_(size) {}
// move only // move only
mjCCache(mjCCache&& other) = default; mjCCache(mjCCache&& other) = delete;
mjCCache& operator=(mjCCache&& other) = default; mjCCache& operator=(mjCCache&& other) = delete;
mjCCache(const mjCCache& other) = delete; mjCCache(const mjCCache& other) = delete;
mjCCache& operator=(const mjCCache& other) = delete; mjCCache& operator=(const mjCCache& other) = delete;
@@ -186,20 +196,11 @@ class mjCCache {
std::size_t size_ = 0; // current size of the cache in bytes std::size_t size_ = 0; // current size of the cache in bytes
std::size_t max_size_ = 0; // max size of the cache in bytes std::size_t max_size_ = 0; // max size of the cache in bytes
// compare function for the priority queue
static constexpr auto compare_ = [](const mjCAsset* e1,
const mjCAsset* e2) {
if (e1->AccessCount() != e2->AccessCount()) {
return e1->AccessCount() < e2->AccessCount();
}
return e1->InsertNum() < e2->InsertNum();
};
// internal constant look up table for assets // internal constant look up table for assets
std::unordered_map<std::string, mjCAsset> lookup_; std::unordered_map<std::string, mjCAsset> lookup_;
// internal priority queue for the cache // internal priority queue for the cache
std::set<mjCAsset*, decltype(compare_)> entries_; std::set<mjCAsset*, mjCAssetCompare> entries_;
// models using the cache along with the assets they reference // models using the cache along with the assets they reference
std::unordered_map<std::string, std::unordered_set<mjCAsset*>> models_; std::unordered_map<std::string, std::unordered_set<mjCAsset*>> models_;
+155 -155
View File
@@ -66,7 +66,7 @@ mjCComposite::mjCComposite(void) {
mj_defaultSolRefImp(solrefsmooth, solimpsmooth); mj_defaultSolRefImp(solrefsmooth, solimpsmooth);
// plugin variables // plugin variables
mjm_defaultPlugin(plugin); mjs_defaultPlugin(plugin);
plugin_name = ""; plugin_name = "";
plugin_instance_name = ""; plugin_instance_name = "";
plugin.name = (mjString)&plugin_name; plugin.name = (mjString)&plugin_name;
@@ -223,7 +223,7 @@ void mjCComposite::SetDefault(void) {
// make composite object // make composite object
bool mjCComposite::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) { bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
mjCModel* model = (mjCModel*)spec->element; mjCModel* model = (mjCModel*)spec->element;
// check geom type // check geom type
@@ -306,7 +306,7 @@ bool mjCComposite::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz)
// overwrite plugin name // overwrite plugin name
if (plugin_instance_name.empty() && plugin.active) { if (plugin_instance_name.empty() && plugin.active) {
plugin_instance_name = "composite" + prefix; plugin_instance_name = "composite" + prefix;
((mjCPlugin*)plugin.instance)->name = plugin_instance_name; (static_cast<mjCPlugin*>(plugin.instance))->name = plugin_instance_name;
} }
// dispatch // dispatch
@@ -350,7 +350,7 @@ bool mjCComposite::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz)
bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int error_sz) { bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int error_sz) {
char txt[100]; char txt[100];
std::vector<int> face; std::vector<int> face;
@@ -432,7 +432,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
mjtNum t = 1; mjtNum t = 1;
if (dim == 2 && plugin.active) { if (dim == 2 && plugin.active) {
try { try {
mjCPlugin* pplugin = (mjCPlugin*)plugin.instance; mjCPlugin* pplugin = static_cast<mjCPlugin*>(plugin.instance);
t = std::stod(pplugin->config_attribs["thickness"], nullptr); t = std::stod(pplugin->config_attribs["thickness"], nullptr);
} catch (const std::invalid_argument& e) { } catch (const std::invalid_argument& e) {
return comperr(error, "Invalid thickness attribute", error_sz); return comperr(error, "Invalid thickness attribute", error_sz);
@@ -464,13 +464,13 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
// create bodies and geoms // create bodies and geoms
for (int i=0; i<uservert.size()/3; i++) { for (int i=0; i<uservert.size()/3; i++) {
// create body // create body
mjmBody* b = mjm_addBody(body, NULL); mjsBody* b = mjs_addBody(body, NULL);
if (!username.empty()) { if (!username.empty()) {
mjm_setString(b->name, username[i].c_str()); mjs_setString(b->name, username[i].c_str());
} else { } else {
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i); mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
mjm_setString(b->name, txt); mjs_setString(b->name, txt);
} }
// set body position // set body position
@@ -481,8 +481,8 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
// add slider joints if none defined // add slider joints if none defined
if (!add[mjCOMPKIND_PARTICLE]) { if (!add[mjCOMPKIND_PARTICLE]) {
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
mjmJoint* jnt = mjm_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec); mjsJoint* jnt = mjs_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
jnt->type = mjJNT_SLIDE; jnt->type = mjJNT_SLIDE;
mjuu_setvec(jnt->pos, 0, 0, 0); mjuu_setvec(jnt->pos, 0, 0, 0);
mjuu_setvec(jnt->axis, 0, 0, 0); mjuu_setvec(jnt->axis, 0, 0, 0);
@@ -493,30 +493,30 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
// add user-specified joints // add user-specified joints
else { else {
for (auto defjnt : defjoint[mjCOMPKIND_PARTICLE]) { for (auto defjnt : defjoint[mjCOMPKIND_PARTICLE]) {
mjmJoint* jnt = mjm_addJoint(b, &defjnt.spec); mjsJoint* jnt = mjs_addJoint(b, &defjnt.spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
} }
} }
// add geom // add geom
mjmGeom* g = mjm_addGeom(b, &def[0].spec); mjsGeom* g = mjs_addGeom(b, &def[0].spec);
mjm_setDefault(g->element, mjm_getDefault(body->element)); mjs_setDefault(g->element, mjs_getDefault(body->element));
// add site // add site
mjmSite* s = mjm_addSite(b, &def[0].spec); mjsSite* s = mjs_addSite(b, &def[0].spec);
mjm_setDefault(s->element, mjm_getDefault(body->element)); mjs_setDefault(s->element, mjs_getDefault(body->element));
s->type = mjGEOM_SPHERE; s->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sS%d", prefix.c_str(), i); mju::sprintf_arr(txt, "%sS%d", prefix.c_str(), i);
mjm_setString(s->name, txt); mjs_setString(s->name, txt);
// add plugin // add plugin
if (plugin.active) { if (plugin.active) {
mjmPlugin* pplugin = &b->plugin; mjsPlugin* pplugin = &b->plugin;
mjCPlugin* cplugin = (mjCPlugin*)plugin.instance; mjCPlugin* cplugin = static_cast<mjCPlugin*>(plugin.instance);
pplugin->active = true; pplugin->active = true;
pplugin->instance = (mjElement)plugin.instance; pplugin->instance = plugin.instance;
mjm_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
mjm_setString(pplugin->name, mjm_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
if (i==0 && !cplugin->config_attribs["face"].empty()) { if (i==0 && !cplugin->config_attribs["face"].empty()) {
return comperr(error, "Face attribute already exists in plugin", error_sz); return comperr(error, "Face attribute already exists in plugin", error_sz);
@@ -560,18 +560,18 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
mju::sprintf_arr(txt2, "%sS%d", prefix.c_str(), v1); mju::sprintf_arr(txt2, "%sS%d", prefix.c_str(), v1);
// create tendon // create tendon
mjmTendon* ten = mjm_addTendon(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjsTendon* ten = mjs_addTendon(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjm_setDefault(ten->element, &model->defaults[0]->spec); mjs_setDefault(ten->element, &model->defaults[0]->spec);
mjm_setString(ten->name, txt0); mjs_setString(ten->name, txt0);
ten->group = 4; ten->group = 4;
mjm_wrapSite(ten, txt1); mjs_wrapSite(ten, txt1);
mjm_wrapSite(ten, txt2); mjs_wrapSite(ten, txt2);
// add equality constraint // add equality constraint
mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjm_setDefault(eq->element, &model->defaults[0]->spec); mjs_setDefault(eq->element, &model->defaults[0]->spec);
eq->type = mjEQ_TENDON; eq->type = mjEQ_TENDON;
mjm_setString(eq->name1, mjm_getString(ten->name)); mjs_setString(eq->name1, mjs_getString(ten->name));
} }
} }
@@ -593,7 +593,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
// make grid connected with tendons // make grid connected with tendons
bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int error_sz) { bool mjCComposite::MakeGrid(mjCModel* model, mjsBody* body, char* error, int error_sz) {
char txt[100], txt1[100], txt2[100]; char txt[100], txt1[100], txt2[100];
// check dimensionality // check dimensionality
@@ -615,9 +615,9 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
for (int ix=0; ix<count[0]; ix++) { for (int ix=0; ix<count[0]; ix++) {
for (int iy=0; iy<count[1]; iy++) { for (int iy=0; iy<count[1]; iy++) {
// create body // create body
mjmBody* b = mjm_addBody(body, NULL); mjsBody* b = mjs_addBody(body, NULL);
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy); mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
mjm_setString(b->name, txt); mjs_setString(b->name, txt);
// set body position // set body position
b->pos[0] = offset[0] + spacing*(ix - 0.5*count[0]); b->pos[0] = offset[0] + spacing*(ix - 0.5*count[0]);
@@ -625,18 +625,18 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
b->pos[2] = offset[2]; b->pos[2] = offset[2];
// add geom // add geom
mjmGeom* g = mjm_addGeom(b, &def[0].spec); mjsGeom* g = mjs_addGeom(b, &def[0].spec);
mjm_setDefault(g->element, mjm_getDefault(body->element)); mjs_setDefault(g->element, mjs_getDefault(body->element));
g->type = mjGEOM_SPHERE; g->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sG%d_%d", prefix.c_str(), ix, iy); mju::sprintf_arr(txt, "%sG%d_%d", prefix.c_str(), ix, iy);
mjm_setString(g->name, txt); mjs_setString(g->name, txt);
// add site // add site
mjmSite* s = mjm_addSite(b, &def[0].spec); mjsSite* s = mjs_addSite(b, &def[0].spec);
mjm_setDefault(s->element, mjm_getDefault(body->element)); mjs_setDefault(s->element, mjs_getDefault(body->element));
s->type = mjGEOM_SPHERE; s->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sS%d_%d", prefix.c_str(), ix, iy); mju::sprintf_arr(txt, "%sS%d_%d", prefix.c_str(), ix, iy);
mjm_setString(s->name, txt); mjs_setString(s->name, txt);
// skip pinned elements // skip pinned elements
bool skip = false; bool skip = false;
@@ -651,12 +651,12 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
} }
// add slider joint // add slider joint
mjmJoint* jnt[3]; mjsJoint* jnt[3];
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
jnt[i] = mjm_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec); jnt[i] = mjs_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec);
mjm_setDefault(jnt[i]->element, mjm_getDefault(body->element)); mjs_setDefault(jnt[i]->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sJ%d_%d_%d", prefix.c_str(), i, ix, iy); mju::sprintf_arr(txt, "%sJ%d_%d_%d", prefix.c_str(), i, ix, iy);
mjm_setString(jnt[i]->name, txt); mjs_setString(jnt[i]->name, txt);
jnt[i]->type = mjJNT_SLIDE; jnt[i]->type = mjJNT_SLIDE;
mjuu_setvec(jnt[i]->pos, 0, 0, 0); mjuu_setvec(jnt[i]->pos, 0, 0, 0);
mjuu_setvec(jnt[i]->axis, 0, 0, 0); mjuu_setvec(jnt[i]->axis, 0, 0, 0);
@@ -682,10 +682,10 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
ten->WrapSite(txt2); ten->WrapSite(txt2);
// add equality constraint // add equality constraint
mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjm_setDefault(eq->element, &model->defaults[0]->spec); mjs_setDefault(eq->element, &model->defaults[0]->spec);
eq->type = mjEQ_TENDON; eq->type = mjEQ_TENDON;
mjm_setString(eq->name1, ten->name.c_str()); mjs_setString(eq->name1, ten->name.c_str());
} }
} }
} }
@@ -709,7 +709,7 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
bool mjCComposite::MakeCable(mjCModel* model, mjmBody* body, char* error, int error_sz) { bool mjCComposite::MakeCable(mjCModel* model, mjsBody* body, char* error, int error_sz) {
// check dim // check dim
if (dim!=1) { if (dim!=1) {
return comperr(error, "Cable must be one-dimensional", error_sz); return comperr(error, "Cable must be one-dimensional", error_sz);
@@ -723,9 +723,9 @@ bool mjCComposite::MakeCable(mjCModel* model, mjmBody* body, char* error, int er
} }
// add name to model // add name to model
mjmText* pte = mjm_addText(&model->spec); mjsText* pte = mjs_addText(&model->spec);
mjm_setString(pte->name, ("composite_" + prefix).c_str()); mjs_setString(pte->name, ("composite_" + prefix).c_str());
mjm_setString(pte->data, ("rope_" + prefix).c_str()); mjs_setString(pte->data, ("rope_" + prefix).c_str());
// populate uservert if not specified // populate uservert if not specified
if (uservert.empty()) { if (uservert.empty()) {
@@ -780,7 +780,7 @@ bool mjCComposite::MakeCable(mjCModel* model, mjmBody* body, char* error, int er
mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]) { mjsBody* mjCComposite::AddCableBody(mjCModel* model, mjsBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]) {
char txt_geom[100], txt_site[100], txt_slide[100]; char txt_geom[100], txt_site[100], txt_slide[100];
char this_body[100], next_body[100], this_joint[100]; char this_body[100], next_body[100], this_joint[100];
mjtNum dquat[4], this_quat[4]; mjtNum dquat[4], this_quat[4];
@@ -836,8 +836,8 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN
mju::sprintf_arr(txt_slide, "%sJs%d", prefix.c_str(), ix); mju::sprintf_arr(txt_slide, "%sJs%d", prefix.c_str(), ix);
// add body // add body
body = mjm_addBody(body, 0); body = mjs_addBody(body, 0);
mjm_setString(body->name, this_body); mjs_setString(body->name, this_body);
if (first) { if (first) {
mjuu_setvec(body->pos, offset[0]+uservert[3*ix], mjuu_setvec(body->pos, offset[0]+uservert[3*ix],
offset[1]+uservert[3*ix+1], offset[1]+uservert[3*ix+1],
@@ -851,9 +851,9 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN
} }
// add geom // add geom
mjmGeom* geom = mjm_addGeom(body, &def[0].spec); mjsGeom* geom = mjs_addGeom(body, &def[0].spec);
mjm_setDefault(geom->element, mjm_getDefault(body->element)); mjs_setDefault(geom->element, mjs_getDefault(body->element));
mjm_setString(geom->name, txt_geom); mjs_setString(geom->name, txt_geom);
if (def[0].spec.geom->type==mjGEOM_CYLINDER || if (def[0].spec.geom->type==mjGEOM_CYLINDER ||
def[0].spec.geom->type==mjGEOM_CAPSULE) { def[0].spec.geom->type==mjGEOM_CAPSULE) {
mjuu_zerovec(geom->fromto, 6); mjuu_zerovec(geom->fromto, 6);
@@ -866,11 +866,11 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN
// add plugin // add plugin
if (plugin.active) { if (plugin.active) {
mjmPlugin* pplugin = &body->plugin; mjsPlugin* pplugin = &body->plugin;
pplugin->active = true; pplugin->active = true;
pplugin->instance = (mjElement)plugin.instance; pplugin->instance = plugin.instance;
mjm_setString(pplugin->name, mjm_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
mjm_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
} }
// update orientation // update orientation
@@ -878,27 +878,27 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN
// add curvature joint // add curvature joint
if (!first || strcmp(initial.c_str(), "none")) { if (!first || strcmp(initial.c_str(), "none")) {
mjmJoint* jnt = mjm_addJoint(body, &defjoint[mjCOMPKIND_JOINT][0].spec); mjsJoint* jnt = mjs_addJoint(body, &defjoint[mjCOMPKIND_JOINT][0].spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
jnt->type = (first && strcmp(initial.c_str(), "free")==0) ? mjJNT_FREE : mjJNT_BALL; jnt->type = (first && strcmp(initial.c_str(), "free")==0) ? mjJNT_FREE : mjJNT_BALL;
jnt->damping = jnt->type==mjJNT_FREE ? 0 : jnt->damping; jnt->damping = jnt->type==mjJNT_FREE ? 0 : jnt->damping;
jnt->armature = jnt->type==mjJNT_FREE ? 0 : jnt->armature; jnt->armature = jnt->type==mjJNT_FREE ? 0 : jnt->armature;
jnt->frictionloss = jnt->type==mjJNT_FREE ? 0 : jnt->frictionloss; jnt->frictionloss = jnt->type==mjJNT_FREE ? 0 : jnt->frictionloss;
mjm_setString(jnt->name, this_joint); mjs_setString(jnt->name, this_joint);
} }
// exclude contact pair // exclude contact pair
if (!last) { if (!last) {
mjmExclude* exclude = mjm_addExclude(&model->spec); mjsExclude* exclude = mjs_addExclude(&model->spec);
mjm_setString(exclude->bodyname1, std::string(this_body).c_str()); mjs_setString(exclude->bodyname1, std::string(this_body).c_str());
mjm_setString(exclude->bodyname2, std::string(next_body).c_str()); mjs_setString(exclude->bodyname2, std::string(next_body).c_str());
} }
// add site at the boundary // add site at the boundary
if (last || first) { if (last || first) {
mjmSite* site = mjm_addSite(body, &def[0].spec); mjsSite* site = mjs_addSite(body, &def[0].spec);
mjm_setDefault(site->element, mjm_getDefault(body->element)); mjs_setDefault(site->element, mjs_getDefault(body->element));
mjm_setString(site->name, txt_site); mjs_setString(site->name, txt_site);
mjuu_setvec(site->pos, last ? length : 0, 0, 0); mjuu_setvec(site->pos, last ? length : 0, 0, 0);
mjuu_setvec(site->quat, 1, 0, 0, 0); mjuu_setvec(site->quat, 1, 0, 0, 0);
} }
@@ -908,7 +908,7 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN
// make rope // make rope
bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int error_sz) { bool mjCComposite::MakeRope(mjCModel* model, mjsBody* body, char* error, int error_sz) {
// check dim // check dim
if (dim!=1) { if (dim!=1) {
return comperr(error, "Rope must be one-dimensional", error_sz); return comperr(error, "Rope must be one-dimensional", error_sz);
@@ -917,7 +917,7 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err
// check root body name prefix // check root body name prefix
char txt[200]; char txt[200];
mju::sprintf_arr(txt, "%sB", prefix.c_str()); mju::sprintf_arr(txt, "%sB", prefix.c_str());
std::string body_name = mjm_getString(body->name); std::string body_name = mjs_getString(body->name);
if (std::strncmp(txt, body_name.substr(0, strlen(txt)).c_str(), mju::sizeof_arr(txt))) { if (std::strncmp(txt, body_name.substr(0, strlen(txt)).c_str(), mju::sizeof_arr(txt))) {
mju::strcat_arr(txt, " must be the beginning of root body name"); mju::strcat_arr(txt, " must be the beginning of root body name");
return comperr(error, txt, error_sz); return comperr(error, txt, error_sz);
@@ -937,7 +937,7 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err
AddRopeBody(model, body, ox, ox); AddRopeBody(model, body, ox, ox);
// add elements: right // add elements: right
mjmBody* pbody = body; mjsBody* pbody = body;
for (int ix=ox; ix<count[0]-1; ix++) { for (int ix=ox; ix<count[0]-1; ix++) {
pbody = AddRopeBody(model, pbody, ix, ix+1); pbody = AddRopeBody(model, pbody, ix, ix+1);
} }
@@ -953,20 +953,20 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err
char txt2[200]; char txt2[200];
// add equality constraint // add equality constraint
mjmEquality* eq = mjm_addEquality(&model->spec, 0); mjsEquality* eq = mjs_addEquality(&model->spec, 0);
eq->type = mjEQ_CONNECT; eq->type = mjEQ_CONNECT;
mju::sprintf_arr(txt, "%sB0", prefix.c_str()); mju::sprintf_arr(txt, "%sB0", prefix.c_str());
mju::sprintf_arr(txt2, "%sB%d", prefix.c_str(), count[0]-1); mju::sprintf_arr(txt2, "%sB%d", prefix.c_str(), count[0]-1);
mjm_setString(eq->name1, txt); mjs_setString(eq->name1, txt);
mjm_setString(eq->name2, txt2); mjs_setString(eq->name2, txt2);
mjuu_setvec(eq->data, -0.5*spacing, 0, 0); mjuu_setvec(eq->data, -0.5*spacing, 0, 0);
mju_copy(eq->solref, solrefsmooth, mjNREF); mju_copy(eq->solref, solrefsmooth, mjNREF);
mju_copy(eq->solimp, solimpsmooth, mjNIMP); mju_copy(eq->solimp, solimpsmooth, mjNIMP);
// remove contact between connected bodies // remove contact between connected bodies
mjmExclude* pair = mjm_addExclude(&model->spec); mjsExclude* pair = mjs_addExclude(&model->spec);
mjm_setString(pair->bodyname1, std::string(txt).c_str()); mjs_setString(pair->bodyname1, std::string(txt).c_str());
mjm_setString(pair->bodyname2, std::string(txt2).c_str()); mjs_setString(pair->bodyname2, std::string(txt2).c_str());
} }
return true; return true;
@@ -975,16 +975,16 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err
// add child body for cloth // add child body for cloth
mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int ix1) { mjsBody* mjCComposite::AddRopeBody(mjCModel* model, mjsBody* body, int ix, int ix1) {
char txt[100]; char txt[100];
bool isroot = (ix==ix1); bool isroot = (ix==ix1);
double dx = spacing*(ix1-ix); double dx = spacing*(ix1-ix);
// add child if not root // add child if not root
if (!isroot) { if (!isroot) {
body = mjm_addBody(body, 0); body = mjs_addBody(body, 0);
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), ix1); mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), ix1);
mjm_setString(body->name, txt); mjs_setString(body->name, txt);
// loop // loop
if (type==mjCOMPTYPE_LOOP) { if (type==mjCOMPTYPE_LOOP) {
@@ -1007,10 +1007,10 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i
} }
// add geom // add geom
mjmGeom* geom = mjm_addGeom(body, &def[0].spec); mjsGeom* geom = mjs_addGeom(body, &def[0].spec);
mjm_setDefault(geom->element, mjm_getDefault(body->element)); mjs_setDefault(geom->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sG%d", prefix.c_str(), ix1); mju::sprintf_arr(txt, "%sG%d", prefix.c_str(), ix1);
mjm_setString(geom->name, txt); mjs_setString(geom->name, txt);
mjuu_setvec(geom->pos, 0, 0, 0); mjuu_setvec(geom->pos, 0, 0, 0);
mjuu_setvec(geom->quat, sqrt(0.5), 0, sqrt(0.5), 0); mjuu_setvec(geom->quat, sqrt(0.5), 0, sqrt(0.5), 0);
@@ -1022,10 +1022,10 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i
// add main joint // add main joint
for (int i=0; i<2; i++) { for (int i=0; i<2; i++) {
// add joint // add joint
mjmJoint* jnt = mjm_addJoint(body, &defjoint[mjCOMPKIND_JOINT][0].spec); mjsJoint* jnt = mjs_addJoint(body, &defjoint[mjCOMPKIND_JOINT][0].spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sJ%d_%d", prefix.c_str(), i, ix1); mju::sprintf_arr(txt, "%sJ%d_%d", prefix.c_str(), i, ix1);
mjm_setString(jnt->name, txt); mjs_setString(jnt->name, txt);
jnt->type = mjJNT_HINGE; jnt->type = mjJNT_HINGE;
mjuu_setvec(jnt->pos, -0.5*dx, 0, 0); mjuu_setvec(jnt->pos, -0.5*dx, 0, 0);
mjuu_setvec(jnt->axis, 0, 0, 0); mjuu_setvec(jnt->axis, 0, 0, 0);
@@ -1035,37 +1035,37 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i
// add twist joint // add twist joint
if (add[mjCOMPKIND_TWIST]) { if (add[mjCOMPKIND_TWIST]) {
// add joint // add joint
mjmJoint* jnt = mjm_addJoint(body, &defjoint[mjCOMPKIND_TWIST][0].spec); mjsJoint* jnt = mjs_addJoint(body, &defjoint[mjCOMPKIND_TWIST][0].spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sJT%d", prefix.c_str(), ix1); mju::sprintf_arr(txt, "%sJT%d", prefix.c_str(), ix1);
mjm_setString(jnt->name, txt); mjs_setString(jnt->name, txt);
jnt->type = mjJNT_HINGE; jnt->type = mjJNT_HINGE;
mjuu_setvec(jnt->pos, -0.5*dx, 0, 0); mjuu_setvec(jnt->pos, -0.5*dx, 0, 0);
mjuu_setvec(jnt->axis, 1, 0, 0); mjuu_setvec(jnt->axis, 1, 0, 0);
// add constraint // add constraint
mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TWIST].spec); mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_TWIST].spec);
mjm_setDefault(eq->element, &model->defaults[0]->spec); mjs_setDefault(eq->element, &model->defaults[0]->spec);
eq->type = mjEQ_JOINT; eq->type = mjEQ_JOINT;
mjm_setString(eq->name1, mjm_getString(jnt->name)); mjs_setString(eq->name1, mjs_getString(jnt->name));
} }
// add stretch joint // add stretch joint
if (add[mjCOMPKIND_STRETCH]) { if (add[mjCOMPKIND_STRETCH]) {
// add joint // add joint
mjmJoint* jnt = mjm_addJoint(body, &defjoint[mjCOMPKIND_STRETCH][0].spec); mjsJoint* jnt = mjs_addJoint(body, &defjoint[mjCOMPKIND_STRETCH][0].spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sJS%d", prefix.c_str(), ix1); mju::sprintf_arr(txt, "%sJS%d", prefix.c_str(), ix1);
mjm_setString(jnt->name, txt); mjs_setString(jnt->name, txt);
jnt->type = mjJNT_SLIDE; jnt->type = mjJNT_SLIDE;
mjuu_setvec(jnt->pos, -0.5*dx, 0, 0); mjuu_setvec(jnt->pos, -0.5*dx, 0, 0);
mjuu_setvec(jnt->axis, 1, 0, 0); mjuu_setvec(jnt->axis, 1, 0, 0);
// add constraint // add constraint
mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_STRETCH].spec); mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_STRETCH].spec);
mjm_setDefault(eq->element, &model->defaults[0]->spec); mjs_setDefault(eq->element, &model->defaults[0]->spec);
eq->type = mjEQ_JOINT; eq->type = mjEQ_JOINT;
mjm_setString(eq->name1, mjm_getString(jnt->name)); mjs_setString(eq->name1, mjs_getString(jnt->name));
} }
return body; return body;
@@ -1110,7 +1110,7 @@ void mjCComposite::BoxProject(double* pos) {
// make 3d box, ellipsoid or cylinder // make 3d box, ellipsoid or cylinder
bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int error_sz) { bool mjCComposite::MakeBox(mjCModel* model, mjsBody* body, char* error, int error_sz) {
char txt[100]; char txt[100];
// check dim // check dim
@@ -1119,11 +1119,11 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
} }
// center geom: two times bigger // center geom: two times bigger
mjmGeom* geom = mjm_addGeom(body, &def[0].spec); mjsGeom* geom = mjs_addGeom(body, &def[0].spec);
mjm_setDefault(geom->element, mjm_getDefault(body->element)); mjs_setDefault(geom->element, mjs_getDefault(body->element));
geom->type = mjGEOM_SPHERE; geom->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sGcenter", prefix.c_str()); mju::sprintf_arr(txt, "%sGcenter", prefix.c_str());
mjm_setString(geom->name, txt); mjs_setString(geom->name, txt);
mjuu_setvec(geom->pos, 0, 0, 0); mjuu_setvec(geom->pos, 0, 0, 0);
geom->size[0] *= 2; geom->size[0] *= 2;
geom->size[1] = 0; geom->size[1] = 0;
@@ -1143,9 +1143,9 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
iy==0 || iy==count[1]-1 || iy==0 || iy==count[1]-1 ||
iz==0 || iz==count[2]-1) { iz==0 || iz==count[2]-1) {
// create body // create body
mjmBody* b = mjm_addBody(body, NULL); mjsBody* b = mjs_addBody(body, NULL);
mju::sprintf_arr(txt, "%sB%d_%d_%d", prefix.c_str(), ix, iy, iz); mju::sprintf_arr(txt, "%sB%d_%d_%d", prefix.c_str(), ix, iy, iz);
mjm_setString(b->name, txt); mjs_setString(b->name, txt);
// set body position (+/- 1) // set body position (+/- 1)
b->pos[0] = 2.0*ix/(count[0]-1) - 1; b->pos[0] = 2.0*ix/(count[0]-1) - 1;
@@ -1160,10 +1160,10 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
mjuu_normvec(b->alt.zaxis, 3); mjuu_normvec(b->alt.zaxis, 3);
// add geom // add geom
mjmGeom* g = mjm_addGeom(b, &def[0].spec); mjsGeom* g = mjs_addGeom(b, &def[0].spec);
mjm_setDefault(g->element, mjm_getDefault(body->element)); mjs_setDefault(g->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sG%d_%d_%d", prefix.c_str(), ix, iy, iz); mju::sprintf_arr(txt, "%sG%d_%d_%d", prefix.c_str(), ix, iy, iz);
mjm_setString(g->name, txt); mjs_setString(g->name, txt);
// offset inwards, enforce sphere or capsule // offset inwards, enforce sphere or capsule
if (g->type==mjGEOM_CAPSULE) { if (g->type==mjGEOM_CAPSULE) {
@@ -1174,22 +1174,22 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
} }
// add slider joint // add slider joint
mjmJoint* jnt = mjm_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec); mjsJoint* jnt = mjs_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec);
mjm_setDefault(jnt->element, mjm_getDefault(body->element)); mjs_setDefault(jnt->element, mjs_getDefault(body->element));
mju::sprintf_arr(txt, "%sJ%d_%d_%d", prefix.c_str(), ix, iy, iz); mju::sprintf_arr(txt, "%sJ%d_%d_%d", prefix.c_str(), ix, iy, iz);
mjm_setString(jnt->name, txt); mjs_setString(jnt->name, txt);
jnt->type = mjJNT_SLIDE; jnt->type = mjJNT_SLIDE;
mjuu_setvec(jnt->pos, 0, 0, 0); mjuu_setvec(jnt->pos, 0, 0, 0);
mjuu_setvec(jnt->axis, 0, 0, 1); mjuu_setvec(jnt->axis, 0, 0, 1);
// add fix constraint // add fix constraint
mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_JOINT].spec); mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_JOINT].spec);
mjm_setDefault(eq->element, &model->defaults[0]->spec); mjs_setDefault(eq->element, &model->defaults[0]->spec);
eq->type = mjEQ_JOINT; eq->type = mjEQ_JOINT;
mjm_setString(eq->name1, mjm_getString(jnt->name)); mjs_setString(eq->name1, mjs_getString(jnt->name));
// add joint to tendon // add joint to tendon
ten->WrapJoint(std::string(mjm_getString(jnt->name)), 1); ten->WrapJoint(std::string(mjs_getString(jnt->name)), 1);
// add neighbor constraints // add neighbor constraints
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
@@ -1203,12 +1203,12 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
char txt2[200]; char txt2[200];
mju::sprintf_arr(txt2, mju::sprintf_arr(txt2,
"%sJ%d_%d_%d", prefix.c_str(), ix1, iy1, iz1); "%sJ%d_%d_%d", prefix.c_str(), ix1, iy1, iz1);
mjmEquality* eqn = mjm_addEquality(&model->spec, 0); mjsEquality* eqn = mjs_addEquality(&model->spec, 0);
mju_copy(eqn->solref, solrefsmooth, mjNREF); mju_copy(eqn->solref, solrefsmooth, mjNREF);
mju_copy(eqn->solimp, solimpsmooth, mjNIMP); mju_copy(eqn->solimp, solimpsmooth, mjNIMP);
eqn->type = mjEQ_JOINT; eqn->type = mjEQ_JOINT;
mjm_setString(eqn->name1, txt); mjs_setString(eqn->name1, txt);
mjm_setString(eqn->name2, txt2); mjs_setString(eqn->name2, txt2);
} }
} }
} }
@@ -1217,10 +1217,10 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
} }
// finalize fixed tendon // finalize fixed tendon
mjmEquality* eqt = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjsEquality* eqt = mjs_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjm_setDefault(eqt->element, &model->defaults[0]->spec); mjs_setDefault(eqt->element, &model->defaults[0]->spec);
eqt->type = mjEQ_TENDON; eqt->type = mjEQ_TENDON;
mjm_setString(eqt->name1, ten->name.c_str()); mjs_setString(eqt->name1, ten->name.c_str());
// skin // skin
if (skin) { if (skin) {
@@ -1253,10 +1253,10 @@ void mjCComposite::MakeShear(mjCModel* model) {
ten->name = txt; ten->name = txt;
// equality constraint // equality constraint
mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_SHEAR].spec); mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_SHEAR].spec);
mjm_setDefault(eq->element, &model->defaults[0]->spec); mjs_setDefault(eq->element, &model->defaults[0]->spec);
eq->type = mjEQ_TENDON; eq->type = mjEQ_TENDON;
mjm_setString(eq->name1, txt); mjs_setString(eq->name1, txt);
} }
} }
} }
@@ -1264,18 +1264,18 @@ void mjCComposite::MakeShear(mjCModel* model) {
// copy local vectors to skin // copy local vectors to skin
void mjCComposite::CopyIntoSkin(mjmSkin* skin) { void mjCComposite::CopyIntoSkin(mjsSkin* skin) {
mjm_setInt(skin->face, face.data(), face.size()); mjs_setInt(skin->face, face.data(), face.size());
mjm_setFloat(skin->vert, vert.data(), vert.size()); mjs_setFloat(skin->vert, vert.data(), vert.size());
mjm_setFloat(skin->bindpos, bindpos.data(), bindpos.size()); mjs_setFloat(skin->bindpos, bindpos.data(), bindpos.size());
mjm_setFloat(skin->bindquat, bindquat.data(), bindquat.size()); mjs_setFloat(skin->bindquat, bindquat.data(), bindquat.size());
mjm_setFloat(skin->texcoord, texcoord.data(), texcoord.size()); mjs_setFloat(skin->texcoord, texcoord.data(), texcoord.size());
for (int i=0; i<vertid.size(); i++) { for (int i=0; i<vertid.size(); i++) {
mjm_appendIntVec(skin->vertid, vertid[i].data(), vertid[i].size()); mjs_appendIntVec(skin->vertid, vertid[i].data(), vertid[i].size());
} }
for (int i=0; i< vertweight.size(); i++) { for (int i=0; i< vertweight.size(); i++) {
mjm_appendFloatVec(skin->vertweight, vertweight[i].data(), vertweight[i].size()); mjs_appendFloatVec(skin->vertweight, vertweight[i].data(), vertweight[i].size());
} }
face.clear(); face.clear();
@@ -1295,10 +1295,10 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
int N = count[0]*count[1]; int N = count[0]*count[1];
// add skin, set name and material // add skin, set name and material
mjmSkin* skin = mjm_addSkin(&model->spec); mjsSkin* skin = mjs_addSkin(&model->spec);
mju::sprintf_arr(txt, "%sSkin", prefix.c_str()); mju::sprintf_arr(txt, "%sSkin", prefix.c_str());
mjm_setString(skin->name, txt); mjs_setString(skin->name, txt);
mjm_setString(skin->material, skinmaterial.c_str()); mjs_setString(skin->material, skinmaterial.c_str());
mjuu_copyvec(skin->rgba, skinrgba, 4); mjuu_copyvec(skin->rgba, skinrgba, 4);
skin->inflate = inflate; skin->inflate = inflate;
skin->group = skingroup; skin->group = skingroup;
@@ -1316,7 +1316,7 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
vert.push_back(0); vert.push_back(0);
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i); mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
mjm_appendString(skin->bodyname, txt); mjs_appendString(skin->bodyname, txt);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
@@ -1426,7 +1426,7 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
// add bones in 2D // add bones in 2D
void mjCComposite::MakeClothBones(mjCModel* model, mjmSkin* skin) { void mjCComposite::MakeClothBones(mjCModel* model, mjsSkin* skin) {
char txt[100]; char txt[100];
int N = count[0]*count[1]; int N = count[0]*count[1];
@@ -1441,7 +1441,7 @@ void mjCComposite::MakeClothBones(mjCModel* model, mjmSkin* skin) {
} }
// bind pose // bind pose
mjm_appendString(skin->bodyname, txt); mjs_appendString(skin->bodyname, txt);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
@@ -1459,7 +1459,7 @@ void mjCComposite::MakeClothBones(mjCModel* model, mjmSkin* skin) {
void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjmSkin* skin) { void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjsSkin* skin) {
char txt[100]; char txt[100];
// populate bones // populate bones
@@ -1473,7 +1473,7 @@ void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjmSkin* skin) {
} }
// bind pose // bind pose
mjm_appendString(skin->bodyname, txt); mjs_appendString(skin->bodyname, txt);
bindpos.push_back(ix*spacing); bindpos.push_back(ix*spacing);
bindpos.push_back(iy*spacing); bindpos.push_back(iy*spacing);
bindpos.push_back(0); bindpos.push_back(0);
@@ -1492,7 +1492,7 @@ void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjmSkin* skin) {
// add bones to 1D // add bones to 1D
void mjCComposite::MakeCableBones(mjCModel* model, mjmSkin* skin) { void mjCComposite::MakeCableBones(mjCModel* model, mjsSkin* skin) {
char this_body[100]; char this_body[100];
int N = count[0]*count[1]; int N = count[0]*count[1];
@@ -1510,14 +1510,14 @@ void mjCComposite::MakeCableBones(mjCModel* model, mjmSkin* skin) {
// bind pose // bind pose
if (iy==0) { if (iy==0) {
mjm_appendString(skin->bodyname, this_body); mjs_appendString(skin->bodyname, this_body);
bindpos.push_back((ix==count[0]-1) ? -2*def[0].spec.geom->size[0] : 0); bindpos.push_back((ix==count[0]-1) ? -2*def[0].spec.geom->size[0] : 0);
bindpos.push_back(-def[0].spec.geom->size[1]); bindpos.push_back(-def[0].spec.geom->size[1]);
bindpos.push_back(0); bindpos.push_back(0);
bindquat.push_back(1); bindquat.push_back(0); bindquat.push_back(1); bindquat.push_back(0);
bindquat.push_back(0); bindquat.push_back(0); bindquat.push_back(0); bindquat.push_back(0);
} else { } else {
mjm_appendString(skin->bodyname, this_body); mjs_appendString(skin->bodyname, this_body);
bindpos.push_back((ix==count[0]-1) ? -2*def[0].spec.geom->size[0] : 0); bindpos.push_back((ix==count[0]-1) ? -2*def[0].spec.geom->size[0] : 0);
bindpos.push_back(def[0].spec.geom->size[1]); bindpos.push_back(def[0].spec.geom->size[1]);
bindpos.push_back(0); bindpos.push_back(0);
@@ -1534,7 +1534,7 @@ void mjCComposite::MakeCableBones(mjCModel* model, mjmSkin* skin) {
void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjmSkin* skin) { void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjsSkin* skin) {
// populate bones // populate bones
for (int ix=0; ix<count[0]; ix++) { for (int ix=0; ix<count[0]; ix++) {
for (int iy=0; iy<count[1]; iy++) { for (int iy=0; iy<count[1]; iy++) {
@@ -1563,7 +1563,7 @@ void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjmSkin* skin) {
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
} }
mjm_appendString(skin->bodyname, txt); mjs_appendString(skin->bodyname, txt);
bindquat.push_back(1); bindquat.push_back(1);
bindquat.push_back(0); bindquat.push_back(0);
bindquat.push_back(0); bindquat.push_back(0);
@@ -1888,10 +1888,10 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
// add skin, set name and material // add skin, set name and material
char txt[100]; char txt[100];
mjmSkin* skin = mjm_addSkin(&model->spec); mjsSkin* skin = mjs_addSkin(&model->spec);
mju::sprintf_arr(txt, "%sSkin", prefix.c_str()); mju::sprintf_arr(txt, "%sSkin", prefix.c_str());
mjm_setString(skin->name, txt); mjs_setString(skin->name, txt);
mjm_setString(skin->material, skinmaterial.c_str()); mjs_setString(skin->material, skinmaterial.c_str());
mjuu_copyvec(skin->rgba, skinrgba, 4); mjuu_copyvec(skin->rgba, skinrgba, 4);
skin->inflate = inflate; skin->inflate = inflate;
skin->group = skingroup; skin->group = skingroup;
@@ -2043,10 +2043,10 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
mju::sprintf_arr(cnt2, "%d", count[2]-1); mju::sprintf_arr(cnt2, "%d", count[2]-1);
// add skin, set name and material // add skin, set name and material
mjmSkin* skin = mjm_addSkin(&model->spec); mjsSkin* skin = mjs_addSkin(&model->spec);
mju::sprintf_arr(txt, "%sSkin", prefix.c_str()); mju::sprintf_arr(txt, "%sSkin", prefix.c_str());
mjm_setString(skin->name, txt); mjs_setString(skin->name, txt);
mjm_setString(skin->material, skinmaterial.c_str()); mjs_setString(skin->material, skinmaterial.c_str());
mjuu_copyvec(skin->rgba, skinrgba, 4); mjuu_copyvec(skin->rgba, skinrgba, 4);
skin->inflate = skininflate; skin->inflate = skininflate;
skin->group = skingroup; skin->group = skingroup;
@@ -2191,7 +2191,7 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
// make one face of 3D skin, box // make one face of 3D skin, box
void mjCComposite::MakeSkin3Box(mjmSkin* skin, int c0, int c1, int side, void mjCComposite::MakeSkin3Box(mjsSkin* skin, int c0, int c1, int side,
int& vcnt, const char* format) { int& vcnt, const char* format) {
char txt[100]; char txt[100];
@@ -2224,7 +2224,7 @@ void mjCComposite::MakeSkin3Box(mjmSkin* skin, int c0, int c1, int side,
mju::sprintf_arr(txt, format, prefix.c_str(), i0, i1); mju::sprintf_arr(txt, format, prefix.c_str(), i0, i1);
// bind pose: origin // bind pose: origin
mjm_appendString(skin->bodyname, txt); mjs_appendString(skin->bodyname, txt);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
@@ -2246,7 +2246,7 @@ void mjCComposite::MakeSkin3Box(mjmSkin* skin, int c0, int c1, int side,
// make one face of 3D skin, smooth // make one face of 3D skin, smooth
void mjCComposite::MakeSkin3Smooth(mjmSkin* skin, int c0, int c1, int side, void mjCComposite::MakeSkin3Smooth(mjsSkin* skin, int c0, int c1, int side,
const std::map<string, int>& vmap, const char* format) { const std::map<string, int>& vmap, const char* format) {
char txt00[100], txt01[100], txt10[100], txt11[100]; char txt00[100], txt01[100], txt10[100], txt11[100];
@@ -2281,7 +2281,7 @@ void mjCComposite::MakeSkin3Smooth(mjmSkin* skin, int c0, int c1, int side,
} }
// bind pose: origin // bind pose: origin
mjm_appendString(skin->bodyname, txt00); mjs_appendString(skin->bodyname, txt00);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
bindpos.push_back(0); bindpos.push_back(0);
+16 -16
View File
@@ -69,25 +69,25 @@ class mjCComposite {
bool AddDefaultJoint(char* error = NULL, int error_sz = 0); bool AddDefaultJoint(char* error = NULL, int error_sz = 0);
void AdjustSoft(mjtNum* solref, mjtNum* solimp, int level); void AdjustSoft(mjtNum* solref, mjtNum* solimp, int level);
bool Make(mjSpec* spec, mjmBody* body, char* error, int error_sz); bool Make(mjSpec* spec, mjsBody* body, char* error, int error_sz);
bool MakeParticle(mjCModel* model, mjmBody* body, char* error, int error_sz); bool MakeParticle(mjCModel* model, mjsBody* body, char* error, int error_sz);
bool MakeGrid(mjCModel* model, mjmBody* body, char* error, int error_sz); bool MakeGrid(mjCModel* model, mjsBody* body, char* error, int error_sz);
bool MakeRope(mjCModel* model, mjmBody* body, char* error, int error_sz); bool MakeRope(mjCModel* model, mjsBody* body, char* error, int error_sz);
bool MakeCable(mjCModel* model, mjmBody* body, char* error, int error_sz); bool MakeCable(mjCModel* model, mjsBody* body, char* error, int error_sz);
bool MakeBox(mjCModel* model, mjmBody* body, char* error, int error_sz); bool MakeBox(mjCModel* model, mjsBody* body, char* error, int error_sz);
void MakeShear(mjCModel* model); void MakeShear(mjCModel* model);
void MakeSkin2(mjCModel* model, mjtNum inflate); void MakeSkin2(mjCModel* model, mjtNum inflate);
void MakeSkin2Subgrid(mjCModel* model, mjtNum inflate); void MakeSkin2Subgrid(mjCModel* model, mjtNum inflate);
void MakeClothBones(mjCModel* model, mjmSkin* skin); void MakeClothBones(mjCModel* model, mjsSkin* skin);
void MakeClothBonesSubgrid(mjCModel* model, mjmSkin* skin); void MakeClothBonesSubgrid(mjCModel* model, mjsSkin* skin);
void MakeCableBones(mjCModel* model, mjmSkin* skin); void MakeCableBones(mjCModel* model, mjsSkin* skin);
void MakeCableBonesSubgrid(mjCModel* model, mjmSkin* skin); void MakeCableBonesSubgrid(mjCModel* model, mjsSkin* skin);
void MakeSkin3(mjCModel* model); void MakeSkin3(mjCModel* model);
void MakeSkin3Box(mjmSkin* skin, int c0, int c1, int side, int& vcnt, const char* format); void MakeSkin3Box(mjsSkin* skin, int c0, int c1, int side, int& vcnt, const char* format);
void MakeSkin3Smooth(mjmSkin* skin, int c0, int c1, int side, void MakeSkin3Smooth(mjsSkin* skin, int c0, int c1, int side,
const std::map<std::string, int>& vmap, const char* format); const std::map<std::string, int>& vmap, const char* format);
void BoxProject(double* pos); void BoxProject(double* pos);
@@ -116,7 +116,7 @@ class mjCComposite {
// plugin support // plugin support
std::string plugin_name; std::string plugin_name;
std::string plugin_instance_name; std::string plugin_instance_name;
mjmPlugin plugin; mjsPlugin plugin;
// skin // skin
bool skin; // generate skin bool skin; // generate skin
@@ -136,11 +136,11 @@ class mjCComposite {
int dim; // dimensionality int dim; // dimensionality
private: private:
mjmBody* AddRopeBody(mjCModel* model, mjmBody* body, int ix, int ix1); mjsBody* AddRopeBody(mjCModel* model, mjsBody* body, int ix, int ix1);
mjmBody* AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]); mjsBody* AddCableBody(mjCModel* model, mjsBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]);
// temporary skin vectors // temporary skin vectors
void CopyIntoSkin(mjmSkin* skin); void CopyIntoSkin(mjsSkin* skin);
std::vector<int> face; std::vector<int> face;
std::vector<float> vert; std::vector<float> vert;
std::vector<float> bindpos; std::vector<float> bindpos;
+365 -104
View File
@@ -12,16 +12,14 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "user/user_api.h" #include <algorithm>
#include "user/user_flexcomp.h"
#include <stdio.h>
#include <cstddef> #include <cstddef>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <sstream>
#include <stdio.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <sstream>
#include <mujoco/mjmacro.h> #include <mujoco/mjmacro.h>
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
@@ -34,6 +32,7 @@
#include "engine/engine_util_errmem.h" #include "engine/engine_util_errmem.h"
#include "engine/engine_util_misc.h" #include "engine/engine_util_misc.h"
#include "engine/engine_util_spatial.h" #include "engine/engine_util_spatial.h"
#include "user/user_flexcomp.h"
#include "user/user_model.h" #include "user/user_model.h"
#include "user/user_objects.h" #include "user/user_objects.h"
#include "user/user_util.h" #include "user/user_util.h"
@@ -58,6 +57,12 @@ static void ReadFromBuffer(T* dst, const char* src) {
} }
static void ReadStrFromBuffer(char* dest, const char* src, int maxlen) {
std::strncpy(dest, src, maxlen);
}
// constructor: set defaults outside mjCDef // constructor: set defaults outside mjCDef
mjCFlexcomp::mjCFlexcomp(void) { mjCFlexcomp::mjCFlexcomp(void) {
type = mjFCOMPTYPE_GRID; type = mjFCOMPTYPE_GRID;
@@ -72,7 +77,8 @@ mjCFlexcomp::mjCFlexcomp(void) {
rigid = false; rigid = false;
centered = false; centered = false;
mjm_defaultPlugin(plugin); mjs_defaultPlugin(plugin);
mjs_defaultOrientation(alt);
plugin_name = ""; plugin_name = "";
plugin_instance_name = ""; plugin_instance_name = "";
plugin.name = (mjString)&plugin_name; plugin.name = (mjString)&plugin_name;
@@ -82,9 +88,9 @@ mjCFlexcomp::mjCFlexcomp(void) {
// make flexcomp object // make flexcomp object
bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) { bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
mjCModel* model = (mjCModel*)spec->element; mjCModel* model = (mjCModel*)spec->element;
mjmFlex* dflex = def.spec.flex; mjsFlex* dflex = def.spec.flex;
int dim = dflex->dim; int dim = dflex->dim;
bool radial = (type == mjFCOMPTYPE_BOX || bool radial = (type == mjFCOMPTYPE_BOX ||
type == mjFCOMPTYPE_CYLINDER || type == mjFCOMPTYPE_CYLINDER ||
@@ -94,7 +100,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
type == mjFCOMPTYPE_GMSH); type == mjFCOMPTYPE_GMSH);
// check parent body name // check parent body name
if (std::string(mjm_getString(body->name)).empty()) { if (std::string(mjs_getString(body->name)).empty()) {
return comperr(error, "Parent body must have name", error_sz); return comperr(error, "Parent body must have name", error_sz);
} }
@@ -131,7 +137,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
} }
// compute orientation // compute orientation
const char* alterr = alt.Set(quat, model->spec.degree, model->spec.euler); const char* alterr = mjs_resolveOrientation(quat, model->spec.degree, model->spec.euler, &alt);
if (alterr) { if (alterr) {
return comperr(error, alterr, error_sz); return comperr(error, alterr, error_sz);
} }
@@ -381,7 +387,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
// create flex, copy parameters // create flex, copy parameters
mjCFlex* flex = model->AddFlex(); mjCFlex* flex = model->AddFlex();
mjmFlex* pf = &flex->spec; mjsFlex* pf = &flex->spec;
int id = flex->id; int id = flex->id;
*flex = def.flex; *flex = def.flex;
@@ -389,13 +395,13 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
flex->model = model; flex->model = model;
flex->id = id; flex->id = id;
mjm_setString(pf->name, name.c_str()); mjs_setString(pf->name, name.c_str());
mjm_setInt(pf->elem, element.data(), element.size()); mjs_setInt(pf->elem, element.data(), element.size());
mjm_setFloat(pf->texcoord, texcoord.data(), texcoord.size()); mjs_setFloat(pf->texcoord, texcoord.data(), texcoord.size());
// rigid: set parent name, nothing else to do // rigid: set parent name, nothing else to do
if (rigid) { if (rigid) {
mjm_appendString(pf->vertbody, mjm_getString(body->name)); mjs_appendString(pf->vertbody, mjs_getString(body->name));
return true; return true;
} }
@@ -406,7 +412,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
// overwrite plugin name // overwrite plugin name
if (plugin.active && plugin_instance_name.empty()) { if (plugin.active && plugin_instance_name.empty()) {
plugin_instance_name = "flexcomp_" + name; plugin_instance_name = "flexcomp_" + name;
((mjCPlugin*)plugin.instance)->name = plugin_instance_name; static_cast<mjCPlugin*>(plugin.instance)->name = plugin_instance_name;
} }
// create bodies, construct flex vert and vertbody // create bodies, construct flex vert and vertbody
@@ -418,22 +424,22 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
// pinned: parent body // pinned: parent body
if (pinned[i]) { if (pinned[i]) {
mjm_appendString(pf->vertbody, mjm_getString(body->name)); mjs_appendString(pf->vertbody, mjs_getString(body->name));
// add plugin // add plugin
if (plugin.active) { if (plugin.active) {
mjmPlugin* pplugin = &body->plugin; mjsPlugin* pplugin = &body->plugin;
pplugin->active = true; pplugin->active = true;
pplugin->instance = (mjElement)plugin.instance; pplugin->instance = static_cast<mjElement*>(plugin.instance);
mjm_setString(pplugin->name, mjm_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
mjm_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
} }
} }
// not pinned: new body // not pinned: new body
else { else {
// add new body at vertex coordinates // add new body at vertex coordinates
mjmBody* pb = mjm_addBody(body, 0); mjsBody* pb = mjs_addBody(body, 0);
// set frame and inertial // set frame and inertial
pb->pos[0] = point[3*i]; pb->pos[0] = point[3*i];
@@ -448,7 +454,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
// add radial slider // add radial slider
if (radial) { if (radial) {
mjmJoint* jnt = mjm_addJoint(pb, 0); mjsJoint* jnt = mjs_addJoint(pb, 0);
// set properties // set properties
jnt->type = mjJNT_SLIDE; jnt->type = mjJNT_SLIDE;
@@ -461,7 +467,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
else { else {
for (int j=0; j < 3; j++) { for (int j=0; j < 3; j++) {
// add joint to body // add joint to body
mjmJoint* jnt = mjm_addJoint(pb, 0); mjsJoint* jnt = mjs_addJoint(pb, 0);
// set properties // set properties
jnt->type = mjJNT_SLIDE; jnt->type = mjJNT_SLIDE;
@@ -474,8 +480,8 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
// construct body name, add to vertbody // construct body name, add to vertbody
char txt[100]; char txt[100];
mju::sprintf_arr(txt, "%s_%d", name.c_str(), i); mju::sprintf_arr(txt, "%s_%d", name.c_str(), i);
mjm_setString(pb->name, txt); mjs_setString(pb->name, txt);
mjm_appendString(pf->vertbody, mjm_getString(pb->name)); mjs_appendString(pf->vertbody, mjs_getString(pb->name));
// clear flex vertex coordinates if allocated // clear flex vertex coordinates if allocated
if (!centered) { if (!centered) {
@@ -486,26 +492,26 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjmBody* body, char* error, int error_sz) {
// add plugin // add plugin
if (plugin.active) { if (plugin.active) {
mjmPlugin* pplugin = &pb->plugin; mjsPlugin* pplugin = &pb->plugin;
pplugin->active = true; pplugin->active = true;
pplugin->instance = (mjElement)plugin.instance; pplugin->instance = static_cast<mjElement*>(plugin.instance);
mjm_setString(pplugin->name, mjm_getString(plugin.name)); mjs_setString(pplugin->name, mjs_getString(plugin.name));
mjm_setString(pplugin->instance_name, plugin_instance_name.c_str()); mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
} }
} }
} }
if (!centered) { if (!centered) {
mjm_setDouble(pf->vert, point.data(), point.size()); mjs_setDouble(pf->vert, point.data(), point.size());
} }
// create edge equality constraint // create edge equality constraint
if (equality) { if (equality) {
mjmEquality* pe = mjm_addEquality(&model->spec, &def.spec); mjsEquality* pe = mjs_addEquality(&model->spec, &def.spec);
mjm_setDefault(pe->element, &model->defaults[0]->spec); mjs_setDefault(pe->element, &model->defaults[0]->spec);
pe->type = mjEQ_FLEX; pe->type = mjEQ_FLEX;
pe->active = true; pe->active = true;
mjm_setString(pe->name1, name.c_str()); mjs_setString(pe->name1, name.c_str());
} }
return true; return true;
@@ -885,8 +891,8 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
} }
// load resource // load resource
string filename = mjuu_makefullname(mjm_getString(model->spec.modelfiledir), string filename = mjuu_makefullname(mjs_getString(model->spec.modelfiledir),
mjm_getString(model->spec.meshdir), file); mjs_getString(model->spec.meshdir), file);
mjResource* resource = nullptr; mjResource* resource = nullptr;
try { try {
@@ -957,7 +963,6 @@ static int findstring(const char* buffer, int buffer_sz, const char* str) {
// scan buffer // scan buffer
for (int i=0; i < buffer_sz-len; i++) { for (int i=0; i < buffer_sz-len; i++) {
// check for string at position i // check for string at position i
bool found = true; bool found = true;
for (int k=0; k < len; k++) { for (int k=0; k < len; k++) {
@@ -992,8 +997,8 @@ bool mjCFlexcomp::MakeGMSH(mjCModel* model, char* error, int error_sz) {
} }
// open resource // open resource
string filename = mjuu_makefullname(mjm_getString(model->spec.modelfiledir), string filename = mjuu_makefullname(mjs_getString(model->spec.modelfiledir),
mjm_getString(model->spec.meshdir), file); mjs_getString(model->spec.meshdir), file);
mjResource* resource = nullptr; mjResource* resource = nullptr;
try { try {
@@ -1019,55 +1024,11 @@ bool mjCFlexcomp::MakeGMSH(mjCModel* model, char* error, int error_sz) {
// load GMSH file from resource // load GMSH format 4.1
void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) { void mjCFlexcomp::LoadGMSH41(char* buffer, int binary, int nodeend,
// get buffer from resource int nodebegin, int elemend, int elembegin){
char* buffer = 0; // header size
int buffer_sz = mju_readResource(resource, (const void**) &buffer); constexpr int kGmsh41HeaderSize = 52;
// check buffer
if (buffer_sz<0) {
throw mjCError(NULL, "Could not read GMSH file");
} else if (buffer_sz==0) {
throw mjCError(NULL, "Empty GMSH file");
} else if (buffer_sz<11 || strncmp(buffer, "$MeshFormat", 11)) {
throw mjCError(NULL, "GMSH file must begin with $MeshFormat");
}
// check version, determine ascii or binary
double version;
int binary;
if (sscanf(buffer+11, "%lf %d", &version, &binary) != 2) {
throw mjCError(NULL, "Could not read GMSH file header");
}
if (mju_round(100*version)!=410) {
throw mjCError(NULL, "Only GMSH file format 4.1 supported");
}
// find section begin/end
int nodebegin = findstring(buffer, buffer_sz, "$Nodes");
int nodeend = findstring(buffer, buffer_sz, "$EndNodes");
int elembegin = findstring(buffer, buffer_sz, "$Elements");
int elemend = findstring(buffer, buffer_sz, "$EndElements");
// check sections
if (nodebegin<0) {
throw mjCError(NULL, "GMSH file missing $Nodes");
}
if (nodeend<nodebegin) {
throw mjCError(NULL, "GMSH file missing $EndNodes after $Nodes");
}
if (elembegin<0) {
throw mjCError(NULL, "GMSH file missing $Elements");
}
if (elemend<elembegin) {
throw mjCError(NULL, "GMSH file missing $EndElements after $Elements");
}
// correct begin for string size, +1 for LF in binary (CRLF in Win ascii works)
nodebegin += (int)strlen("$Nodes") + 1;
elembegin += (int)strlen("$Elements") + 1;
// base for node tags, to be subtracted from element data // base for node tags, to be subtracted from element data
size_t minNodeTag, numEntityBlocks, numNodes, maxNodeTag, numNodesInBlock, tag; size_t minNodeTag, numEntityBlocks, numNodes, maxNodeTag, numNodesInBlock, tag;
int entityDim, entityTag, parametric; int entityDim, entityTag, parametric;
@@ -1075,8 +1036,7 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
// ascii nodes // ascii nodes
if (binary == 0) { if (binary == 0) {
// convert node char buffer to stringstream // convert node char buffer to stringstream
buffer[nodeend] = 0; stringstream ss(string(buffer + nodebegin, nodeend - nodebegin));
stringstream ss(buffer+nodebegin);
// read header // read header
ss >> numEntityBlocks >> numNodes >> minNodeTag >> maxNodeTag; ss >> numEntityBlocks >> numNodes >> minNodeTag >> maxNodeTag;
@@ -1119,11 +1079,10 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
point.push_back(x); point.push_back(x);
} }
} }
// binary nodes // binary nodes
else { else {
// check header size: 5 size_t, 3 int // check header size
if (nodeend-nodebegin < 52) { if (nodeend-nodebegin < kGmsh41HeaderSize) {
throw mjCError(NULL, "Invalid nodes header"); throw mjCError(NULL, "Invalid nodes header");
} }
@@ -1148,15 +1107,20 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
} }
def.spec.flex->dim = entityDim; def.spec.flex->dim = entityDim;
// nodeData: node tag and 3 nodes
constexpr int numNodeComponents = 4;
constexpr int componentSize = 8;
int nodeDataSize = numNodeComponents*componentSize;
// check section byte size // check section byte size
if (nodeend-nodebegin < 52+numNodes*4*8) { if (nodeend-nodebegin < kGmsh41HeaderSize + numNodes*nodeDataSize) {
throw mjCError(NULL, "Insufficient byte size of Nodes"); throw mjCError(NULL, "Insufficient byte size of Nodes");
} }
// check node tags: must range from minNodeTag to maxNodeTag // check node tags: must range from minNodeTag to maxNodeTag
const char* tagbuffer = buffer + nodebegin + 52; const char* tagbuffer = buffer + nodebegin + kGmsh41HeaderSize;
for (size_t i=0; i < numNodes; i++) { for (size_t i=0; i < numNodes; i++) {
ReadFromBuffer(&tag, tagbuffer+i*8); ReadFromBuffer(&tag, tagbuffer + i*componentSize);
if (tag != i+minNodeTag) { if (tag != i+minNodeTag) {
throw mjCError(NULL, "Node tags must be sequential"); throw mjCError(NULL, "Node tags must be sequential");
} }
@@ -1165,9 +1129,9 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
// read points // read points
double x; double x;
point.reserve(3*numNodes); point.reserve(3*numNodes);
const char* pointbuffer = buffer + nodebegin + 52 + 8*numNodes; const char* pointbuffer = buffer + nodebegin + kGmsh41HeaderSize + componentSize*numNodes;
for (size_t i=0; i < 3*numNodes; i++) { for (size_t i=0; i < 3*numNodes; i++) {
ReadFromBuffer(&x, pointbuffer+i*8); ReadFromBuffer(&x, pointbuffer + i*componentSize);
point.push_back(x); point.push_back(x);
} }
} }
@@ -1222,8 +1186,8 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
// binary elements // binary elements
else { else {
// check header size: 5 size_t, 3 int // check header size
if (elemend-elembegin < 52) { if (elemend-elembegin < kGmsh41HeaderSize) {
throw mjCError(NULL, "Invalid elements header"); throw mjCError(NULL, "Invalid elements header");
} }
@@ -1254,17 +1218,22 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
throw mjCError(NULL, "Element type inconsistent with dimensionality"); throw mjCError(NULL, "Element type inconsistent with dimensionality");
} }
// elementData: element tag and n node tags
int numElementComponents = (entityDim+2);
constexpr int componentSize = 8;
int elementDataSize = numElementComponents*componentSize;
// check section byte size // check section byte size
if (elemend-elembegin < 52+numElements*(entityDim+2)*8) { if (elemend - elembegin < kGmsh41HeaderSize + numElements*elementDataSize) {
throw mjCError(NULL, "Insufficient byte size of Elements"); throw mjCError(NULL, "Insufficient byte size of Elements");
} }
// read elements, discard tags // read elements, discard tags
element.reserve((entityDim+1)*numElements); element.reserve((entityDim+1)*numElements);
const char* elembuffer = buffer + elembegin + 52; const char* elembuffer = buffer + elembegin + kGmsh41HeaderSize;
for (size_t i=0; i < numElements; i++) { for (size_t i=0; i < numElements; i++) {
// skip element tag // skip element tag
elembuffer += 8; elembuffer += componentSize;
// read vertex ids // read vertex ids
size_t elemid; size_t elemid;
@@ -1272,8 +1241,300 @@ void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
ReadFromBuffer(&elemid, elembuffer); ReadFromBuffer(&elemid, elembuffer);
int elementid = elemid - minNodeTag; int elementid = elemid - minNodeTag;
element.push_back(elementid); element.push_back(elementid);
elembuffer += 8; elembuffer += componentSize;
} }
} }
} }
} }
// load GMSH format 2.2
void mjCFlexcomp::LoadGMSH22(char* buffer, int binary, int nodeend,
int nodebegin, int elemend, int elembegin) {
// ascii nodes
if (binary == 0) {
// convert node char buffer to stringstream
stringstream ss(string(buffer + nodebegin, nodeend - nodebegin));
// read header
size_t maxNodeTag = 0;
ss >> maxNodeTag;
if (!ss.good()) {
throw mjCError(NULL, "Error reading Nodes header");
}
size_t numNodes = maxNodeTag;
// read points, discard tag
point.reserve(3*numNodes);
for (size_t i=0; i < numNodes; i++) {
size_t tag;
double x;
ss >> tag;
if (!ss.good()) {
throw mjCError(NULL, "Error reading node tags");
}
// reading nodes
for (int k=0; k < 3; k++) {
ss >> x;
if (!ss.good()) {
throw mjCError(NULL, "Error reading node coordinates");
}
point.push_back(x);
}
}
}
// binary nodes
else {
// header size for gmshApp
constexpr int nodeHeaderSizeGmshApp = 5;
// header size compatible with both gmshApp and Ftetwild
constexpr int nodeHeaderSize = nodeHeaderSizeGmshApp - 1;
// check header size
if (nodeend-nodebegin < nodeHeaderSize) {
throw mjCError(NULL, "Invalid nodes header");
}
// parse maxNodeTag and then cast it to int
char maxNodeTagChar[20];
ReadStrFromBuffer(maxNodeTagChar, buffer + nodebegin, std::min(10, nodeend - nodebegin));
size_t measuredHeaderSize = strnlen(maxNodeTagChar, 20) - 1;
size_t maxNodeTag = std::stoi(maxNodeTagChar);
size_t numNodes = maxNodeTag;
// node data: node tag and 3 nodes
int nodeSize = sizeof(double);
int indexSize = sizeof(int);
int nodeDataSize = indexSize + 3*nodeSize;
// check section byte size
if (nodeend - nodebegin < nodeHeaderSize + numNodes*nodeDataSize) {
throw mjCError(NULL, "Insufficient byte size of Nodes");
}
// read point, discard tag
point.reserve(3*numNodes);
// beginning of buffer containing node info
const char* tagBuffer = buffer + nodebegin + measuredHeaderSize;
for (int i=0; i < numNodes; i++) {
int tag;
int offset = i*(sizeof(int) + sizeof(double)*3);
ReadFromBuffer(&tag, tagBuffer + offset);
for (int k=0; k < 3; k++) {
double x;
const char* nodeBuffer = tagBuffer + sizeof(int) + sizeof(double)*k;
ReadFromBuffer(&x, nodeBuffer + offset);
point.push_back(x);
}
}
}
size_t entityDim = 3;
def.spec.flex->dim = entityDim;
// ascii elements
if (binary == 0) {
// convert element char buffer to stringstream
buffer[elemend] = 0;
stringstream ss(buffer + elembegin);
// read header
size_t maxElementTag = 0;
ss >> maxElementTag;
if (!ss.good()) {
throw mjCError(NULL, "Error reading Elements header");
}
size_t numElements = maxElementTag;
// read elements, discard all tags
element.reserve((entityDim+1)*numElements);
for (size_t i=0; i < numElements; i++) {
int tag = 0, type = 0, numTags = 0, nodeTag = 0, physicalEntityTag = 0,
elmentModelEntityTag = 0;
ss >> tag >> type >> numTags;
if (!ss.good()) {
throw mjCError(NULL, "Error reading Elements");
}
if (numTags > 0) {
ss >> physicalEntityTag >> elmentModelEntityTag;
if (!ss.good()) {
throw mjCError(NULL, "Error reading Elements");
}
}
for (int k=0; k <= entityDim; k++) {
ss >> nodeTag;
if (!ss.good()) {
throw mjCError(NULL, "Error reading Elements");
}
element.push_back((int)(nodeTag-1));
}
}
}
// binary elements
else {
// header size for gmshApp
constexpr int elementHeaderSizeGmshApp = 6;
// header size for Ftetwild
constexpr int elementHeaderSizeFtetwild = 17;
// check header size
if (elemend - elembegin < elementHeaderSizeGmshApp) {
throw mjCError(NULL, "Invalid elements header");
}
// reading elements
char maxElementTagChar[20];
ReadStrFromBuffer(maxElementTagChar, buffer + elembegin, std::min(10, elemend - elembegin));
int measuredHeaderSize = strnlen(maxElementTagChar, 20) - 1;
int maxElementTag = std::stoi(maxElementTagChar);
int numElements = maxElementTag;
int tag, numTags;
int nodeTag;
// size of single component in element data
int componentSize = sizeof(int);
// element buffer
const char* elementsBuffer = buffer + elembegin + measuredHeaderSize;
ReadFromBuffer(&numTags, elementsBuffer + componentSize*2);
ReadFromBuffer(&tag, elementsBuffer + componentSize*3);
// element data(Ftetwild): tag and 4 nodeTag
constexpr int numComponentsFtetwild = 5;
// element data(gmshApp): 4 Info components, 2 entity tag and 4 nodeTags
constexpr int numInfoComponents = 4;
constexpr int numEntityTagComponents = 2;
constexpr int numNodeTags = 4;
constexpr int numComponentsGmshApp = numInfoComponents +
numEntityTagComponents + numNodeTags;
// single element data size
int elementDataSizeFtetwild = numComponentsFtetwild*componentSize;
int elementDataSizeGmshApp = numComponentsGmshApp*componentSize;
// elements section buffer size
int elementsBufferSizeFtetwild = elementHeaderSizeFtetwild +
numElements*elementDataSizeFtetwild;
int elementsBufferSizeGmshApp = elementHeaderSizeGmshApp +
numElements*elementDataSizeGmshApp;
// check section byte size for ftetwild
if (elemend - elembegin < elementsBufferSizeFtetwild) {
throw mjCError(NULL, "Insufficient byte size of Elements");
}
// Handling elements produced by gmsh
if (numTags > 0) {
// check section byte size for gmsh
if (elemend - elembegin < elementsBufferSizeGmshApp) {
throw mjCError(NULL, "Insufficient byte size of Elements");
}
// read first element
for (int k =0; k<numNodeTags; k++) {
ReadFromBuffer(&nodeTag, elementsBuffer + componentSize*(6+k));
element.push_back(nodeTag-1);
}
// read every other element
for (int i=1; i < numElements; i++) {
const char* numTagsBuffer = elementsBuffer + componentSize*2;
const char* tagBuffer = elementsBuffer + componentSize*3;
int offset = i*elementDataSizeGmshApp;
ReadFromBuffer(&numTags, numTagsBuffer + offset);
ReadFromBuffer(&tag, tagBuffer+offset);
for (int k =0; k < numNodeTags; k++) {
const char* nodeTagBuffer = elementsBuffer + componentSize*(6+k);
ReadFromBuffer(&nodeTag, nodeTagBuffer + offset);
element.push_back(nodeTag-1);
}
}
}
// Handling elements produced by ftetwild
else {
// read first element
for (int k =0; k < numNodeTags; k++) {
const char* nodeTagBuffer = elementsBuffer + componentSize*(4+k);
ReadFromBuffer(&nodeTag, nodeTagBuffer);
element.push_back(nodeTag-1);
}
// read every other element
for (int i=0; i<numElements-1; i++) {
int offset = componentSize*(4+2) + i*elementDataSizeFtetwild;
const char* tagBuffer = elementsBuffer + componentSize*2;
ReadFromBuffer(&tag, tagBuffer + offset);
for (int k=0; k < numNodeTags; k++) {
const char* nodeTagBuffer = elementsBuffer + componentSize*(3+k);
ReadFromBuffer(&nodeTag, nodeTagBuffer + offset);
element.push_back(nodeTag-1);
}
}
}
}
}
// load GMSH file from resource
void mjCFlexcomp::LoadGMSH(mjCModel* model, mjResource* resource) {
// get buffer from resource
char* buffer = 0;
int buffer_sz = mju_readResource(resource, (const void**) &buffer);
// check buffer
if (buffer_sz < 0) {
throw mjCError(NULL, "Could not read GMSH file");
} else if (buffer_sz == 0) {
throw mjCError(NULL, "Empty GMSH file");
} else if (buffer_sz < 11 || strncmp(buffer, "$MeshFormat", 11)) {
throw mjCError(NULL, "GMSH file must begin with $MeshFormat");
}
// check version, determine ascii or binary
double version;
int binary;
if (sscanf(buffer + 11, "%lf %d", &version, &binary) != 2) {
throw mjCError(NULL, "Could not read GMSH file header");
}
if (mju_round(100*version) != 220 && mju_round(100*version) != 410) {
throw mjCError(NULL, "Only GMSH file format versions 4.1 and 2.2 are supported");
}
// find section begin/end
int nodebegin = findstring(buffer, buffer_sz, "$Nodes");
int nodeend = findstring(buffer, buffer_sz, "$EndNodes");
int elembegin = findstring(buffer, buffer_sz, "$Elements");
int elemend = findstring(buffer, buffer_sz, "$EndElements");
// check sections
if (nodebegin < 0) {
throw mjCError(NULL, "GMSH file missing $Nodes");
}
if (nodeend < nodebegin) {
throw mjCError(NULL, "GMSH file missing $EndNodes after $Nodes");
}
if (elembegin < 0) {
throw mjCError(NULL, "GMSH file missing $Elements");
}
if (elemend < elembegin) {
throw mjCError(NULL, "GMSH file missing $EndElements after $Elements");
}
// correct begin for string size, +1 for LF in binary (CRLF in Win ascii works)
nodebegin += (int)strlen("$Nodes") + 1;
elembegin += (int)strlen("$Elements") + 1;
// Support for 4.1
if (mju_round(100*version) == 410) {
LoadGMSH41(buffer, binary, nodeend, nodebegin, elemend, elembegin);
}
// Support for 2.2
else if (mju_round(100*version) == 220) {
LoadGMSH22(buffer, binary, nodeend, nodebegin, elemend, elembegin);
}
}
+8 -3
View File
@@ -42,7 +42,7 @@ typedef enum _mjtFcompType {
class mjCFlexcomp { class mjCFlexcomp {
public: public:
mjCFlexcomp(void); mjCFlexcomp(void);
bool Make(mjSpec* spec, mjmBody* body, char* error, int error_sz); bool Make(mjSpec* spec, mjsBody* body, char* error, int error_sz);
bool MakeGrid(char* error, int error_sz); bool MakeGrid(char* error, int error_sz);
bool MakeBox(char* error, int error_sz); bool MakeBox(char* error, int error_sz);
@@ -50,6 +50,11 @@ class mjCFlexcomp {
bool MakeMesh(mjCModel* model, char* error, int error_sz); bool MakeMesh(mjCModel* model, char* error, int error_sz);
bool MakeGMSH(mjCModel* model, char* error, int error_sz); bool MakeGMSH(mjCModel* model, char* error, int error_sz);
void LoadGMSH(mjCModel* model, mjResource* resource); void LoadGMSH(mjCModel* model, mjResource* resource);
void LoadGMSH41(char* buffer, int binary, int nodeend, int nodebegin,
int elemend, int elembegin);
void LoadGMSH22(char* buffer, int binary, int nodeend, int nodebegin,
int elemend, int elembegin);
int GridID(int ix, int iy); int GridID(int ix, int iy);
int GridID(int ix, int iy, int iz); int GridID(int ix, int iy, int iz);
@@ -79,7 +84,7 @@ class mjCFlexcomp {
// pose transform relative to parent body // pose transform relative to parent body
double pos[3]; // position double pos[3]; // position
double quat[4]; // orientation double quat[4]; // orientation
mjCAlternative alt; // alternative orientation mjsOrientation alt; // alternative orientation
// set by user or computed internally // set by user or computed internally
bool rigid; // all vertices are in parent body (all pinned) bool rigid; // all vertices are in parent body (all pinned)
@@ -93,7 +98,7 @@ class mjCFlexcomp {
// plugin support // plugin support
std::string plugin_name; std::string plugin_name;
std::string plugin_instance_name; std::string plugin_instance_name;
mjmPlugin plugin; mjsPlugin plugin;
}; };
#endif // MUJOCO_SRC_USER_USER_FLEXCOMP_H_ #endif // MUJOCO_SRC_USER_USER_FLEXCOMP_H_
+54 -47
View File
@@ -22,7 +22,7 @@
// default model attributes // default model attributes
void mjm_defaultSpec(mjSpec& model) { void mjs_defaultSpec(mjSpec& model) {
memset(&model, 0, sizeof(mjSpec)); memset(&model, 0, sizeof(mjSpec));
// default statistics // default statistics
@@ -75,9 +75,16 @@ void mjm_defaultSpec(mjSpec& model) {
// default orientation attributes
void mjs_defaultOrientation(mjsOrientation& orient) {
orient.axisangle[0] = orient.xyaxes[0] = orient.zaxis[0] = orient.euler[0] = mjNAN;
}
// default body attributes // default body attributes
void mjm_defaultBody(mjmBody& body) { void mjs_defaultBody(mjsBody& body) {
memset(&body, 0, sizeof(mjmBody)); memset(&body, 0, sizeof(mjsBody));
// body frame // body frame
body.pos[0] = mjNAN; body.pos[0] = mjNAN;
@@ -94,8 +101,8 @@ void mjm_defaultBody(mjmBody& body) {
// default frame attributes // default frame attributes
void mjm_defaultFrame(mjmFrame& frame) { void mjs_defaultFrame(mjsFrame& frame) {
memset(&frame, 0, sizeof(mjmFrame)); memset(&frame, 0, sizeof(mjsFrame));
mju_zero3(frame.pos); mju_zero3(frame.pos);
mjuu_setvec(frame.quat, 1, 0, 0, 0); mjuu_setvec(frame.quat, 1, 0, 0, 0);
frame.alt.axisangle[0] = frame.alt.xyaxes[0] = frame.alt.zaxis[0] = frame.alt.euler[0] = mjNAN; frame.alt.axisangle[0] = frame.alt.xyaxes[0] = frame.alt.zaxis[0] = frame.alt.euler[0] = mjNAN;
@@ -104,8 +111,8 @@ void mjm_defaultFrame(mjmFrame& frame) {
// default joint attributes // default joint attributes
void mjm_defaultJoint(mjmJoint& joint) { void mjs_defaultJoint(mjsJoint& joint) {
memset(&joint, 0, sizeof(mjmJoint)); memset(&joint, 0, sizeof(mjsJoint));
joint.type = mjJNT_HINGE; joint.type = mjJNT_HINGE;
joint.axis[2] = 1; joint.axis[2] = 1;
@@ -119,8 +126,8 @@ void mjm_defaultJoint(mjmJoint& joint) {
// default geom attributes // default geom attributes
void mjm_defaultGeom(mjmGeom& geom) { void mjs_defaultGeom(mjsGeom& geom) {
memset(&geom, 0, sizeof(mjmGeom)); memset(&geom, 0, sizeof(mjsGeom));
// type // type
geom.type = mjGEOM_SPHERE; geom.type = mjGEOM_SPHERE;
@@ -163,9 +170,9 @@ void mjm_defaultGeom(mjmGeom& geom) {
// default site attributes // default site attributes
void mjm_defaultSite(mjmSite& site) { void mjs_defaultSite(mjsSite& site) {
// set everything to 0 / false / NULL // set everything to 0 / false / NULL
memset(&site, 0, sizeof(mjmSite)); memset(&site, 0, sizeof(mjsSite));
// type // type
site.type = mjGEOM_SPHERE; site.type = mjGEOM_SPHERE;
@@ -184,8 +191,8 @@ void mjm_defaultSite(mjmSite& site) {
// default cam attributes // default cam attributes
void mjm_defaultCamera(mjmCamera& cam) { void mjs_defaultCamera(mjsCamera& cam) {
memset(&cam, 0, sizeof(mjmCamera)); memset(&cam, 0, sizeof(mjsCamera));
// type // type
cam.mode = mjCAMLIGHT_FIXED; cam.mode = mjCAMLIGHT_FIXED;
@@ -203,8 +210,8 @@ void mjm_defaultCamera(mjmCamera& cam) {
// default light attributes // default light attributes
void mjm_defaultLight(mjmLight& light) { void mjs_defaultLight(mjsLight& light) {
memset(&light, 0, sizeof(mjmLight)); memset(&light, 0, sizeof(mjsLight));
// mode // mode
light.mode = mjCAMLIGHT_FIXED; light.mode = mjCAMLIGHT_FIXED;
@@ -223,8 +230,8 @@ void mjm_defaultLight(mjmLight& light) {
// default flex attributes // default flex attributes
void mjm_defaultFlex(mjmFlex& flex) { void mjs_defaultFlex(mjsFlex& flex) {
memset(&flex, 0, sizeof(mjmFlex)); memset(&flex, 0, sizeof(mjsFlex));
// set contact defaults // set contact defaults
flex.contype = 1; flex.contype = 1;
@@ -247,8 +254,8 @@ void mjm_defaultFlex(mjmFlex& flex) {
// default mesh attributes // default mesh attributes
void mjm_defaultMesh(mjmMesh& mesh) { void mjs_defaultMesh(mjsMesh& mesh) {
memset(&mesh, 0, sizeof(mjmMesh)); memset(&mesh, 0, sizeof(mjsMesh));
mjuu_setvec(mesh.refpos, 0, 0, 0); mjuu_setvec(mesh.refpos, 0, 0, 0);
mjuu_setvec(mesh.refquat, 1, 0, 0, 0); mjuu_setvec(mesh.refquat, 1, 0, 0, 0);
mjuu_setvec(mesh.scale, 1, 1, 1); mjuu_setvec(mesh.scale, 1, 1, 1);
@@ -258,15 +265,15 @@ void mjm_defaultMesh(mjmMesh& mesh) {
// default height field attributes // default height field attributes
void mjm_defaultHField(mjmHField& hfield) { void mjs_defaultHField(mjsHField& hfield) {
memset(&hfield, 0, sizeof(mjmHField)); memset(&hfield, 0, sizeof(mjsHField));
} }
// default skin attributes // default skin attributes
void mjm_defaultSkin(mjmSkin& skin) { void mjs_defaultSkin(mjsSkin& skin) {
memset(&skin, 0, sizeof(mjmSkin)); memset(&skin, 0, sizeof(mjsSkin));
skin.rgba[0] = skin.rgba[1] = skin.rgba[2] = 0.5f; skin.rgba[0] = skin.rgba[1] = skin.rgba[2] = 0.5f;
skin.rgba[3] = 1.0f; skin.rgba[3] = 1.0f;
skin.inflate = 0; skin.inflate = 0;
@@ -276,8 +283,8 @@ void mjm_defaultSkin(mjmSkin& skin) {
// default texture attributes // default texture attributes
void mjm_defaultTexture(mjmTexture& texture) { void mjs_defaultTexture(mjsTexture& texture) {
memset(&texture, 0, sizeof(mjmTexture)); memset(&texture, 0, sizeof(mjsTexture));
texture.type = mjTEXTURE_CUBE; texture.type = mjTEXTURE_CUBE;
mjuu_setvec(texture.rgb1, 0.8, 0.8, 0.8); mjuu_setvec(texture.rgb1, 0.8, 0.8, 0.8);
mjuu_setvec(texture.rgb2, 0.5, 0.5, 0.5); mjuu_setvec(texture.rgb2, 0.5, 0.5, 0.5);
@@ -290,8 +297,8 @@ void mjm_defaultTexture(mjmTexture& texture) {
// default material attributes // default material attributes
void mjm_defaultMaterial(mjmMaterial& material) { void mjs_defaultMaterial(mjsMaterial& material) {
memset(&material, 0, sizeof(mjmMaterial)); memset(&material, 0, sizeof(mjsMaterial));
material.texuniform = false; material.texuniform = false;
material.texrepeat[0] = material.texrepeat[1] = 1; material.texrepeat[0] = material.texrepeat[1] = 1;
material.emission = 0; material.emission = 0;
@@ -304,8 +311,8 @@ void mjm_defaultMaterial(mjmMaterial& material) {
// default pair attributes // default pair attributes
void mjm_defaultPair(mjmPair& pair) { void mjs_defaultPair(mjsPair& pair) {
memset(&pair, 0, sizeof(mjmPair)); memset(&pair, 0, sizeof(mjsPair));
pair.condim = 3; pair.condim = 3;
mj_defaultSolRefImp(pair.solref, pair.solimp); mj_defaultSolRefImp(pair.solref, pair.solimp);
pair.friction[0] = 1; pair.friction[0] = 1;
@@ -318,8 +325,8 @@ void mjm_defaultPair(mjmPair& pair) {
// default equality attributes // default equality attributes
void mjm_defaultEquality(mjmEquality& equality) { void mjs_defaultEquality(mjsEquality& equality) {
memset(&equality, 0, sizeof(mjmEquality)); memset(&equality, 0, sizeof(mjsEquality));
equality.type = mjEQ_CONNECT; equality.type = mjEQ_CONNECT;
equality.active = 1; equality.active = 1;
mj_defaultSolRefImp(equality.solref, equality.solimp); mj_defaultSolRefImp(equality.solref, equality.solimp);
@@ -330,8 +337,8 @@ void mjm_defaultEquality(mjmEquality& equality) {
// default tendon attributes // default tendon attributes
void mjm_defaultTendon(mjmTendon& tendon) { void mjs_defaultTendon(mjsTendon& tendon) {
memset(&tendon, 0, sizeof(mjmTendon)); memset(&tendon, 0, sizeof(mjsTendon));
tendon.limited = mjLIMITED_AUTO; tendon.limited = mjLIMITED_AUTO;
tendon.springlength[0] = tendon.springlength[1] = -1; tendon.springlength[0] = tendon.springlength[1] = -1;
mj_defaultSolRefImp(tendon.solref_limit, tendon.solimp_limit); mj_defaultSolRefImp(tendon.solref_limit, tendon.solimp_limit);
@@ -344,8 +351,8 @@ void mjm_defaultTendon(mjmTendon& tendon) {
// default actuator attributes // default actuator attributes
void mjm_defaultActuator(mjmActuator& actuator) { void mjs_defaultActuator(mjsActuator& actuator) {
memset(&actuator, 0, sizeof(mjmActuator)); memset(&actuator, 0, sizeof(mjsActuator));
// gain, bias // gain, bias
actuator.gaintype = mjGAIN_FIXED; actuator.gaintype = mjGAIN_FIXED;
@@ -370,8 +377,8 @@ void mjm_defaultActuator(mjmActuator& actuator) {
// default sensor attributes // default sensor attributes
void mjm_defaultSensor(mjmSensor& sensor) { void mjs_defaultSensor(mjsSensor& sensor) {
memset(&sensor, 0, sizeof(mjmSensor)); memset(&sensor, 0, sizeof(mjsSensor));
sensor.type = mjSENS_TOUCH; sensor.type = mjSENS_TOUCH;
sensor.datatype = mjDATATYPE_REAL; sensor.datatype = mjDATATYPE_REAL;
sensor.needstage = mjSTAGE_ACC; sensor.needstage = mjSTAGE_ACC;
@@ -380,36 +387,36 @@ void mjm_defaultSensor(mjmSensor& sensor) {
// Default numeric attributes. // Default numeric attributes.
void mjm_defaultNumeric(mjmNumeric& numeric) { void mjs_defaultNumeric(mjsNumeric& numeric) {
memset(&numeric, 0, sizeof(mjmNumeric)); memset(&numeric, 0, sizeof(mjsNumeric));
} }
// Default text attributes. // Default text attributes.
void mjm_defaultText(mjmText& text) { void mjs_defaultText(mjsText& text) {
memset(&text, 0, sizeof(mjmText)); memset(&text, 0, sizeof(mjsText));
} }
// Default tuple attributes. // Default tuple attributes.
void mjm_defaultTuple(mjmTuple& tuple) { void mjs_defaultTuple(mjsTuple& tuple) {
memset(&tuple, 0, sizeof(mjmTuple)); memset(&tuple, 0, sizeof(mjsTuple));
} }
// Default keyframe attributes. // Default keyframe attributes.
void mjm_defaultKey(mjmKey& key) { void mjs_defaultKey(mjsKey& key) {
memset(&key, 0, sizeof(mjmKey)); memset(&key, 0, sizeof(mjsKey));
} }
// default plugin attributes // default plugin attributes
void mjm_defaultPlugin(mjmPlugin& plugin) { void mjs_defaultPlugin(mjsPlugin& plugin) {
memset(&plugin, 0, sizeof(mjmPlugin)); memset(&plugin, 0, sizeof(mjsPlugin));
plugin.plugin_slot = -1; plugin.plugin_slot = -1;
} }
+235 -31
View File
@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include <algorithm> #include <algorithm>
#include <climits>
#include <cmath> #include <cmath>
#include <csetjmp> #include <csetjmp>
#include <cstddef> #include <cstddef>
@@ -60,6 +61,7 @@
#include "engine/engine_util_misc.h" #include "engine/engine_util_misc.h"
#include "engine/engine_util_solve.h" #include "engine/engine_util_solve.h"
#include "engine/engine_util_spatial.h" #include "engine/engine_util_spatial.h"
#include "user/user_cache.h"
#include "user/user_model.h" #include "user/user_model.h"
#include "user/user_objects.h" #include "user/user_objects.h"
#include "user/user_util.h" #include "user/user_util.h"
@@ -129,7 +131,8 @@ static void ReadFromBuffer(T* dst, const char* src) {
//------------------ class mjCMesh implementation -------------------------------------------------- //------------------ class mjCMesh implementation --------------------------------------------------
mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) { mjCMesh::mjCMesh(mjCModel* _model, mjCDef* _def) {
mjm_defaultMesh(spec); mjs_defaultMesh(spec);
elemtype = mjOBJ_MESH;
// clear internal variables // clear internal variables
mjuu_setvec(pos_surface_, 0, 0, 0); mjuu_setvec(pos_surface_, 0, 0, 0);
@@ -194,46 +197,67 @@ mjCMesh& mjCMesh::operator=(const mjCMesh& other) {
if (this != &other) { if (this != &other) {
this->spec = other.spec; this->spec = other.spec;
*static_cast<mjCMesh_*>(this) = static_cast<const mjCMesh_&>(other); *static_cast<mjCMesh_*>(this) = static_cast<const mjCMesh_&>(other);
*static_cast<mjmMesh*>(this) = static_cast<const mjmMesh&>(other); *static_cast<mjsMesh*>(this) = static_cast<const mjsMesh&>(other);
if (other.vert_) { if (other.vert_) {
size_t nvert = 3*other.nvert_*sizeof(float); size_t nvert = 3*other.nvert_*sizeof(float);
this->vert_ = (float*)mju_malloc(nvert); this->vert_ = (float*)mju_malloc(nvert);
memcpy(this->vert_, other.vert_, nvert); memcpy(this->vert_, other.vert_, nvert);
} else {
this->vert_ = NULL;
} }
if (other.normal_) { if (other.normal_) {
size_t nnormal = 3*other.nnormal_*sizeof(float); size_t nnormal = 3*other.nnormal_*sizeof(float);
this->normal_ = (float*)mju_malloc(nnormal); this->normal_ = (float*)mju_malloc(nnormal);
memcpy(this->normal_, other.normal_, nnormal); memcpy(this->normal_, other.normal_, nnormal);
} else {
this->normal_ = NULL;
} }
if (other.center_) { if (other.center_) {
size_t ncenter = 3*other.nface_*sizeof(double); size_t ncenter = 3*other.nface_*sizeof(double);
this->center_ = (double*)mju_malloc(ncenter); this->center_ = (double*)mju_malloc(ncenter);
memcpy(this->center_, other.center_, ncenter); memcpy(this->center_, other.center_, ncenter);
} else {
this->center_ = NULL;
} }
if (other.texcoord_) { if (other.texcoord_) {
size_t ntexcoord = 2*other.ntexcoord_*sizeof(float); size_t ntexcoord = 2*other.ntexcoord_*sizeof(float);
this->texcoord_ = (float*)mju_malloc(ntexcoord); this->texcoord_ = (float*)mju_malloc(ntexcoord);
memcpy(this->texcoord_, other.texcoord_, ntexcoord); memcpy(this->texcoord_, other.texcoord_, ntexcoord);
} else {
this->texcoord_ = NULL;
} }
if (other.face_) { if (other.face_) {
size_t nface = 3*other.nface_*sizeof(int); size_t nface = 3*other.nface_*sizeof(int);
this->face_ = (int*)mju_malloc(nface); this->face_ = (int*)mju_malloc(nface);
memcpy(this->face_, other.face_, nface); memcpy(this->face_, other.face_, nface);
} else {
this->face_ = NULL;
} }
if (other.facenormal_) { if (other.facenormal_) {
size_t nfacenormal = 3*other.nface_*sizeof(int); size_t nfacenormal = 3*other.nface_*sizeof(int);
this->facenormal_ = (int*)mju_malloc(nfacenormal); this->facenormal_ = (int*)mju_malloc(nfacenormal);
memcpy(this->facenormal_, other.facenormal_, nfacenormal); memcpy(this->facenormal_, other.facenormal_, nfacenormal);
} else {
this->facenormal_ = NULL;
} }
if (other.facetexcoord_) { if (other.facetexcoord_) {
size_t nfacetexcoord = 3*other.nface_*sizeof(int); size_t nfacetexcoord = 3*other.nface_*sizeof(int);
this->facetexcoord_ = (int*)mju_malloc(nfacetexcoord); this->facetexcoord_ = (int*)mju_malloc(nfacetexcoord);
memcpy(this->facetexcoord_, other.facetexcoord_, nfacetexcoord); memcpy(this->facetexcoord_, other.facetexcoord_, nfacetexcoord);
} else {
this->facetexcoord_ = NULL;
} }
if (other.graph_) { if (other.graph_) {
size_t szgraph = szgraph_*sizeof(int); size_t szgraph = szgraph_*sizeof(int);
this->graph_ = (int*)mju_malloc(szgraph); this->graph_ = (int*)mju_malloc(szgraph);
memcpy(this->graph_, other.graph_, szgraph); memcpy(this->graph_, other.graph_, szgraph);
} else {
this->graph_ = NULL;
}
if (other.plugin.instance) {
mjCPlugin* new_plugin = new mjCPlugin(*static_cast<mjCPlugin*>(other.plugin.instance));
plugin = new_plugin->spec;
model->plugins.push_back(new_plugin);
} }
} }
PointToLocal(); PointToLocal();
@@ -243,7 +267,7 @@ mjCMesh& mjCMesh::operator=(const mjCMesh& other) {
void mjCMesh::PointToLocal() { void mjCMesh::PointToLocal() {
spec.element = (mjElement)this; spec.element = static_cast<mjElement*>(this);
spec.name = (mjString)&name; spec.name = (mjString)&name;
spec.classname = (mjString)&classname; spec.classname = (mjString)&classname;
spec.file = (mjString)&spec_file_; spec.file = (mjString)&spec_file_;
@@ -260,7 +284,7 @@ void mjCMesh::PointToLocal() {
void mjCMesh::CopyFromSpec() { void mjCMesh::CopyFromSpec() {
*static_cast<mjmMesh*>(this) = spec; *static_cast<mjsMesh*>(this) = spec;
file_ = spec_file_; file_ = spec_file_;
content_type_ = spec_content_type_; content_type_ = spec_content_type_;
uservert_ = spec_uservert_; uservert_ = spec_uservert_;
@@ -336,8 +360,9 @@ void mjCMesh::LoadSDF() {
name.c_str(), id); name.c_str(), id);
} }
mjCPlugin* plugin_instance = (mjCPlugin*)plugin.instance; mjCPlugin* plugin_instance = static_cast<mjCPlugin*>(plugin.instance);
model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance); model->ResolvePlugin(this, plugin_name, plugin_instance_name, &plugin_instance);
plugin.instance = plugin_instance;
const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot); const mjpPlugin* pplugin = mjp_getPluginAtSlot(plugin_instance->spec.plugin_slot);
if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) { if (!(pplugin->capabilityflags & mjPLUGIN_SDF)) {
throw mjCError(this, "plugin '%s' does not support signed distance fields", pplugin->name); throw mjCError(this, "plugin '%s' does not support signed distance fields", pplugin->name);
@@ -410,6 +435,7 @@ void mjCMesh::LoadSDF() {
// compiler // compiler
void mjCMesh::Compile(const mjVFS* vfs) { void mjCMesh::Compile(const mjVFS* vfs) {
CopyFromSpec(); CopyFromSpec();
visual_ = true;
// load file // load file
if (!file_.empty()) { if (!file_.empty()) {
@@ -526,7 +552,8 @@ void mjCMesh::Compile(const mjVFS* vfs) {
// check vertices exist // check vertices exist
for (int i=0; i<userface_.size(); i++) { for (int i=0; i<userface_.size(); i++) {
if (userface_[i] >= nvert_ || userface_[i] < 0) { if (userface_[i] >= nvert_ || userface_[i] < 0) {
throw mjCError(this, "index in face does not exist in vertex array"); throw mjCError(this, "in face %d, vertex index %d does not exist",
nullptr, i / 3, userface_[i]);
} }
} }
@@ -967,6 +994,19 @@ void mjCMesh::RemoveRepeated() {
void mjCMesh::LoadOBJ(mjResource* resource) { void mjCMesh::LoadOBJ(mjResource* resource) {
tinyobj::ObjReader objReader; tinyobj::ObjReader objReader;
const void* bytes = nullptr; const void* bytes = nullptr;
// try loading from cache
mjCCache *cache = reinterpret_cast<mjCCache*>(mj_globalCache());
if (cache) {
auto asset = cache->Get(resource->name);
if (asset.has_value() &&
!mju_isModifiedResource(resource, asset->Timestamp().c_str())) {
if (LoadCachedOBJ(asset.value())) {
return;
}
}
}
int buffer_sz = mju_readResource(resource, &bytes); int buffer_sz = mju_readResource(resource, &bytes);
if (buffer_sz < 0) { if (buffer_sz < 0) {
throw mjCError(this, "could not read OBJ file '%s'", resource->name); throw mjCError(this, "could not read OBJ file '%s'", resource->name);
@@ -1030,8 +1070,116 @@ void mjCMesh::LoadOBJ(mjResource* resource) {
for (int i=0; i<usertexcoord_.size()/2; i++) { for (int i=0; i<usertexcoord_.size()/2; i++) {
usertexcoord_[2*i+1] = 1-usertexcoord_[2*i+1]; usertexcoord_[2*i+1] = 1-usertexcoord_[2*i+1];
} }
// try caching asset
if (cache) {
mjCAsset asset("", resource->name, resource->timestamp);
asset.AddVector("uservert_", uservert_);
asset.AddVector("usernormal_", usernormal_);
asset.AddVector("usertexcoord_", usertexcoord_);
if (!objReader.GetShapes().empty()) {
const auto& mesh = objReader.GetShapes()[0].mesh;
std::vector<int> vertex_index;
vertex_index.reserve(mesh.indices.size());
std::vector<int> normal_index;
normal_index.reserve(mesh.indices.size());
std::vector<int> texcoord_index;
texcoord_index.reserve(mesh.indices.size());
for (tinyobj::index_t index : mesh.indices) {
vertex_index.push_back(index.vertex_index);
normal_index.push_back(index.normal_index);
texcoord_index.push_back(index.texcoord_index);
} }
asset.AddVector("num_face_vertices", mesh.num_face_vertices);
asset.AddVector("vertex_index", vertex_index);
asset.AddVector("normal_index", normal_index);
asset.AddVector("texcoord_index", texcoord_index);
} else {
asset.AddVector("num_face_vertices", std::vector<unsigned char>());
asset.AddVector("vertex_index", std::vector<int>());
asset.AddVector("normal_index", std::vector<int>());
asset.AddVector("texcoord_index", std::vector<int>());
}
cache->Insert(std::move(asset));
}
}
// load OBJ from cached asset, return true on success
bool mjCMesh::LoadCachedOBJ(const mjCAsset& asset) {
// check that asset has all data
if (!asset.HasData("uservert_") || !asset.HasData("usernormal_")
|| !asset.HasData("usertexcoord_") || !asset.HasData("num_face_vertices")
|| !asset.HasData("vertex_index") || !asset.HasData("normal_index")
|| !asset.HasData("texcoord_index")) {
return false;
}
uservert_ = asset.GetVector<float>("uservert_").value();
usernormal_ = asset.GetVector<float>("usernormal_").value();
usertexcoord_ = asset.GetVector<float>("usertexcoord_").value();
vector<int> vertex_index = asset.GetVector<int>("vertex_index").value();
vector<int> normal_index = asset.GetVector<int>("normal_index").value();
vector<int> texcoord_index = asset.GetVector<int>("texcoord_index").value();
vector<unsigned char> num_face_vertices =
asset.GetVector<unsigned char>("num_face_vertices").value();
bool righthand = (scale[0] * scale[1] * scale[2]) > 0;
for (int face = 0, i = 0; i < vertex_index.size();) {
int nfacevert = num_face_vertices[face];
if (nfacevert < 3 || nfacevert > 4) {
throw mjCError(
this, "only tri or quad meshes are supported for OBJ (file '%s')",
asset.Id().c_str());
}
userface_.push_back(vertex_index[i]);
userface_.push_back(vertex_index[i + (righthand == 1 ? 1 : 2)]);
userface_.push_back(vertex_index[i + (righthand == 1 ? 2 : 1)]);
if (!usernormal_.empty()) {
userfacenormal_.push_back(normal_index[i]);
userfacenormal_.push_back(normal_index[i + (righthand == 1 ? 1 : 2)]);
userfacenormal_.push_back(normal_index[i + (righthand == 1 ? 2 : 1)]);
}
if (!usertexcoord_.empty()) {
userfacetexcoord_.push_back(texcoord_index[i]);
userfacetexcoord_.push_back(texcoord_index[i + (righthand == 1 ? 1 : 2)]);
userfacetexcoord_.push_back(texcoord_index[i + (righthand == 1 ? 2 : 1)]);
}
if (nfacevert == 4) {
userface_.push_back(vertex_index[i]);
userface_.push_back(vertex_index[i + (righthand == 1 ? 2 : 3)]);
userface_.push_back(vertex_index[i + (righthand == 1 ? 3 : 2)]);
if (!usernormal_.empty()) {
userfacenormal_.push_back(normal_index[i]);
userfacenormal_.push_back(normal_index[i + (righthand == 1 ? 1 : 2)]);
userfacenormal_.push_back(normal_index[i + (righthand == 1 ? 2 : 1)]);
}
if (!usertexcoord_.empty()) {
userfacetexcoord_.push_back(texcoord_index[i]);
userfacetexcoord_.push_back(texcoord_index[i + (righthand == 1 ? 1 : 2)]);
userfacetexcoord_.push_back(texcoord_index[i + (righthand == 1 ? 2 : 1)]);
}
}
i += nfacevert;
++face;
}
return true;
}
// load STL binary mesh // load STL binary mesh
void mjCMesh::LoadSTL(mjResource* resource) { void mjCMesh::LoadSTL(mjResource* resource) {
@@ -1146,6 +1294,12 @@ void mjCMesh::LoadMSH(mjResource* resource) {
throw mjCError(this, "invalid sizes in MSH file '%s'", resource->name); throw mjCError(this, "invalid sizes in MSH file '%s'", resource->name);
} }
if (nvert_ >= INT_MAX / sizeof(float) / 3 ||
nnormal_ >= INT_MAX / sizeof(float) / 3 ||
ntexcoord_ >= INT_MAX / sizeof(float) / 2 ||
nface_ >= INT_MAX / sizeof(int) / 3) {
throw mjCError(this, "too large sizes in MSH file '%s'.", resource->name);
}
// check file size // check file size
if (buffer_sz != 4*sizeof(int) + 3*nvert_*sizeof(float) + 3*nnormal_*sizeof(float) + if (buffer_sz != 4*sizeof(int) + 3*nvert_*sizeof(float) + 3*nnormal_*sizeof(float) +
2*ntexcoord_*sizeof(float) + 3*nface_*sizeof(int)) { 2*ntexcoord_*sizeof(float) + 3*nface_*sizeof(int)) {
@@ -1493,7 +1647,7 @@ void mjCMesh::CheckMesh(mjtGeomInertia type) {
if (!processed_) { if (!processed_) {
return; return;
} }
if (invalidorientation_.first>=0 || invalidorientation_.second>=0) if ((invalidorientation_.first>=0 || invalidorientation_.second>=0) && model->exactmeshinertia)
throw mjCError(this, throw mjCError(this,
"faces of mesh '%s' have inconsistent orientation. Please check the " "faces of mesh '%s' have inconsistent orientation. Please check the "
"faces containing the vertices %d and %d.", "faces containing the vertices %d and %d.",
@@ -1910,7 +2064,8 @@ void mjCMesh::MakeCenter(void) {
// constructor // constructor
mjCSkin::mjCSkin(mjCModel* _model) { mjCSkin::mjCSkin(mjCModel* _model) {
mjm_defaultSkin(spec); mjs_defaultSkin(spec);
elemtype = mjOBJ_SKIN;
// set model pointer // set model pointer
model = _model; model = _model;
@@ -1939,8 +2094,26 @@ mjCSkin::mjCSkin(mjCModel* _model) {
mjCSkin::mjCSkin(const mjCSkin& other) {
*this = other;
}
mjCSkin& mjCSkin::operator=(const mjCSkin& other) {
if (this != &other) {
this->spec = other.spec;
*static_cast<mjCSkin_*>(this) = static_cast<const mjCSkin_&>(other);
*static_cast<mjsSkin*>(this) = static_cast<const mjsSkin&>(other);
}
PointToLocal();
return *this;
}
void mjCSkin::PointToLocal() { void mjCSkin::PointToLocal() {
spec.element = (mjElement)this; spec.element = static_cast<mjElement*>(this);
spec.name = (mjString)&name; spec.name = (mjString)&name;
spec.classname = (mjString)&classname; spec.classname = (mjString)&classname;
spec.file = (mjString)&spec_file_; spec.file = (mjString)&spec_file_;
@@ -1958,8 +2131,16 @@ void mjCSkin::PointToLocal() {
void mjCSkin::NameSpace(const mjCModel* m) {
for (int i=0; i<(int)spec_bodyname_.size(); i++) {
spec_bodyname_[i] = m->prefix + spec_bodyname_[i] + m->suffix;
}
}
void mjCSkin::CopyFromSpec() { void mjCSkin::CopyFromSpec() {
*static_cast<mjmSkin*>(this) = spec; *static_cast<mjsSkin*>(this) = spec;
file_ = spec_file_; file_ = spec_file_;
material_ = spec_material_; material_ = spec_material_;
vert_ = spec_vert_; vert_ = spec_vert_;
@@ -2001,6 +2182,20 @@ mjCSkin::~mjCSkin() {
void mjCSkin::ResolveReferences(const mjCModel* m) {
size_t nbone = bodyname_.size();
bodyid.resize(nbone);
for (int i=0; i<nbone; i++) {
mjCBase* pbody = m->FindObject(mjOBJ_BODY, bodyname_[i]);
if (!pbody) {
throw mjCError(this, "unknown body '%s' in skin", bodyname_[i].c_str());
}
bodyid[i] = pbody->id;
}
}
// compiler // compiler
void mjCSkin::Compile(const mjVFS* vfs) { void mjCSkin::Compile(const mjVFS* vfs) {
CopyFromSpec(); CopyFromSpec();
@@ -2081,14 +2276,7 @@ void mjCSkin::Compile(const mjVFS* vfs) {
} }
// resolve body names // resolve body names
bodyid.resize(nbone); ResolveReferences(model);
for (int i=0; i<nbone; i++) {
mjCBase* pbody = model->FindObject(mjOBJ_BODY, bodyname_[i]);
if (!pbody) {
throw mjCError(this, "unknown body '%s' in skin", bodyname_[i].c_str());
}
bodyid[i] = pbody->id;
}
// resolve material name // resolve material name
mjCBase* pmat = model->FindObject(mjOBJ_MATERIAL, material_); mjCBase* pmat = model->FindObject(mjOBJ_MATERIAL, material_);
@@ -2301,7 +2489,8 @@ constexpr int eledge[3][6][2] = {{{ 0, 1}, {-1, -1}, {-1, -1},
// constructor // constructor
mjCFlex::mjCFlex(mjCModel* _model) { mjCFlex::mjCFlex(mjCModel* _model) {
mjm_defaultFlex(spec); mjs_defaultFlex(spec);
elemtype = mjOBJ_FLEX;
// set model // set model
model = _model; model = _model;
@@ -2328,7 +2517,7 @@ mjCFlex& mjCFlex::operator=(const mjCFlex& other) {
if (this != &other) { if (this != &other) {
this->spec = other.spec; this->spec = other.spec;
*static_cast<mjCFlex_*>(this) = static_cast<const mjCFlex_&>(other); *static_cast<mjCFlex_*>(this) = static_cast<const mjCFlex_&>(other);
*static_cast<mjmFlex*>(this) = static_cast<const mjmFlex&>(other); *static_cast<mjsFlex*>(this) = static_cast<const mjsFlex&>(other);
} }
PointToLocal(); PointToLocal();
return *this; return *this;
@@ -2336,7 +2525,7 @@ mjCFlex& mjCFlex::operator=(const mjCFlex& other) {
void mjCFlex::PointToLocal() { void mjCFlex::PointToLocal() {
spec.element = (mjElement)this; spec.element = static_cast<mjElement*>(this);
spec.name = (mjString)&name; spec.name = (mjString)&name;
spec.classname = (mjString)&classname; spec.classname = (mjString)&classname;
spec.material = (mjString)&spec_material_; spec.material = (mjString)&spec_material_;
@@ -2348,8 +2537,17 @@ void mjCFlex::PointToLocal() {
} }
void mjCFlex::NameSpace(const mjCModel* m) {
for (int i=0; i<(int)spec_vertbody_.size(); i++) {
spec_vertbody_[i] = m->prefix + spec_vertbody_[i] + m->suffix;
}
}
void mjCFlex::CopyFromSpec() { void mjCFlex::CopyFromSpec() {
*static_cast<mjmFlex*>(this) = spec; *static_cast<mjsFlex*>(this) = spec;
spec.info = (mjString)&info; spec.info = (mjString)&info;
material_ = spec_material_; material_ = spec_material_;
vertbody_ = spec_vertbody_; vertbody_ = spec_vertbody_;
@@ -2380,6 +2578,18 @@ void mjCFlex::DelTexcoord() {
} }
void mjCFlex::ResolveReferences(const mjCModel* m) {
for (int i=0; i<(int)vertbody_.size(); i++) {
mjCBase* pbody = m->FindObject(mjOBJ_BODY, vertbody_[i]);
if (pbody) {
vertbodyid.push_back(pbody->id);
} else {
throw mjCError(this, "unkown body '%s' in flex", vertbody_[i].c_str());
}
}
}
// compiler // compiler
void mjCFlex::Compile(const mjVFS* vfs) { void mjCFlex::Compile(const mjVFS* vfs) {
CopyFromSpec(); CopyFromSpec();
@@ -2441,14 +2651,7 @@ void mjCFlex::Compile(const mjVFS* vfs) {
} }
// resolve body ids // resolve body ids
for (int i=0; i<(int)vertbody_.size(); i++) { ResolveReferences(model);
mjCBase* pbody = model->FindObject(mjOBJ_BODY, vertbody_[i]);
if (pbody) {
vertbodyid.push_back(pbody->id);
} else {
throw mjCError(this, "unkown body '%s' in flex", vertbody_[i].c_str());
}
}
// process elements // process elements
for (int e=0; e<(int)elem_.size()/(dim+1); e++) { for (int e=0; e<(int)elem_.size()/(dim+1); e++) {
@@ -2564,7 +2767,8 @@ void mjCFlex::Compile(const mjVFS* vfs) {
for (int i=0; i<(int)vertbodyid.size(); i++) { for (int i=0; i<(int)vertbodyid.size(); i++) {
if (model->bodies[vertbodyid[i]]->plugin.instance) { if (model->bodies[vertbodyid[i]]->plugin.instance) {
mjCPlugin* plugin_instance = (mjCPlugin*)model->bodies[vertbodyid[i]]->plugin.instance; mjCPlugin* plugin_instance =
static_cast<mjCPlugin*>(model->bodies[vertbodyid[i]]->plugin.instance);
plugin_instance->config_attribs["face"] = userface; plugin_instance->config_attribs["face"] = userface;
plugin_instance->config_attribs["edge"] = useredge; plugin_instance->config_attribs["edge"] = useredge;
} }
+321 -146
View File
@@ -83,7 +83,8 @@ static void copyvec(T1* dest, T2* src, int n) {
// constructor // constructor
mjCModel::mjCModel() { mjCModel::mjCModel() {
mjm_defaultSpec(spec); mjs_defaultSpec(spec);
elemtype = mjOBJ_UNKNOWN;
spec_comment_.clear(); spec_comment_.clear();
spec_modelfiledir_.clear(); spec_modelfiledir_.clear();
spec_meshdir_.clear(); spec_meshdir_.clear();
@@ -120,6 +121,8 @@ mjCModel::mjCModel() {
tuples.clear(); tuples.clear();
keys.clear(); keys.clear();
defaults.clear(); defaults.clear();
prefix = "";
suffix = "";
Clear(); Clear();
//------------------------ master default set //------------------------ master default set
@@ -138,6 +141,152 @@ mjCModel::mjCModel() {
world->def = defaults[0]; world->def = defaults[0];
bodies.push_back(world); bodies.push_back(world);
// create mjCBase lists from children lists
CreateObjectLists();
// point to model from spec
PointToLocal();
// this class allocated the plugins
plugin_owner = true;
}
mjCModel::mjCModel(const mjCModel& other) {
*this = other;
}
mjCModel& mjCModel::operator=(const mjCModel& other) {
if (this != &other) {
plugin_owner = false;
this->spec = other.spec;
*static_cast<mjCModel_*>(this) = static_cast<const mjCModel_&>(other);
*static_cast<mjSpec*>(this) = static_cast<const mjSpec&>(other);
// the world copy constructor takes care of copying the tree
mjCBody* world = new mjCBody(*other.bodies[0], this);
bodies.push_back(world);
// add everything else
*this += other;
// copy name maps
for (int i=0; i<mjNOBJECT; i++) {
ids[i] = other.ids[i];
}
}
return *this;
}
// copy vector of elements from another model to this model
template <class T>
void mjCModel::CopyList(std::vector<T*>& dest,
const std::vector<T*>& source,
std::map<mjCDef*, int>& def_map,
const std::vector<mjCDef*>& defaults) {
// loop over the elements from the other model
for (T* element : source) {
try {
// try to find the referenced object in this model
element->NameSpace(element->model);
element->CopyFromSpec();
element->ResolveReferences(this);
} catch (mjCError err) {
// if not present, skip the element
continue;
}
// copy the element from the other model to this model
dest.push_back(new T(*element));
dest.back()->model = this;
dest.back()->def = defaults[def_map[element->def]];
}
}
mjCModel& mjCModel::operator+=(const mjCModel& other) {
if (this != &other) {
// create global lists
MakeLists(bodies[0]);
CreateObjectLists();
ProcessLists();
// copy all elements not in the tree
std::map<mjCDef*, int> def_map;
for (int i = 0; i < other.defaults.size(); i++) {
defaults.push_back(new mjCDef(*other.defaults[i]));
def_map[other.defaults[i]] = i;
}
CopyList(flexes, other.flexes, def_map, defaults);
CopyList(meshes, other.meshes, def_map, defaults);
CopyList(skins, other.skins, def_map, defaults);
CopyList(hfields, other.hfields, def_map, defaults);
CopyList(textures, other.textures, def_map, defaults);
CopyList(materials, other.materials, def_map, defaults);
CopyList(pairs, other.pairs, def_map, defaults);
CopyList(excludes, other.excludes, def_map, defaults);
CopyList(tendons, other.tendons, def_map, defaults);
CopyList(equalities, other.equalities, def_map, defaults);
CopyList(actuators, other.actuators, def_map, defaults);
CopyList(sensors, other.sensors, def_map, defaults);
CopyList(numerics, other.numerics, def_map, defaults);
CopyList(texts, other.texts, def_map, defaults);
CopyList(tuples, other.tuples, def_map, defaults);
CopyList(keys, other.keys, def_map, defaults);
// plugins are global
plugins = other.plugins;
active_plugins = other.active_plugins;
// update defaults for the copied objects
for (int i = 1; i < other.bodies.size(); i++) {
bodies[i]->def = defaults[def_map[other.bodies[i]->def]];
}
for (int i = 0; i < other.joints.size(); i++) {
joints[i]->def = defaults[def_map[other.joints[i]->def]];
}
for (int i = 0; i < other.geoms.size(); i++) {
geoms[i]->def = defaults[def_map[other.geoms[i]->def]];
}
for (int i = 0; i < other.sites.size(); i++) {
sites[i]->def = defaults[def_map[other.sites[i]->def]];
}
for (int i = 0; i < other.cameras.size(); i++) {
cameras[i]->def = defaults[def_map[other.cameras[i]->def]];
}
for (int i = 0; i < other.lights.size(); i++) {
lights[i]->def = defaults[def_map[other.lights[i]->def]];
}
// cast children to mjCBase
// restore to the same state as other
if (!compiled) {
mjCBody* world = bodies[0];
bodies.clear();
frames.clear();
joints.clear();
geoms.clear();
sites.clear();
cameras.clear();
lights.clear();
bodies.push_back(world);
}
}
PointToLocal();
return *this;
}
// TODO: we should not use C-type casting with multiple C++ inheritance
void mjCModel::CreateObjectLists() {
for (int i = 0; i < mjNOBJECT; ++i) { for (int i = 0; i < mjNOBJECT; ++i) {
object_lists[i] = nullptr; object_lists[i] = nullptr;
} }
@@ -166,23 +315,12 @@ mjCModel::mjCModel() {
object_lists[mjOBJ_TUPLE] = (std::vector<mjCBase*>*) &tuples; object_lists[mjOBJ_TUPLE] = (std::vector<mjCBase*>*) &tuples;
object_lists[mjOBJ_KEY] = (std::vector<mjCBase*>*) &keys; object_lists[mjOBJ_KEY] = (std::vector<mjCBase*>*) &keys;
object_lists[mjOBJ_PLUGIN] = (std::vector<mjCBase*>*) &plugins; object_lists[mjOBJ_PLUGIN] = (std::vector<mjCBase*>*) &plugins;
// point to model from spec
PointToLocal();
}
mjCModel::mjCModel(const mjCModel& other) {
*this = other;
PointToLocal();
} }
void mjCModel::PointToLocal() { void mjCModel::PointToLocal() {
spec.element = (mjElement)this; spec.element = static_cast<mjElement*>(this);
spec.comment = (mjString)&spec_comment_; spec.comment = (mjString)&spec_comment_;
spec.modelfiledir = (mjString)&spec_modelfiledir_; spec.modelfiledir = (mjString)&spec_modelfiledir_;
spec.modelname = (mjString)&spec_modelname_; spec.modelname = (mjString)&spec_modelname_;
@@ -230,9 +368,12 @@ mjCModel::~mjCModel() {
for (int i=0; i<texts.size(); i++) delete texts[i]; for (int i=0; i<texts.size(); i++) delete texts[i];
for (int i=0; i<tuples.size(); i++) delete tuples[i]; for (int i=0; i<tuples.size(); i++) delete tuples[i];
for (int i=0; i<keys.size(); i++) delete keys[i]; for (int i=0; i<keys.size(); i++) delete keys[i];
for (int i=0; i<plugins.size(); i++) delete plugins[i];
for (int i=0; i<defaults.size(); i++) delete defaults[i]; for (int i=0; i<defaults.size(); i++) delete defaults[i];
if (plugin_owner) {
for (int i=0; i<plugins.size(); i++) delete plugins[i];
}
// clear pointer lists created in model construction // clear pointer lists created in model construction
flexes.clear(); flexes.clear();
meshes.clear(); meshes.clear();
@@ -339,7 +480,6 @@ void mjCModel::Clear(void) {
hasImplicitPluginElem = false; hasImplicitPluginElem = false;
compiled = false; compiled = false;
errInfo = mjCError(); errInfo = mjCError();
fixCount = 0;
qpos0.clear(); qpos0.clear();
} }
@@ -498,35 +638,28 @@ mjCBase* mjCModel::GetObject(mjtObj type, int id) {
//------------------------ API FOR ACCESS TO PRIVATE VARIABLES ------------------------------------- //------------------------ API FOR ACCESS TO PRIVATE VARIABLES -------------------------------------
// compiled flag // compiled flag
bool mjCModel::IsCompiled(void) { bool mjCModel::IsCompiled(void) const {
return compiled; return compiled;
} }
// number of massless bodies that were fixed
int mjCModel::GetFixed(void) {
return fixCount;
}
// get reference of error object // get reference of error object
const mjCError& mjCModel::GetError(void) { const mjCError& mjCModel::GetError(void) const {
return errInfo; return errInfo;
} }
// pointer to world body // pointer to world body
mjCBody* mjCModel::GetWorld(void) { mjCBody* mjCModel::GetWorld(void) const {
return bodies[0]; return bodies[0];
} }
// find default class name in array // find default class name in array
mjCDef* mjCModel::FindDef(string name) { mjCDef* mjCModel::FindDef(string name) const {
for (int i=0; i<(int)defaults.size(); i++) { for (int i=0; i<(int)defaults.size(); i++) {
if (defaults[i]->name==name) { if (defaults[i]->name==name) {
return defaults[i]; return defaults[i];
@@ -589,7 +722,7 @@ static T* findobject(std::string_view name, const vector<T*>& list, const mjKeyM
} }
// find object in global lists given string type and name // find object in global lists given string type and name
mjCBase* mjCModel::FindObject(mjtObj type, string name) { mjCBase* mjCModel::FindObject(mjtObj type, string name) const {
if (!object_lists[type]) { if (!object_lists[type]) {
return nullptr; return nullptr;
} }
@@ -598,8 +731,46 @@ mjCBase* mjCModel::FindObject(mjtObj type, string name) {
// find body by name
mjCBody* mjCModel::FindBody(mjCBody* body, std::string name) const {
if (body->name == name) {
return body;
}
for (auto child : body->bodies) {
auto candidate = FindBody(child, name);
if (candidate) {
return candidate;
}
}
return nullptr;
}
// find frame by name
mjCFrame* mjCModel::FindFrame(mjCBody* body, std::string name) const{
for (auto frame : body->frames) {
if (frame->name == name) {
return frame;
}
}
for (auto body : body->bodies) {
auto candidate = FindFrame(body, name);
if (candidate) {
return candidate;
}
}
return nullptr;
}
// detect null pose // detect null pose
bool mjCModel::IsNullPose(const mjtNum* pos, const mjtNum* quat) { bool mjCModel::IsNullPose(const mjtNum* pos, const mjtNum* quat) const {
bool result = true; bool result = true;
// check position if given // check position if given
@@ -761,112 +932,154 @@ void mjCModel::DeleteAll<mjCTexture>(std::vector<mjCTexture*>& elements) {
elements.clear(); elements.clear();
} }
// set nuser fields
void mjCModel::SetNuser(){
if (nuser_body == -1) {
nuser_body = 0;
for (int i=0; i<bodies.size(); i++) {
nuser_body = mjMAX(nuser_body, bodies[i]->spec_userdata_.size());
}
}
if (nuser_jnt == -1) {
nuser_jnt = 0;
for (int i=0; i<joints.size(); i++) {
nuser_jnt = mjMAX(nuser_jnt, joints[i]->spec_userdata_.size());
}
}
if (nuser_geom == -1) {
nuser_geom = 0;
for (int i=0; i<geoms.size(); i++) {
nuser_geom = mjMAX(nuser_geom, geoms[i]->spec_userdata_.size());
}
}
if (nuser_site == -1) {
nuser_site = 0;
for (int i=0; i<sites.size(); i++) {
nuser_site = mjMAX(nuser_site, sites[i]->spec_userdata_.size());
}
}
if (nuser_cam == -1) {
nuser_cam = 0;
for (int i=0; i<cameras.size(); i++) {
nuser_cam = mjMAX(nuser_cam, cameras[i]->spec_userdata_.size());
}
}
if (nuser_tendon == -1) {
nuser_tendon = 0;
for (int i=0; i<tendons.size(); i++) {
nuser_tendon = mjMAX(nuser_tendon, tendons[i]->spec_userdata_.size());
}
}
if (nuser_actuator == -1) {
nuser_actuator = 0;
for (int i=0; i<actuators.size(); i++) {
nuser_actuator = mjMAX(nuser_actuator, actuators[i]->spec_userdata_.size());
}
}
if (nuser_sensor == -1) {
nuser_sensor = 0;
for (int i=0; i<sensors.size(); i++) {
nuser_sensor = mjMAX(nuser_sensor, sensors[i]->spec_userdata_.size());
}
}
}
// index assets // index assets
void mjCModel::IndexAssets(bool discard) { void mjCModel::IndexAssets(bool discard) {
// assets referenced in geoms // assets referenced in geoms
for (int i=0; i<geoms.size(); i++) { for (int i=0; i<geoms.size(); i++) {
mjCGeom* pgeom = geoms[i]; mjCGeom* geom = geoms[i];
// find material by name // find material by name
if (!pgeom->get_material().empty()) { if (!geom->get_material().empty()) {
mjCBase* m = FindObject(mjOBJ_MATERIAL, pgeom->get_material()); mjCBase* material = FindObject(mjOBJ_MATERIAL, geom->get_material());
if (m) { if (material) {
pgeom->matid = m->id; geom->matid = material->id;
} else { } else {
throw mjCError(pgeom, "material '%s' not found in geom %d", pgeom->get_material().c_str(), i); throw mjCError(geom, "material '%s' not found in geom %d", geom->get_material().c_str(), i);
} }
} }
// find mesh by name // find mesh by name
if (!pgeom->get_meshname().empty()) { if (!geom->get_meshname().empty()) {
mjCBase* m = FindObject(mjOBJ_MESH, pgeom->get_meshname()); mjCBase* mesh = FindObject(mjOBJ_MESH, geom->get_meshname());
if (m) { if (mesh) {
if (discard && geoms[i]->visual_) { if (!geom->visual_) {
// do not associate with a mesh ((mjCMesh*)mesh)->SetNotVisual(); // reset to true by mesh->Compile()
pgeom->mesh = nullptr;
} else {
// associate mesh with geom
pgeom->mesh = (mjCMesh*)m;
// mark mesh as not visual
// this is irreversible so only performed when IndexAssets is called with discard
if (discard) {
pgeom->mesh->SetNotVisual();
}
} }
geom->mesh = (discard && geom->visual_) ? nullptr : (mjCMesh*)mesh;
} else { } else {
throw mjCError(pgeom, "mesh '%s' not found in geom %d", pgeom->get_meshname().c_str(), i); throw mjCError(geom, "mesh '%s' not found in geom %d", geom->get_meshname().c_str(), i);
} }
} }
// find hfield by name // find hfield by name
if (!pgeom->get_hfieldname().empty()) { if (!geom->get_hfieldname().empty()) {
mjCBase* m = FindObject(mjOBJ_HFIELD, pgeom->get_hfieldname()); mjCBase* hfield = FindObject(mjOBJ_HFIELD, geom->get_hfieldname());
if (m) { if (hfield) {
pgeom->hfield = (mjCHField*)m; geom->hfield = (mjCHField*)hfield;
} else { } else {
throw mjCError(pgeom, "hfield '%s' not found in geom %d", pgeom->get_hfieldname().c_str(), i); throw mjCError(geom, "hfield '%s' not found in geom %d", geom->get_hfieldname().c_str(), i);
} }
} }
} }
// assets referenced in skins // assets referenced in skins
for (int i=0; i<skins.size(); i++) { for (int i=0; i<skins.size(); i++) {
mjCSkin* pskin = skins[i]; mjCSkin* skin = skins[i];
// find material by name // find material by name
if (!pskin->material_.empty()) { if (!skin->material_.empty()) {
mjCBase* m = FindObject(mjOBJ_MATERIAL, pskin->material_); mjCBase* material = FindObject(mjOBJ_MATERIAL, skin->material_);
if (m) { if (material) {
pskin->matid = m->id; skin->matid = material->id;
} else { } else {
throw mjCError(pskin, "material '%s' not found in skin %d", pskin->material_.c_str(), i); throw mjCError(skin, "material '%s' not found in skin %d", skin->material_.c_str(), i);
} }
} }
} }
// materials referenced in sites // materials referenced in sites
for (int i=0; i<sites.size(); i++) { for (int i=0; i<sites.size(); i++) {
mjCSite* psite = sites[i]; mjCSite* site = sites[i];
// find material by name // find material by name
if (!psite->material_.empty()) { if (!site->material_.empty()) {
mjCBase* m = FindObject(mjOBJ_MATERIAL, psite->get_material()); mjCBase* material = FindObject(mjOBJ_MATERIAL, site->get_material());
if (m) { if (material) {
psite->matid = m->id; site->matid = material->id;
} else { } else {
throw mjCError(psite, "material '%s' not found in site %d", psite->material_.c_str(), i); throw mjCError(site, "material '%s' not found in site %d", site->material_.c_str(), i);
} }
} }
} }
// materials referenced in tendons // materials referenced in tendons
for (int i=0; i<tendons.size(); i++) { for (int i=0; i<tendons.size(); i++) {
mjCTendon* pten = tendons[i]; mjCTendon* tendon = tendons[i];
// find material by name // find material by name
if (!pten->material_.empty()) { if (!tendon->material_.empty()) {
mjCBase* m = FindObject(mjOBJ_MATERIAL, pten->material_); mjCBase* material = FindObject(mjOBJ_MATERIAL, tendon->material_);
if (m) { if (material) {
pten->matid = m->id; tendon->matid = material->id;
} else { } else {
throw mjCError(pten, "material '%s' not found in tendon %d", pten->material_.c_str(), i); throw mjCError(tendon, "material '%s' not found in tendon %d", tendon->material_.c_str(), i);
} }
} }
} }
// textures referenced in materials // textures referenced in materials
for (int i=0; i<materials.size(); i++) { for (int i=0; i<materials.size(); i++) {
mjCMaterial* pmat = materials[i]; mjCMaterial* material = materials[i];
// find texture by name // find texture by name
if (!pmat->texture_.empty()) { if (!material->texture_.empty()) {
mjCBase* m = FindObject(mjOBJ_TEXTURE, pmat->texture_); mjCBase* texture = FindObject(mjOBJ_TEXTURE, material->texture_);
if (m) { if (texture) {
pmat->texid = m->id; material->texid = texture->id;
} else { } else {
throw mjCError(pmat, "texture '%s' not found in material %d", pmat->texture_.c_str(), i); throw mjCError(material, "texture '%s' not found in material %d", material->texture_.c_str(), i);
} }
} }
} }
@@ -1331,7 +1544,7 @@ static int namelist(vector<T*>& list, int adr, int* name_adr, char* names, int*
continue; continue;
} }
uint64_t j = mj_hashdjb2(list[i]->name.c_str(), map_size); uint64_t j = mj_hashString(list[i]->name.c_str(), map_size);
// find first empty slot using linear probing // find first empty slot using linear probing
for (; map[j]!=-1; j=(j+1) % map_size) {} for (; map[j]!=-1; j=(j+1) % map_size) {}
@@ -1555,6 +1768,7 @@ void mjCModel::CopyTree(mjModel* m) {
m->jnt_group[jid] = pj->group; m->jnt_group[jid] = pj->group;
m->jnt_limited[jid] = (mjtByte)pj->is_limited(); m->jnt_limited[jid] = (mjtByte)pj->is_limited();
m->jnt_actfrclimited[jid] = (mjtByte)pj->is_actfrclimited(); m->jnt_actfrclimited[jid] = (mjtByte)pj->is_actfrclimited();
m->jnt_actgravcomp[jid] = pj->actgravcomp;
m->jnt_qposadr[jid] = qposadr; m->jnt_qposadr[jid] = qposadr;
m->jnt_dofadr[jid] = dofadr; m->jnt_dofadr[jid] = dofadr;
m->jnt_bodyid[jid] = pj->body->id; m->jnt_bodyid[jid] = pj->body->id;
@@ -2144,7 +2358,7 @@ void mjCModel::CopyObjects(mjModel* m) {
m->hfield_adr[i] = data_adr; m->hfield_adr[i] = data_adr;
// copy elevation data // copy elevation data
memcpy(m->hfield_data + data_adr, phf->data, phf->nrow*phf->ncol*sizeof(float)); memcpy(m->hfield_data + data_adr, phf->data.data(), phf->nrow*phf->ncol*sizeof(float));
// advance counter // advance counter
data_adr += phf->nrow*phf->ncol; data_adr += phf->nrow*phf->ncol;
@@ -2163,7 +2377,7 @@ void mjCModel::CopyObjects(mjModel* m) {
m->tex_adr[i] = data_adr; m->tex_adr[i] = data_adr;
// copy rgb data // copy rgb data
memcpy(m->tex_rgb + data_adr, ptex->rgb, 3*ptex->width*ptex->height); memcpy(m->tex_rgb + data_adr, ptex->rgb.data(), 3*ptex->width*ptex->height);
// advance counter // advance counter
data_adr += 3*ptex->width*ptex->height; data_adr += 3*ptex->width*ptex->height;
@@ -2719,6 +2933,21 @@ static void processlist(mjListKeyMap& ids, vector<T*>& list,
} }
// set object ids, check for repeated names
void mjCModel::ProcessLists() {
for (int i = 0; i < mjNOBJECT; i++) {
if (i != mjOBJ_XBODY && object_lists[i]) {
processlist(ids, *object_lists[i], (mjtObj) i);
}
}
// check repeated names in meta elements
processlist(ids, frames, mjOBJ_FRAME);
}
// error handler for low-level engine // error handler for low-level engine
static thread_local std::jmp_buf error_jmp_buf; static thread_local std::jmp_buf error_jmp_buf;
static thread_local char errortext[500] = ""; static thread_local char errortext[500] = "";
@@ -2852,14 +3081,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
CheckEmptyNames(); CheckEmptyNames();
// set object ids, check for repeated names // set object ids, check for repeated names
for (int i = 0; i < mjNOBJECT; i++) { ProcessLists();
if (i != mjOBJ_XBODY && object_lists[i]) {
processlist(ids, *object_lists[i], (mjtObj) i);
}
}
// check repeated names in meta elements
processlist(ids, frames, mjOBJ_FRAME);
// delete visual assets // delete visual assets
if (discardvisual) { if (discardvisual) {
@@ -2869,8 +3091,8 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
DeleteAll(textures); DeleteAll(textures);
} }
// convert names into indices // map names to asset references
IndexAssets(false); IndexAssets(/*discard=*/false);
// mark meshes that need convex hull // mark meshes that need convex hull
for (int i=0; i<geoms.size(); i++) { for (int i=0; i<geoms.size(); i++) {
@@ -2880,61 +3102,14 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
} }
} }
// automatically set nuser fields
SetNuser();
// compile meshes (needed for geom compilation) // compile meshes (needed for geom compilation)
for (int i=0; i<meshes.size(); i++) { for (int i=0; i<meshes.size(); i++) {
meshes[i]->Compile(vfs); meshes[i]->Compile(vfs);
} }
// automatically set nuser fields
if (nuser_body == -1) {
nuser_body = 0;
for (int i=0; i<bodies.size(); i++) {
nuser_body = mjMAX(nuser_body, bodies[i]->spec_userdata_.size());
}
}
if (nuser_jnt == -1) {
nuser_jnt = 0;
for (int i=0; i<joints.size(); i++) {
nuser_jnt = mjMAX(nuser_jnt, joints[i]->spec_userdata_.size());
}
}
if (nuser_geom == -1) {
nuser_geom = 0;
for (int i=0; i<geoms.size(); i++) {
nuser_geom = mjMAX(nuser_geom, geoms[i]->spec_userdata_.size());
}
}
if (nuser_site == -1) {
nuser_site = 0;
for (int i=0; i<sites.size(); i++) {
nuser_site = mjMAX(nuser_site, sites[i]->spec_userdata_.size());
}
}
if (nuser_cam == -1) {
nuser_cam = 0;
for (int i=0; i<cameras.size(); i++) {
nuser_cam = mjMAX(nuser_cam, cameras[i]->spec_userdata_.size());
}
}
if (nuser_tendon == -1) {
nuser_tendon = 0;
for (int i=0; i<tendons.size(); i++) {
nuser_tendon = mjMAX(nuser_tendon, tendons[i]->spec_userdata_.size());
}
}
if (nuser_actuator == -1) {
nuser_actuator = 0;
for (int i=0; i<actuators.size(); i++) {
nuser_actuator = mjMAX(nuser_actuator, actuators[i]->spec_userdata_.size());
}
}
if (nuser_sensor == -1) {
nuser_sensor = 0;
for (int i=0; i<sensors.size(); i++) {
nuser_sensor = mjMAX(nuser_sensor, sensors[i]->spec_userdata_.size());
}
}
// compile objects in kinematic tree // compile objects in kinematic tree
for (int i=0; i<bodies.size(); i++) { for (int i=0; i<bodies.size(); i++) {
bodies[i]->Compile(); // also compiles joints, geoms, sites, cameras, lights bodies[i]->Compile(); // also compiles joints, geoms, sites, cameras, lights
@@ -3057,7 +3232,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
std::vector<std::vector<int>> plugin_to_actuators(nplugin); std::vector<std::vector<int>> plugin_to_actuators(nplugin);
for (int i = 0; i < nu; ++i) { for (int i = 0; i < nu; ++i) {
if (actuators[i]->plugin.active) { if (actuators[i]->plugin.active) {
int actuator_plugin = ((mjCPlugin*)actuators[i]->plugin.instance)->id; int actuator_plugin = static_cast<mjCPlugin*>(actuators[i]->plugin.instance)->id;
m->actuator_plugin[i] = actuator_plugin; m->actuator_plugin[i] = actuator_plugin;
plugin_to_actuators[actuator_plugin].push_back(i); plugin_to_actuators[actuator_plugin].push_back(i);
} else { } else {
@@ -3067,7 +3242,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
for (int i = 0; i < nbody; ++i) { for (int i = 0; i < nbody; ++i) {
if (bodies[i]->plugin.active) { if (bodies[i]->plugin.active) {
m->body_plugin[i] = ((mjCPlugin*)bodies[i]->plugin.instance)->id; m->body_plugin[i] = static_cast<mjCPlugin*>(bodies[i]->plugin.instance)->id;
} else { } else {
m->body_plugin[i] = -1; m->body_plugin[i] = -1;
} }
@@ -3075,7 +3250,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
for (int i = 0; i < ngeom; ++i) { for (int i = 0; i < ngeom; ++i) {
if (geoms[i]->plugin.active) { if (geoms[i]->plugin.active) {
m->geom_plugin[i] = ((mjCPlugin*)geoms[i]->plugin.instance)->id; m->geom_plugin[i] = static_cast<mjCPlugin*>(geoms[i]->plugin.instance)->id;
} else { } else {
m->geom_plugin[i] = -1; m->geom_plugin[i] = -1;
} }
@@ -3084,7 +3259,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
std::vector<std::vector<int>> plugin_to_sensors(nplugin); std::vector<std::vector<int>> plugin_to_sensors(nplugin);
for (int i = 0; i < nsensor; ++i) { for (int i = 0; i < nsensor; ++i) {
if (sensors[i]->type == mjSENS_PLUGIN) { if (sensors[i]->type == mjSENS_PLUGIN) {
int sensor_plugin = ((mjCPlugin*)sensors[i]->plugin.instance)->id; int sensor_plugin = static_cast<mjCPlugin*>(sensors[i]->plugin.instance)->id;
m->sensor_plugin[i] = sensor_plugin; m->sensor_plugin[i] = sensor_plugin;
plugin_to_sensors[sensor_plugin].push_back(i); plugin_to_sensors[sensor_plugin].push_back(i);
} else { } else {
+173 -148
View File
@@ -33,133 +33,14 @@
typedef std::map<std::string, int, std::less<> > mjKeyMap; typedef std::map<std::string, int, std::less<> > mjKeyMap;
typedef std::array<mjKeyMap, mjNOBJECT> mjListKeyMap; typedef std::array<mjKeyMap, mjNOBJECT> mjListKeyMap;
// mjCModel contains everything needed to generate the low-level model. class mjCModel_ : public mjElement {
// It can be constructed manually by calling 'Add' functions and setting
// the public fields of the various objects. Alternatively it can constructed
// by loading an XML file via mjCXML. Once an mjCModel object is
// constructed, 'Compile' can be called to generate the corresponding mjModel object
// (which is the low-level model). The mjCModel object can then be deleted.
class mjCModel : private mjSpec {
friend class mjCBody;
friend class mjCCamera;
friend class mjCGeom;
friend class mjCFlex;
friend class mjCHField;
friend class mjCFrame;
friend class mjCJoint;
friend class mjCEquality;
friend class mjCMesh;
friend class mjCSkin;
friend class mjCSite;
friend class mjCTendon;
friend class mjCTexture;
friend class mjCActuator;
friend class mjCSensor;
friend class mjCDef;
friend class mjXReader;
friend class mjXWriter;
public: public:
mjCModel(); // attach namespaces
mjCModel(const mjCModel& other); std::string prefix;
~mjCModel(); std::string suffix;
void CopyFromSpec(); // copy spec to private attributes
void PointToLocal();
mjSpec spec; protected:
bool compiled; // already compiled flag
mjModel* Compile(const mjVFS* vfs = nullptr); // construct mjModel
bool CopyBack(const mjModel*); // DECOMPILER: copy numeric back
void FuseStatic(); // fuse static bodies with parent
void FuseReindex(mjCBody* body); // reindex elements during fuse
// API for adding model elements
mjCFlex* AddFlex();
mjCMesh* AddMesh(mjCDef* def = nullptr);
mjCSkin* AddSkin();
mjCHField* AddHField();
mjCTexture* AddTexture();
mjCMaterial* AddMaterial(mjCDef* def = nullptr);
mjCPair* AddPair(mjCDef* def = nullptr); // geom pair for inclusion
mjCBodyPair* AddExclude(); // body pair for exclusion
mjCEquality* AddEquality(mjCDef* def = nullptr); // equality constraint
mjCTendon* AddTendon(mjCDef* def = nullptr);
mjCActuator* AddActuator(mjCDef* def = nullptr);
mjCSensor* AddSensor();
mjCNumeric* AddNumeric();
mjCText* AddText();
mjCTuple* AddTuple();
mjCKey* AddKey();
mjCPlugin* AddPlugin();
// delete elements marked as discard=true
template <class T> void Delete(std::vector<T*>& elements,
const std::vector<bool>& discard);
// delete all elements
template <class T> void DeleteAll(std::vector<T*>& elements);
// API for access to model elements (outside tree)
int NumObjects(mjtObj type); // number of objects in specified list
mjCBase* GetObject(mjtObj type, int id); // pointer to specified object
// API for access to other variables
bool IsCompiled(); // is model already compiled
int GetFixed(); // number of fixed massless bodies
const mjCError& GetError(void); // get reference of error object
mjCBody* GetWorld(); // pointer to world body
mjCDef* FindDef(std::string name); // find default class name
mjCDef* AddDef(std::string name, int parentid); // add default class to array
mjCBase* FindObject(mjtObj type, std::string name); // find object given type and name
bool IsNullPose(const mjtNum* pos, const mjtNum* quat); // detect null pose
// accessors
std::string get_meshdir(void) const { return meshdir_; }
std::string get_texturedir(void) const { return texturedir_; }
// resolve plugin instance, create a new one if needed
void ResolvePlugin(mjCBase* obj, const std::string& plugin_name,
const std::string& plugin_instance_name,
mjCPlugin** plugin_instance);
// settings for each defaults class
std::vector<mjCDef*> defaults;
// list of active plugins
std::vector<std::pair<const mjpPlugin*, int>> active_plugins;
private:
void TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs);
mjModel* _Compile(const mjVFS* vfs);
// clear objects allocated by Compile
void Clear(void);
// add object of any type
template <class T> T* AddObject(std::vector<T*>& list, std::string type);
// add object of any type, with def parameter
template <class T> T* AddObjectDef(std::vector<T*>& list, std::string type,
mjCDef* def);
// if asset name is missing, set to filename
template<class T> void SetDefaultNames(std::vector<T*>& assets);
// delete material from object
template <class T> void DeleteMaterial(std::vector<T*>& list,
std::string_view name = "");
// compile phases
void MakeLists(mjCBody* body); // make lists of bodies, geoms, joints, sites
void IndexAssets(bool discard); // convert asset names into indices
void CheckEmptyNames(); // check empty names
void SetSizes(); // compute sizes
void AutoSpringDamper(mjModel*); // automatic stiffness and damping computation
void LengthRange(mjModel*, mjData*); // compute actuator lengthrange
void CopyNames(mjModel*); // copy names, compute name addresses
void CopyPaths(mjModel*); // copy paths, compute path addresses
void CopyObjects(mjModel*); // copy objects outside kinematic tree
void CopyTree(mjModel*); // copy objects inside kinematic tree
// sizes set from object list lengths // sizes set from object list lengths
int nbody; // number of bodies int nbody; // number of bodies
@@ -224,6 +105,168 @@ class mjCModel : private mjSpec {
int nD; // number of non-zeros in sparse dof-dof matrix int nD; // number of non-zeros in sparse dof-dof matrix
int nB; // number of non-zeros in sparse body-dof matrix int nB; // number of non-zeros in sparse body-dof matrix
// statistics, as computed by mj_setConst
double meaninertia_auto; // mean diagonal inertia, as computed by mj_setConst
double meanmass_auto; // mean body mass, as computed by mj_setConst
double meansize_auto; // mean body size, as computed by mj_setConst
double extent_auto; // spatial extent, as computed by mj_setConst
double center_auto[3]; // center of model, as computed by mj_setConst
// save qpos0, to recognize changed key_qpos in write
std::vector<mjtNum> qpos0;
// variable-size attributes
std::string comment_; // comment at top of XML
std::string modelfiledir_; // path to model file
std::string modelname_;
std::string meshdir_;
std::string texturedir_;
std::string spec_comment_;
std::string spec_modelfiledir_;
std::string spec_modelname_;
std::string spec_meshdir_;
std::string spec_texturedir_;
};
// mjCModel contains everything needed to generate the low-level model.
// It can be constructed manually by calling 'Add' functions and setting
// the public fields of the various objects. Alternatively it can constructed
// by loading an XML file via mjCXML. Once an mjCModel object is
// constructed, 'Compile' can be called to generate the corresponding mjModel object
// (which is the low-level model). The mjCModel object can then be deleted.
class mjCModel : public mjCModel_, private mjSpec {
friend class mjCBase;
friend class mjCBody;
friend class mjCCamera;
friend class mjCGeom;
friend class mjCFlex;
friend class mjCHField;
friend class mjCFrame;
friend class mjCJoint;
friend class mjCEquality;
friend class mjCMesh;
friend class mjCSkin;
friend class mjCSite;
friend class mjCTendon;
friend class mjCTexture;
friend class mjCActuator;
friend class mjCSensor;
friend class mjCDef;
friend class mjXReader;
friend class mjXWriter;
public:
mjCModel();
mjCModel(const mjCModel& other);
mjCModel& operator=(const mjCModel& other);
mjCModel& operator+=(const mjCModel& other);
~mjCModel();
void CopyFromSpec(); // copy spec to private attributes
void PointToLocal();
mjSpec spec;
mjModel* Compile(const mjVFS* vfs = nullptr); // construct mjModel
bool CopyBack(const mjModel*); // DECOMPILER: copy numeric back
void FuseStatic(); // fuse static bodies with parent
void FuseReindex(mjCBody* body); // reindex elements during fuse
// API for adding model elements
mjCFlex* AddFlex();
mjCMesh* AddMesh(mjCDef* def = nullptr);
mjCSkin* AddSkin();
mjCHField* AddHField();
mjCTexture* AddTexture();
mjCMaterial* AddMaterial(mjCDef* def = nullptr);
mjCPair* AddPair(mjCDef* def = nullptr); // geom pair for inclusion
mjCBodyPair* AddExclude(); // body pair for exclusion
mjCEquality* AddEquality(mjCDef* def = nullptr); // equality constraint
mjCTendon* AddTendon(mjCDef* def = nullptr);
mjCActuator* AddActuator(mjCDef* def = nullptr);
mjCSensor* AddSensor();
mjCNumeric* AddNumeric();
mjCText* AddText();
mjCTuple* AddTuple();
mjCKey* AddKey();
mjCPlugin* AddPlugin();
// copy vector of elements to this model
template <class T> void CopyList(std::vector<T*>& dest,
const std::vector<T*>& source,
std::map<mjCDef*, int>& def_map,
const std::vector<mjCDef*>& defaults);
// delete elements marked as discard=true
template <class T> void Delete(std::vector<T*>& elements,
const std::vector<bool>& discard);
// delete all elements
template <class T> void DeleteAll(std::vector<T*>& elements);
// API for access to model elements (outside tree)
int NumObjects(mjtObj type); // number of objects in specified list
mjCBase* GetObject(mjtObj type, int id); // pointer to specified object
// API for access to other variables
bool IsCompiled() const; // is model already compiled
const mjCError& GetError(void) const; // get reference of error object
mjCBody* GetWorld() const; // pointer to world body
mjCDef* FindDef(std::string name) const; // find default class name
mjCDef* AddDef(std::string name, int parentid); // add default class to array
mjCBase* FindObject(mjtObj type, std::string name) const; // find object given type and name
mjCBody* FindBody(mjCBody* body, std::string name) const; // find body given name
mjCFrame* FindFrame(mjCBody* body, std::string name) const; // find frame given name
bool IsNullPose(const mjtNum* pos, const mjtNum* quat) const; // detect null pose
// accessors
std::string get_meshdir(void) const { return meshdir_; }
std::string get_texturedir(void) const { return texturedir_; }
// resolve plugin instance, create a new one if needed
void ResolvePlugin(mjCBase* obj, const std::string& plugin_name,
const std::string& plugin_instance_name,
mjCPlugin** plugin_instance);
// settings for each defaults class
std::vector<mjCDef*> defaults;
// list of active plugins
std::vector<std::pair<const mjpPlugin*, int>> active_plugins;
private:
void TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs);
mjModel* _Compile(const mjVFS* vfs);
// clear objects allocated by Compile
void Clear(void);
// add object of any type
template <class T> T* AddObject(std::vector<T*>& list, std::string type);
// add object of any type, with def parameter
template <class T> T* AddObjectDef(std::vector<T*>& list, std::string type,
mjCDef* def);
// if asset name is missing, set to filename
template<class T> void SetDefaultNames(std::vector<T*>& assets);
// delete material from object
template <class T> void DeleteMaterial(std::vector<T*>& list,
std::string_view name = "");
// compile phases
void MakeLists(mjCBody* body); // make lists of bodies, geoms, joints, sites
void SetNuser(); // set nuser fields
void IndexAssets(bool discard); // convert asset names into indices
void CheckEmptyNames(); // check empty names
void SetSizes(); // compute sizes
void AutoSpringDamper(mjModel*); // automatic stiffness and damping computation
void LengthRange(mjModel*, mjData*); // compute actuator lengthrange
void CopyNames(mjModel*); // copy names, compute name addresses
void CopyPaths(mjModel*); // copy paths, compute path addresses
void CopyObjects(mjModel*); // copy objects outside kinematic tree
void CopyTree(mjModel*); // copy objects inside kinematic tree
// objects created here // objects created here
std::vector<mjCFlex*> flexes; // list of flexes std::vector<mjCFlex*> flexes; // list of flexes
std::vector<mjCMesh*> meshes; // list of meshes std::vector<mjCMesh*> meshes; // list of meshes
@@ -255,32 +298,14 @@ class mjCModel : private mjSpec {
// array of pointers to each object list (enumerated by type) // array of pointers to each object list (enumerated by type)
std::array<std::vector<mjCBase*>*, mjNOBJECT> object_lists; std::array<std::vector<mjCBase*>*, mjNOBJECT> object_lists;
// statistics, as computed by mj_setConst // create mjCBase lists from children lists
double meaninertia_auto; // mean diagonal inertia, as computed by mj_setConst void CreateObjectLists();
double meanmass_auto; // mean body mass, as computed by mj_setConst
double meansize_auto; // mean body size, as computed by mj_setConst
double extent_auto; // spatial extent, as computed by mj_setConst
double center_auto[3]; // center of model, as computed by mj_setConst
// populate objects ids
void ProcessLists();
mjListKeyMap ids; // map from object names to ids mjListKeyMap ids; // map from object names to ids
bool compiled; // already compiled flag (cannot be compiled again)
mjCError errInfo; // last error info mjCError errInfo; // last error info
int fixCount; // how many bodies have been fixed bool plugin_owner; // this class allocated the plugins
// save qpos0, to recognize changed key_qpos in write
std::vector<mjtNum> qpos0;
// variable-size attributes
std::string comment_; // comment at top of XML
std::string modelfiledir_; // path to model file
std::string modelname_;
std::string meshdir_;
std::string texturedir_;
std::string spec_comment_;
std::string spec_modelfiledir_;
std::string spec_modelname_;
std::string spec_meshdir_;
std::string spec_texturedir_;
}; };
#endif // MUJOCO_SRC_USER_USER_MODEL_H_ #endif // MUJOCO_SRC_USER_USER_MODEL_H_
+806 -442
View File
File diff suppressed because it is too large Load Diff
+135 -82
View File
@@ -15,10 +15,8 @@
#ifndef MUJOCO_SRC_USER_USER_OBJECTS_H_ #ifndef MUJOCO_SRC_USER_USER_OBJECTS_H_
#define MUJOCO_SRC_USER_USER_OBJECTS_H_ #define MUJOCO_SRC_USER_USER_OBJECTS_H_
#include <array>
#include <functional> #include <functional>
#include <map> #include <map>
#include <optional>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <utility> #include <utility>
@@ -28,10 +26,10 @@
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
#include <mujoco/mjplugin.h> #include <mujoco/mjplugin.h>
#include "user/user_api.h" #include "user/user_api.h"
#include "user/user_cache.h"
// forward declarations of all mjC/X classes // forward declarations of all mjC/X classes
class mjCError; class mjCError;
class mjCAlternative;
class mjCBase; class mjCBase;
class mjCBody; class mjCBody;
class mjCFrame; class mjCFrame;
@@ -83,13 +81,10 @@ class [[nodiscard]] mjCError {
// alternative specifications of frame orientation // alternative specifications of frame orientation
class mjCAlternative : public mjmOrientation { const char* ResolveOrientation(double* quat, // set frame quat
public:
mjCAlternative(); // constuctor
const char* Set(double* quat, // set frame quat
bool degree, // angle format: degree/radian bool degree, // angle format: degree/radian
const char* sequence); // euler sequence format: "xyz" const char* sequence, // euler sequence format: "xyz"
}; const mjsOrientation& orient);
@@ -144,7 +139,27 @@ class mjCBoundingVolumeHierarchy : public mjCBoundingVolumeHierarchy_ {
mjCBoundingVolume* GetBoundingVolume(int id); mjCBoundingVolume* GetBoundingVolume(int id);
private: private:
int MakeBVH(std::vector<const mjCBoundingVolume*>& elements, int lev = 0); // internal class used during BVH construction, for partial sorting of bounding volumes
struct BVElement {
const mjCBoundingVolume* e;
// position of the element in the BVH axes
mjtNum lpos[3];
};
struct BVElementCompare {
int axis = 0;
bool operator()(const BVElement& e1, const BVElement& e2) const {
if (e1.lpos[axis] != e2.lpos[axis]) {
return e1.lpos[axis] < e2.lpos[axis];
}
// comparing pointers gives a stable sort, because they both come from the same array
return e1.e < e2.e;
}
};
int MakeBVH(std::vector<BVElement>::iterator elements_begin,
std::vector<BVElement>::iterator elements_end, int lev = 0);
}; };
@@ -152,13 +167,14 @@ class mjCBoundingVolumeHierarchy : public mjCBoundingVolumeHierarchy_ {
//------------------------- class mjCBase ---------------------------------------------------------- //------------------------- class mjCBase ----------------------------------------------------------
// Generic functionality for all derived classes // Generic functionality for all derived classes
class mjCBase_ { class mjCBase_ : public mjElement {
public: public:
int id; // object id
std::string name; // object name std::string name; // object name
std::string classname; // defaults class name std::string classname; // defaults class name
int id; // object id
std::string info; // error message info set by the user std::string info; // error message info set by the user
mjCModel* model; // pointer to model that created object std::string prefix; // prefix for model operations
std::string suffix; // suffix for model operations
}; };
class mjCBase : public mjCBase_ { class mjCBase : public mjCBase_ {
@@ -178,11 +194,18 @@ class mjCBase : public mjCBase_ {
// Copy spec into private attributes // Copy spec into private attributes
virtual void CopyFromSpec() {} virtual void CopyFromSpec() {}
// Throws an error if any of the references is missing
virtual void ResolveReferences(const mjCModel* m) {}
// Appends prefix and suffix to reference
virtual void NameSpace(const mjCModel* m) {}
// Copy assignment // Copy assignment
mjCBase& operator=(const mjCBase& other); mjCBase& operator=(const mjCBase& other);
mjCDef* def; // defaults class used to init this object mjCDef* def; // defaults class used to init this object
mjCFrame* frame; // pointer to frame transformation mjCFrame* frame; // pointer to frame transformation
mjCModel* model; // pointer to model that created object
protected: protected:
mjCBase(); // constructor mjCBase(); // constructor
@@ -196,10 +219,6 @@ class mjCBase : public mjCBase_ {
// Describes a rigid body // Describes a rigid body
class mjCBody_ : public mjCBase { class mjCBody_ : public mjCBase {
public:
mjCAlternative alt_;
mjCAlternative ialt_;
protected: protected:
// variables computed by 'Compile' and 'AddXXX' // variables computed by 'Compile' and 'AddXXX'
int parentid; // parent index in global array int parentid; // parent index in global array
@@ -226,12 +245,13 @@ class mjCBody_ : public mjCBase {
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCBody : public mjCBody_, private mjmBody { class mjCBody : public mjCBody_, private mjsBody {
friend class mjCJoint; friend class mjCJoint;
friend class mjCGeom; friend class mjCGeom;
friend class mjCSite; friend class mjCSite;
friend class mjCCamera; friend class mjCCamera;
friend class mjCComposite; friend class mjCComposite;
friend class mjCFrame;
friend class mjCLight; friend class mjCLight;
friend class mjCFlex; friend class mjCFlex;
friend class mjCFlexcomp; friend class mjCFlexcomp;
@@ -253,11 +273,17 @@ class mjCBody : public mjCBody_, private mjmBody {
mjCCamera* AddCamera(mjCDef* = 0); mjCCamera* AddCamera(mjCDef* = 0);
mjCLight* AddLight(mjCDef* = 0); mjCLight* AddLight(mjCDef* = 0);
// API for adding existing objects to body
mjCBody& operator+=(mjCBody& other);
// API for accessing objects // API for accessing objects
int NumObjects(mjtObj type); int NumObjects(mjtObj type);
mjCBase* GetObject(mjtObj type, int id); mjCBase* GetObject(mjtObj type, int id);
mjCBase* FindObject(mjtObj type, std::string name, bool recursive = true); mjCBase* FindObject(mjtObj type, std::string name, bool recursive = true);
// Propagate suffix and prefix to the whole tree
void NameSpace(const mjCModel* m);
// set explicitinertial to true // set explicitinertial to true
void MakeInertialExplicit(); void MakeInertialExplicit();
@@ -266,7 +292,7 @@ class mjCBody : public mjCBody_, private mjmBody {
const char* FullInertia(double quat[4], double inertia[3]); const char* FullInertia(double quat[4], double inertia[3]);
// variables set by user // variables set by user
mjmBody spec; mjsBody spec;
// inherited // inherited
using mjCBase::name; using mjCBase::name;
@@ -278,7 +304,7 @@ class mjCBody : public mjCBody_, private mjmBody {
private: private:
mjCBody(mjCModel*); // constructor mjCBody(mjCModel*); // constructor
mjCBody(const mjCBody& other); // copy constructor mjCBody(const mjCBody& other, mjCModel* _model); // copy constructor
mjCBody& operator=(const mjCBody& other); // copy assignment mjCBody& operator=(const mjCBody& other); // copy assignment
~mjCBody(); // destructor ~mjCBody(); // destructor
@@ -306,10 +332,9 @@ class mjCBody : public mjCBody_, private mjmBody {
class mjCFrame_ : public mjCBase { class mjCFrame_ : public mjCBase {
protected: protected:
bool compiled; // frame already compiled bool compiled; // frame already compiled
mjCAlternative alt_;
}; };
class mjCFrame : public mjCFrame_, private mjmFrame { class mjCFrame : public mjCFrame_, private mjsFrame {
friend class mjCBase; friend class mjCBase;
friend class mjCBody; friend class mjCBody;
friend class mjCGeom; friend class mjCGeom;
@@ -320,19 +345,25 @@ class mjCFrame : public mjCFrame_, private mjmFrame {
friend class mjCModel; friend class mjCModel;
public: public:
mjmFrame spec; mjsFrame spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
void CopyFromSpec(void); void CopyFromSpec(void);
void PointToLocal(void); void PointToLocal(void);
void SetParent(mjCBody* _body);
mjCFrame& operator+=(const mjCBody& other);
mjCFrame& operator+=(const mjCFrame& other);
private: private:
mjCFrame(mjCModel* = 0, mjCFrame* = 0); // constructor mjCFrame(mjCModel* = 0, mjCFrame* = 0); // constructor
mjCFrame(const mjCFrame& other); // copy constructor mjCFrame(const mjCFrame& other); // copy constructor
mjCFrame& operator=(const mjCFrame& other); // copy assignment mjCFrame& operator=(const mjCFrame& other); // copy assignment
void Compile(void); // compiler void Compile(void); // compiler
mjCBody* body; // body that owns the frame
}; };
@@ -349,7 +380,7 @@ class mjCJoint_ : public mjCBase {
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCJoint : public mjCJoint_, private mjmJoint { class mjCJoint : public mjCJoint_, private mjsJoint {
friend class mjCDef; friend class mjCDef;
friend class mjCEquality; friend class mjCEquality;
friend class mjCBody; friend class mjCBody;
@@ -359,7 +390,7 @@ class mjCJoint : public mjCJoint_, private mjmJoint {
friend class mjXURDF; friend class mjXURDF;
public: public:
mjmJoint spec; mjsJoint spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -393,7 +424,6 @@ class mjCGeom_ : public mjCBase {
bool inferinertia; // true if inertia should be computed from geom bool inferinertia; // true if inertia should be computed from geom
protected: protected:
mjCAlternative alt_;
bool visual_; // true: geom does not collide and is unreferenced bool visual_; // true: geom does not collide and is unreferenced
int matid; // id of geom's material int matid; // id of geom's material
mjCMesh* mesh; // geom's mesh mjCMesh* mesh; // geom's mesh
@@ -417,7 +447,7 @@ class mjCGeom_ : public mjCBase {
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCGeom : public mjCGeom_, private mjmGeom { class mjCGeom : public mjCGeom_, private mjsGeom {
friend class mjCDef; friend class mjCDef;
friend class mjCMesh; friend class mjCMesh;
friend class mjCPair; friend class mjCPair;
@@ -429,7 +459,7 @@ class mjCGeom : public mjCGeom_, private mjmGeom {
public: public:
using mjCBase::name; using mjCBase::name;
mjmGeom spec; // variables set by user mjsGeom spec; // variables set by user
double GetVolume(void); // compute geom volume double GetVolume(void); // compute geom volume
void SetInertia(void); // compute and set geom inertia void SetInertia(void); // compute and set geom inertia
bool IsVisual(void) const { return visual_; } bool IsVisual(void) const { return visual_; }
@@ -473,8 +503,6 @@ class mjCGeom : public mjCGeom_, private mjmGeom {
class mjCSite_ : public mjCBase { class mjCSite_ : public mjCBase {
protected: protected:
mjCAlternative alt_;
// variable-size data // variable-size data
std::string material_; std::string material_;
std::vector<double> userdata_; std::vector<double> userdata_;
@@ -486,7 +514,7 @@ class mjCSite_ : public mjCBase {
int matid; // material id for rendering int matid; // material id for rendering
}; };
class mjCSite : public mjCSite_, private mjmSite { class mjCSite : public mjCSite_, private mjsSite {
friend class mjCDef; friend class mjCDef;
friend class mjCBody; friend class mjCBody;
friend class mjCModel; friend class mjCModel;
@@ -494,9 +522,9 @@ class mjCSite : public mjCSite_, private mjmSite {
friend class mjXURDF; friend class mjXURDF;
public: public:
mjmSite spec; // variables set by user mjsSite spec; // variables set by user
// use strings from mjCBase rather than mjStrings from mjmSite // use strings from mjCBase rather than mjStrings from mjsSite
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -525,14 +553,13 @@ class mjCCamera_ : public mjCBase {
protected: protected:
mjCBody* body; // camera's body mjCBody* body; // camera's body
int targetbodyid; // id of target body; -1: none int targetbodyid; // id of target body; -1: none
mjCAlternative alt_;
std::string targetbody_; std::string targetbody_;
std::string spec_targetbody_; std::string spec_targetbody_;
std::vector<double> userdata_; std::vector<double> userdata_;
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCCamera : public mjCCamera_, private mjmCamera { class mjCCamera : public mjCCamera_, private mjsCamera {
friend class mjCDef; friend class mjCDef;
friend class mjCBody; friend class mjCBody;
friend class mjCModel; friend class mjCModel;
@@ -540,7 +567,7 @@ class mjCCamera : public mjCCamera_, private mjmCamera {
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmCamera spec; mjsCamera spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -572,14 +599,14 @@ class mjCLight_ : public mjCBase {
std::string spec_targetbody_; std::string spec_targetbody_;
}; };
class mjCLight : public mjCLight_, private mjmLight { class mjCLight : public mjCLight_, private mjsLight {
friend class mjCDef; friend class mjCDef;
friend class mjCBody; friend class mjCBody;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmLight spec; mjsLight spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -633,7 +660,7 @@ class mjCFlex_ : public mjCBase {
std::vector<float> spec_texcoord_; std::vector<float> spec_texcoord_;
}; };
class mjCFlex: public mjCFlex_, private mjmFlex { class mjCFlex: public mjCFlex_, private mjsFlex {
friend class mjCDef; friend class mjCDef;
friend class mjCModel; friend class mjCModel;
friend class mjCFlexcomp; friend class mjCFlexcomp;
@@ -641,13 +668,15 @@ class mjCFlex: public mjCFlex_, private mjmFlex {
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmFlex spec; mjsFlex spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
void CopyFromSpec(void); void CopyFromSpec(void);
void PointToLocal(void); void PointToLocal(void);
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
// used by mjXWriter and mjCModel // used by mjXWriter and mjCModel
const std::string& get_material() { return material_; } const std::string& get_material() { return material_; }
@@ -735,7 +764,8 @@ class mjCMesh_ : public mjCBase {
std::vector<double> face_aabb_; // bounding boxes of all faces std::vector<double> face_aabb_; // bounding boxes of all faces
}; };
class mjCMesh: public mjCMesh_, private mjmMesh { class mjCMesh: public mjCMesh_, private mjsMesh {
friend class mjCModel;
friend class mjCFlexcomp; friend class mjCFlexcomp;
friend class mjXWriter; friend class mjXWriter;
public: public:
@@ -744,7 +774,7 @@ class mjCMesh: public mjCMesh_, private mjmMesh {
mjCMesh& operator=(const mjCMesh& other); // copy assignment mjCMesh& operator=(const mjCMesh& other); // copy assignment
~mjCMesh(); ~mjCMesh();
mjmMesh spec; mjsMesh spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -808,6 +838,7 @@ class mjCMesh: public mjCMesh_, private mjmMesh {
private: private:
void LoadOBJ(mjResource* resource); // load mesh in wavefront OBJ format void LoadOBJ(mjResource* resource); // load mesh in wavefront OBJ format
bool LoadCachedOBJ(const mjCAsset& asset); // load OBJ from cache asset, return true on success
void LoadSTL(mjResource* resource); // load mesh in STL BIN format void LoadSTL(mjResource* resource); // load mesh in STL BIN format
void LoadMSH(mjResource* resource); // load mesh in MSH BIN format void LoadMSH(mjResource* resource); // load mesh in MSH BIN format
void LoadSDF(); // generate mesh using marching cubes void LoadSDF(); // generate mesh using marching cubes
@@ -870,12 +901,12 @@ class mjCSkin_ : public mjCBase {
std::vector<int> bodyid; // body ids std::vector<int> bodyid; // body ids
}; };
class mjCSkin: public mjCSkin_, private mjmSkin { class mjCSkin: public mjCSkin_, private mjsSkin {
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmSkin spec; mjsSkin spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -901,6 +932,8 @@ class mjCSkin: public mjCSkin_, private mjmSkin {
mjCSkin& operator=(const mjCSkin& other); // copy assignment mjCSkin& operator=(const mjCSkin& other); // copy assignment
~mjCSkin(); // destructor ~mjCSkin(); // destructor
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
void Compile(const mjVFS* vfs); // compiler void Compile(const mjVFS* vfs); // compiler
void LoadSKN(mjResource* resource); // load skin in SKN BIN format void LoadSKN(mjResource* resource); // load skin in SKN BIN format
}; };
@@ -912,6 +945,8 @@ class mjCSkin: public mjCSkin_, private mjmSkin {
class mjCHField_ : public mjCBase { class mjCHField_ : public mjCBase {
protected: protected:
std::vector<float> data; // elevation data, row-major format
std::string file_; std::string file_;
std::string content_type_; std::string content_type_;
std::vector<float> userdata_; std::vector<float> userdata_;
@@ -920,13 +955,13 @@ class mjCHField_ : public mjCBase {
std::vector<float> spec_userdata_; std::vector<float> spec_userdata_;
}; };
class mjCHField : public mjCHField_, private mjmHField { class mjCHField : public mjCHField_, private mjsHField {
friend class mjCGeom; friend class mjCGeom;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmHField spec; mjsHField spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::info; using mjCBase::info;
@@ -944,7 +979,6 @@ class mjCHField : public mjCHField_, private mjmHField {
mjCHField& operator=(const mjCHField& other); // copy assignment mjCHField& operator=(const mjCHField& other); // copy assignment
~mjCHField(); // destructor ~mjCHField(); // destructor
float* data; // elevation data, row-major format
void Compile(const mjVFS* vfs); // compiler void Compile(const mjVFS* vfs); // compiler
void LoadCustom(mjResource* resource); // load from custom format void LoadCustom(mjResource* resource); // load from custom format
@@ -958,6 +992,8 @@ class mjCHField : public mjCHField_, private mjmHField {
class mjCTexture_ : public mjCBase { class mjCTexture_ : public mjCBase {
protected: protected:
std::vector<mjtByte> rgb; // rgb data
std::string file_; std::string file_;
std::string content_type_; std::string content_type_;
std::vector<std::string> cubefiles_; std::vector<std::string> cubefiles_;
@@ -966,7 +1002,7 @@ class mjCTexture_ : public mjCBase {
std::vector<std::string> spec_cubefiles_; std::vector<std::string> spec_cubefiles_;
}; };
class mjCTexture : public mjCTexture_, private mjmTexture { class mjCTexture : public mjCTexture_, private mjsTexture {
friend class mjCModel; friend class mjCModel;
friend class mjXReader; friend class mjXReader;
friend class mjXWriter; friend class mjXWriter;
@@ -974,7 +1010,7 @@ class mjCTexture : public mjCTexture_, private mjmTexture {
public: public:
~mjCTexture(); // destructor ~mjCTexture(); // destructor
mjmTexture spec; mjsTexture spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -1009,8 +1045,6 @@ class mjCTexture : public mjCTexture_, private mjmTexture {
void LoadCustom(mjResource* resource, void LoadCustom(mjResource* resource,
std::vector<unsigned char>& image, std::vector<unsigned char>& image,
unsigned int& w, unsigned int& h); unsigned int& w, unsigned int& h);
mjtByte* rgb; // rgb data
}; };
@@ -1025,13 +1059,13 @@ class mjCMaterial_ : public mjCBase {
std::string spec_texture_; std::string spec_texture_;
}; };
class mjCMaterial : public mjCMaterial_, private mjmMaterial { class mjCMaterial : public mjCMaterial_, private mjsMaterial {
friend class mjCDef; friend class mjCDef;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmMaterial spec; mjsMaterial spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -1064,20 +1098,22 @@ class mjCPair_ : public mjCBase {
std::string spec_geomname2_; std::string spec_geomname2_;
}; };
class mjCPair : public mjCPair_, private mjmPair { class mjCPair : public mjCPair_, private mjsPair {
friend class mjCDef; friend class mjCDef;
friend class mjCBody; friend class mjCBody;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmPair spec; mjsPair spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
void CopyFromSpec(); void CopyFromSpec();
void PointToLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
std::string get_geomname1() { return geomname1_; } std::string get_geomname1() { return geomname1_; }
std::string get_geomname2() { return geomname2_; } std::string get_geomname2() { return geomname2_; }
@@ -1114,17 +1150,19 @@ class mjCBodyPair_ : public mjCBase {
std::string spec_bodyname2_; std::string spec_bodyname2_;
}; };
class mjCBodyPair : public mjCBodyPair_, private mjmExclude { class mjCBodyPair : public mjCBodyPair_, private mjsExclude {
friend class mjCBody; friend class mjCBody;
friend class mjCModel; friend class mjCModel;
public: public:
mjmExclude spec; mjsExclude spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::info; using mjCBase::info;
void CopyFromSpec(); void CopyFromSpec();
void PointToLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
std::string get_bodyname1() const { return bodyname1_; } std::string get_bodyname1() const { return bodyname1_; }
std::string get_bodyname2() const { return bodyname2_; } std::string get_bodyname2() const { return bodyname2_; }
@@ -1156,20 +1194,22 @@ class mjCEquality_ : public mjCBase {
std::string spec_name2_; std::string spec_name2_;
}; };
class mjCEquality : public mjCEquality_, private mjmEquality { class mjCEquality : public mjCEquality_, private mjsEquality {
friend class mjCDef; friend class mjCDef;
friend class mjCBody; friend class mjCBody;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmEquality spec; mjsEquality spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
void CopyFromSpec(); void CopyFromSpec();
void PointToLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
private: private:
mjCEquality(mjCModel* = 0, mjCDef* = 0); // constructor mjCEquality(mjCModel* = 0, mjCDef* = 0); // constructor
@@ -1195,13 +1235,13 @@ class mjCTendon_ : public mjCBase {
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCTendon : public mjCTendon_, private mjmTendon { class mjCTendon : public mjCTendon_, private mjsTendon {
friend class mjCDef; friend class mjCDef;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmTendon spec; mjsTendon spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -1227,6 +1267,9 @@ class mjCTendon : public mjCTendon_, private mjmTendon {
void CopyFromSpec(); void CopyFromSpec();
void PointToLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
void SetModel(mjCModel* _model);
bool is_limited() const; bool is_limited() const;
@@ -1252,15 +1295,18 @@ class mjCWrap_ : public mjCBase {
std::string sidesite; // name of side site std::string sidesite; // name of side site
}; };
class mjCWrap : public mjCWrap_, private mjmWrap { class mjCWrap : public mjCWrap_, private mjsWrap {
friend class mjCTendon; friend class mjCTendon;
friend class mjCModel; friend class mjCModel;
public: public:
mjmWrap spec; mjsWrap spec;
using mjCBase::info; using mjCBase::info;
void PointToLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
mjCBase* obj; // wrap object pointer mjCBase* obj; // wrap object pointer
private: private:
@@ -1268,8 +1314,6 @@ class mjCWrap : public mjCWrap_, private mjmWrap {
mjCWrap(const mjCWrap& other); // copy constructor mjCWrap(const mjCWrap& other); // copy constructor
mjCWrap& operator=(const mjCWrap& other); // copy assignment mjCWrap& operator=(const mjCWrap& other); // copy assignment
void Compile(void); // compiler
mjCTendon* tendon; // tendon owning this wrap mjCTendon* tendon; // tendon owning this wrap
}; };
@@ -1293,12 +1337,12 @@ class mjCPlugin : public mjCPlugin_ {
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmPlugin spec; mjsPlugin spec;
mjCBase* parent; // parent object (only used when generating error message) mjCBase* parent; // parent object (only used when generating error message)
mjCPlugin(const mjCPlugin& other); // copy constructor
private: private:
mjCPlugin(mjCModel*); // constructor mjCPlugin(mjCModel*); // constructor
mjCPlugin(const mjCPlugin& other); // copy constructor
mjCPlugin& operator=(const mjCPlugin& other); // copy assignment mjCPlugin& operator=(const mjCPlugin& other); // copy assignment
void Compile(void); // compiler void Compile(void); // compiler
@@ -1326,13 +1370,13 @@ class mjCActuator_ : public mjCBase {
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCActuator : public mjCActuator_, private mjmActuator { class mjCActuator : public mjCActuator_, private mjsActuator {
friend class mjCDef; friend class mjCDef;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmActuator spec; mjsActuator spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -1355,6 +1399,10 @@ class mjCActuator : public mjCActuator_, private mjmActuator {
void Compile(void); // compiler void Compile(void); // compiler
void CopyFromSpec(); void CopyFromSpec();
void PointToLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
mjCBase* ptarget; // transmission target
}; };
@@ -1377,13 +1425,13 @@ class mjCSensor_ : public mjCBase {
std::vector<double> spec_userdata_; std::vector<double> spec_userdata_;
}; };
class mjCSensor : public mjCSensor_, private mjmSensor { class mjCSensor : public mjCSensor_, private mjsSensor {
friend class mjCDef; friend class mjCDef;
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmSensor spec; mjsSensor spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::classname; using mjCBase::classname;
using mjCBase::info; using mjCBase::info;
@@ -1400,9 +1448,12 @@ class mjCSensor : public mjCSensor_, private mjmSensor {
void Compile(void); // compiler void Compile(void); // compiler
void CopyFromSpec(); void CopyFromSpec();
void MakePointerLocal(); void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
mjCBase* obj; // sensorized object mjCBase* obj; // sensorized object
mjCBase* ref; // sensorized reference
}; };
@@ -1416,12 +1467,12 @@ class mjCNumeric_ : public mjCBase {
std::vector<double> spec_data_; std::vector<double> spec_data_;
}; };
class mjCNumeric : public mjCNumeric_, private mjmNumeric { class mjCNumeric : public mjCNumeric_, private mjsNumeric {
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmNumeric spec; mjsNumeric spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::info; using mjCBase::info;
@@ -1448,12 +1499,12 @@ class mjCText_ : public mjCBase {
std::string spec_data_; std::string spec_data_;
}; };
class mjCText : public mjCText_, private mjmText { class mjCText : public mjCText_, private mjsText {
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmText spec; mjsText spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::info; using mjCBase::info;
@@ -1485,17 +1536,19 @@ class mjCTuple_ : public mjCBase {
std::vector<double> spec_objprm_; std::vector<double> spec_objprm_;
}; };
class mjCTuple : public mjCTuple_, private mjmTuple { class mjCTuple : public mjCTuple_, private mjsTuple {
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmTuple spec; mjsTuple spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::info; using mjCBase::info;
void PointToLocal(); void PointToLocal();
void CopyFromSpec(); void CopyFromSpec();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
private: private:
mjCTuple(mjCModel*); // constructor mjCTuple(mjCModel*); // constructor
@@ -1527,12 +1580,12 @@ class mjCKey_ : public mjCBase {
std::vector<double> spec_ctrl_; std::vector<double> spec_ctrl_;
}; };
class mjCKey : public mjCKey_, private mjmKey { class mjCKey : public mjCKey_, private mjsKey {
friend class mjCModel; friend class mjCModel;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjmKey spec; mjsKey spec;
using mjCBase::name; using mjCBase::name;
using mjCBase::info; using mjCBase::info;
@@ -1553,7 +1606,7 @@ class mjCKey : public mjCKey_, private mjmKey {
//------------------------- class mjCDef ----------------------------------------------------------- //------------------------- class mjCDef -----------------------------------------------------------
// Describes one set of defaults // Describes one set of defaults
class mjCDef { class mjCDef : public mjElement {
friend class mjXWriter; friend class mjXWriter;
public: public:
@@ -1569,7 +1622,7 @@ class mjCDef {
int parentid; // id of parent class int parentid; // id of parent class
std::vector<int> childid; // ids of child classes std::vector<int> childid; // ids of child classes
mjmDefault spec; mjsDefault spec;
// default objects (TODO: they should become private) // default objects (TODO: they should become private)
mjCJoint joint; mjCJoint joint;
+38 -7
View File
@@ -15,7 +15,7 @@
#include "xml/xml.h" #include "xml/xml.h"
#include <locale.h> #include <locale.h>
#include "user/user_api.h" #include <cstring>
#if defined(__APPLE__) || defined(__FreeBSD__) #if defined(__APPLE__) || defined(__FreeBSD__)
#include <xlocale.h> #include <xlocale.h>
@@ -29,6 +29,7 @@
#include "tinyxml2.h" #include "tinyxml2.h"
#include <mujoco/mujoco.h>
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
#include <mujoco/mjplugin.h> #include <mujoco/mjplugin.h>
#include "cc/array_safety.h" #include "cc/array_safety.h"
@@ -344,14 +345,14 @@ mjSpec* mjParseXML(const char* filename, const mjVFS* vfs,
} }
// create model, set filedir // create model, set filedir
model = mjm_createSpec(); model = mjs_createSpec();
const char* dir; const char* dir;
int ndir = 0; int ndir = 0;
mju_getResourceDir(resource, &dir, &ndir); mju_getResourceDir(resource, &dir, &ndir);
if (dir != nullptr) { if (dir != nullptr) {
mjm_setString(model->modelfiledir, std::string(dir, ndir).c_str()); mjs_setString(model->modelfiledir, std::string(dir, ndir).c_str());
} else { } else {
mjm_setString(model->modelfiledir, ""); mjs_setString(model->modelfiledir, "");
} }
// close resource // close resource
@@ -363,8 +364,8 @@ mjSpec* mjParseXML(const char* filename, const mjVFS* vfs,
// find include elements, replace them with subtree from xml file // find include elements, replace them with subtree from xml file
std::unordered_set<std::string> included = {filename}; std::unordered_set<std::string> included = {filename};
mjXReader parser; mjXReader parser;
parser.SetModelFileDir(mjm_getString(model->modelfiledir)); parser.SetModelFileDir(mjs_getString(model->modelfiledir));
mjIncludeXML(parser, root, mjm_getString(model->modelfiledir), vfs, included); mjIncludeXML(parser, root, mjs_getString(model->modelfiledir), vfs, included);
// parse MuJoCo model // parse MuJoCo model
parser.SetModel(model); parser.SetModel(model);
@@ -393,9 +394,39 @@ mjSpec* mjParseXML(const char* filename, const mjVFS* vfs,
// catch known errors // catch known errors
catch (mjXError err) { catch (mjXError err) {
mjCopyError(error, err.message, error_sz); mjCopyError(error, err.message, error_sz);
mjm_deleteSpec(model); mjs_deleteSpec(model);
return nullptr; return nullptr;
} }
return model; return model;
} }
static void RegisterResourceProvider() {
// register string resource provider if not registered before
if (mjp_getResourceProvider("LoadModelFromString:") == nullptr) {
mjpResourceProvider resourceProvider;
mjp_defaultResourceProvider(&resourceProvider);
resourceProvider.prefix = "LoadModelFromString";
resourceProvider.open = +[](mjResource* resource) {
resource->data = &(resource->name[strlen("LoadModelFromString:")]);
return 1;
};
resourceProvider.read =
+[](mjResource* resource, const void** buffer) {
*buffer = resource->data;
return (int) strlen((const char*) resource->data);
};
resourceProvider.close = +[](mjResource* resource) {};
mjp_registerResourceProvider(&resourceProvider);
}
}
mjSpec* ParseSpecFromString(std::string_view xml, char* error,
int error_size, mjVFS* vfs) {
RegisterResourceProvider();
std::string xml2 = {xml.begin(), xml.end()};
std::string str = "LoadModelFromString:" + xml2;
return mjParseXML(str.c_str(), vfs, error, error_size);
}
+5
View File
@@ -29,5 +29,10 @@ std::string mjWriteXML(mjSpec* model, char* error, int error_sz);
// Main parser function // Main parser function
MJAPI mjSpec* mjParseXML(const char* filename, const mjVFS* vfs, char* error, int error_sz); MJAPI mjSpec* mjParseXML(const char* filename, const mjVFS* vfs, char* error, int error_sz);
// Returns a newly-allocated mjSpec, loaded from the contents of xml.
// On failure returns nullptr and populates the error array if present.
MJAPI mjSpec* ParseSpecFromString(std::string_view xml, char* error = nullptr,
int error_size = 0, mjVFS* vfs = nullptr);
#endif // MUJOCO_SRC_XML_XML_H_ #endif // MUJOCO_SRC_XML_XML_H_
+7 -7
View File
@@ -56,7 +56,7 @@ std::optional<std::string> GlobalModel::ToXML(const mjModel* m, char* error,
mjCopyError(error, "No XML model loaded", error_sz); mjCopyError(error, "No XML model loaded", error_sz);
return std::nullopt; return std::nullopt;
} }
mjm_copyBack(model_, m); mjs_copyBack(model_, m);
std::string result = mjWriteXML(model_, error, error_sz); std::string result = mjWriteXML(model_, error, error_sz);
if (result.empty()) { if (result.empty()) {
return std::nullopt; return std::nullopt;
@@ -67,7 +67,7 @@ std::optional<std::string> GlobalModel::ToXML(const mjModel* m, char* error,
void GlobalModel::Set(mjSpec* model) { void GlobalModel::Set(mjSpec* model) {
std::lock_guard<std::mutex> lock(*mutex_); std::lock_guard<std::mutex> lock(*mutex_);
if (model_ != nullptr) { if (model_ != nullptr) {
mjm_deleteSpec(model_); mjs_deleteSpec(model_);
} }
model_ = model; model_ = model;
} }
@@ -93,21 +93,21 @@ mjModel* mj_loadXML(const char* filename, const mjVFS* vfs,
// parse new model // parse new model
std::unique_ptr<mjSpec, std::function<void(mjSpec*)>> model( std::unique_ptr<mjSpec, std::function<void(mjSpec*)>> model(
mjParseXML(filename, vfs, error, error_sz), mjParseXML(filename, vfs, error, error_sz),
[](mjSpec* m) { mjm_deleteSpec(m); }); [](mjSpec* m) { mjs_deleteSpec(m); });
if (!model) { if (!model) {
return nullptr; return nullptr;
} }
// compile new model // compile new model
mjModel* m = mjm_compile(model.get(), vfs); mjModel* m = mjs_compile(model.get(), vfs);
if (!m) { if (!m) {
mjCopyError(error, mjm_getError(model.get()), error_sz); mjCopyError(error, mjs_getError(model.get()), error_sz);
return nullptr; return nullptr;
} }
// handle compile warning // handle compile warning
if (mjm_isWarning(model.get())) { if (mjs_isWarning(model.get())) {
mjCopyError(error, mjm_getError(model.get()), error_sz); mjCopyError(error, mjs_getError(model.get()), error_sz);
} else if (error) { } else if (error) {
error[0] = '\0'; error[0] = '\0';
} }
+2 -1
View File
@@ -24,6 +24,7 @@
#include "user/user_api.h" #include "user/user_api.h"
#include "user/user_model.h" #include "user/user_model.h"
#include "user/user_objects.h" #include "user/user_objects.h"
#include "xml/xml_util.h"
#include "tinyxml2.h" #include "tinyxml2.h"
namespace { namespace {
@@ -51,7 +52,7 @@ void mjXBase::SetModel(mjSpec* _model) {
// read alternative orientation specification // read alternative orientation specification
int mjXBase::ReadAlternative(XMLElement* elem, mjmOrientation& alt) { int mjXBase::ReadAlternative(XMLElement* elem, mjsOrientation& alt) {
string text; string text;
int read = (int)(elem->Attribute("quat") != 0) + int read = (int)(elem->Attribute("quat") != 0) +
(ReadAttr(elem, "axisangle", 4, alt.axisangle, text) ? 1 : 0) + (ReadAttr(elem, "axisangle", 4, alt.axisangle, text) ? 1 : 0) +
+1 -1
View File
@@ -90,7 +90,7 @@ class mjXBase : public mjXUtil {
virtual void SetModel(mjSpec*); virtual void SetModel(mjSpec*);
// read alternative orientation specification // read alternative orientation specification
static int ReadAlternative(tinyxml2::XMLElement* elem, mjmOrientation& alt); static int ReadAlternative(tinyxml2::XMLElement* elem, mjsOrientation& alt);
protected: protected:
mjSpec* model; // internally-allocated model mjSpec* model; // internally-allocated model
File diff suppressed because it is too large Load Diff
+19 -19
View File
@@ -54,8 +54,8 @@ class mjXReader : public mjXBase {
void Visual(tinyxml2::XMLElement* section); // visual section void Visual(tinyxml2::XMLElement* section); // visual section
void Statistic(tinyxml2::XMLElement* section); // statistic section void Statistic(tinyxml2::XMLElement* section); // statistic section
void Asset(tinyxml2::XMLElement* section); // asset section void Asset(tinyxml2::XMLElement* section); // asset section
void Body(tinyxml2::XMLElement* section, mjmBody* pbody, void Body(tinyxml2::XMLElement* section, mjsBody* pbody,
mjmFrame* pframe); // body/world section mjsFrame* pframe); // body/world section
void Contact(tinyxml2::XMLElement* section); // contact section void Contact(tinyxml2::XMLElement* section); // contact section
void Deformable(tinyxml2::XMLElement* section); // deformable section void Deformable(tinyxml2::XMLElement* section); // deformable section
void Equality(tinyxml2::XMLElement* section); // equality section void Equality(tinyxml2::XMLElement* section); // equality section
@@ -65,25 +65,25 @@ class mjXReader : public mjXBase {
void Keyframe(tinyxml2::XMLElement* section); // keyframe section void Keyframe(tinyxml2::XMLElement* section); // keyframe section
// single element parsers, used in defaults and main body // single element parsers, used in defaults and main body
void OneFlex(tinyxml2::XMLElement* elem, mjmFlex* pflex); void OneFlex(tinyxml2::XMLElement* elem, mjsFlex* pflex);
void OneMesh(tinyxml2::XMLElement* elem, mjmMesh* pmesh); void OneMesh(tinyxml2::XMLElement* elem, mjsMesh* pmesh);
void OneSkin(tinyxml2::XMLElement* elem, mjmSkin* pskin); void OneSkin(tinyxml2::XMLElement* elem, mjsSkin* pskin);
void OneMaterial(tinyxml2::XMLElement* elem, mjmMaterial* pmaterial); void OneMaterial(tinyxml2::XMLElement* elem, mjsMaterial* pmaterial);
void OneJoint(tinyxml2::XMLElement* elem, mjmJoint* pjoint); void OneJoint(tinyxml2::XMLElement* elem, mjsJoint* pjoint);
void OneGeom(tinyxml2::XMLElement* elem, mjmGeom* pgeom); void OneGeom(tinyxml2::XMLElement* elem, mjsGeom* pgeom);
void OneSite(tinyxml2::XMLElement* elem, mjmSite* site); void OneSite(tinyxml2::XMLElement* elem, mjsSite* site);
void OneCamera(tinyxml2::XMLElement* elem, mjmCamera* pcamera); void OneCamera(tinyxml2::XMLElement* elem, mjsCamera* pcamera);
void OneLight(tinyxml2::XMLElement* elem, mjmLight* plight); void OneLight(tinyxml2::XMLElement* elem, mjsLight* plight);
void OnePair(tinyxml2::XMLElement* elem, mjmPair* ppair); void OnePair(tinyxml2::XMLElement* elem, mjsPair* ppair);
void OneEquality(tinyxml2::XMLElement* elem, mjmEquality* pequality); void OneEquality(tinyxml2::XMLElement* elem, mjsEquality* pequality);
void OneTendon(tinyxml2::XMLElement* elem, mjmTendon* ptendon); void OneTendon(tinyxml2::XMLElement* elem, mjsTendon* ptendon);
void OneActuator(tinyxml2::XMLElement* elem, mjmActuator* pactuator); void OneActuator(tinyxml2::XMLElement* elem, mjsActuator* pactuator);
void OneComposite(tinyxml2::XMLElement* elem, mjmBody* pbody, mjmDefault* def); void OneComposite(tinyxml2::XMLElement* elem, mjsBody* pbody, mjsDefault* def);
void OneFlexcomp(tinyxml2::XMLElement* elem, mjmBody* pbody); void OneFlexcomp(tinyxml2::XMLElement* elem, mjsBody* pbody);
void OnePlugin(tinyxml2::XMLElement* elem, mjmPlugin* plugin); void OnePlugin(tinyxml2::XMLElement* elem, mjsPlugin* plugin);
mjXSchema schema; // schema used for validation mjXSchema schema; // schema used for validation
mjmDefault* GetClass(tinyxml2::XMLElement* section); // get default class name mjsDefault* GetClass(tinyxml2::XMLElement* section); // get default class name
bool readingdefaults; // true while reading defaults bool readingdefaults; // true while reading defaults
+17 -17
View File
@@ -307,6 +307,7 @@ void mjXWriter::OneJoint(XMLElement* elem, mjCJoint* pjoint, mjCDef* def) {
WriteAttr(elem, "range", 2, pjoint->range, def->joint.range); WriteAttr(elem, "range", 2, pjoint->range, def->joint.range);
WriteAttrKey(elem, "actuatorfrclimited", TFAuto_map, 3, pjoint->actfrclimited, WriteAttrKey(elem, "actuatorfrclimited", TFAuto_map, 3, pjoint->actfrclimited,
def->joint.actfrclimited); def->joint.actfrclimited);
WriteAttrKey(elem, "actuatorgravcomp", bool_map, 2, pjoint->actgravcomp, def->joint.actgravcomp);
WriteAttr(elem, "actuatorfrcrange", 2, pjoint->actfrcrange, def->joint.actfrcrange); WriteAttr(elem, "actuatorfrcrange", 2, pjoint->actfrcrange, def->joint.actfrcrange);
WriteAttr(elem, "margin", 1, &pjoint->margin, &def->joint.margin); WriteAttr(elem, "margin", 1, &pjoint->margin, &def->joint.margin);
WriteAttr(elem, "armature", 1, &pjoint->armature, &def->joint.armature); WriteAttr(elem, "armature", 1, &pjoint->armature, &def->joint.armature);
@@ -553,33 +554,33 @@ void mjXWriter::OneEquality(XMLElement* elem, mjCEquality* peq, mjCDef* def) {
switch (peq->type) { switch (peq->type) {
case mjEQ_CONNECT: case mjEQ_CONNECT:
WriteAttrTxt(elem, "body1", mjm_getString(peq->name1)); WriteAttrTxt(elem, "body1", mjs_getString(peq->name1));
WriteAttrTxt(elem, "body2", mjm_getString(peq->name2)); WriteAttrTxt(elem, "body2", mjs_getString(peq->name2));
WriteAttr(elem, "anchor", 3, peq->data); WriteAttr(elem, "anchor", 3, peq->data);
break; break;
case mjEQ_WELD: case mjEQ_WELD:
WriteAttrTxt(elem, "body1", mjm_getString(peq->name1)); WriteAttrTxt(elem, "body1", mjs_getString(peq->name1));
WriteAttrTxt(elem, "body2", mjm_getString(peq->name2)); WriteAttrTxt(elem, "body2", mjs_getString(peq->name2));
WriteAttr(elem, "anchor", 3, peq->data); WriteAttr(elem, "anchor", 3, peq->data);
WriteAttr(elem, "torquescale", 1, peq->data+10); WriteAttr(elem, "torquescale", 1, peq->data+10);
WriteAttr(elem, "relpose", 7, peq->data+3); WriteAttr(elem, "relpose", 7, peq->data+3);
break; break;
case mjEQ_JOINT: case mjEQ_JOINT:
WriteAttrTxt(elem, "joint1", mjm_getString(peq->name1)); WriteAttrTxt(elem, "joint1", mjs_getString(peq->name1));
WriteAttrTxt(elem, "joint2", mjm_getString(peq->name2)); WriteAttrTxt(elem, "joint2", mjs_getString(peq->name2));
WriteAttr(elem, "polycoef", 5, peq->data); WriteAttr(elem, "polycoef", 5, peq->data);
break; break;
case mjEQ_TENDON: case mjEQ_TENDON:
WriteAttrTxt(elem, "tendon1", mjm_getString(peq->name1)); WriteAttrTxt(elem, "tendon1", mjs_getString(peq->name1));
WriteAttrTxt(elem, "tendon2", mjm_getString(peq->name2)); WriteAttrTxt(elem, "tendon2", mjs_getString(peq->name2));
WriteAttr(elem, "polycoef", 5, peq->data); WriteAttr(elem, "polycoef", 5, peq->data);
break; break;
case mjEQ_FLEX: case mjEQ_FLEX:
WriteAttrTxt(elem, "flex", mjm_getString(peq->name1)); WriteAttrTxt(elem, "flex", mjs_getString(peq->name1));
break; break;
default: default:
@@ -731,16 +732,16 @@ void mjXWriter::OneActuator(XMLElement* elem, mjCActuator* pact, mjCDef* def) {
// write plugin // write plugin
void mjXWriter::OnePlugin(XMLElement* elem, mjmPlugin* plugin) { void mjXWriter::OnePlugin(XMLElement* elem, mjsPlugin* plugin) {
const std::string instance_name = std::string(mjm_getString(plugin->instance_name)); const std::string instance_name = std::string(mjs_getString(plugin->instance_name));
const std::string plugin_name = std::string(mjm_getString(plugin->name)); const std::string plugin_name = std::string(mjs_getString(plugin->name));
if (!instance_name.empty()) { if (!instance_name.empty()) {
WriteAttrTxt(elem, "instance", instance_name); WriteAttrTxt(elem, "instance", instance_name);
} else { } else {
WriteAttrTxt(elem, "plugin", plugin_name); WriteAttrTxt(elem, "plugin", plugin_name);
const mjpPlugin* pplugin = mjp_getPluginAtSlot( const mjpPlugin* pplugin = mjp_getPluginAtSlot(
((mjCPlugin*)plugin->instance)->spec.plugin_slot); static_cast<mjCPlugin*>(plugin->instance)->spec.plugin_slot);
const char* c = &((mjCPlugin*)plugin->instance)->flattened_attributes[0]; const char* c = &(static_cast<mjCPlugin*>(plugin->instance)->flattened_attributes[0]);
for (int i = 0; i < pplugin->nattribute; ++i) { for (int i = 0; i < pplugin->nattribute; ++i) {
std::string value(c); std::string value(c);
if (!value.empty()) { if (!value.empty()) {
@@ -783,13 +784,13 @@ string mjXWriter::Write(char *error, size_t error_sz) {
// create document and root // create document and root
XMLDocument doc; XMLDocument doc;
XMLElement* root = doc.NewElement("mujoco"); XMLElement* root = doc.NewElement("mujoco");
root->SetAttribute("model", mjm_getString(model->modelname)); root->SetAttribute("model", mjs_getString(model->modelname));
// insert root // insert root
doc.InsertFirstChild(root); doc.InsertFirstChild(root);
// write comment if present // write comment if present
string text = mjm_getString(model->comment); string text = mjs_getString(model->comment);
if (!text.empty()) { if (!text.empty()) {
XMLComment* comment = doc.NewComment(text.c_str()); XMLComment* comment = doc.NewComment(text.c_str());
root->LinkEndChild(comment); root->LinkEndChild(comment);
@@ -937,7 +938,6 @@ void mjXWriter::Option(XMLElement* root) {
WRITEENBL("energy", mjENBL_ENERGY) WRITEENBL("energy", mjENBL_ENERGY)
WRITEENBL("fwdinv", mjENBL_FWDINV) WRITEENBL("fwdinv", mjENBL_FWDINV)
WRITEENBL("invdiscrete", mjENBL_INVDISCRETE) WRITEENBL("invdiscrete", mjENBL_INVDISCRETE)
WRITEENBL("sensornoise", mjENBL_SENSORNOISE)
WRITEENBL("multiccd", mjENBL_MULTICCD) WRITEENBL("multiccd", mjENBL_MULTICCD)
WRITEENBL("island", mjENBL_ISLAND) WRITEENBL("island", mjENBL_ISLAND)
#undef WRITEENBL #undef WRITEENBL
+1 -1
View File
@@ -72,7 +72,7 @@ class mjXWriter : public mjXBase {
void OneEquality(tinyxml2::XMLElement* elem, mjCEquality* pequality, mjCDef* def); void OneEquality(tinyxml2::XMLElement* elem, mjCEquality* pequality, mjCDef* def);
void OneTendon(tinyxml2::XMLElement* elem, mjCTendon* ptendon, mjCDef* def); void OneTendon(tinyxml2::XMLElement* elem, mjCTendon* ptendon, mjCDef* def);
void OneActuator(tinyxml2::XMLElement* elem, mjCActuator* pactuator, mjCDef* def); void OneActuator(tinyxml2::XMLElement* elem, mjCActuator* pactuator, mjCDef* def);
void OnePlugin(tinyxml2::XMLElement* elem, mjmPlugin* plugin); void OnePlugin(tinyxml2::XMLElement* elem, mjsPlugin* plugin);
bool writingdefaults; // true during defaults write bool writingdefaults; // true during defaults write
}; };
+50 -50
View File
@@ -20,7 +20,6 @@
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
#include "user/user_api.h" #include "user/user_api.h"
#include "user/user_objects.h"
#include "user/user_util.h" #include "user/user_util.h"
#include "xml/xml_native_reader.h" #include "xml/xml_native_reader.h"
#include "xml/xml_urdf.h" #include "xml/xml_urdf.h"
@@ -112,7 +111,7 @@ void mjXURDF::Parse(
// get model name // get model name
std::string modelname; std::string modelname;
if (ReadAttrTxt(root, "name", modelname)) { if (ReadAttrTxt(root, "name", modelname)) {
mjm_setString(model->modelname, modelname.c_str()); mjs_setString(model->modelname, modelname.c_str());
} }
// find and register all materials // find and register all materials
@@ -206,16 +205,16 @@ void mjXURDF::Parse(
// override the pose for the base link and add a free joint // override the pose for the base link and add a free joint
for (int i = 0; i < (int)urName.size(); i++) { for (int i = 0; i < (int)urName.size(); i++) {
if (urParent[i] < 0) { if (urParent[i] < 0) {
mjmBody* world = mjm_findBody(model, "world"); mjsBody* world = mjs_findBody(model, "world");
mjmBody* pbody = mjm_findChild(world, urName[i].c_str()); mjsBody* pbody = mjs_findChild(world, urName[i].c_str());
mjuu_copyvec(pbody->pos, pos, 3); mjuu_copyvec(pbody->pos, pos, 3);
mjuu_copyvec(pbody->quat, quat, 4); mjuu_copyvec(pbody->quat, quat, 4);
// add a free joint to allow motion of the body // add a free joint to allow motion of the body
// if the mass is 0, assume the object is static // if the mass is 0, assume the object is static
if (!static_body && pbody->mass > 0) { if (!static_body && pbody->mass > 0) {
mjmJoint* pjoint = mjm_addJoint(pbody, 0); mjsJoint* pjoint = mjs_addJoint(pbody, 0);
mjm_setString(pjoint->name, (urName[i] + "_free_joint").c_str()); mjs_setString(pjoint->name, (urName[i] + "_free_joint").c_str());
pjoint->type = mjJNT_FREE; pjoint->type = mjJNT_FREE;
} }
} }
@@ -226,14 +225,14 @@ void mjXURDF::Parse(
void mjXURDF::Body(XMLElement* body_elem) { void mjXURDF::Body(XMLElement* body_elem) {
std::string name, text; std::string name, text;
XMLElement *elem, *temp, *temp1; XMLElement *elem, *temp, *temp1;
mjmBody *pbody, *world; mjsBody *pbody, *world;
mjmGeom* pgeom; mjsGeom* pgeom;
// get body name and pointer to mjmBody // get body name and pointer to mjsBody
ReadAttrTxt(body_elem, "name", name, true); ReadAttrTxt(body_elem, "name", name, true);
name = GetPrefixedName(name); name = GetPrefixedName(name);
world = mjm_findBody(model, "world"); world = mjs_findBody(model, "world");
pbody = mjm_findChild(world, name.c_str()); pbody = mjs_findChild(world, name.c_str());
if (!pbody) { if (!pbody) {
throw mjXError(body_elem, "URDF body not found"); // SHOULD NOT OCCUR throw mjXError(body_elem, "URDF body not found"); // SHOULD NOT OCCUR
} }
@@ -272,7 +271,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
// lquat = rotation from specified to default (joint/body) inertial frame // lquat = rotation from specified to default (joint/body) inertial frame
double lquat[4] = {1, 0, 0, 0}; double lquat[4] = {1, 0, 0, 0};
double tmpquat[4] = {1, 0, 0, 0}; double tmpquat[4] = {1, 0, 0, 0};
const char* altres = mjm_setFullInertia(pbody, lquat, pbody->inertia); const char* altres = mjs_setFullInertia(pbody, lquat, pbody->inertia);
// inertia are sometimes 0 in URDF files: ignore error in altres, fix later // inertia are sometimes 0 in URDF files: ignore error in altres, fix later
(void) altres; (void) altres;
@@ -326,7 +325,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
mjXUtil::ReadAttrTxt(elem, "name", geom_name); mjXUtil::ReadAttrTxt(elem, "name", geom_name);
name = GetPrefixedName(name); name = GetPrefixedName(name);
if (urGeomNames.find(geom_name) == urGeomNames.end()) { if (urGeomNames.find(geom_name) == urGeomNames.end()) {
mjm_setString(pgeom->name, geom_name.c_str()); mjs_setString(pgeom->name, geom_name.c_str());
urGeomNames.insert(geom_name); urGeomNames.insert(geom_name);
} else { } else {
std::cerr << "WARNING: Geom with duplicate name '" << geom_name std::cerr << "WARNING: Geom with duplicate name '" << geom_name
@@ -349,7 +348,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
mjXUtil::ReadAttrTxt(elem, "name", geom_name); mjXUtil::ReadAttrTxt(elem, "name", geom_name);
geom_name = GetPrefixedName(geom_name); geom_name = GetPrefixedName(geom_name);
if (urGeomNames.find(geom_name) == urGeomNames.end()) { if (urGeomNames.find(geom_name) == urGeomNames.end()) {
mjm_setString(pgeom->name, geom_name.c_str()); mjs_setString(pgeom->name, geom_name.c_str());
urGeomNames.insert(geom_name); urGeomNames.insert(geom_name);
} else { } else {
std::cerr << "WARNING: Geom with duplicate name '" << geom_name std::cerr << "WARNING: Geom with duplicate name '" << geom_name
@@ -374,8 +373,8 @@ void mjXURDF::Parse(XMLElement* root) {
void mjXURDF::Joint(XMLElement* joint_elem) { void mjXURDF::Joint(XMLElement* joint_elem) {
std::string jntname, name, text; std::string jntname, name, text;
XMLElement *elem; XMLElement *elem;
mjmBody *pbody, *parent, *world; mjsBody *pbody, *parent, *world;
mjmJoint *pjoint=0, *pjoint1=0, *pjoint2=0; mjsJoint *pjoint=0, *pjoint1=0, *pjoint2=0;
int jointtype; int jointtype;
// get type and name // get type and name
@@ -390,8 +389,8 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
elem = FindSubElem(joint_elem, "parent", true); elem = FindSubElem(joint_elem, "parent", true);
ReadAttrTxt(elem, "link", name, true); ReadAttrTxt(elem, "link", name, true);
name = GetPrefixedName(name); name = GetPrefixedName(name);
world = mjm_findBody(model, "world"); world = mjs_findBody(model, "world");
parent = mjm_findChild(world, name.c_str()); parent = mjs_findChild(world, name.c_str());
if (!parent) { // SHOULD NOT OCCUR if (!parent) { // SHOULD NOT OCCUR
throw mjXError(elem, "invalid parent name in URDF joint definition"); throw mjXError(elem, "invalid parent name in URDF joint definition");
} }
@@ -400,8 +399,8 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
elem = FindSubElem(joint_elem, "child", true); elem = FindSubElem(joint_elem, "child", true);
ReadAttrTxt(elem, "link", name, true); ReadAttrTxt(elem, "link", name, true);
name = GetPrefixedName(name); name = GetPrefixedName(name);
world = mjm_findBody(model, "world"); world = mjs_findBody(model, "world");
pbody = mjm_findChild(world, name.c_str()); pbody = mjs_findChild(world, name.c_str());
if (!pbody) { // SHOULD NOT OCCUR if (!pbody) { // SHOULD NOT OCCUR
throw mjXError(elem, "invalid child name in URDF joint definition"); throw mjXError(elem, "invalid child name in URDF joint definition");
} }
@@ -418,16 +417,16 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
switch (jointtype) { switch (jointtype) {
case 0: // revolute case 0: // revolute
case 1: // continuous case 1: // continuous
pjoint = mjm_addJoint(pbody, 0); pjoint = mjs_addJoint(pbody, 0);
mjm_setString(pjoint->name, jntname.c_str()); mjs_setString(pjoint->name, jntname.c_str());
pjoint->type = mjJNT_HINGE; pjoint->type = mjJNT_HINGE;
mjuu_setvec(pjoint->pos, 0, 0, 0); mjuu_setvec(pjoint->pos, 0, 0, 0);
mjuu_copyvec(pjoint->axis, axis, 3); mjuu_copyvec(pjoint->axis, axis, 3);
break; break;
case 2: // prismatic case 2: // prismatic
pjoint = mjm_addJoint(pbody, 0); pjoint = mjs_addJoint(pbody, 0);
mjm_setString(pjoint->name, jntname.c_str()); mjs_setString(pjoint->name, jntname.c_str());
pjoint->type = mjJNT_SLIDE; pjoint->type = mjJNT_SLIDE;
mjuu_setvec(pjoint->pos, 0, 0, 0); mjuu_setvec(pjoint->pos, 0, 0, 0);
mjuu_copyvec(pjoint->axis, axis, 3); mjuu_copyvec(pjoint->axis, axis, 3);
@@ -437,8 +436,8 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
return; return;
case 4: // floating case 4: // floating
pjoint = mjm_addJoint(pbody, 0); pjoint = mjs_addJoint(pbody, 0);
mjm_setString(pjoint->name, jntname.c_str()); mjs_setString(pjoint->name, jntname.c_str());
pjoint->type = mjJNT_FREE; pjoint->type = mjJNT_FREE;
break; break;
@@ -448,8 +447,8 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
mjuu_quat2mat(mat, quat); mjuu_quat2mat(mat, quat);
// construct slider along x // construct slider along x
pjoint = mjm_addJoint(pbody, 0); pjoint = mjs_addJoint(pbody, 0);
mjm_setString(pjoint->name, (jntname + "_TX").c_str()); mjs_setString(pjoint->name, (jntname + "_TX").c_str());
pjoint->type = mjJNT_SLIDE; pjoint->type = mjJNT_SLIDE;
tmpaxis[0] = mat[0]; tmpaxis[0] = mat[0];
tmpaxis[1] = mat[3]; tmpaxis[1] = mat[3];
@@ -458,8 +457,8 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
mjuu_copyvec(pjoint->axis, tmpaxis, 3); mjuu_copyvec(pjoint->axis, tmpaxis, 3);
// construct slider along y // construct slider along y
pjoint1 = mjm_addJoint(pbody, 0); pjoint1 = mjs_addJoint(pbody, 0);
mjm_setString(pjoint1->name, (jntname + "_TY").c_str()); mjs_setString(pjoint1->name, (jntname + "_TY").c_str());
pjoint1->type = mjJNT_SLIDE; pjoint1->type = mjJNT_SLIDE;
tmpaxis[0] = mat[1]; tmpaxis[0] = mat[1];
tmpaxis[1] = mat[4]; tmpaxis[1] = mat[4];
@@ -468,8 +467,8 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
mjuu_copyvec(pjoint1->axis, tmpaxis, 3); mjuu_copyvec(pjoint1->axis, tmpaxis, 3);
// construct hinge around z = locaxis // construct hinge around z = locaxis
pjoint2 = mjm_addJoint(pbody, 0); pjoint2 = mjs_addJoint(pbody, 0);
mjm_setString(pjoint2->name, (jntname + "_RZ").c_str()); mjs_setString(pjoint2->name, (jntname + "_RZ").c_str());
pjoint2->type = mjJNT_HINGE; pjoint2->type = mjJNT_HINGE;
mjuu_setvec(pjoint2->pos, 0, 0, 0); mjuu_setvec(pjoint2->pos, 0, 0, 0);
mjuu_copyvec(pjoint2->axis, axis, 3); mjuu_copyvec(pjoint2->axis, axis, 3);
@@ -506,7 +505,7 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
// parse origin and geometry elements of visual or collision // parse origin and geometry elements of visual or collision
mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) { mjsGeom* mjXURDF::Geom(XMLElement* geom_elem, mjsBody* pbody, bool collision) {
XMLElement *elem, *temp; XMLElement *elem, *temp;
std::string text, meshfile; std::string text, meshfile;
@@ -514,8 +513,8 @@ mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
elem = FindSubElem(geom_elem, "geometry", true); elem = FindSubElem(geom_elem, "geometry", true);
// add BOX geom, modify type later // add BOX geom, modify type later
mjmGeom* pgeom = mjm_addGeom(pbody, 0); mjsGeom* pgeom = mjs_addGeom(pbody, 0);
mjm_setString(pgeom->name, ""); mjs_setString(pgeom->name, "");
pgeom->type = mjGEOM_BOX; pgeom->type = mjGEOM_BOX;
if (collision) { if (collision) {
pgeom->contype = 1; pgeom->contype = 1;
@@ -576,19 +575,19 @@ mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
meshname = mjuu_stripext(meshname); meshname = mjuu_stripext(meshname);
// look for existing mesh // look for existing mesh
mjmMesh* mesh = mjm_findMesh(model, meshname.c_str()); mjsMesh* mesh = mjs_findMesh(model, meshname.c_str());
mjmMesh* pmesh = 0; mjsMesh* pmesh = 0;
// does not exist: create // does not exist: create
if (!mesh) { if (!mesh) {
pmesh = mjm_addMesh(model, 0); pmesh = mjs_addMesh(model, 0);
} }
// exists with different scale: append name with '1', create // exists with different scale: append name with '1', create
else if (mesh->scale[0]!=meshscale[0] || else if (mesh->scale[0]!=meshscale[0] ||
mesh->scale[1]!=meshscale[1] || mesh->scale[1]!=meshscale[1] ||
mesh->scale[2]!=meshscale[2]) { mesh->scale[2]!=meshscale[2]) {
pmesh = mjm_addMesh(model, 0); pmesh = mjs_addMesh(model, 0);
meshname = meshname + "1"; meshname = meshname + "1";
} }
@@ -598,9 +597,9 @@ mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
} }
// set fields // set fields
mjm_setString(pmesh->file, meshfile.c_str()); mjs_setString(pmesh->file, meshfile.c_str());
mjm_setString(pmesh->name, meshname.c_str()); mjs_setString(pmesh->name, meshname.c_str());
mjm_setString(pgeom->meshname, meshname.c_str()); mjs_setString(pgeom->meshname, meshname.c_str());
pmesh->scale[0] = meshscale[0]; pmesh->scale[0] = meshscale[0];
pmesh->scale[1] = meshscale[1]; pmesh->scale[1] = meshscale[1];
pmesh->scale[2] = meshscale[2]; pmesh->scale[2] = meshscale[2];
@@ -633,9 +632,10 @@ void mjXURDF::Origin(XMLElement* origin_elem, double* pos, double* quat) {
ReadAttr(temp, "xyz", 3, pos, text); ReadAttr(temp, "xyz", 3, pos, text);
// orientation // orientation
mjCAlternative alt; mjsOrientation alt;
mjs_defaultOrientation(alt);
if (ReadAttr(temp, "rpy", 3, alt.euler, text)) { if (ReadAttr(temp, "rpy", 3, alt.euler, text)) {
alt.Set(quat, 0, "XYZ"); mjs_resolveOrientation(quat, 0, "XYZ", &alt);
} }
} }
} }
@@ -683,22 +683,22 @@ void mjXURDF::AddBody(std::string name) {
// add body with given number to the mjCModel tree, process children // add body with given number to the mjCModel tree, process children
void mjXURDF::AddToTree(int n) { void mjXURDF::AddToTree(int n) {
// get pointer to parent in mjCModel tree // get pointer to parent in mjCModel tree
mjmBody *parent = 0, *child = 0, *world = 0; mjsBody *parent = 0, *child = 0, *world = 0;
if (urParent[n]>=0) { if (urParent[n]>=0) {
world = mjm_findBody(model, "world"); world = mjs_findBody(model, "world");
parent = mjm_findChild(world, urName[urParent[n]].c_str()); parent = mjs_findChild(world, urName[urParent[n]].c_str());
if (!parent) if (!parent)
throw mjXError(0, "URDF body parent should already be in tree: %s", throw mjXError(0, "URDF body parent should already be in tree: %s",
urName[urParent[n]].c_str()); // SHOULD NOT OCCUR urName[urParent[n]].c_str()); // SHOULD NOT OCCUR
} else { } else {
parent = mjm_findBody(model, "world"); parent = mjs_findBody(model, "world");
} }
// add this body // add this body
if (urName[n] != "world") { if (urName[n] != "world") {
child = mjm_addBody(parent, 0); child = mjs_addBody(parent, 0);
mjm_setString(child->name, urName[n].c_str()); mjs_setString(child->name, urName[n].c_str());
} }
// add children recursively // add children recursively
+2 -2
View File
@@ -51,8 +51,8 @@ class mjXURDF : public mjXBase {
void AddToTree(int n); // add body to mjCModel tree void AddToTree(int n); // add body to mjCModel tree
void Body(tinyxml2::XMLElement* body_elem); // parse body void Body(tinyxml2::XMLElement* body_elem); // parse body
void Joint(tinyxml2::XMLElement* joint_elem); // parse joint void Joint(tinyxml2::XMLElement* joint_elem); // parse joint
mjmGeom* Geom(tinyxml2::XMLElement* geom_elem, mjsGeom* Geom(tinyxml2::XMLElement* geom_elem,
mjmBody* pbody, bool collision); // parse origin and geometry of geom mjsBody* pbody, bool collision); // parse origin and geometry of geom
void Origin(tinyxml2::XMLElement* origin_elem, double* pos, double* quat); // parse origin element void Origin(tinyxml2::XMLElement* origin_elem, double* pos, double* quat); // parse origin element
void MakeMaterials(tinyxml2::XMLElement* elem); // find all materials recursively void MakeMaterials(tinyxml2::XMLElement* elem); // find all materials recursively
+2 -3
View File
@@ -523,14 +523,13 @@ bool mjXUtil::SameVector(const T* vec1, const T* vec2, int n) {
return false; return false;
} }
bool same = true;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
if (std::abs(vec1[i] - vec2[i]) > std::numeric_limits<T>::epsilon()) { if (std::abs(vec1[i] - vec2[i]) > std::numeric_limits<T>::epsilon()) {
same = false; return false;
} }
} }
return same; return true;
} }
template bool mjXUtil::SameVector(const double* vec1, const double* vec2, int n); template bool mjXUtil::SameVector(const double* vec1, const double* vec2, int n);
+74
View File
@@ -765,6 +765,80 @@ TEST_F(ActuatorTest, ActuatorForceClamping) {
mj_deleteModel(model); mj_deleteModel(model);
} }
// Apply gravity compensation via actuators
TEST_F(ActuatorTest, ActuatorGravcomp) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<body gravcomp="1">
<joint name="joint" type="slide" axis="0 0 1"
actuatorfrcrange="-2 2" actuatorgravcomp="true"/>
<geom type="box" size=".05 .05 .05" mass="1"/>
</body>
</worldbody>
<actuator>
<motor name="actuator" joint="joint"/>
</actuator>
<sensor>
<actuatorfrc actuator="actuator"/>
<jointactuatorfrc joint="joint"/>
</sensor>
</mujoco>
)";
mjModel* model = LoadModelFromString(xml);
mjData* data = mj_makeData(model);
mj_forward(model, data);
// expect force clamping as specified in the model
EXPECT_EQ(data->actuator_force[0], 0);
EXPECT_EQ(data->qfrc_actuator[0], 2);
EXPECT_EQ(data->qfrc_passive[0], 0);
EXPECT_EQ(data->sensordata[0], 0);
EXPECT_EQ(data->sensordata[1], 2);
// reduce gravity so gravcomp is not clamped
model->opt.gravity[2] = -1;
mj_forward(model, data);
EXPECT_EQ(data->actuator_force[0], 0);
EXPECT_EQ(data->qfrc_actuator[0], 1);
EXPECT_EQ(data->qfrc_passive[0], 0);
EXPECT_EQ(data->sensordata[0], 0);
EXPECT_EQ(data->sensordata[1], 1);
// add control, see that it adds up
data->ctrl[0] = 0.5;
mj_forward(model, data);
EXPECT_EQ(data->actuator_force[0], 0.5);
EXPECT_EQ(data->qfrc_actuator[0], 1.5);
EXPECT_EQ(data->qfrc_passive[0], 0);
EXPECT_EQ(data->sensordata[0], 0.5);
EXPECT_EQ(data->sensordata[1], 1.5);
// add larger control, expect clamping
data->ctrl[0] = 1.5;
mj_forward(model, data);
EXPECT_EQ(data->actuator_force[0], 1.5);
EXPECT_EQ(data->qfrc_actuator[0], 2);
EXPECT_EQ(data->qfrc_passive[0], 0);
EXPECT_EQ(data->sensordata[0], 1.5);
EXPECT_EQ(data->sensordata[1], 2);
// disable actgravcomp, expect gravcomp as a passive force
model->jnt_actgravcomp[0] = 0;
mj_forward(model, data);
EXPECT_EQ(data->actuator_force[0], 1.5);
EXPECT_EQ(data->qfrc_actuator[0], 1.5);
EXPECT_EQ(data->qfrc_passive[0], 1);
EXPECT_EQ(data->sensordata[0], 1.5);
EXPECT_EQ(data->sensordata[1], 1.5);
mj_deleteData(data);
mj_deleteModel(model);
}
// ----------------------- filterexact actuators ------------------------------- // ----------------------- filterexact actuators -------------------------------
using FilterExactTest = MujocoTest; using FilterExactTest = MujocoTest;
+33
View File
@@ -15,7 +15,10 @@
// Tests for engine/engine_resource.c // Tests for engine/engine_resource.c
#include <array> #include <array>
#include <cstdint>
#include <cstring> #include <cstring>
#include <ctime>
#include <string>
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
@@ -24,6 +27,7 @@
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "src/engine/engine_plugin.h" #include "src/engine/engine_plugin.h"
#include "src/engine/engine_resource.h" #include "src/engine/engine_resource.h"
#include "src/engine/engine_util_misc.h"
#include "test/fixture.h" #include "test/fixture.h"
namespace mujoco { namespace mujoco {
@@ -327,5 +331,34 @@ TEST_F(ResourceTest, NameWithInvalidPrefix) {
ASSERT_THAT(resource, IsNull()); ASSERT_THAT(resource, IsNull());
} }
TEST_F(ResourceTest, OSFilesystemTimestamps) {
time_t t;
// some random file
const char* const file = "engine/testdata/collision_box/boxbox_deep.xml";
const std::string xml_path = GetTestDataFilePath(file);
mjResource* resource = mju_openResource(xml_path.c_str(), nullptr, 0);
mju_decodeBase64((uint8_t*) &t, resource->timestamp);
// equal timestamps
EXPECT_EQ(mju_isModifiedResource(resource, resource->timestamp), 0);
std::array<char, 512> test_timestamp;
// older resource timestamp
t++;
mju_encodeBase64(test_timestamp.data(), (uint8_t*) &t, sizeof(time_t));
EXPECT_EQ(mju_isModifiedResource(resource, test_timestamp.data()), -1);
// newer resource timestamp
t -= 2;
mju_encodeBase64(test_timestamp.data(), (uint8_t*) &t, sizeof(time_t));
EXPECT_EQ(mju_isModifiedResource(resource, test_timestamp.data()), 1);
mju_closeResource(resource);
}
} // namespace } // namespace
} // namespace mujoco } // namespace mujoco
+33
View File
@@ -95,5 +95,38 @@ TEST_F(EngineUtilBlasTest, MjuSymmetrize) {
3, 3.5, 3)); 3, 3.5, 3));
} }
TEST_F(EngineUtilBlasTest, MjuMulMat3) {
const mjtNum mat1[9] = {
1, 2, 3,
4, 5, 6,
7, 8, 9
};
const mjtNum mat2[9] = {
2, 3, 4,
5, 6, 7,
8, 9, 10
};
mjtNum res1[9] = {0};
mjtNum res2[9] = {0};
mju_mulMatMat3(res1, mat1, mat2);
mju_mulMatMat(res2, mat1, mat2, 3, 3, 3);
for (int i = 0; i < 9; ++i) {
EXPECT_EQ(res1[i], res2[i]);
}
mju_mulMatTMat3(res1, mat1, mat2);
mju_mulMatTMat(res2, mat1, mat2, 3, 3, 3);
for (int i = 0; i < 9; ++i) {
EXPECT_EQ(res1[i], res2[i]);
}
mju_mulMatMatT3(res1, mat1, mat2);
mju_mulMatMatT(res2, mat1, mat2, 3, 3, 3);
for (int i = 0; i < 9; ++i) {
EXPECT_EQ(res1[i], res2[i]);
}
}
} // namespace } // namespace
} // namespace mujoco } // namespace mujoco
+31 -2
View File
@@ -20,6 +20,8 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "src/engine/engine_resource.h"
#include "src/engine/engine_vfs.h"
#include "test/fixture.h" #include "test/fixture.h"
namespace mujoco { namespace mujoco {
@@ -28,7 +30,7 @@ namespace {
using ::testing::NotNull; using ::testing::NotNull;
using EngineVfsTest = MujocoTest; using EngineVfsTest = MujocoTest;
TEST_F(EngineVfsTest, AddFileTest) { TEST_F(EngineVfsTest, AddFile) {
constexpr char path[] = "engine/testdata/actuation/"; constexpr char path[] = "engine/testdata/actuation/";
const std::string dir = GetTestDataFilePath(path); const std::string dir = GetTestDataFilePath(path);
std::string file1 = "activation.xml"; std::string file1 = "activation.xml";
@@ -81,7 +83,7 @@ TEST_F(EngineVfsTest, AddFileTest) {
mj_deleteVFS(vfs.get()); mj_deleteVFS(vfs.get());
} }
TEST_F(EngineVfsTest, AddBufferTest) { TEST_F(EngineVfsTest, AddBuffer) {
auto vfs = std::make_unique<mjVFS>(); auto vfs = std::make_unique<mjVFS>();
mj_defaultVFS(vfs.get()); mj_defaultVFS(vfs.get());
std::string buffer = "<mujoco/>"; std::string buffer = "<mujoco/>";
@@ -94,5 +96,32 @@ TEST_F(EngineVfsTest, AddBufferTest) {
mj_deleteVFS(vfs.get()); mj_deleteVFS(vfs.get());
} }
TEST_F(EngineVfsTest, Timestamps) {
static constexpr char cube[] = R"(
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000)";
auto vfs = std::make_unique<mjVFS>();
mj_defaultVFS(vfs.get());
mj_addBufferVFS(vfs.get(), "cube.obj", cube, sizeof(cube));
mjResource* resource = mju_openVfsResource("cube.obj", vfs.get());
// same timestamps
EXPECT_EQ(mju_isModifiedResource(resource, resource->timestamp), 0);
// different timestamps
EXPECT_EQ(mju_isModifiedResource(resource, "QQ=="), 1);
mju_closeResource(resource);
mj_deleteVFS(vfs.get());
}
} // namespace } // namespace
} // namespace mujoco } // namespace mujoco
+6 -6
View File
@@ -6,7 +6,7 @@
(e.g. 4 consecutive ball joints is not a realistic kinematic design) (e.g. 4 consecutive ball joints is not a realistic kinematic design)
--> -->
<option viscosity="10" integrator="implicit"> <option viscosity="10" integrator="implicit">
<flag gravity="disable" contact="disable"/> <flag contact="disable"/>
</option> </option>
<statistic meansize=".05"/> <statistic meansize=".05"/>
@@ -29,7 +29,7 @@
commands is achievable by individual joint actuators with the specified torque limits. commands is achievable by individual joint actuators with the specified torque limits.
See https://mujoco.readthedocs.io/en/latest//modeling.html#actuator-force-clamping See https://mujoco.readthedocs.io/en/latest//modeling.html#actuator-force-clamping
--> -->
<joint stiffness="1e-1" actuatorfrcrange="-1 1"/> <joint armature="1e-3" damping="1e-3" stiffness="1e-2" actuatorfrcrange="-1 1" actuatorgravcomp="true"/>
<site type="box" size=".012 .012 .012" rgba=".7 .7 .8 1"/> <site type="box" size=".012 .012 .012" rgba=".7 .7 .8 1"/>
</default> </default>
@@ -37,19 +37,19 @@
<light pos="0 0 2"/> <light pos="0 0 2"/>
<geom type="box" size=".25 .25 .01" pos="0 0 -.01"/> <geom type="box" size=".25 .25 .01" pos="0 0 -.01"/>
<site name="reference" pos="0 0 .25"/> <site name="reference" pos="0 0 .25"/>
<body name="arm" pos="-.25 .25 0"> <body name="arm" pos="-.25 .25 0" gravcomp="1">
<joint axis="1 0 0"/> <joint axis="1 0 0"/>
<joint axis="0 1 0"/> <joint axis="0 1 0"/>
<geom type="box" size=".01" fromto="0 0 0 0 0 .25"/> <geom type="box" size=".01" fromto="0 0 0 0 0 .25"/>
<body pos="0 0 .25"> <body pos="0 0 .25" gravcomp="1">
<joint axis="0 1 0"/> <joint axis="0 1 0"/>
<joint axis="0 0 1"/> <joint axis="0 0 1"/>
<geom type="box" size=".01" fromto="0 0 0 .25 0 0"/> <geom type="box" size=".01" fromto="0 0 0 .25 0 0"/>
<body pos=".25 0 0"> <body pos=".25 0 0" gravcomp="1">
<joint axis="1 0 0"/> <joint axis="1 0 0"/>
<joint axis="0 0 1"/> <joint axis="0 0 1"/>
<geom type="box" size=".01" fromto="0 0 0 0 -.2 0"/> <geom type="box" size=".01" fromto="0 0 0 0 -.2 0"/>
<body pos="0 -.2 0"> <body pos="0 -.2 0" gravcomp="1">
<joint axis="1 0 0"/> <joint axis="1 0 0"/>
<joint axis="0 0 1"/> <joint axis="0 0 1"/>
<joint axis="0 1 0"/> <joint axis="0 1 0"/>
+8 -2
View File
@@ -32,8 +32,14 @@ test_model() {
# this test can take several minutes under ASAN # this test can take several minutes under ASAN
return 0 return 0
fi fi
if [[ "$model" == */benchmark/testdata/humanoid200.xml if [[ "$model" == */benchmark/testdata/humanoid200.xml ||
|| "$model" == */engine/testdata/collision_convex/stacked_boxes.xml "$model" == */engine/testdata/collision_convex/stacked_boxes.xml ||
"$model" == */user/testdata/shark_41_ascii_gmshApp.xml ||
"$model" == */user/testdata/shark_22_ascii_fTetWild.xml ||
"$model" == */user/testdata/shark_22_ascii_gmshApp.xml ||
"$model" == */user/testdata/shark_22_binary_fTetWild.xml ||
"$model" == */user/testdata/shark_41_binary_gmshApp.xml ||
"$model" == */user/testdata/shark_22_binary_gmshApp.xml
]]; then ]]; then
iterations=2 iterations=2
fi fi
+16 -2
View File
@@ -17,8 +17,13 @@
1.618 0 -1 1.618 0 -1
-1.618 0 1 -1.618 0 1
-1.618 0 -1"/> -1.618 0 -1"/>
<hfield name="hfield" nrow="3" ncol="3" size=".2 .2 .1 .03"/> <hfield name="hfield" nrow="3" ncol="3" size=".2 .2 .03 .03"
elevation="1 0 1
0 1 0
1 0 1"/>
<texture builtin="gradient" height="100" rgb1="1 1 1" rgb2="0 0 0" type="skybox" width="100"/> <texture builtin="gradient" height="100" rgb1="1 1 1" rgb2="0 0 0" type="skybox" width="100"/>
<texture name="grid" type="cube" builtin="checker" width="32" height="32" rgb1=".1 .2 .3" rgb2="1 1 1"/>
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
</asset> </asset>
<default> <default>
@@ -41,7 +46,7 @@
<geom name="floor" type="plane" size="4 4 .1"/> <geom name="floor" type="plane" size="4 4 .1"/>
<geom type="hfield" hfield="hfield" pos="-.4 .6 .05" rgba="0 0 1 1"/> <geom type="hfield" hfield="hfield" pos="-.4 .6 .05" rgba="0 0 1 1"/>
<body name="head" pos="0 0 .7"> <body name="head" pos="0 0 .7">
<geom type="ellipsoid" size=".2 .2 .4" rgba="1 1 0 1" density="100"/> <geom type="ellipsoid" size=".2 .2 .4" density="100" material="grid"/>
<site name="head" pos="0 0 .4" size=".1 .1 .05" type="box"/> <site name="head" pos="0 0 .4" size=".1 .1 .05" type="box"/>
<site name="anchor0" pos="0 .2 0"/> <site name="anchor0" pos="0 .2 0"/>
<site name="rf" pos="0 0 -0.41" zaxis="0 0 -1"/> <site name="rf" pos="0 0 -0.41" zaxis="0 0 -1"/>
@@ -161,4 +166,13 @@
qpos="0.0133625 -0.013799 0.659429 0.999776 0.019159 0.00902704 0.000572574 -0.00776575 0.0983289 0.999861 -0.00869796 -0.0141805 0.000912197 0.00700633 0.0930296 0.00637469 -0.00313231 0.119692 0.0051478 -0.0469067 0 -0.500224 0.300659 0.69913 1 -0.000367766 -0.000265698 -0.000109715 -0.319851 0.525628 0.702735 0.29858 0.698263 -0.0490604 -0.648746 -0.579432 0.4206 0.749601 0.900145 -0.208463 0.346664 -0.161576 -0.200033 0.300084 0.976421 0.878429 -0.00171382 0.00127086 -0.477867" qpos="0.0133625 -0.013799 0.659429 0.999776 0.019159 0.00902704 0.000572574 -0.00776575 0.0983289 0.999861 -0.00869796 -0.0141805 0.000912197 0.00700633 0.0930296 0.00637469 -0.00313231 0.119692 0.0051478 -0.0469067 0 -0.500224 0.300659 0.69913 1 -0.000367766 -0.000265698 -0.000109715 -0.319851 0.525628 0.702735 0.29858 0.698263 -0.0490604 -0.648746 -0.579432 0.4206 0.749601 0.900145 -0.208463 0.346664 -0.161576 -0.200033 0.300084 0.976421 0.878429 -0.00171382 0.00127086 -0.477867"
qvel="0.508861 -0.243772 -0.327162 0.549686 1.13746 0.0282475 -0.0865243 1.06414 -0.239958 -0.532111 -0.00133789 -0.0654491 0.533148 -0.253161 0.122149 0.824764 0.723529 -0.674175 0 -0.00154509 -0.00568917 0.00479921 0.00541817 0.00115895 0.00317796 -0.160161 -0.599488 -1.38103 14.9789 -1.05454 -13.9252 -0.31223 -0.0102486 -0.405851 5.43992 -4.71514 0.114928 -0.00123758 0.000187845 -0.244109 -0.190199 0.0697975 -16.3286"/> qvel="0.508861 -0.243772 -0.327162 0.549686 1.13746 0.0282475 -0.0865243 1.06414 -0.239958 -0.532111 -0.00133789 -0.0654491 0.533148 -0.253161 0.122149 0.824764 0.723529 -0.674175 0 -0.00154509 -0.00568917 0.00479921 0.00541817 0.00115895 0.00317796 -0.160161 -0.599488 -1.38103 14.9789 -1.05454 -13.9252 -0.31223 -0.0102486 -0.405851 5.43992 -4.71514 0.114928 -0.00123758 0.000187845 -0.244109 -0.190199 0.0697975 -16.3286"/>
</keyframe> </keyframe>
<custom>
<numeric name="numeric" data="1 2 3"/>
<text name="text" data="abc"/>
<tuple name="tuple">
<element objtype="body" objname="cylinder" prm="1"/>
<element objtype="joint" objname="hipz_0" prm="2"/>
</tuple>
</custom>
</mujoco> </mujoco>

Some files were not shown because too many files have changed in this diff Show More