diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index fcd7b54d..01c79d92 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -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 ` 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 ` 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: diff --git a/doc/XMLschema.rst b/doc/XMLschema.rst index f18ef816..32da3890 100644 --- a/doc/XMLschema.rst +++ b/doc/XMLschema.rst @@ -340,11 +340,11 @@ | :ref:`composite | \* | :class: mjcf-attributes | | ` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`prefix` | :ref:`type` | :ref:`count` | :ref:`spacing` | | +| | | | :ref:`prefix` | :ref:`type` | :ref:`count` | :ref:`offset` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`offset` | :ref:`flatinertia` | :ref:`solrefsmooth` | :ref:`solimpsmooth` | | +| | | | :ref:`flatinertia` | :ref:`vertex` | :ref:`initial` | :ref:`curve` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`vertex` | :ref:`initial` | :ref:`curve` | :ref:`size` | | +| | | | :ref:`size` | | | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_2| composite |br| |_2| |L| | | .. table:: | @@ -363,21 +363,6 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_2| composite |br| |_2| |L| | | .. table:: | -| :ref:`tendon | \* | :class: mjcf-attributes | -| ` | | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`kind` | :ref:`group` | :ref:`stiffness` | :ref:`damping` | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`solreffix` | :ref:`solimpfix` | :ref:`limited` | :ref:`range` | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`margin` | :ref:`solreflimit` | :ref:`solimplimit` | :ref:`frictionloss` | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`solreffriction` | :ref:`solimpfriction` | :ref:`material` | :ref:`rgba` | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`width` | | | | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| |_2| composite |br| |_2| |L| | | .. table:: | | :ref:`skin | ? | :class: mjcf-attributes | | ` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | @@ -409,13 +394,6 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_2| composite |br| |_2| |L| | | .. table:: | -| :ref:`pin | \* | :class: mjcf-attributes | -| ` | | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`coord` | | | | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| |_2| composite |br| |_2| |L| | | .. table:: | | :ref:`plugin | \* | :class: mjcf-attributes | | ` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | diff --git a/doc/changelog.rst b/doc/changelog.rst index 456651ed..e5984f2c 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -36,6 +36,9 @@ General - Added :ref:`potential` and :ref:`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` + instead, for example `this model + `__. .. admonition:: Breaking API changes :class: attention diff --git a/doc/modeling.rst b/doc/modeling.rst index f61dad1f..1bf52b60 100644 --- a/doc/modeling.rst +++ b/doc/modeling.rst @@ -1164,34 +1164,8 @@ see the XML model files in the distribution for the complete examples. **Particle**. -|image4| |image5| - -.. code-block:: xml - - - - - - - -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 -` 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. +The particle type is deprecated. It is recommended to use the more generic :ref:`replicate` instead, for +example `this model `__. **Grid**. diff --git a/model/adhesion/active_adhesion.xml b/model/adhesion/active_adhesion.xml index 1c6d6ce0..db99db98 100644 --- a/model/adhesion/active_adhesion.xml +++ b/model/adhesion/active_adhesion.xml @@ -94,9 +94,18 @@ - - - + + + + + + + + + + + + diff --git a/model/composite/asset/carpet.png b/model/composite/asset/carpet.png deleted file mode 100644 index 64f1c680..00000000 Binary files a/model/composite/asset/carpet.png and /dev/null differ diff --git a/model/composite/particle.xml b/model/composite/particle.xml deleted file mode 100644 index 83aef5f0..00000000 --- a/model/composite/particle.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - diff --git a/model/composite/asset/marble.png b/model/replicate/asset/marble.png similarity index 100% rename from model/composite/asset/marble.png rename to model/replicate/asset/marble.png diff --git a/model/replicate/particle.xml b/model/replicate/particle.xml index 0ad5f559..6f3bc056 100644 --- a/model/replicate/particle.xml +++ b/model/replicate/particle.xml @@ -1,20 +1,51 @@ + + - - - - + + \ No newline at end of file + diff --git a/model/composite/particle_free2d.xml b/model/replicate/particle_free2d.xml similarity index 76% rename from model/composite/particle_free2d.xml rename to model/replicate/particle_free2d.xml index 624bc8e0..65c9eafa 100644 --- a/model/composite/particle_free2d.xml +++ b/model/replicate/particle_free2d.xml @@ -35,11 +35,15 @@ - - - - - - + + + + + + + + + + diff --git a/model/composite/scene.xml b/model/replicate/scene.xml similarity index 94% rename from model/composite/scene.xml rename to model/replicate/scene.xml index 05bbbc87..cb39cea0 100644 --- a/model/composite/scene.xml +++ b/model/replicate/scene.xml @@ -29,11 +29,9 @@ - - diff --git a/src/user/user_composite.cc b/src/user/user_composite.cc index 8972eca2..8f733bef 100644 --- a/src/user/user_composite.cc +++ b/src/user/user_composite.cc @@ -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; igroup = 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)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 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; ixname, 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; ixbodyname, 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; ixbodyname, 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"}, - {"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]; diff --git a/src/xml/xml_native_reader.h b/src/xml/xml_native_reader.h index 86612184..41aacbbb 100644 --- a/src/xml/xml_native_reader.h +++ b/src/xml/xml_native_reader.h @@ -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_ diff --git a/test/benchmark/step_benchmark_test.cc b/test/benchmark/step_benchmark_test.cc index a2039d80..551e312c 100644 --- a/test/benchmark/step_benchmark_test.cc +++ b/test/benchmark/step_benchmark_test.cc @@ -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); diff --git a/test/engine/testdata/collision_primitive/spheres_cylinders.xml b/test/engine/testdata/collision_primitive/spheres_cylinders.xml index 4d966455..4048d6e8 100644 --- a/test/engine/testdata/collision_primitive/spheres_cylinders.xml +++ b/test/engine/testdata/collision_primitive/spheres_cylinders.xml @@ -39,25 +39,49 @@ - - - - + + + + + + + + + + - - - - + + + + + + + + + + - - - - + + + + + + + + + + - - - - + + + + + + + + + + diff --git a/test/user/user_composite_test.cc b/test/user/user_composite_test.cc index b7e063bf..07f66c0f 100644 --- a/test/user/user_composite_test.cc +++ b/test/user/user_composite_test.cc @@ -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"( - - + + + + + + )"; + std::array 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"( + + + + @@ -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"( - - - - - - - - )"; - std::array 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 diff --git a/test/xml/xml_native_reader_test.cc b/test/xml/xml_native_reader_test.cc index 72db3566..9ce70cd4 100644 --- a/test/xml/xml_native_reader_test.cc +++ b/test/xml/xml_native_reader_test.cc @@ -1897,7 +1897,7 @@ TEST_F(XMLReaderTest, InvalidSkinGroup) { - +