Remove the particle composite (replaced by replicate).

PiperOrigin-RevId: 730089997
Change-Id: If8d18fb56ae01241e76f84dbf7951e034026d829
This commit is contained in:
Alessio Quaglino
2025-02-23 03:13:20 -08:00
committed by Copybara-Service
parent 0fcd20f0da
commit c52d1b3941
20 changed files with 164 additions and 527 deletions
-100
View File
@@ -3010,13 +3010,6 @@ coordinates results in compiler error. See :ref:`CComposite` in the modeling gui
parent body. Note that some types imply a grid of certain dimensionality, so the requirements for this attribute
depend on the specified type.
.. _body-composite-spacing:
:at:`spacing`: :at-val:`real, required`
The spacing between the centers of the grid elements. This spacing is the same in all dimensions. It should normally
be set to a value larger than the geom size, otherwise there will be a lot of contacts in the reference model
configuration (which is allowed but rarely desirable).
.. _body-composite-offset:
:at:`offset`: :at-val:`real(3), "0 0 0"`
@@ -3034,16 +3027,6 @@ coordinates results in compiler error. See :ref:`CComposite` in the modeling gui
geom shapes, but instead will set the body inertias directly and disable the automatic computation of inertia from
geom shape for the composite body only.
.. _body-composite-solrefsmooth:
.. _body-composite-solimpsmooth:
:at:`solrefsmooth`, :at:`solimpsmooth`
These are the solref and solimp attributes of the loop-closure equality constraint for loop types, and the
smoothness-preserving equality constraint for box, cylinder and ellipsoid types. For all other types they have no
effect. They obey the same rules as all other solref and solimp attributes in MJCF, except their defaults here are
adjusted depending on the composite type. See :ref:`CSolver`.
.. _body-composite-vertex:
:at:`vertex`: :at-val:`real(3*nvert), optional`
@@ -3147,73 +3130,6 @@ joints should be created, as well as to adjust the attributes of both automatic
Same meaning as regular :ref:`joint <body-joint>` attributes.
.. _composite-tendon:
:el-prefix:`composite/` |-| **tendon** (*)
''''''''''''''''''''''''''''''''''''''''''
Tendons are treated similarly to joints in composite objects. The tendon kind specified here together with the composite
body type imply the tendon type as used in the rest of MJCF. This sub-element is used to both create optional tendons,
and adjust the attributes of automatic and optional tendons. One difference from joints is that all tendons used in
composite objects are equality-constrained.
.. _composite-tendon-kind:
:at:`kind`: :at-val:`[main, shear], required`
The **main** kind corresponds to tendons holding the composite body together. These are the spatial tendons that
connect neighboring bodies in grid and cloth, and the fixed tendon used to preserve the volume of box, cylinder and
ellipsoid. For other composite types this sub-element has no effect.
The **shear** kind corresponds to diagonal tendons that prevent shear (as opposed to enabling - which is the function
of optional joints). Such tendons can be created in 2D grid objects and cloth objects. For all other composite object
types this sub-element has no effect.
.. _composite-tendon-solreffix:
.. _composite-tendon-solimpfix:
:at:`solreffix`, :at:`solimpfix`
These are the solref and solimp attributes used to equality-constrain the tendon. The defaults are adjusted depending
on the composite type. Otherwise these attributes obey the same rules as all other solref and solimp attributes in
MJCF. See :ref:`CSolver`.
.. _composite-tendon-group:
.. _composite-tendon-stiffness:
.. _composite-tendon-damping:
.. _composite-tendon-limited:
.. _composite-tendon-range:
.. _composite-tendon-margin:
.. _composite-tendon-solreflimit:
.. _composite-tendon-solimplimit:
.. _composite-tendon-frictionloss:
.. _composite-tendon-solreffriction:
.. _composite-tendon-solimpfriction:
.. _composite-tendon-material:
.. _composite-tendon-rgba:
.. _composite-tendon-width:
.. |body/composite/tendon attrib list| replace::
:at:`group`, :at:`stiffness`, :at:`damping`, :at:`limited`, :at:`range`, :at:`margin`, :at:`solreflimit`,
:at:`solimplimit`, :at:`frictionloss`, :at:`solreffriction`, :at:`solimpfriction`, :at:`material`, :at:`rgba`,
:at:`width`
|body/composite/tendon attrib list|
Same meaning as regular :ref:`tendon <tendon>` attributes.
.. _composite-geom:
:el-prefix:`composite/` |-| **geom** (?)
@@ -3335,22 +3251,6 @@ automatically-generated skin.
bi-cubic interpolation. This increases the quality of the rendering (especially in the absence of textures) but also
slows down the renderer, so use it with caution. Values above 3 are unlikely to be needed.
.. _composite-pin:
:el-prefix:`composite/` |-| **pin** (*)
'''''''''''''''''''''''''''''''''''''''
This sub-element can be used to pin some of the element bodies in grid objects (both 1D and 2D). Pinning means that the
corresponding body has no joints, and therefore it is rigidly fixed to the parent body. When the parent is the world,
this has the effect of hanging a string or a cloth in space. If the parent body is moving, this can be used to model a
handle where the composite object is attached. For other composite types this sub-element has no effect.
.. _composite-pin-coord:
:at:`coord`: :at-val:`int(2), required`
The grid coordinates of the element body which should be pinned. The coordinates are zero-based. For 1D grids this
attribute can have only one number, in which case the second number is automatically set to 0.
.. _composite-plugin:
+3 -25
View File
@@ -340,11 +340,11 @@
| :ref:`composite | \* | :class: mjcf-attributes |
| <body-composite>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`prefix<body-composite-prefix>` | :ref:`type<body-composite-type>` | :ref:`count<body-composite-count>` | :ref:`spacing<body-composite-spacing>` | |
| | | | :ref:`prefix<body-composite-prefix>` | :ref:`type<body-composite-type>` | :ref:`count<body-composite-count>` | :ref:`offset<body-composite-offset>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`offset<body-composite-offset>` | :ref:`flatinertia<body-composite-flatinertia>` | :ref:`solrefsmooth<body-composite-solrefsmooth>` | :ref:`solimpsmooth<body-composite-solimpsmooth>` | |
| | | | :ref:`flatinertia<body-composite-flatinertia>` | :ref:`vertex<body-composite-vertex>` | :ref:`initial<body-composite-initial>` | :ref:`curve<body-composite-curve>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`vertex<body-composite-vertex>` | :ref:`initial<body-composite-initial>` | :ref:`curve<body-composite-curve>` | :ref:`size<body-composite-size>` | |
| | | | :ref:`size<body-composite-size>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| composite |br| |_2| |L| | | .. table:: |
@@ -363,21 +363,6 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| composite |br| |_2| |L| | | .. table:: |
| :ref:`tendon | \* | :class: mjcf-attributes |
| <composite-tendon>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`kind<composite-tendon-kind>` | :ref:`group<composite-tendon-group>` | :ref:`stiffness<composite-tendon-stiffness>` | :ref:`damping<composite-tendon-damping>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`solreffix<composite-tendon-solreffix>` | :ref:`solimpfix<composite-tendon-solimpfix>` | :ref:`limited<composite-tendon-limited>` | :ref:`range<composite-tendon-range>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`margin<composite-tendon-margin>` | :ref:`solreflimit<composite-tendon-solreflimit>` | :ref:`solimplimit<composite-tendon-solimplimit>` | :ref:`frictionloss<composite-tendon-frictionloss>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`solreffriction<composite-tendon-solreffriction>` | :ref:`solimpfriction<composite-tendon-solimpfriction>` | :ref:`material<composite-tendon-material>` | :ref:`rgba<composite-tendon-rgba>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`width<composite-tendon-width>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| composite |br| |_2| |L| | | .. table:: |
| :ref:`skin | ? | :class: mjcf-attributes |
| <composite-skin>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
@@ -409,13 +394,6 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| composite |br| |_2| |L| | | .. table:: |
| :ref:`pin | \* | :class: mjcf-attributes |
| <composite-pin>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`coord<composite-pin-coord>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| composite |br| |_2| |L| | | .. table:: |
| :ref:`plugin | \* | :class: mjcf-attributes |
| <composite-plugin>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+3
View File
@@ -36,6 +36,9 @@ General
- Added :ref:`potential<sensor-e_potential>` and :ref:`kinetic<sensor-e_kinetic>` energy sensors.
- Improved shadow rendering in the native renderer.
- Moved ``introspect`` to ``python/introspect``.
- Removed the ``particle`` composite type. It is recommended to use the more generic :ref:`replicate<replicate>`
instead, for example `this model
<https://github.com/google-deepmind/mujoco/blob/main/model/replicate/particle.xml>`__.
.. admonition:: Breaking API changes
:class: attention
+2 -28
View File
@@ -1164,34 +1164,8 @@ see the XML model files in the distribution for the complete examples.
**Particle**.
|image4| |image5|
.. code-block:: xml
<worldbody>
<composite type="particle" count="10 10 10" spacing="0.07" offset="0 0 1">
<geom size=".02" rgba=".8 .2 .1 1"/>
</composite>
</worldbody>
The above XML is all it takes to create a system with 1000 particles with initial positions on a 10-10-10 grid, and
set the size, color, spacing and offset of the particles. The resulting element bodies become children of the world
body. One could adjust many other properties including the softness of the contacts and the joint attributes. The plot
on the right shows the joints. Each element body has 3 orthogonal slider joints, allowing it to translate but not
rotate. The idea is that particles should have position but no orientation. MuJoCo bodies always have orientation,
however by using only slider joints we do not allow the orientation to change. The geom defaults are adjusted
automatically so that they make frictionless contacts with each other and with the rest of the model. So this system
has 1000 bodies (each with a geom), 3000 degrees of freedom and around 1000 active contacts. Evaluating the dynamics
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
<CDeformable>` 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 <CDeformable>` section, which outlines how to use
:ref:`flexcomp<body-flexcomp>` to create such an object. It is easy to port models create with composite particles to
flex, see the folder `elasticity/ <https://github.com/google-deepmind/mujoco/tree/main/model/plugin/elasticity>`__ for
several examples.
The particle type is deprecated. It is recommended to use the more generic :ref:`replicate<replicate>` instead, for
example `this model <https://github.com/google-deepmind/mujoco/blob/main/model/replicate/particle.xml>`__.
**Grid**.
+12 -3
View File
@@ -94,9 +94,18 @@
<site name="pin_right" pos=".025 0 .025"/>
</body>
<composite type="particle" count="4 4 4" spacing="0.025" offset=".11 .01 .1">
<geom size=".012" rgba=".5 .8 .5 1" solref=".005 1"/>
</composite>
<replicate count="4" offset=".025 0 0">
<replicate count="4" offset="0 .025 0">
<replicate count="4" offset="0 0 .025">
<body pos=".06 -.04 .05">
<joint type="slide" axis="1 0 0"/>
<joint type="slide" axis="0 1 0"/>
<joint type="slide" axis="0 0 1"/>
<geom type="sphere" size=".012" rgba=".5 .8 .5 1" solref=".005 1" condim="1"/>
</body>
</replicate>
</replicate>
</replicate>
</worldbody>
<equality>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

-45
View File
@@ -1,45 +0,0 @@
<!-- Copyright 2021 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.
-->
<mujoco model="Particle">
<!-- Degree of Freedom: 3000
Actuators: 0
-->
<include file="scene.xml"/>
<option solver="CG" tolerance="1e-6" timestep=".01"/>
<size memory="1G"/>
<visual>
<map stiffness="100"/>
</visual>
<default>
<default class="wall">
<geom type="plane" size=".5 .5 .05"/>
</default>
</default>
<worldbody>
<geom name="+x" class="wall" zaxis="1 0 0" pos="-.5 0 -.25"/>
<geom name="-x" class="wall" zaxis="-1 0 0" pos=".5 0 -.25"/>
<geom name="+y" class="wall" zaxis="0 1 0" pos="0 -.5 -.25"/>
<geom name="-y" class="wall" zaxis="0 -1 0" pos="0 .5 -.25"/>
<composite type="particle" count="10 10 10" spacing="0.07" offset="0 0 1">
<geom size=".025" rgba=".8 .2 .1 1"/>
</composite>
</worldbody>
</mujoco>

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 311 KiB

+40 -9
View File
@@ -1,20 +1,51 @@
<!-- Copyright 2021 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.
-->
<mujoco model="Particle">
<include file="container.xml"/>
<size memory="1G"/>
<!-- Degree of Freedom: 3000
Actuators: 0
-->
<include file="scene.xml"/>
<option solver="CG" tolerance="1e-6" timestep=".01"/>
<size memory="1G"/>
<visual>
<map stiffness="100"/>
</visual>
<default>
<default class="wall">
<geom type="plane" size=".5 .5 .05"/>
</default>
</default>
<worldbody>
<geom name="+x" class="wall" zaxis="1 0 0" pos="-.5 0 -.25"/>
<geom name="-x" class="wall" zaxis="-1 0 0" pos=".5 0 -.25"/>
<geom name="+y" class="wall" zaxis="0 1 0" pos="0 -.5 -.25"/>
<geom name="-y" class="wall" zaxis="0 -1 0" pos="0 .5 -.25"/>
<replicate count="10" offset=".07 0 0">
<replicate count="10" offset="0 .07 0">
<replicate count="10" offset="0 0 .07">
<body pos="-0.35 -0.35 0.65">
<joint type="slide" axis="1 0 0" group="3"/>
<joint type="slide" axis="0 1 0" group="3"/>
<joint type="slide" axis="0 0 1" group="3"/>
<geom size="0.025" condim="1" priority="1" rgba="0.8 0.2 0.1 1"/>
<body pos="-.315 -.315 1">
<joint type="slide" axis="1 0 0"/>
<joint type="slide" axis="0 1 0"/>
<joint type="slide" axis="0 0 1"/>
<geom size=".025" rgba=".8 .2 .1 1" condim="1"/>
</body>
</replicate>
</replicate>
@@ -35,9 +35,15 @@
<geom name="-x" class="wall" zaxis="-1 0 0" pos=".5 0 -.25"/>
<geom name="+y" class="wall" zaxis="0 1 0" pos="0 -.5 -.25"/>
<geom name="-y" class="wall" zaxis="0 -1 0" pos="0 .5 -.25"/>
<composite type="particle" count="3 3 3" spacing="0.07" offset="0 0 1">
<geom type="box" size=".025 .025 .025" rgba=".8 .2 .1 1" condim="3"/>
<joint kind="particle" type="free"/>
</composite>
<replicate count="3" offset=".07 0 0">
<replicate count="3" offset="0 .07 0">
<replicate count="3" offset="0 0 .07">
<body pos="-.07 -.07 1">
<freejoint/>
<geom type="box" size=".025 .025 .025" rgba=".8 .2 .1 1" condim="3"/>
</body>
</replicate>
</replicate>
</replicate>
</worldbody>
</mujoco>
</mujoco>
@@ -35,11 +35,15 @@
<geom name="-x" class="wall" zaxis="-1 0 0" pos=".5 0 -.25"/>
<geom name="+y" class="wall" zaxis="0 1 0" pos="0 -.5 -.25"/>
<geom name="-y" class="wall" zaxis="0 -1 0" pos="0 .5 -.25"/>
<composite type="particle" count="15 15 1" spacing="0.06" offset="0 0 .1">
<geom type="ellipsoid" size=".025 .02 .015" rgba=".8 .2 .1 1"/>
<joint kind="particle" type="slide" axis="1 0 0"/>
<joint kind="particle" type="slide" axis="0 1 0"/>
<joint kind="particle" type="hinge" axis="0 0 1"/>
</composite>
<replicate count="15" offset=".06 0 0">
<replicate count="15" offset="0 .06 0">
<body pos="-.42 -.42 .1">
<joint type="slide" axis="1 0 0"/>
<joint type="slide" axis="0 1 0"/>
<joint type="hinge" axis="0 0 1"/>
<geom type="ellipsoid" size=".025 .02 .015" rgba=".8 .2 .1 1"/>
</body>
</replicate>
</replicate>
</worldbody>
</mujoco>
@@ -29,11 +29,9 @@
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="512"/>
<texture name="texplane" type="2d" builtin="checker" rgb1=".2 .3 .4" rgb2=".1 0.15 0.2"
width="512" height="512" mark="cross" markrgb=".8 .8 .8"/>
<texture name="texcarpet" type="2d" file="carpet.png"/>
<texture name="texmarble" type="cube" file="marble.png"/>
<material name="matplane" reflectance="0.3" texture="texplane" texrepeat="1 1" texuniform="true"/>
<material name="matcarpet" texture="texcarpet"/>
<material name="matmarble" texture="texmarble" rgba=".7 .7 .7 1"/>
</asset>
+9 -200
View File
@@ -57,7 +57,6 @@ mjCComposite::mjCComposite(void) {
prefix.clear();
type = mjCOMPTYPE_PARTICLE;
count[0] = count[1] = count[2] = 1;
spacing = 0;
mjuu_setvec(offset, 0, 0, 0);
flatinertia = 0;
@@ -123,32 +122,12 @@ void mjCComposite::SetDefault(void) {
AddDefaultJoint();
// set default geom and tendon group to 0 if needed to be visible
if (!skin ||
type==mjCOMPTYPE_PARTICLE ||
type==mjCOMPTYPE_CABLE) {
if (!skin || type==mjCOMPTYPE_CABLE) {
for (int i=0; i<mjNCOMPKINDS; i++) {
def[i].spec.geom->group = 0;
def[i].spec.tendon->group = 0;
}
}
// other type-specific adjustments
switch (type) {
case mjCOMPTYPE_PARTICLE: // particle
// no friction with anything
def[0].spec.geom->condim = 1;
def[0].spec.geom->priority = 1;
break;
case mjCOMPTYPE_CABLE: // cable
break;
default:
// SHOULD NOT OCCUR
mju_error("Invalid composite type: %d", type);
break;
}
}
@@ -157,14 +136,6 @@ void mjCComposite::SetDefault(void) {
bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
mjCModel* model = (mjCModel*)spec->element;
// check geom type
if ((def[0].spec.geom->type!=mjGEOM_SPHERE &&
def[0].spec.geom->type!=mjGEOM_CAPSULE &&
def[0].spec.geom->type!=mjGEOM_ELLIPSOID) &&
type!=mjCOMPTYPE_PARTICLE && type!=mjCOMPTYPE_CABLE) {
return comperr(error, "Composite geom type must be sphere, capsule or ellipsoid", error_sz);
}
// check counts
for (int i=0; i<3; i++) {
if (count[i]<1) {
@@ -172,25 +143,11 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
}
}
// check spacing
if (type==mjCOMPTYPE_GRID || (type==mjCOMPTYPE_PARTICLE && uservert.empty())) {
if (spacing < mju_max(def[0].spec.geom->size[0],
mju_max(def[0].spec.geom->size[1], def[0].spec.geom->size[2]))) {
return comperr(error, "Spacing must be larger than geometry size",
error_sz);
}
}
// check cable sizes are nonzero if vertices are not prescribed
if (mjuu_dot3(size, size)<mjMINVAL && uservert.empty()) {
return comperr(error, "Positive spacing or length expected in composite", error_sz);
}
// check spacing is not used by cable
if (spacing && type==mjCOMPTYPE_CABLE) {
return comperr(error, "Spacing is not supported by cable composite", error_sz);
}
// check either uservert or count but not both
if (!uservert.empty()) {
if (count[0]>1) {
@@ -249,7 +206,10 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
// dispatch
switch (type) {
case mjCOMPTYPE_PARTICLE:
return MakeParticle(model, body, error, error_sz);
return comperr(error,
"The \"particle\" composite type is deprecated. Please use "
"\"replicate\" instead.",
error_sz);
case mjCOMPTYPE_GRID:
return comperr(error,
@@ -285,84 +245,6 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int error_sz) {
char txt[100];
std::vector<int> face;
// populate vertices and names
if (uservert.empty()) {
if (spacing < mju_max(def[0].spec.geom->size[0],
mju_max(def[0].spec.geom->size[1], def[0].spec.geom->size[2])))
return comperr(error, "Spacing must be larger than geometry size", error_sz);
for (int ix=0; ix<count[0]; ix++) {
for (int iy=0; iy<count[1]; iy++) {
for (int iz=0; iz<count[2]; iz++) {
uservert.push_back(spacing*(ix - 0.5*count[0]));
uservert.push_back(spacing*(iy - 0.5*count[1]));
uservert.push_back(spacing*(iz - 0.5*count[2]));
mju::sprintf_arr(txt, "%sB%d_%d_%d", prefix.c_str(), ix, iy, iz);
username.push_back(std::string(txt));
}
}
}
}
// create bodies and geoms
for (int i=0; i<uservert.size()/3; i++) {
// create body
mjsBody* b = mjs_addBody(body, NULL);
if (!username.empty()) {
mjs_setString(b->name, username[i].c_str());
} else {
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
mjs_setString(b->name, txt);
}
// set body position
b->pos[0] = offset[0] + uservert[3*i];
b->pos[1] = offset[1] + uservert[3*i+1];
b->pos[2] = offset[2] + uservert[3*i+2];
// add slider joints if none defined
if (!add[mjCOMPKIND_PARTICLE]) {
for (int i=0; i<3; i++) {
mjsJoint* jnt = mjs_addJoint(b, &defjoint[mjCOMPKIND_JOINT][0].spec);
mjs_setDefault(jnt->element, mjs_getDefault(body->element));
jnt->type = mjJNT_SLIDE;
mjuu_setvec(jnt->pos, 0, 0, 0);
mjuu_setvec(jnt->axis, 0, 0, 0);
jnt->axis[i] = 1;
}
}
// add user-specified joints
else {
for (auto& defjnt : defjoint[mjCOMPKIND_PARTICLE]) {
mjsJoint* jnt = mjs_addJoint(b, &defjnt.spec);
mjs_setDefault(jnt->element, mjs_getDefault(body->element));
}
}
// add geom
mjsGeom* g = mjs_addGeom(b, &def[0].spec);
mjs_setDefault(g->element, mjs_getDefault(body->element));
// add site
mjsSite* s = mjs_addSite(b, &def[0].spec);
mjs_setDefault(s->element, mjs_getDefault(body->element));
s->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sS%d", prefix.c_str(), i);
mjs_setString(s->name, txt);
}
return true;
}
bool mjCComposite::MakeCable(mjCModel* model, mjsBody* body, char* error, int error_sz) {
// check dim
if (dim!=1) {
@@ -677,83 +559,14 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
}
// couple with bones
if (type==mjCOMPTYPE_PARTICLE) {
MakeClothBones(model, skin);
} else if (type==mjCOMPTYPE_CABLE) {
MakeCableBones(model, skin);
}
MakeCableBones(model, skin);
CopyIntoSkin(skin);
}
// add bones in 2D
void mjCComposite::MakeClothBones(mjCModel* model, mjsSkin* skin) {
char txt[100];
int N = count[0]*count[1];
// populate bones
for (int ix=0; ix<count[0]; ix++) {
for (int iy=0; iy<count[1]; iy++) {
// body name
if (type==mjCOMPTYPE_GRID) {
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
} else {
mju::sprintf_arr(txt, "%sB%d_%d_0", prefix.c_str(), ix, iy);
}
// bind pose
mjs_appendString(skin->bodyname, txt);
bindpos.push_back(0);
bindpos.push_back(0);
bindpos.push_back(0);
bindquat.push_back(1);
bindquat.push_back(0);
bindquat.push_back(0);
bindquat.push_back(0);
// create vertid and vertweight
vertid.push_back({ix*count[1]+iy, N + ix*count[1]+iy});
vertweight.push_back({1, 1});
}
}
}
void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjsSkin* skin) {
char txt[100];
// populate bones
for (int ix=0; ix<count[0]; ix++) {
for (int iy=0; iy<count[1]; iy++) {
// body name
if (type==mjCOMPTYPE_GRID) {
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
} else {
mju::sprintf_arr(txt, "%sB%d_%d_0", prefix.c_str(), ix, iy);
}
// bind pose
mjs_appendString(skin->bodyname, txt);
bindpos.push_back(ix*spacing);
bindpos.push_back(iy*spacing);
bindpos.push_back(0);
bindquat.push_back(1);
bindquat.push_back(0);
bindquat.push_back(0);
bindquat.push_back(0);
// empty vertid and vertweight
vertid.push_back({});
vertweight.push_back({});
}
}
}
// add bones to 1D
void mjCComposite::MakeCableBones(mjCModel* model, mjsSkin* skin) {
char this_body[100];
@@ -1160,7 +973,7 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
skin->group = skingroup;
// populate mesh: two sides
mjtNum S = spacing/(1+skinsubgrid);
mjtNum S = 0;
int C0 = count[0] + (count[0]-1)*skinsubgrid;
int C1 = count[1] + (count[1]-1)*skinsubgrid;
int NN = C0*C1;
@@ -1236,11 +1049,7 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
face.push_back(NN + iy+1 + (C0-1)*C1);
}
if (type==mjCOMPTYPE_PARTICLE) {
MakeClothBonesSubgrid(model, skin);
} else if (type==mjCOMPTYPE_CABLE) {
MakeCableBonesSubgrid(model, skin);
}
MakeCableBonesSubgrid(model, skin);
// bind vertices to bones: one big square at a time
for (int ix=0; ix<count[0]-1; ix++) {
+2 -5
View File
@@ -49,7 +49,8 @@ typedef enum _mjtCompKind {
typedef enum _mjtCompShape {
mjCOMPSHAPE_LINE = 0,
mjCOMPSHAPE_INVALID = -1,
mjCOMPSHAPE_LINE,
mjCOMPSHAPE_COS,
mjCOMPSHAPE_SIN,
mjCOMPSHAPE_ZERO,
@@ -66,13 +67,10 @@ class mjCComposite {
bool AddDefaultJoint(char* error = NULL, int error_sz = 0);
bool Make(mjSpec* spec, mjsBody* body, char* error, int error_sz);
bool MakeParticle(mjCModel* model, mjsBody* body, char* error, int error_sz);
bool MakeCable(mjCModel* model, mjsBody* body, char* error, int error_sz);
void MakeSkin2(mjCModel* model, mjtNum inflate);
void MakeSkin2Subgrid(mjCModel* model, mjtNum inflate);
void MakeClothBones(mjCModel* model, mjsSkin* skin);
void MakeClothBonesSubgrid(mjCModel* model, mjsSkin* skin);
void MakeCableBones(mjCModel* model, mjsSkin* skin);
void MakeCableBonesSubgrid(mjCModel* model, mjsSkin* skin);
@@ -80,7 +78,6 @@ class mjCComposite {
std::string prefix; // name prefix
mjtCompType type; // composite type
int count[3]; // geom count in each dimension
double spacing; // spacing between elements
double offset[3]; // position offset for particle and grid
double flatinertia; // flatten ineria of cloth elements; 0: disable
+8 -56
View File
@@ -287,25 +287,18 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"<"},
{"config", "*", "2", "key", "value"},
{">"},
{"composite", "*", "12", "prefix", "type", "count", "spacing", "offset",
"flatinertia", "solrefsmooth", "solimpsmooth", "vertex",
"initial", "curve", "size"},
{"composite", "*", "9", "prefix", "type", "count", "offset",
"flatinertia", "vertex", "initial", "curve", "size"},
{"<"},
{"joint", "*", "17", "kind", "group", "stiffness", "damping", "armature",
"solreffix", "solimpfix", "type", "axis",
"limited", "range", "margin", "solreflimit", "solimplimit",
"frictionloss", "solreffriction", "solimpfriction"},
{"tendon", "*", "17", "kind", "group", "stiffness", "damping",
"solreffix", "solimpfix",
"limited", "range", "margin", "solreflimit", "solimplimit",
"frictionloss", "solreffriction", "solimpfriction",
"material", "rgba", "width"},
{"skin", "?", "6", "texcoord", "material", "group", "rgba", "inflate", "subgrid"},
{"geom", "?", "17", "type", "contype", "conaffinity", "condim",
"group", "priority", "size", "material", "rgba", "friction", "mass",
"density", "solmix", "solref", "solimp", "margin", "gap"},
{"site", "?", "4", "group", "size", "material", "rgba"},
{"pin", "*", "1", "coord"},
{"plugin", "*", "2", "plugin", "instance"},
{"<"},
{"config", "*", "2", "key", "value"},
@@ -766,13 +759,6 @@ const mjMap shape_map[mjNCOMPSHAPES] = {
};
// composite tendon kind
const mjMap tkind_map[2] = {
{"main", mjCOMPKIND_TENDON},
{"shear", mjCOMPKIND_SHEAR}
};
// mesh type
const mjMap meshtype_map[2] = {
{"false", mjINERTIA_VOLUME},
@@ -2412,7 +2398,6 @@ void mjXReader::OneComposite(XMLElement* elem, mjsBody* body, const mjsDefault*
comp.type = (mjtCompType)n;
}
ReadAttr(elem, "count", 3, comp.count, text, false, false);
ReadAttr(elem, "spacing", 1, &comp.spacing, text, false);
ReadAttr(elem, "offset", 3, comp.offset, text);
ReadAttr(elem, "flatinertia", 1, &comp.flatinertia, text);
@@ -2436,11 +2421,17 @@ void mjXReader::OneComposite(XMLElement* elem, mjsBody* body, const mjsDefault*
std::istringstream iss(curves);
int i = 0;
while (iss) {
if (curves.empty()) {
break;
}
iss >> text;
if (i>2) {
throw mjXError(elem, "The curve array must have a maximum of 3 components");
}
comp.curve[i++] = (mjtCompShape)FindKey(shape_map, mjNCOMPSHAPES, text);
if (comp.curve[i-1] == -1) {
throw mjXError(elem, "The curve array contains an invalid shape");
}
if (iss.eof()){
break;
}
@@ -2557,45 +2548,6 @@ void mjXReader::OneComposite(XMLElement* elem, mjsBody* body, const mjsDefault*
ejnt = NextSiblingElement(ejnt, "joint");
}
// tendon
XMLElement* eten = FirstChildElement(elem, "tendon");
while (eten) {
// kind
int kind;
MapValue(eten, "kind", &kind, tkind_map, 2, true);
comp.add[kind] = true;
// get default structs
mjsTendon& dtendon = *comp.def[kind].spec.tendon;
mjsEquality& dequality = *comp.def[kind].spec.equality;
// solreffix, solimpfix
ReadAttr(eten, "solreffix", mjNREF, dequality.solref, text, false, false);
ReadAttr(eten, "solimpfix", mjNIMP, dequality.solimp, text, false, false);
// tendon attributes
string material;
MapValue(elem, "limited", &dtendon.limited, TFAuto_map, 3);
ReadAttrInt(eten, "group", &dtendon.group);
ReadAttr(eten, "solreflimit", mjNREF, dtendon.solref_limit, text, false, false);
ReadAttr(eten, "solimplimit", mjNIMP, dtendon.solimp_limit, text, false, false);
ReadAttr(eten,
"solreffriction", mjNREF, dtendon.solref_friction, text, false, false);
ReadAttr(eten,
"solimpfriction", mjNIMP, dtendon.solimp_friction, text, false, false);
ReadAttr(eten, "range", 2, dtendon.range, text);
ReadAttr(eten, "margin", 1, &dtendon.margin, text);
ReadAttr(eten, "stiffness", 1, &dtendon.stiffness, text);
ReadAttr(eten, "damping", 1, &dtendon.damping, text);
ReadAttr(eten, "frictionloss", 1, &dtendon.frictionloss, text);
ReadAttrTxt(eten, "material", material);
mjs_setString(dtendon.material, material.c_str());
ReadAttr(eten, "rgba", 4, dtendon.rgba, text);
ReadAttr(eten, "width", 1, &dtendon.width, text);
// advance
eten = NextSiblingElement(eten, "tendon");
}
// make composite
char error[200];
+1 -1
View File
@@ -101,7 +101,7 @@ class mjXReader : public mjXBase {
};
// MJCF schema
#define nMJCF 239
#define nMJCF 237
extern const char* MJCF[nMJCF][mjXATTRNUM];
#endif // MUJOCO_SRC_XML_XML_NATIVE_READER_H_
+1 -1
View File
@@ -80,7 +80,7 @@ BENCHMARK(BM_StepFlagPlugin);
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepParticle(benchmark::State& state) {
MujocoErrorTestGuard guard;
static mjModel* model = LoadModelFromPath("composite/particle.xml");
static mjModel* model = LoadModelFromPath("replicate/particle.xml");
run_step_benchmark(model, state);
}
BENCHMARK(BM_StepParticle);
@@ -39,25 +39,49 @@
<geom name="+y" class="wall" zaxis="0 1 0" pos="0 -.5 -.25"/>
<geom name="-y" class="wall" zaxis="0 -1 0" pos="0 .5 -.25"/>
<composite type="particle" count="3 3 2" spacing="0.2" offset="0 0 1">
<geom type="sphere" size=".09" rgba=".8 .2 .1 1" condim="3"/>
<joint kind="particle" type="free"/>
</composite>
<replicate count="3" offset=".2 0 0">
<replicate count="3" offset="0 .2 0">
<replicate count="2" offset="0 0 .2">
<body pos="-.2 -.2 1">
<freejoint/>
<geom type="sphere" size=".09" rgba=".8 .2 .1 1" condim="3"/>
</body>
</replicate>
</replicate>
</replicate>
<composite type="particle" count="3 3 2" spacing="0.2" offset="0 0 1.6" prefix="A">
<geom type="cylinder" size=".09 .02" rgba=".8 .2 .1 1" condim="3"/>
<joint kind="particle" type="free"/>
</composite>
<replicate count="3" offset=".2 0 0" prefix="A">
<replicate count="3" offset="0 .2 0">
<replicate count="2" offset="0 0 .2">
<body pos="-.2 -.2 1.6">
<freejoint/>
<geom type="cylinder" size=".09 .02" rgba=".8 .2 .1 1" condim="3"/>
</body>
</replicate>
</replicate>
</replicate>
<composite type="particle" count="3 3 2" spacing="0.2" offset="0 0 2.2" prefix="B">
<geom type="cylinder" size=".02 .09" rgba=".8 .2 .1 1" condim="3"/>
<joint kind="particle" type="free"/>
</composite>
<replicate count="3" offset=".2 0 0" prefix="B">
<replicate count="3" offset="0 .2 0">
<replicate count="2" offset="0 0 .2">
<body pos="-.2 -.2 2.2">
<freejoint/>
<geom type="cylinder" size=".02 .09" rgba=".8 .2 .1 1" condim="3"/>
</body>
</replicate>
</replicate>
</replicate>
<composite type="particle" count="3 3 2" spacing="0.2" offset="0 0 2.8" prefix="C">
<geom type="sphere" size=".06" rgba=".8 .2 .1 1" condim="3"/>
<joint kind="particle" type="free"/>
</composite>
<replicate count="3" offset=".2 0 0" prefix="C">
<replicate count="3" offset="0 .2 0">
<replicate count="2" offset="0 0 .2">
<body pos="-.2 -.2 2.8">
<freejoint/>
<geom type="sphere" size=".06" rgba=".8 .2 .1 1" condim="3"/>
</body>
</replicate>
</replicate>
</replicate>
</worldbody>
</mujoco>
+21 -24
View File
@@ -35,14 +35,30 @@ using ::testing::NotNull;
using ::testing::HasSubstr;
using UserCompositeTest = MujocoTest;
// ------------- test automatic inference of nuser_xxx -------------------------
// ------------------------ cable tests ---------------------------------------
TEST_F(UserCompositeTest, SpacingGreaterThanGeometry) {
TEST_F(UserCompositeTest, ShapeCanBeOmitted) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<composite type="particle" count="282 2">
<geom size="8"/>
<composite type="cable" count="100 1 1" curve="s">
<geom type="box" size="1 1 1"/>
</composite>
</worldbody>
</mujoco>
)";
std::array<char, 1024> error;
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(m, NotNull()) << error.data();
mj_deleteModel(m);
}
TEST_F(UserCompositeTest, InvalidShape) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<composite type="cable" count="100 1 1" curve="s s exp">
<geom type="box" size="1 1 1"/>
</composite>
</worldbody>
</mujoco>
@@ -51,26 +67,7 @@ TEST_F(UserCompositeTest, SpacingGreaterThanGeometry) {
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(m, IsNull()) << error.data();
EXPECT_THAT(error.data(),
HasSubstr("Spacing must be larger than geometry size"));
}
TEST_F(UserCompositeTest, SpacingEqualToGeometry) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<composite type="particle" count="282 2" spacing="8">
<geom size="8"/>
</composite>
</worldbody>
</mujoco>
)";
std::array<char, 1024> error;
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(m, NotNull()) << error.data();
mjData* d = mj_makeData(m);
mj_step(m, d);
mj_deleteData(d);
mj_deleteModel(m);
HasSubstr("The curve array contains an invalid shape"));
}
} // namespace
+1 -1
View File
@@ -1897,7 +1897,7 @@ TEST_F(XMLReaderTest, InvalidSkinGroup) {
<mujoco>
<worldbody>
<body>
<composite prefix="B0" type="grid" count="6 6 1" spacing=".2">
<composite prefix="B0" type="grid" count="6 6 1">
<geom size=".1"/>
<skin group="6"/>
</composite>