diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst
index e1b78754..afb6e339 100644
--- a/doc/XMLreference.rst
+++ b/doc/XMLreference.rst
@@ -1321,9 +1321,9 @@ also known as terrain map, is a 2D matrix of elevation data. The data can be spe
.. _asset-hfield-content_type:
-:at:`content_type`: :at-val: `string, optional`
+:at:`content_type`: :at-val:`string, optional`
If the file attribute is specified, then this sets the
- `Media Type `_ (formerly known as MIME types) of the
+ `Media Type `__ (formerly known as MIME types) of the
file to be loaded. Any filename extensions will be overloaded. Currently ``image/png`` and
``image/vnd.mujoco.hfield`` are supported.
@@ -1576,173 +1576,23 @@ Associate this mesh with an :ref:`engine plugin`. Either :at:`plugin`
Instance name, used for explicit plugin instantiation.
-
-.. _deformable-skin:
.. _asset-skin:
:el-prefix:`asset/` |-| **skin** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-Skinned meshes (or skins) were added in MuJoCo 2.0. These are deformable meshes whose vertex positions and normals are
-computed each time the model is rendered. MuJoCo skins are only used for visualization and do not affect the physics
-in any way. In particular, collisions involve the geoms of the bodies to which the skin is attached, and not the skin
-itself. Unlike regular meshes which are referenced from geoms and participate in collisions, the skin is not
-referenced from anywhere else in the model. It is a stand-alone asset that is used by renderer and not by the
-simulator.
-
-The skin has vertex positions and normals updated at runtime, and triangle faces and optional texture coordinates
-which are predefined. It also has "bones" used for updating. Bones are regular MuJoCo bodies referenced with the
-:el:`bone` subelement. Each bone has a list of vertex indices and corresponding real-valued weights which specify how
-much the bone position and orientation influence the corresponding vertex. The vertex has local coordinates with
-respect to every bone that influences it. The local coordinates are computed by the model compiler, given global
-vertex coordinates and global bind poses for each body. The bind poses do not have to correspond to the model
-reference configuration qpos0. Note that the vertex positions and bone bind poses provided in the skin definition are
-always global, even if the model itself is defined in local coordinates.
-
-At runtime the local coordinates of each vertex with respect to each bone that influences it are converted to global
-coordinates, and averaged in proportion to the corresponding weights to obtain a single set of 3D coordinates for each
-vertex. Normals then are computed automatically given the resulting global vertex positions and face information.
-Finally, the skin can be inflated by applying an offset to each vertex position along its (computed) normal.
-Skins are one-sided for rendering purposes; this is because back-face culling is needed to avoid shading and aliasing
-artifacts. When the skin is a closed 3D shape this does not matter because the back sides cannot be seen. But if the
-skin is a 2D object, we have to specify both sides and offset them slightly to avoid artifacts. Note that the
-composite objects introduced in MuJoCo 2.0 generate skins automatically. So one can save an XML model with a composite
-object, and obtain an elaborate example of how a skin is specified in the XML.
-
-Similar to meshes, skins can be specified directly in the XML via attributes documented later, or loaded from a binary
-SKN file which is in a custom format. The specification of skins is more complex than meshes because of the bone
-subelements. The file format starts with a header of 4 integers: nvertex, ntexcoord, nface, nbone. The first three are
-the same as in meshes, and specify the total number of vertices, texture coordinate pairs, and triangle faces in the
-skin. ntexcoord can be zero or equal to nvertex. nbone specifies the number of MuJoCo bodies that will be used as
-bones in the skin. The header is followed by the vertex, texcoord and face data, followed by a specification for each
-bone. The bone specification contains the name of the corresponding model body, 3D bind position, 4D bind quaternion,
-number of vertices influenced by the bone, and the vertex index array and weight array. Body names are represented as
-fixed-length character arrays and are expected to be 0-terminated. Characters after the first 0 are ignored. The
-contents of the SKN file are:
-
-.. code:: Text
-
- (int32) nvertex
- (int32) ntexcoord
- (int32) nface
- (int32) nbone
- (float) vertex_positions[3*nvertex]
- (float) vertex_texcoords[2*ntexcoord]
- (int32) face_vertex_indices[3*nface]
- for each bone:
- (char) body_name[40]
- (float) bind_position[3]
- (float) bind_quaternion[4]
- (int32) vertex_count
- (int32) vertex_index[vertex_count]
- (float) vertex_weight[vertex_count]
-
-Similar to the other custom binary formats used in MuJoCo, the file size in bytes is strictly enforced by the model
-compiler. The skin file format has subelements so the overall file size formula is difficult to write down, but should
-be clear from the above specification.
-
-.. _deformable-skin-name:
.. _asset-skin-name:
-
-:at:`name`: :at-val:`string, optional`
- Name of the skin.
-
-.. _deformable-skin-file:
.. _asset-skin-file:
-
-:at:`file`: :at-val:`string, optional`
- The SKN file from which the skin will be loaded. The path is determined as described in the meshdir attribute of
- :ref:`compiler `. If the file is omitted, the skin specification must be provided in the XML using the
- attributes below.
-
-.. _deformable-skin-vertex:
.. _asset-skin-vertex:
-
-:at:`vertex`: :at-val:`real(3*nvert), optional`
- Vertex 3D positions, in the global bind pose where the skin is defined.
-
-.. _deformable-skin-texcoord:
.. _asset-skin-texcoord:
-
-:at:`texcoord`: :at-val:`real(2*nvert), optional`
- Vertex 2D texture coordinates, between 0 and 1. Note that skin and geom texturing are somewhat different. Geoms can
- use automated texture coordinate generation while skins cannot. This is because skin data are computed directly in
- global coordinates. So if the material references a texture, one should specify explicit texture coordinates for the
- skin using this attribute. Otherwise the texture will appear to be stationary in the world while the skin moves
- around (creating an interesting effect but probably not as intended).
-
-.. _deformable-skin-face:
.. _asset-skin-face:
-
-:at:`face`: :at-val:`int(3*nface), optional`
- Trinagular skin faces. Each face is a triple of vertex indices, which are integers between zero and nvert-1.
-
-.. _deformable-skin-inflate:
.. _asset-skin-inflate:
-
-:at:`inflate`: :at-val:`real, "0"`
- If this number is not zero, the position of vertex during updating will be offset along the vertex normal, but the
- distance specified in this attribute. This is particularly useful for skins representing flexible 2D shapes.
-
-.. _deformable-skin-material:
.. _asset-skin-material:
-
-:at:`material`: :at-val:`string, optional`
- If specified, this attribute applies a material to the skin.
-
-.. _deformable-skin-rgba:
.. _asset-skin-rgba:
-
-:at:`rgba`: :at-val:`real(4), "0.5 0.5 0.5 1"`
- Instead of creating material assets and referencing them, this attribute can be used to set color and transparency
- only. This is not as flexible as the material mechanism, but is more convenient and is often sufficient. If the value
- of this attribute is different from the internal default, it takes precedence over the material.
-
-.. _deformable-skin-group:
.. _asset-skin-group:
-:at:`group`: :at-val:`int, "0"`
- Integer group to which the skin belongs. This attribute can be used for custom tags. It is also used by the
- visualizer to enable and disable the rendering of entire groups of skins.
-
-
-.. _skin-bone:
-
-:el-prefix:`skin/` |-| **bone** (*)
-'''''''''''''''''''''''''''''''''''
-
-This element defines a bone of the skin. The bone is a regular MuJoCo body which is referenced by name here.
-
-
-.. _skin-bone-body:
-
-:at:`body`: :at-val:`string, required`
- Name of the body corresponding to this bone.
-
-.. _skin-bone-bindpos:
-
-:at:`bindpos`: :at-val:`real(3), required`
- Global body position corresponding to the bind pose.
-
-.. _skin-bone-bindquat:
-
-:at:`bindquat`: :at-val:`real(4), required`
- Global body orientation corresponding to the bind pose.
-
-.. _skin-bone-vertid:
-
-:at:`vertid`: :at-val:`int(nvert), required`
- Integer indices of the vertices influenced by this bone. The vertex index corresponds to the order of the vertex in
- the skin mesh. The number of vertex indices specified here (nvert) must equal the number of vertex weights specified
- with the next attribute. The same vertex may be influenced by multiple bones, and each vertex must be influenced by
- at least one bone.
-
-.. _skin-bone-vertweight:
-
-:at:`vertweight`: :at-val:`real(nvert), required`
- Weights for the vertices influenced by this bone, in the same order as the vertex indices. Negative weights are
- allowed (which is needed for cubic interpolation for example) however the sum of all bone weights for a given vertex
- must be positive.
+:ref:`Skins` have been moved under the new grouping element :ref:`deformable`. They can
+still be specified here but this functionality is now deprecated and will be removed in the future.
.. _asset-material:
@@ -1750,7 +1600,7 @@ This element defines a bone of the skin. The bone is a regular MuJoCo body which
:el-prefix:`asset/` |-| **material** (*)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-This element creates a material asset. It can be referenced from :ref:`skins `, :ref:`geoms `,
+This element creates a material asset. It can be referenced from :ref:`skins `, :ref:`geoms `,
:ref:`sites ` and :ref:`tendons ` to set their appearance. Note that all these elements also have a
local rgba attribute, which is more convenient when only colors need to be adjusted, because it does not require
creating materials and referencing them. Materials are useful for adjusting appearance properties beyond color. However
@@ -1920,19 +1770,17 @@ adjust it properly through the XML.
:at:`o_margin`: :at-val:`real, "0"`
This attribute replaces the margin parameter of all active contact pairs when :ref:`Contact override ` is
- enabled. Otherwise MuJoCo uses the element-specific margin attribute of :ref:`geom ` or :ref:`pair
- ` depending on how the contact pair was generated. See also :ref:`Collision` in the Computation
- chapter. The related gap parameter does not have a global override.
+ enabled. Otherwise MuJoCo uses the element-specific margin attribute of :ref:`geom` or
+ :ref:`pair` depending on how the contact pair was generated. See also :ref:`Collision` in the
+ Computation chapter. The related gap parameter does not have a global override.
.. _option-o_solref:
-
.. _option-o_solimp:
-
.. _option-o_friction:
:at:`o_solref`, :at:`o_solimp`, :at:`o_friction`
- These attributes replace the solref, solimp, and friction parameters of all active contact pairs when contact
- override is enabled. See :ref:`CSolver` for details.
+ These attributes replace the solref, solimp and friction parameters of all active contact pairs when contact override is
+ enabled. See :ref:`CSolver` for details.
.. _option-integrator:
@@ -3714,171 +3562,344 @@ Associate this composite with an :ref:`engine plugin`. Either :at:`plu
Instance name, used for explicit plugin instantiation.
+
.. _body-flexcomp:
-:el-prefix:`body/` |-| **flex** (*)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:el-prefix:`body/` |-| **flexcomp** (*)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Similar to :el:`composite`, this element (new in MuJoCo 3.0) is not a model element, but rather a macro which expands
+into multiple model elements representing a deformable entity. In particular this macro creates one
+:ref:`flex` element, a number of bodies that are children of the body in which the :el:`flexcomp` is
+defined, and optionally one :ref:`flex equality` which constrains all flex edges to their initial length.
+A number of attributes are specified here and then passed through to the automatically-constructed flex. The primary
+role of :el:`flexcomp` is to automate the creation of a (possibly large) collection of moving bodies with corresponding
+joints, and connect them with stretchable flex elements. See :ref:`flex` and :ref:`deformable
+objects` documentation for specifics on how flexes work. Here we only describe the automated construction
+process.
+
+An important distinction between :el:`flex` and :el:`flexcomp` is that the flex references bodies and specifies vertex
+coordinates in the frames of those bodies, while the flexcomp defines *points*. Each flexcomp point corresponds to one
+body and one vertex in the underlying flex. If the flexcomp point is *pinned*, the corresponding flex body is the parent
+body of the flexcomp, while the corresponding flex vertex coordinates equal the flexcomp point coordinates. If the
+flexcomp point is not pinned, a new child body is created at the coordinates of the flexcomp point (within the flexcomp
+parent body), and then the coordinates of the flex vertex within that new body are (0,0,0). The mechanism for
+:ref:`pinning` flexcomp points is explained below.
+
+Composite objects (available prior to MuJoCo 3.0) needed bodies with geoms for collisions, and sites for connecting
+tendons which generated shape-preserving forces. In contrast, flexes generate their own collisions and shape-preserving
+forces (as well as rendering), thus the bodies created here are much simpler: no geoms, sites or tendons are needed.
+Most of the bodies created here have 3 orthogonal slider joints, corresponding to freely moving point masses. In some
+cases we generate radial slider joints, allowing only expansion and contraction. Since no geoms are generated, the
+bodies need to have explicit inertial parameters.
+
+Below is a simple example of a flexcomp, modeling a (somewhat flexible) double pendulum with one end pinned to the
+world:
+
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+This flexcomp has 3 points, however the first point is pinned to the world (i.e. the parent of the flexcomp) and so only
+two bodies are automatically created, namely FL_1 and FL_2. Here is what this flexcomp generates after loading and
+saving the XML:
+
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-.. _body-flexcomp-name:
.. _body-flexcomp-class:
-.. _body-flexcomp-type:
+:at:`class`: :at-val:`string, optional`
+ Defaults class for setting unspecified attributes.
+
+.. _body-flexcomp-name:
+
+:at:`name`: :at-val:`string, required`
+ The name of the flex element being generated automatically. This name is used as a prefix for all bodies that are
+ automatically generated here, and is also referenced by the corresponding flex equality constraint (if applicable).
.. _body-flexcomp-dim:
+:at:`dim`: :at-val:`int(1), "2"`
+ Dimensionality of the flex object. This value must be 1, 2 or 3. The flex elements are capsules in 1D, triangles with
+ radius in 2D, and tetrahedra with radius in 3D. Certain flexcomp types imply a dimensionality, in which case the
+ value specified here is ignored.
+
+.. _body-flexcomp-type:
+
+:at:`type`: :at-val:`[grid, box, cylinder, ellipsoid, mesh, gmsh, direct], "grid"`
+ This attribute determines the type of :el:`flexcomp` object. The remaining attributes and sub-elements are then
+ interpreted according to the type. Default settings are also adjusted depending on the type. Different types
+ correspond to different methods for specifying the flexcomp points and the stretchable elements that connect them.
+ They fall in three categories: direct specification entered in the XML, direct specification loaded from file, and
+ automated generation from higher-level specification.
+
+ **grid** generates a rectangular grid of points in 1D, 2D or 3D as specified by :at:`dim`. The number of points in
+ each dimension is determined by :at:`count` while the grid spacing in each dimension is determined by :at:`spacing`.
+ Make sure the spacing is sufficiently large relative to :at:`radius` to avoid permanent contacts. In 2D and 3D the
+ grid is automatically triangulated, and corresponding flex elements are created (triangles or tetrahedra). In 1D the
+ elements are capsules connecting consecutive pairs of points.
+
+ **box** generates a 3D box object, however flex bodies are only generated on the outer shell. Each flex body has a
+ radial slider joint allowing it to move in and out from the center of the box. The parent body would normally be a
+ floating body. The box surface is triangulated, and each flex element is a tetrahedron connecting the center of the
+ box with one triangle face. :at:`count` and :at:`spacing` determine the count and spacing of the flex bodies, similar
+ to the **grid** type in 3D. Note that the resulting flex has the same topology as the box generated by
+ :el:`composite`.
+
+ **cylinder** is the same as **box**, except the points are projected on the surface of a cylinder.
+
+ **ellipsoid** is the same as **box**, except the points are projected on the surface of an ellipsoid.
+
+ **mesh** loads the flexcomp points and elements (i.e. triangles) from a mesh file, in the same file formats as mesh
+ assets. A mesh asset is not actually added to the model. Instead the vertex and face data from the mesh file are used
+ to populate the point and element data of the flexcomp. :at:`dim` is automatically set to 2. Recall that a mesh asset
+ 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).
+
+ **gmsh** is similar to mesh, but it loads a `GMSH file `__
+ in format 4.1 (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
+ topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes.
+ Only the Nodes and Elements sections of the GMHS file are processed, and used to populate the point and element data
+ of the flexcomp. The parser will generate an error if the 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 generate a corresponding soft entity. If such a mesh is available in a
+ different file format, use the freely available `GMSH software `__ to convert it to GMSH 4.1.
+
+ **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
+ convenience compared to specifing the corresponding flex directly.
+
.. _body-flexcomp-count:
+:at:`count`: :at-val:`int(3), "10 10 10"`
+ The number of automatically generated points in each dimension. This and the next attribute only apply to types grid,
+ box, cylinder, ellipsoid.
+
.. _body-flexcomp-spacing:
-.. _body-flexcomp-radius:
-
-.. _body-flexcomp-rigid:
-
-.. _body-flexcomp-mass:
-
-.. _body-flexcomp-inertiabox:
-
-.. _body-flexcomp-scale:
-
-.. _body-flexcomp-file:
+:at:`spacing`: :at-val:`real(3), "0.02 0.02 0.02"`
+ The spacing between the automatically generated points in each dimension. The spacing should be sufficiently large
+ compared to the radius, to avoid permanent contacts.
.. _body-flexcomp-point:
+:at:`point`: :at-val:`real(3*npoint), optional`
+
+ The 3D coordinates of the points. This attribute is only used with type **direct**. All other flexcomp types generate
+ their own points. The points are used to construct bodies and vertices as explained earlier.
+
.. _body-flexcomp-element:
-.. _body-flexcomp-material:
+:at:`element`: :at-val:`int((dim+1)*npoint), optional`
-.. _body-flexcomp-rgba:
+ The zero-based point ids forming each flex elements. This attribute is only used with type **direct**. All other
+ flexcomp types generate their own elements. This data is passed through to the automatically-generated flex.
.. _body-flexcomp-texcoord:
+:at:`texcoord`: :at-val:`real(2*npoint), optional`
+
+ Texture coordinates of each point, passed through to the automatically-generated flex. Note that flexcomp does not
+ generate texture coordinates automatically, except for 2D grids. For all other types, the user can specify explicit
+ texture coordinates here, even if the points themselves were generated automatically. This requires understanding of
+ the layout of the automatically-generated points and how they correspond to the texture referenced by the material.
+
+.. _body-flexcomp-mass:
+
+:at:`mass`: :at-val:`real(1), "1"`
+ The mass of each automatically-generated body equals this value divided by the number of points. Note that pinning
+ some points does not affect the mass of the other bodies.
+
+.. _body-flexcomp-inertiabox:
+
+:at:`inertiabox`: :at-val:`real(1), "0.005"`
+ Even though the automatically-generated bodies have the physics of point masses, with slider joints, MuJoCo still
+ requires each body to have rotational inertia. The inertias generated here are diagonal, and are computed such that
+ the corresponding equivalent-inertia boxes have sides equal to this value.
+
+.. _body-flexcomp-file:
+
+: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
+ determine the file format. Supported formats are the same as in :ref:`mesh assets`. For gmsh, the file is
+ expected to be in GMSH format 4.1, ascii or binary.
+
+.. _body-flexcomp-rigid:
+
+:at:`rigid`: :at-val:`[true, false], "false"`
+ If this is true, all points correspond to vertices within the parent body, and no new bodies are created. This is
+ equivalent to pinning all points. Note that if all points are indeed pinned, the model compiler will detect that the
+ flex is rigid (which behaves is a non-convex mesh in collision detection).
+
.. _body-flexcomp-pos:
+:at:`pos`: :at-val:`real(3), "0 0 0"`
+ This 3D vector translates all points relative to the frame of the parent body.
+
.. _body-flexcomp-quat:
+:at:`quat`: :at-val:`real(4), "1 0 0 0"`
+ This is a quaternion rotation of all points around the :at:`pos` vector specified above. Together these two vectors
+ define a pose transformation, used to position and orient the points as needed.
+
.. _body-flexcomp-axisangle:
-
.. _body-flexcomp-xyaxes:
-
.. _body-flexcomp-zaxis:
-
.. _body-flexcomp-euler:
-.. _body-flexcomp-group:
+:at:`axisangle`, :at:`xyaxes`, :at:`zaxis`, :at:`euler`
+ Alternative specification of rotation, that can be used instead of :at:`quat`.
+
+.. _body-flexcomp-scale:
+
+:at:`scale`: :at-val:`real(3), "1 1 1"`
+ Scaling of all point coordinates, for types that specify coordinates explicitly. Scaling is applied after the pose
+ transformation.
+
+.. _body-flexcomp-radius:
+.. _body-flexcomp-material:
+.. _body-flexcomp-rgba:
+.. _body-flexcomp-group:
.. _body-flexcomp-flatskin:
-.. _flex-edge:
-.. _flexcomp-edge:
+:at:`radius`, :at:`material`, :at:`rgba`, :at:`group`, :at:`flatskin`
-.. _flex-edge-equality:
-.. _flexcomp-edge-equality:
+These attributes are directly passed through to the automatically-generated :ref:`flex` object and have
+the same meaning.
-.. _flex-edge-solref:
-.. _flexcomp-edge-solref:
-
-.. _flex-edge-solimp:
-.. _flexcomp-edge-solimp:
-
-.. _flex-edge-stiffness:
-.. _flexcomp-edge-stiffness:
-
-.. _flex-edge-damping:
-.. _flexcomp-edge-damping:
-
-.. _flex-contact:
.. _flexcomp-contact:
-.. _flex-contact-contype:
+:el-prefix:`flexcomp/` |-| **contact** (*)
+''''''''''''''''''''''''''''''''''''''''''
+
+.. _flexcomp-contact-internal:
+.. _flexcomp-contact-selfcollide:
+.. _flexcomp-contact-activelayers:
.. _flexcomp-contact-contype:
-
-.. _flex-contact-conaffinity:
.. _flexcomp-contact-conaffinity:
-
-.. _flex-contact-condim:
.. _flexcomp-contact-condim:
-
-.. _flex-contact-priority:
.. _flexcomp-contact-priority:
-
-.. _flex-contact-friction:
.. _flexcomp-contact-friction:
-
-.. _flex-contact-solmix:
.. _flexcomp-contact-solmix:
-
-.. _flex-contact-solref:
.. _flexcomp-contact-solref:
-
-.. _flex-contact-solimp:
.. _flexcomp-contact-solimp:
-
-.. _flex-contact-margin:
.. _flexcomp-contact-margin:
-
-.. _flex-contact-gap:
.. _flexcomp-contact-gap:
-.. _flex-contact-internal:
-.. _flexcomp-contact-internal:
+:at:`internal`, :at:`selfcollide`, :at:`activelayers`, :at:`contype`, :at:`conaffinity`, :at:`condim`, :at:`priority`,
+:at:`friction`, :at:`solmix`, :at:`solimp`, :at:`margin`, :at:`gap`
-.. _flex-contact-selfcollide:
-.. _flexcomp-contact-selfcollide:
+Same as in :ref:`flex/contact`. All attributes are passed through to the automatically-generated flex.
+
+.. _flexcomp-edge:
+
+:el-prefix:`flexcomp/` |-| **edge** (*)
+'''''''''''''''''''''''''''''''''''''''
+
+Each flex element has one edge in 1D (coinciding with the capsule element), three edges in 2D, and six edges in 3D. The
+edges are generated automatically when the flex element is compiled, and the user cannot specify them directly. This
+element is used to adjust the properties of all edges in the flex.
+
+.. _flexcomp-edge-equality:
+
+:at:`equality`: :at-val:`[true, false], "false"`
+ When enabled, an equality constraint of :ref:`type flex` is added to the model, referencing the
+ automatically-generated flex by name.
+
+.. _flexcomp-edge-solref:
+.. _flexcomp-edge-solimp:
+
+:at:`solref`, :at:`solimp`
+ The standard constraint parameters, passed through to the automatically generated equality constraint.
+
+.. _flexcomp-edge-stiffness:
+.. _flexcomp-edge-damping:
+
+:at:`stiffness`, :at:`damping`
+ Edge stiffness and damping, passed through to the automatically generated flex.
-.. _flex-contact-activelayers:
-.. _flexcomp-contact-activelayers:
.. _flexcomp-pin:
+:el-prefix:`flexcomp/` |-| **pin** (*)
+''''''''''''''''''''''''''''''''''''''
+
+Each point is either pinned or not pinned. The effect of pinning was explained earlier. This element is used to specify
+which points are pinned. Note that each attribute below can be used to specify multiple pins, and in addition to that,
+the :el:`pin` element itself can be repeated for user convenience. The effects are cumulative; pinning the same point
+multiple times is allowed.
+
.. _flexcomp-pin-id:
+:at:`id`: :at-val:`int(n), required`
+ Zero-based ids of points to pin. When the points are automatically-generaged, the user needs to understand their
+ layout in order to decide which points to pin. This can be done by first creating a flexcomp without any pins,
+ loading it in the simulator, and showing the body labels.
+
.. _flexcomp-pin-range:
+:at:`range`: :at-val:`int(2*n), required`
+ Ranges of points to pin. Each range is specified by two integers.
+
.. _flexcomp-pin-grid:
+:at:`grid`: :at-val:`int(dim*n), required`
+ Grid coordinates of points to pin. This can only be used with type grid.
+
.. _flexcomp-pin-gridrange:
+:at:`gridrange`: :at-val:`int(2*dim*n), required`
+ Ranges of grid coordinates of points to pin. Each range is specified by (dim) integers for the minimum of the range
+ followed by (dim) integers for the maximum of the range. This can only be used with type grid.
+
.. _flexcomp-plugin:
+:el-prefix:`flexcomp/` |-| **plugin** (?)
+'''''''''''''''''''''''''''''''''''''''''
+
+Associate this flexcomp with an :ref:`engine plugin`. Either :at:`plugin` or :at:`instance` are required.
+
.. _flexcomp-plugin-plugin:
+:at:`plugin`: :at-val:`string, optional`
+ Plugin identifier, used for implicit plugin instantiation.
+
.. _flexcomp-plugin-instance:
-
-.. _deformable:
-
-.. _deformable-flex:
-
-.. _deformable-flex-name:
-
-.. _deformable-flex-group:
-
-.. _deformable-flex-material:
-
-.. _deformable-flex-radius:
-
-.. _deformable-flex-rgba:
-
-.. _deformable-flex-texcoord:
-
-.. _deformable-flex-flatskin:
-
-.. _deformable-flex-selfcollide:
-
-.. _deformable-flex-dim:
-
-.. _deformable-flex-body:
-
-.. _deformable-flex-vertex:
-
-.. _deformable-flex-element:
-
-
-
-**deformable** (*)
-~~~~~~~~~~~~~~~~~~
-
+:at:`instance`: :at-val:`string, optional`
+ Instance name, used for explicit plugin instantiation.
.. _contact:
@@ -3999,6 +4020,342 @@ the :ref:`pair ` element above are checked for collisions.
The name of the second body in the pair.
+.. _deformable:
+
+**deformable** (*)
+~~~~~~~~~~~~~~~~~~
+
+This is a grouping element and does not have any attributes. It groups elements that specify deformable objects, namely flexes and skins.
+
+
+.. _deformable-flex:
+
+:el-prefix:`deformable/` |-| **flex** (*)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Flexible objects (or flexes) were added in MuJoCo 3.0. These are collections of massless stretchable geometric elements
+(capsules, triangles or tetrahedra) connecting vertices that are defined within different moving body frames. These
+stretchable elements support collisions and contact forces, which are then distributed to all the interconnected bodies.
+Flexes also generate passive and constraint forces as needed to simulate deformable entities with the desired material
+properties. The modeling of flexes is automated and simplified by the :ref:`flexcomp` element. In most
+cases, the user will specify a :el:`flexcomp` which will then automatically construct the corresponding low-level
+:el:`flex`. See :ref:`deformable objects` for additional information.
+
+.. _deformable-flex-name:
+
+:at:`name`: :at-val:`string, optional`
+ Name of the flex.
+
+.. _deformable-flex-dim:
+
+:at:`dim`: :at-val:`int, "2"`
+ Dimensionality of the flex. Allowed values are 1, 2 and 3. In 1D the elements are capsules, in 2D the elements are
+ triangles with radius, in 3D the elements are tetrahedra with (optional) radius.
+
+.. _deformable-flex-radius:
+
+:at:`radius`: :at-val:`real, "0.005"`
+ Radius of all flex elements. It can be zero in 3D, but must be positive in 1D and 2D. The radius affects both
+ collision detection and rendering. In 1D and 2D it is needed to make the elements volumetric.
+
+.. _deformable-flex-body:
+
+:at:`body`: :at-val:`string(nvert or 1), required`
+ An array of MuJoCo body names (separated by white space) to which each vertex belongs. The number of body names
+ should either equal the number of vertices (nvert), or be a single body. If a single body is specified, all vertices
+ are defined within that body - in which case the flex becomes a rigid body. The latter functionality effectively
+ creates a general non-convex mesh (unlike mesh geoms which are convexified for collision detection purposes).
+
+.. _deformable-flex-vertex:
+
+:at:`vertex`: :at-val:`real(3*nvert), optional`
+ The local coordinates of the vertices within the corresponding body frames. If this attribute is omitted, all
+ coordinates are (0,0,0) or in other words, the vertices coincide with the centers of the body frames.
+
+.. _deformable-flex-texcoord:
+
+:at:`texcoord`: :at-val:`real(2*nvert), optional`
+ Texture coordinates for each vertex. If omitted, texture mapping for this flex is disabled, even if a texture is
+ specified in the material.
+
+.. _deformable-flex-element:
+
+:at:`element`: :at-val:`int((dim+1)*nelem), required`
+ For each element of the flex, this lists the zero-based indices of the vertices forming that flex element. We need
+ two vertices to specify a capsule, three vertices to specify a triangle, and four vertices to specify a tetrahedron -
+ which is why the number of indices equals (dim+1) times the number of elements. In 2D, the vertices should be listed
+ in counter-clockwise order. In 1D and 3D the order is irrelevant; in 3D the model compiler will rearrange the
+ vertices as needed. Repeated vertex indices within a flex element are not allowed. The topology of the flex is not
+ enforced; it could corespond to a continuous soft body, or a collection of disconnected stretchable elements, or
+ anything in-between.
+
+.. _deformable-flex-flatskin:
+
+:at:`flatskin`: :at-val:`[true, false], "false"`
+ This attribute determines whether 2D and 3D flexes that are rendered in flexskin mode will use smooth or flat
+ shading. The default smooth shading is suitable in most cases, however if the object is intended to have visible
+ sharp edges (such as a cube) then flat shading is more natural.
+
+.. _deformable-flex-material:
+
+:at:`material`: :at-val:`string, optional`
+ If specified, this attribute applies a :ref:`material` to the flex. Note that textures specified in
+ the material will be applied only if the flex has explicit texture coordinates.
+
+.. _deformable-flex-rgba:
+
+:at:`rgba`: :at-val:`real(4), "0.5 0.5 0.5 1"`
+ Instead of creating material assets and referencing them, this attribute can be used to set color and transparency
+ only. This is not as flexible as the material mechanism, but is more convenient and is often sufficient. If the value
+ of this attribute is different from the internal default, it takes precedence over the material.
+
+.. _deformable-flex-group:
+
+:at:`group`: :at-val:`int, "0"`
+ Integer group to which the flex belongs. This attribute can be used for custom tags. It is also used by the
+ visualizer to enable and disable the rendering of entire groups of flexes.
+
+
+.. _flex-edge:
+
+:el-prefix:`flex/` |-| **edge** (?)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This element adjusts the passive or constraint properties of all edges of the flex. A flex edge can have a damping
+passive force and an :ref:`equality constraint` associated with it, resulting in edge constraint forces.
+In the latter case, passive forces are usually unnecessary. For a 1D flex, an edge can also have a passive stiffness,
+while ``Solid`` or ``Membrane`` first-party plugins can be used for the 2D and 3D case, respectively. which would
+generally make edge constraints unnecessary. However these are modeling choices left to the user. MuJoCo allows all
+these mechanisms to be combined as desired.
+
+.. _flex-edge-stiffness:
+
+:at:`stiffness`: :at-val:`real(1), "0"`
+ Stiffness of all edges. Only for 1D flex. For 2D and 3D, plugins must be used.
+
+.. _flex-edge-damping:
+
+:at:`damping`: :at-val:`real(1), "0"`
+ Damping of all edges.
+
+.. _flex-contact:
+
+:el-prefix:`flex/` |-| **contact** (?)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This element adjusts the contact properties of the flex. It is mostly identical to geom contact properties, with some
+extensions specific to flexes.
+
+.. _flex-contact-internal:
+
+:at:`internal`: :at-val:`[true, false], "true"`
+ Enables or disables internal collisions which prevent flex self-penetration and element inversion. Note that flex
+ elements that have shared vertices cannot collide (or else there will be permanent contacts). In 1D and 2D, internal
+ collision checks rely on predefined vertex-element pairs, where the vertex is treated as a sphere with the same
+ radius as the flex. These spheres correspond to non-shared vertices of neighboring elements on the periphery of the
+ flex. The pre-defined vertex-element pairs are generated by the model compiler automatically. In 3D, internal
+ collision checks are performed within each tetraheron: each vertex is collided with the plane corresponding to the
+ opposing triangle face (again using the flex radius). The resulting contacts are always created with condim 1, gap 0,
+ margin 0.
+
+.. _flex-contact-selfcollide:
+
+:at:`selfcollide`: :at-val:`[none, narrow, bvh, sap, auto], "auto"`
+ This determines the strategy for midphase collision pruning of element pairs belonging to the same flex. **none**
+ means flex elements cannot collide with each other. **narrow** means narrow phase only (i.e. all pairs are checked).
+ This is a diagnostic tool and is never a good idea in practice. **bvh** and **sap** refer to bounding volume
+ hierarchies and sweep-and-prune (which are two different strategies for midphase collision pruning). **auto** selects
+ **sap** in 1D and 2D, and **bvh** in 3D. Which strategy performs better depends on the specifics of the model. The
+ automatic setting is just a simple rule which we have found to perform well in general.
+
+.. _flex-contact-activelayers:
+
+:at:`activelayers`: :at-val:`int(1), "1"`
+ This only has an effect for 3D flexes. Each tetrahedron is labeled by the model compiler with an integer
+ corresponding to (graph) distance to the outside surface of the flex. Thus outside-facing elements are in layer 0,
+ their neighbors are in layer 1, etc. This attribute specifies how many layers will be allowed to participate in
+ collisions. The default setting 1 means that only one layer (i.e. layer 0) can collide, with itself and with the rest
+ of the world. This is usually sufficient, however if the outer layer is composed of small tetrahedra, another body
+ can "pierce" it and get stuck. In that case the value should be increased.
+
+
+.. _flex-contact-contype:
+.. _flex-contact-conaffinity:
+.. _flex-contact-condim:
+.. _flex-contact-priority:
+.. _flex-contact-friction:
+.. _flex-contact-solmix:
+.. _flex-contact-solref:
+.. _flex-contact-solimp:
+.. _flex-contact-margin:
+.. _flex-contact-gap:
+
+.. |deformable/flex/contact attrib list| replace::
+ :at:`contype`, :at:`conaffinity`, :at:`condim`, :at:`priority`, :at:`friction`,
+ :at:`solmix`, :at:`solref`, :at:`solimp`, :at:`margin`, :at:`gap`
+
+|deformable/flex/contact attrib list|
+ Same meaning as regular :ref:`geom ` attributes.
+
+
+.. _deformable-skin:
+
+:el-prefix:`deformable/` |-| **skin** (*)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+These are deformable meshes whose vertex positions and normals are computed each time the model is rendered. MuJoCo
+skins are only used for visualization and do not affect the physics in any way. In particular, collisions involve the
+geoms of the bodies to which the skin is attached, and not the skin itself. Unlike regular meshes which are referenced
+from geoms and participate in collisions, the skin is not referenced from anywhere else in the model. It is a
+stand-alone element that is used by renderer and not by the simulator.
+
+The skin has vertex positions and normals updated at runtime, and triangle faces and optional texture coordinates
+which are predefined. It also has "bones" used for updating. Bones are regular MuJoCo bodies referenced with the
+:el:`bone` subelement. Each bone has a list of vertex indices and corresponding real-valued weights which specify how
+much the bone position and orientation influence the corresponding vertex. The vertex has local coordinates with
+respect to every bone that influences it. The local coordinates are computed by the model compiler, given global
+vertex coordinates and global bind poses for each body. The bind poses do not have to correspond to the model
+reference configuration qpos0. Note that the vertex positions and bone bind poses provided in the skin definition are
+always global, even if the model itself is defined in local coordinates.
+
+At runtime the local coordinates of each vertex with respect to each bone that influences it are converted to global
+coordinates, and averaged in proportion to the corresponding weights to obtain a single set of 3D coordinates for each
+vertex. Normals then are computed automatically given the resulting global vertex positions and face information.
+Finally, the skin can be inflated by applying an offset to each vertex position along its (computed) normal.
+Skins are one-sided for rendering purposes; this is because back-face culling is needed to avoid shading and aliasing
+artifacts. When the skin is a closed 3D shape this does not matter because the back sides cannot be seen. But if the
+skin is a 2D object, we have to specify both sides and offset them slightly to avoid artifacts. Note that the
+composite objects introduced in MuJoCo 2.0 generate skins automatically. So one can save an XML model with a composite
+object, and obtain an elaborate example of how a skin is specified in the XML.
+
+Similar to meshes, skins can be specified directly in the XML via attributes documented later, or loaded from a binary
+SKN file which is in a custom format. The specification of skins is more complex than meshes because of the bone
+subelements. The file format starts with a header of 4 integers: nvertex, ntexcoord, nface, nbone. The first three are
+the same as in meshes, and specify the total number of vertices, texture coordinate pairs, and triangle faces in the
+skin. ntexcoord can be zero or equal to nvertex. nbone specifies the number of MuJoCo bodies that will be used as
+bones in the skin. The header is followed by the vertex, texcoord and face data, followed by a specification for each
+bone. The bone specification contains the name of the corresponding model body, 3D bind position, 4D bind quaternion,
+number of vertices influenced by the bone, and the vertex index array and weight array. Body names are represented as
+fixed-length character arrays and are expected to be 0-terminated. Characters after the first 0 are ignored. The
+contents of the SKN file are:
+
+.. code:: Text
+
+ (int32) nvertex
+ (int32) ntexcoord
+ (int32) nface
+ (int32) nbone
+ (float) vertex_positions[3*nvertex]
+ (float) vertex_texcoords[2*ntexcoord]
+ (int32) face_vertex_indices[3*nface]
+ for each bone:
+ (char) body_name[40]
+ (float) bind_position[3]
+ (float) bind_quaternion[4]
+ (int32) vertex_count
+ (int32) vertex_index[vertex_count]
+ (float) vertex_weight[vertex_count]
+
+Similar to the other custom binary formats used in MuJoCo, the file size in bytes is strictly enforced by the model
+compiler. The skin file format has subelements so the overall file size formula is difficult to write down, but should
+be clear from the above specification.
+
+.. _deformable-skin-name:
+
+:at:`name`: :at-val:`string, optional`
+ Name of the skin.
+
+.. _deformable-skin-file:
+
+:at:`file`: :at-val:`string, optional`
+ The SKN file from which the skin will be loaded. The path is determined as described in the meshdir attribute of
+ :ref:`compiler `. If the file is omitted, the skin specification must be provided in the XML using the
+ attributes below.
+
+.. _deformable-skin-vertex:
+
+:at:`vertex`: :at-val:`real(3*nvert), optional`
+ Vertex 3D positions, in the global bind pose where the skin is defined.
+
+.. _deformable-skin-texcoord:
+
+:at:`texcoord`: :at-val:`real(2*nvert), optional`
+ Vertex 2D texture coordinates, between 0 and 1. Note that skin and geom texturing are somewhat different. Geoms can
+ use automated texture coordinate generation while skins cannot. This is because skin data are computed directly in
+ global coordinates. So if the material references a texture, one should specify explicit texture coordinates for the
+ skin using this attribute. Otherwise the texture will appear to be stationary in the world while the skin moves
+ around (creating an interesting effect but probably not as intended).
+
+.. _deformable-skin-face:
+
+:at:`face`: :at-val:`int(3*nface), optional`
+ Trinagular skin faces. Each face is a triple of vertex indices, which are integers between zero and nvert-1.
+
+.. _deformable-skin-inflate:
+
+:at:`inflate`: :at-val:`real, "0"`
+ If this number is not zero, the position of vertex during updating will be offset along the vertex normal, but the
+ distance specified in this attribute. This is particularly useful for skins representing flexible 2D shapes.
+
+.. _deformable-skin-material:
+
+:at:`material`: :at-val:`string, optional`
+ If specified, this attribute applies a material to the skin.
+
+.. _deformable-skin-rgba:
+
+:at:`rgba`: :at-val:`real(4), "0.5 0.5 0.5 1"`
+ Instead of creating material assets and referencing them, this attribute can be used to set color and transparency
+ only. This is not as flexible as the material mechanism, but is more convenient and is often sufficient. If the value
+ of this attribute is different from the internal default, it takes precedence over the material.
+
+.. _deformable-skin-group:
+
+:at:`group`: :at-val:`int, "0"`
+ Integer group to which the skin belongs. This attribute can be used for custom tags. It is also used by the
+ visualizer to enable and disable the rendering of entire groups of skins.
+
+
+.. _skin-bone:
+
+:el-prefix:`skin/` |-| **bone** (*)
+'''''''''''''''''''''''''''''''''''
+
+This element defines a bone of the skin. The bone is a regular MuJoCo body which is referenced by name here.
+
+
+.. _skin-bone-body:
+
+:at:`body`: :at-val:`string, required`
+ Name of the body corresponding to this bone.
+
+.. _skin-bone-bindpos:
+
+:at:`bindpos`: :at-val:`real(3), required`
+ Global body position corresponding to the bind pose.
+
+.. _skin-bone-bindquat:
+
+:at:`bindquat`: :at-val:`real(4), required`
+ Global body orientation corresponding to the bind pose.
+
+.. _skin-bone-vertid:
+
+:at:`vertid`: :at-val:`int(nvert), required`
+ Integer indices of the vertices influenced by this bone. The vertex index corresponds to the order of the vertex in
+ the skin mesh. The number of vertex indices specified here (nvert) must equal the number of vertex weights specified
+ with the next attribute. The same vertex may be influenced by multiple bones, and each vertex must be influenced by
+ at least one bone.
+
+.. _skin-bone-vertweight:
+
+:at:`vertweight`: :at-val:`real(nvert), required`
+ Weights for the vertices influenced by this bone, in the same order as the vertex indices. Negative weights are
+ allowed (which is needed for cubic interpolation for example) however the sum of all bone weights for a given vertex
+ must be positive.
+
+
+
.. _equality:
**equality** (*)
@@ -4098,8 +4455,7 @@ of the other body, without any joint elements in the child body.
:at:`body2`: :at-val:`string, optional`
Name of the second body. If this attribute is omitted, the second body is the world body. Welding a body to the world
- and changing the corresponding component of :ref:`mjData.eq_active` at runtime can be used to fix the body
- temporarily.
+ and changing the corresponding component of mjModel.eq_active at runtime can be used to fix the body temporarily.
.. _equality-weld-relpose:
@@ -4208,19 +4564,26 @@ This element constrains the length of one tendon to be a quartic polynomial of a
.. _equality-flex:
:el-prefix:`equality/` |-| **flex** (*)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This element constrains the lengths of all edges of a specified flex to their respective lengths in the initial model
+configuration. In this way the edges are used to maintain the shape of the deformable entity. Note that all other
+equality constraint types add a fixed number of scalar constraints, while this element adds as many scalar constraints
+as there are edges in the specified flex.
.. _equality-flex-name:
-
.. _equality-flex-class:
+.. _equality-flex-active:
+.. _equality-flex-solref:
+.. _equality-flex-solimp:
+
+:at:`name`, :at:`class`, :at:`active`, :at:`solref`, :at:`solimp`
+ Same as in :ref:`connect ` element.
.. _equality-flex-flex:
-.. _equality-flex-active:
-
-.. _equality-flex-solref:
-
-.. _equality-flex-solimp:
+:at:`flex`: :at-val:`string, required`
+ Name of the flex whose edges are being constrained.
.. _equality-distance:
@@ -7361,44 +7724,6 @@ tendon, slidersite, cranksite.
All :ref:`adhesion ` attributes are available here except: name, class, body.
-.. _default-flex:
-
-.. _default-flex-contype:
-
-.. _default-flex-conaffinity:
-
-.. _default-flex-condim:
-
-.. _default-flex-priority:
-
-.. _default-flex-material:
-
-.. _default-flex-friction:
-
-.. _default-flex-solmix:
-
-.. _default-flex-solref:
-
-.. _default-flex-solimp:
-
-.. _default-flex-margin:
-
-.. _default-flex-gap:
-
-.. _default-flex-stiffness:
-
-.. _default-flex-damping:
-
-.. _default-flex-radius:
-
-.. _default-flex-rgba:
-
-.. _default-flex-dim:
-
-:el-prefix:`default/` |-| **flex** (?)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-
.. _custom:
**custom** (*)
diff --git a/doc/changelog.rst b/doc/changelog.rst
index de8ec530..aee18a76 100644
--- a/doc/changelog.rst
+++ b/doc/changelog.rst
@@ -8,27 +8,47 @@ Upcoming version (not yet released)
New features
^^^^^^^^^^^^
-.. youtube:: Vc1tq0fFvQA
- :align: right
- :width: 240px
-
-1. Added constraint island discovery with :ref:`mj_island`. Constraint islands are disjoint sets of constraints
- and degrees-of-freedom that do not interact. The only solver which currently supports islands is
- :ref:`CG`. Island discovery can be activated using a new :ref:`enable flag`.
- If island discovery is enabled, geoms, contacts and tendons will be colored according to the corresponding island,
- see video.
-
.. youtube:: QewlEqIZi1o
:align: right
:width: 240px
-2. Added new signed distance field (SDF) collision primitive. SDFs can take any shape and are not constrained to be
+1. Added new signed distance field (SDF) collision primitive. SDFs can take any shape and are not constrained to be
convex. Collision points are found by minimizing the maximum of the two colliding SDFs via gradient descent.
- Added new SDF plugin for defining implicit geometries. The plugin must define methods computing an SDF and its
gradient at query points. See the :ref:`documentation` for more details.
-3. Added :ref:`mjThreadPool` and :ref:`mjTask` which allow for multi-threaded operations within the MuJoCo engine
+.. youtube:: ra2bTiZHGlw
+ :align: right
+ :width: 240px
+
+2. Added new low-level model element called ``flex``, used to define deformable objects. These
+ `simplicial complexes `__ can be of dimension 1, 2
+ or 3, corresponding to stretchable lines, triangles or tetrahedra. Two new MJCF elements are used
+ to define flexes. The top-level :ref:`deformable` section contains the low-level flex definition.
+ The :ref:`flexcomp` element, similar to :ref:`composite` is a convenience macro for
+ creating deformables, and supports the GMSH tetrahedral file format.
+
+ - Added `shell `__ passive force plugin,
+ computing bending forces using a constant precomputed Hessian (cotangent operator).
+
+ **Note**: This feature is still under development and subject to change. In particular, deformable object
+ functionality is currently available both via :ref:`deformable` and :ref:`composite`,
+ and both are modifiable by the first-party
+ `elasticity plugins `__. We expect some of
+ this functionallity to be unified in the future.
+
+.. youtube:: Vc1tq0fFvQA
+ :align: right
+ :width: 240px
+
+3. Added constraint island discovery with :ref:`mj_island`. Constraint islands are disjoint sets of constraints
+ and degrees-of-freedom that do not interact. The only solver which currently supports islands is
+ :ref:`CG`. Island discovery can be activated using a new :ref:`enable flag`.
+ If island discovery is enabled, geoms, contacts and tendons will be colored according to the corresponding island,
+ see video.
+
+4. Added :ref:`mjThreadPool` and :ref:`mjTask` which allow for multi-threaded operations within the MuJoCo engine
pipeline. If engine-internal threading is enabled, the following operations will be multi-threaded:
- Island constraint resolution, if island discovery is :ref:`enabled` and the
@@ -40,16 +60,8 @@ New features
Engine-internal threading is a work in progress and currently only available in first-party code via the
:ref:`testspeed` utility, exposed with the ``npoolthread`` flag.
-.. youtube:: ra2bTiZHGlw
- :align: right
- :width: 240px
-
-4. Added capability to initialize :ref:`composite` particles with arbitrary positions.
-
-5. Added `shell `__ passive force plugin:
-
- - Collisions use spheres located at mesh vertices.
- - Stretching as tendon constraints and bending using a constant precomputed Hessian (cotangent operator).
+5. Added capability to initialize :ref:`composite` particles from OBJ files. Fixes :github:issue:`642`
+ and :github:issue:`674`.
General
^^^^^^^
diff --git a/doc/images/modeling/bunny1.png b/doc/images/modeling/bunny1.png
new file mode 100644
index 00000000..d1b6bb3f
Binary files /dev/null and b/doc/images/modeling/bunny1.png differ
diff --git a/doc/images/modeling/bunny2.png b/doc/images/modeling/bunny2.png
new file mode 100644
index 00000000..51b9810b
Binary files /dev/null and b/doc/images/modeling/bunny2.png differ
diff --git a/doc/images/modeling/coil.png b/doc/images/modeling/coil.png
new file mode 100644
index 00000000..9fd9f233
Binary files /dev/null and b/doc/images/modeling/coil.png differ
diff --git a/doc/images/modeling/flexelem.png b/doc/images/modeling/flexelem.png
new file mode 100644
index 00000000..39df7463
Binary files /dev/null and b/doc/images/modeling/flexelem.png differ
diff --git a/doc/modeling.rst b/doc/modeling.rst
index 20718400..8a4d5d0e 100644
--- a/doc/modeling.rst
+++ b/doc/modeling.rst
@@ -1069,6 +1069,14 @@ has 1000 bodies (each with a geom), 3000 degrees of freedom and around 1000 acti
takes around 1 ms on a single core of a modern processor. As with most other MuJoCo models, the soft constraints allow
simulation at much larger timesteps (this model is stable at 30 ms timestep and even higher).
+Particles are also compatible with the passive forces 2D and 3D plugins, discussed in the :ref:`deformable
+` section. However, collisions are limited to the particle themselves and not to the whole boundary of the
+skin that encloses them. This makes contacts very fast but does not guarantee that all penetrations can be avoided. For
+a more complete treatment, see again the :ref:`deformable ` section, which outlines how to use
+:ref:`flexcomp` to create such an object. It is easy to port models create with composite particles to
+flex, see the folder `elasticity/ `__ for
+several examples.
+
**1D grid**.
|image6| |image7|
@@ -1111,59 +1119,51 @@ coordinates. The plot on the right shows a cloth pinned to the world body at the
capsule probe. The skin on the right is subdivided using bi-cubic interpolation, which increases visual quality in the
absence of textures. When textures are present (left) the benefits of subdivision are less visible.
-**Rope and loop**.
+**Cable**.
-|image10| |image11|
+|coil|
.. code-block:: xml
-
-
-
-
-
-
-
+
+
+
-The remaining composite object types create kinematic trees of element bodies, and the parent body becomes the root of
-the tree. This is why :el:`composite` appears inside a moving body, and not inside the world body as in particle and
-grid objects. If it appeared inside the world body, the root of the composite object would not move. Unlike grids and
-particles, the orientation of the element bodies here can change. The kinematic tree is constructed using (mostly)
-hinge joints. In the case of rope and loop objects illustrated here, the tree is a chain. Note the naming of the
-parent body. This name must correspond to one of the automatically-generated names of the element bodies. This
-mechanism is used to specify where the composite object should attach to the parent. Compared to 1D grids, the rope
-and loop are less jittery and can use capsule and ellipsoid geoms in addition to spheres (thus filling the gaps for
-collision detection). However this comes at a price. Because we have long kinematic chains, the resulting differential
-equations become stiff and can no longer be integrated at large timesteps. The examples we provide illustrate
-comfortable timesteps where the models are stable. The rope can be easily tied into a knot using mouse perturbations,
-as shown in the left plot. Using a larger number of smaller elements makes knots and other manipulations even easier.
-The loop is similar to a rope but the first and last element bodies are connected with an equality constraint.
+
+
+
+
+
+
+
+
+
+
+
+
+
+The cable simulates an inextensible elastic 1D object having twist and bending stiffness. It is discretized using a
+sequence of capsules or boxes. Its stiffness and inertia properties are computed directly from the given parameters and
+the shape of the cross section, which allows for anisotropic behaviors, which can be found in e.g. belts or computer
+cables. It is a single kinematic tree, so it is exactly inextensible without the use of additional constraints, enabling
+the use of large time steps. The elastic model is geometrically exact and based on computing the Bishop or twist-free
+frame of the centerline, i.e., the line passing through the center of the cross section. The orientations of the geoms
+are expressed with respect to this frame and then decomposed into twist and bending components, hence different
+stiffnesses can be set independently. Moreover, it is possible to specify if the stress-free configuration is flat or
+curve, such as in the case of coil springs. The cable requires using a first-party :ref:`engine plugin`, which
+may be integrated directly into the engine in the future.
+
+**Rope and loop**.
+
+The rope and loop are deprecated. It is recommended to use the cable for simulating inextensible elastic rods that are
+bent and twisted and 1D flex :ref:`deformable objects ` for extensible strings in a tensile loading
+scenario (e.g. a stretched rubber band).
**Cloth**.
-|image12| |image13|
-
-.. code-block:: xml
-
-
-
-
-
-
-
-
-
-
-The cloth type is an alternative to a 2D grid, and has somewhat different properties. Similar to rope vs. 1D grid, the
-cloth is less jittery than a 2D grid and can also fill collision holes better. This is done by using capsules or
-ellipsoids, and arranging them in the pattern shown on the right. The geom capsules are shown in red, the kinematic
-tree in thick blue, the equality-constrained tendons holding the cloth together in thin gray, and the joints in cyan.
-The element body corresponding to the parent body has a floating joint rendered as a cube, while the rest of the tree
-is constructed using pairs of hinge joints that form universal joints. Note the naming of the parent body: similar to
-rope, it must coincide with one of the automatically-generated element body names in the composite object. Explicit
-pinning is not possible. However if the parent is a static body, the cloth is essentially pinned but only at one
-point. Similar to rope, the cloth object involves long kinematic chains that require relatively small timesteps and
-some damping for stable integration. The parameters can be found in the XML model files in the software distribution.
+The cloth is deprecated. It is recommended to use 2D flex :ref:`deformable objects ` for simulating thin
+elastic structures.
**Box**.
@@ -1222,6 +1222,94 @@ of the system making it softer or harder, damped or springy, etc. Note that box,
involve long kinematic chains, and can be simulated at large timesteps - similar to particle and grid, and unlike rope
and cloth.
+.. _CDeformable:
+
+Deformable objects
+~~~~~~~~~~~~~~~~~~
+
+The :ref:`composite objects ` described earlier were intended to emulate soft bodies in what is effectively
+a rigid-body simulator. This was possible because MuJoCo constraints are soft, but nevertheless it was limited in
+functionality and modeling power. In MuJoCo 3.0 we have introduced true deformable objects involving new model elements.
+The :ref:`skin` described earlier was actually one such element, but it is merely used for
+visualization. We now have a related element :ref:`flex` which generates contact forces, constraint
+forces and passive forces as needed to model a wide range of deformable entities. Both skins and flexes are now defined
+within a new grouping element in the XML called :ref:`deformable`. A flex is a low-level element that
+specifies everything needed at runtime, but is difficult to design at modeling time. To aid with modeling, we have
+further introduced the element :ref:`flexcomp` which automates the creation of the low-level flex,
+similar to how :ref:`composite` automates the creation of (collections of) MuJoCo objects needed to
+emulate a soft body. Flexes may eventually supersede composites, but for now both are useful for somewhat different
+purposes.
+
+A flex is a collection of MuJoCo bodies that are connected with massless stretchable elements. These elements can be
+capsules (1D flex), triangles (2D flex), or tetrahedra (3D flex). In all cases we allow a radius, which makes the
+elements smooth and also volumetric in 1D and 2D. The primitive elements are illustrated below:
+
+|flexelem|
+
+Thus far these look like geoms. But the key difference is that they deform: as the bodies (vertices) move independently
+of each other, the shape of the elements changes in real time. Collisions and contact forces are now generalized to
+handle these deformable geometric elements. Note that when two such elements collide, the contact no longer involves
+just two bodies, but can involve up to 8 bodies (if both elements are tetrahedra). Contact forces are computed as
+before, given the contact frame and relevant quantities expressed in that frame. But then the contact force is
+distributed among all interacting bodies. The notion of contact Jacobian is complicated because the contact point cannot
+be considered fixed in any body frame. Instead we use a weighting scheme to "assign" each contact point to multiple
+bodies. It is also possible to create a rigid flex, by assigning all vertices to the same body. This is a way to
+re-purpose the new flex collision machinery to implement rigid non-convex mesh collisions (unlike mesh geoms which are
+convexified for collision purposes).
+
+**Deformation model**.
+
+In order to preserve the shape of the flex (in a soft sense), we need to generate passive or constraint forces. Prior to
+MuJoCo 3.0 this would involve a large number of tendons plus constraints on tendons and joints. This is still possible
+here, but inefficient both in terms of modeling and in terms of simulation when the flex is large. Instead, the design
+philosophy is to use a single set of parameters and provide two modeling choices: a new (soft) equality constraint type
+that applies to all edges of a given flex, which permits large time steps, or a discretized continuum representation,
+where each element is in a constant stress state, which is equivalent to piecewise linear finite elements and achieves
+improved realism and accuracy. The edge-based model could be seen as a "lumped" stiffness model, where the correct
+coupling of deformation modes (e.g. shear and volumetric) is averaged in a single quantity. The continuum model enables
+instead to specify shear and volumetic stiffnesses separately using the `Poisson's ratio
+`__ of the material. For more details, see the `Saint Venant-Kirchhoff
+`__ hyperelastic model. This
+functionality is currently based on first-party :ref:`engine plugins` as of MuJoCo 3.0 but may be integrated
+into the engine in future releases.
+
+**Creation and visualization**.
+
+.. code-block:: xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Using the :ref:`flexcomp` element, we can create flexes from meshes, including tetrahedral meshes, and
+automatically generate all the bodies/vertices and connect them with suitable elements. We can also create grids and
+other topologies automatically. This machinery makes it easy to create very large flexes, involving thousands or even
+tens of thousands of bodies, elements and edges. Obviously such simulations will not be fast. Even for medium-sized
+flexes, pruning of collision pairs and essential. This is why we have developed elaborate methods for pruning
+self-collisions; see XML reference.
+
+In case of 3D flexes made of tetrahedra, it may be useful to examine how the flex is "triangulated" internally. We have
+a special visualization mode that peels off the outer layers. Below is an example with the Stanford Bunny. Note how it
+has smaller tetrahedra on the outside and larger ones on the inside. This mesh design makes sense, because we want the
+collision surface to be accurate, but on the inside we just need soft material properties - which require less spatial
+resolution.
+
+|bunny1| |bunny2|
+
+
.. _CInclude:
Including files
@@ -1562,3 +1650,11 @@ in a visible way, and the energy fluctuates around the initial value instead of
:height: 250px
.. |particle| image:: images/models/particle.gif
:width: 270px
+.. |flexelem| image:: images/modeling/flexelem.png
+ :width: 400px
+.. |bunny1| image:: images/modeling/bunny1.png
+ :width: 300px
+.. |bunny2| image:: images/modeling/bunny2.png
+ :width: 300px
+.. |coil| image:: images/modeling/coil.png
+ :width: 300px
diff --git a/doc/overview.rst b/doc/overview.rst
index bb89671e..83fdfde1 100644
--- a/doc/overview.rst
+++ b/doc/overview.rst
@@ -588,6 +588,14 @@ available equality constraint types are: connect two bodies at a point (creating
tree); weld two bodies together; make two surfaces slide on each other; fix the position of a joint or tendon; couple
the positions of two joints or two tendons via a cubic polynomial.
+Deformable
+^^^^^^^^^^
+
+These are collections of massless stretchable geometric elements (capsules, triangles or tetrahedra) connecting vertices
+that are defined within different moving body frames. These stretchable elements support collisions and contact forces,
+which are then distributed to all the interconnected bodies. Flexes also generate passive and constraint forces as
+needed to simulate deformable entities with the desired material properties.
+
Contact pair
^^^^^^^^^^^^
diff --git a/doc/programming/extension.rst b/doc/programming/extension.rst
index 9b9dba15..5d8167e3 100644
--- a/doc/programming/extension.rst
+++ b/doc/programming/extension.rst
@@ -256,6 +256,7 @@ Currently, there are three directories of first-party plugins:
bending strains. The 3D solid is a
`Saint Venant-Kirchhoff `__
model discretized with piecewise linear finite elements, which is suitable for large deformations with small strains.
+ See also :ref:`composite ` and :ref:`deformable ` objects.
* **sensor:** The plugins in the `sensor/ `__
directory implement custom sensors. Currently the sole sensor plugin is the touch grid sensor, see the
`README `__ for details.
diff --git a/model/plugin/elasticity/mannequin.xml b/model/plugin/elasticity/mannequin.xml
index ad036287..9237b943 100644
--- a/model/plugin/elasticity/mannequin.xml
+++ b/model/plugin/elasticity/mannequin.xml
@@ -38,7 +38,7 @@
-
+
@@ -116,6 +116,9 @@
+
+
diff --git a/model/plugin/elasticity/poncho_flex.xml b/model/plugin/elasticity/poncho_flex.xml
index d51df2f9..72783d7e 100644
--- a/model/plugin/elasticity/poncho_flex.xml
+++ b/model/plugin/elasticity/poncho_flex.xml
@@ -30,11 +30,15 @@
+
+
+
+
+