Remove plugin support from Composite particles.

This functionality is replaced by FlexComp.

PiperOrigin-RevId: 672503965
Change-Id: I58953267de285f82e416f9f60576a336b7d0da4c
This commit is contained in:
Alessio Quaglino
2024-09-09 04:57:34 -07:00
committed by Copybara-Service
parent 44145742a7
commit 4862b9e765
18 changed files with 39 additions and 1963 deletions
+1 -6
View File
@@ -3136,12 +3136,7 @@ coordinates results in compiler error. See :ref:`CComposite` in the modeling gui
.. _body-composite-vertex:
:at:`vertex`: :at-val:`real(3*nvert), optional`
Vertex 3D positions in global coordinates (cable and shell).
.. _body-composite-face:
:at:`face`: :at-val:`real(3*nvert), optional`
Face connectivity of the vertices (shell only).
Vertex 3D positions in global coordinates (cable only).
.. _body-composite-initial:
+1 -3
View File
@@ -402,9 +402,7 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`offset<body-composite-offset>` | :ref:`flatinertia<body-composite-flatinertia>` | :ref:`solrefsmooth<body-composite-solrefsmooth>` | :ref:`solimpsmooth<body-composite-solimpsmooth>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`vertex<body-composite-vertex>` | :ref:`face<body-composite-face>` | :ref:`initial<body-composite-initial>` | :ref:`curve<body-composite-curve>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`size<body-composite-size>` | | | | |
| | | | :ref:`vertex<body-composite-vertex>` | :ref:`initial<body-composite-initial>` | :ref:`curve<body-composite-curve>` | :ref:`size<body-composite-size>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| composite |br| |_2| |L| | | .. table:: |
+2 -1
View File
@@ -17,7 +17,8 @@ General
the MPR algorithm. The semantics of these options remain identical.
- The functions ``mjs_findMesh`` and ``mjs_findKeyframe`` were replaced by ``mjs_findElement``, which allows to look
for any object type.
- The experimental use of 2D/3D elasticity plugins with :ref:`composite<body-composite>` has been removed. Users
should instead use :ref:`flexcomp<body-flexcomp>`, which provides the correct collision behavior.
- Added the :ref:`nativeccd<option-flag-nativeccd>` flag. When this flag is enabled, general convex collision
detection is handled natively, as opposed to using `libccd <https://github.com/danfis/libccd>`__. This feature is in
early stages of testing.
-54
View File
@@ -1,54 +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="Flag">
<!-- Degree of Freedom (nv): 340
Tendons (ntendon): 288
Actuators (nu): 0
Constraints (nefc): 0
This model of a flag passively flapping in the wind has no constraints and is designed to
exert smooth dynamics computations.
-->
<statistic center=".4 0 .8" extent="1.3"/>
<option wind="5 5 0" density="10" solver="CG" tolerance="1e-6">
</option>
<extension>
<plugin plugin="mujoco.elasticity.shell"/>
</extension>
<worldbody>
<geom name="floor" type="plane" size="0 0 .1"/>
<light diffuse=".6 .6 .6" specular="0.2 0.2 0.2" pos="0 0 4" dir="0 0 -1"/>
<body pos="0 0 1">
<composite type="particle" count="9 19 1" spacing="0.05" flatinertia="0.01">
<skin texcoord="true" inflate="0.005" subgrid="4"/>
<geom type="ellipsoid" size="0.025 0.01 0.025" rgba=".8 .2 .1 1" group="4"/>
<plugin plugin="mujoco.elasticity.shell">
<config key="poisson" value="0"/>
<config key="thickness" value="1e-2"/>
<!--Units are in Pa (SI)-->
<config key="young" value="3e6"/>
</plugin>
</composite>
</body>
</worldbody>
<equality>
<connect body1="B0_0_0" anchor="0 0 0" solref="0.0002 1"/>
</equality>
</mujoco>
-55
View File
@@ -1,55 +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="Floppy">
<include file="scene.xml"/>
<extension>
<plugin plugin="mujoco.elasticity.solid"/>
</extension>
<compiler autolimits="true"/>
<option solver="Newton" tolerance="1e-6" timestep=".001"/>
<size memory="100M"/>
<visual>
<map stiffness="100"/>
</visual>
<worldbody>
<composite type="particle" count="24 4 4" spacing="0.1" offset=".1 0 1.5">
<geom size=".025" rgba=".8 .2 .1 1" group="4"
condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
<skin inflate="0" rgba="0 .7 .7 .6"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0.2"/>
<config key="damping" value="0.002"/>
<!--Units are in Pa (SI)-->
<config key="young" value="5e4"/>
</plugin>
</composite>
<body>
<joint name="hinge" pos="0 0 .5" axis="0 1 0" damping="50"/>
<geom type="cylinder" size=".4" fromto="0 -.5 .5 0 .5 .5" density="300"/>
</body>
</worldbody>
<actuator>
<motor name="cylinder" joint="hinge" gear="1 0 0 0 0 0" ctrlrange="-100 100"/>
</actuator>
</mujoco>
-56
View File
@@ -1,56 +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="Jelly">
<include file="scene.xml"/>
<extension>
<plugin plugin="mujoco.elasticity.solid"/>
</extension>
<option solver="CG" tolerance="1e-6" timestep=".001"/>
<size memory="10M"/>
<visual>
<map stiffness="100"/>
</visual>
<default>
<default class="wall">
<geom type="plane" size=".5 .5 .05"/>
</default>
</default>
<worldbody>
<body mocap="true" pos="-.1 .05 0" zaxis=".5 0 1">
<geom type="capsule" size=".1 .1" group="1" condim="1"/>
</body>
<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="8 8 8" spacing="0.07" offset="0 0 1">
<geom size=".025" rgba=".8 .2 .1 1" group="4"/>
<skin inflate="0" rgba="0 .7 .7 .6"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0"/>
<config key="damping" value="0.001"/>
<!--Units are in Pa (SI)-->
<config key="young" value="5e4"/>
</plugin>
</composite>
</worldbody>
</mujoco>
-53
View File
@@ -1,53 +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="Plate">
<include file="scene.xml"/>
<extension>
<plugin plugin="mujoco.elasticity.shell"/>
</extension>
<option solver="CG" tolerance="1e-6"/>
<size memory="10M"/>
<visual>
<map stiffness="100"/>
</visual>
<default>
<default class="wall">
<geom type="plane" size=".5 .5 .05"/>
</default>
</default>
<worldbody>
<body mocap="true" pos="-.1 .05 0" zaxis=".5 0 1">
<geom type="capsule" size=".1 .1" group="1"/>
</body>
<composite type="particle" count="16 16 1" spacing="0.05" offset="0 0 1">
<geom size=".02" rgba=".8 .2 .1 1" group="4" density="1000"
condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
<skin inflate="0.0001" rgba=".4 0 .3 1" subgrid="1"/>
<plugin plugin="mujoco.elasticity.shell">
<config key="poisson" value="0"/>
<config key="thickness" value="1e-2"/>
<!--Units are in Pa (SI)-->
<config key="young" value="3e7"/>
</plugin>
</composite>
</worldbody>
</mujoco>
File diff suppressed because it is too large Load Diff
-72
View File
@@ -1,72 +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="Press">
<include file="scene.xml"/>
<extension>
<plugin plugin="mujoco.elasticity.solid"/>
</extension>
<compiler autolimits="true"/>
<option solver="Newton" tolerance="1e-6" timestep=".001"/>
<size memory="10M"/>
<visual>
<map stiffness="100"/>
</visual>
<worldbody>
<composite prefix="A" type="particle" count="4 4 4" spacing="0.2" offset="0 0 .5">
<geom size=".025" rgba=".8 .2 .1 1" group="4"
condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
<skin inflate="0" rgba="0 .7 .7 .6"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0.4"/>
<config key="damping" value="0.001"/>
<!--Units are in Pa (SI)-->
<config key="young" value="1e4"/>
</plugin>
</composite>
<composite prefix="B" type="particle" count="4 4 4" spacing="0.2" offset="1 0 .5">
<geom size=".025" rgba=".8 .2 .1 1" group="4"
condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
<skin inflate="0" rgba="0 .7 .7 .6"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0"/>
<config key="damping" value="0.001"/>
<!--Units are in Pa (SI)-->
<config key="young" value="5e4"/>
</plugin>
</composite>
<body>
<joint name="soft" type="slide" axis="0 0 1" damping="500"/>
<geom type="box" size=".35 .35 0.05" pos=".1 .1 .8" density="300"/>
</body>
<body>
<joint name="stiff" type="slide" axis="0 0 1" damping="500"/>
<geom type="box" size=".35 .35 0.05" pos="1.1 .1 .8" density="300"/>
</body>
</worldbody>
<actuator>
<motor name="soft" joint="soft" gear="-1 0 0 0 0 0" ctrlrange="-150 300"/>
<motor name="stiff" joint="stiff" gear="-1 0 0 0 0 0" ctrlrange="-150 1600"/>
</actuator>
</mujoco>
+7 -17
View File
@@ -123,8 +123,7 @@ Membrane::Membrane(const mjModel* m, mjData* d, int instance, mjtNum nu,
}
// vertex positions
mjtNum* body_pos =
f0 < 0 ? m->body_pos + 3*i0 : m->flex_xvert0 + 3*m->flex_vertadr[f0];
mjtNum* body_pos = m->flex_xvert0 + 3*m->flex_vertadr[f0];
// generate triangles from the vertices
nt = CreateStencils<Stencil2D>(elements, edges, simplex, edgeidx);
@@ -136,7 +135,7 @@ Membrane::Membrane(const mjModel* m, mjData* d, int instance, mjtNum nu,
for (int t = 0; t < nt; t++) {
int* v = elements[t].vertices;
for (int i = 0; i < kNumVerts; i++) {
int bi = f0 < 0 ? i0+v[i] : m->flex_vertbodyid[m->flex_vertadr[f0]+v[i]];
int bi = m->flex_vertbodyid[m->flex_vertadr[f0]+v[i]];
if (bi && m->body_plugin[bi] != instance) {
mju_error("Body %d does not have plugin instance %d", bi, instance);
}
@@ -182,12 +181,7 @@ void Membrane::Compute(const mjModel* m, mjData* d, int instance) {
mjtNum kD = damping / m->opt.timestep;
// update edge lengths
if (f0 < 0) {
UpdateSquaredLengths(deformed, edges, d->xpos+3*i0);
} else {
UpdateSquaredLengthsFlex(deformed,
d->flexedge_length + m->flex_edgeadr[f0]);
}
UpdateSquaredLengthsFlex(deformed, d->flexedge_length + m->flex_edgeadr[f0]);
// we add generalized Rayleigh damping as decribed in Section 5.2 of
// Kharevych et al., "Geometric, Variational Integrators for Computer
@@ -199,18 +193,14 @@ void Membrane::Compute(const mjModel* m, mjData* d, int instance) {
}
// compute gradient of elastic energy and insert into passive force
int flex_vertadr = f0 < 0 ? -1 : m->flex_vertadr[f0];
mjtNum* xpos = f0 < 0 ? d->xpos + 3*i0 : d->flexvert_xpos + 3*flex_vertadr;
mjtNum* qfrc = d->qfrc_passive + (f0 < 0 ? m->body_dofadr[i0] : 0);
int flex_vertadr = m->flex_vertadr[f0];
mjtNum* xpos = d->flexvert_xpos + 3*flex_vertadr;
mjtNum* qfrc = d->qfrc_passive;
ComputeForce<Stencil2D>(force, elements, metric, elongation, m, xpos);
// insert into passive force
if (f0 < 0) {
mju_addTo(qfrc, force.data(), force.size());
} else {
AddFlexForce(qfrc, force, m, d, xpos, f0);
}
AddFlexForce(qfrc, force, m, d, xpos, f0);
// update stored lengths
if (kD > 0) {
+7 -17
View File
@@ -131,8 +131,7 @@ Solid::Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
}
// vertex positions
mjtNum* body_pos =
f0 < 0 ? m->body_pos + 3*i0 : m->flex_xvert0 + 3*m->flex_vertadr[f0];
mjtNum* body_pos = m->flex_xvert0 + 3*m->flex_vertadr[f0];
// generate tetrahedra from the vertices
nt = CreateStencils<Stencil3D>(elements, edges, simplex, edgeidx);
@@ -144,7 +143,7 @@ Solid::Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
for (int t = 0; t < nt; t++) {
int* v = elements[t].vertices;
for (int i = 0; i < kNumVerts; i++) {
int bi = f0 < 0 ? i0+v[i] : m->flex_vertbodyid[m->flex_vertadr[f0]+v[i]];
int bi = m->flex_vertbodyid[m->flex_vertadr[f0]+v[i]];
if (bi && m->body_plugin[bi] != instance) {
mju_error("Body %d does not have plugin instance %d", bi, instance);
}
@@ -189,12 +188,7 @@ void Solid::Compute(const mjModel* m, mjData* d, int instance) {
mjtNum kD = damping / m->opt.timestep;
// update edge lengths
if (f0 < 0) {
UpdateSquaredLengths(deformed, edges, d->xpos+3*i0);
} else {
UpdateSquaredLengthsFlex(deformed,
d->flexedge_length + m->flex_edgeadr[f0]);
}
UpdateSquaredLengthsFlex(deformed, d->flexedge_length + m->flex_edgeadr[f0]);
// we add generalized Rayleigh damping as decribed in Section 5.2 of
// Kharevych et al., "Geometric, Variational Integrators for Computer
@@ -206,18 +200,14 @@ void Solid::Compute(const mjModel* m, mjData* d, int instance) {
}
// compute gradient of elastic energy and insert into passive force
int flex_vertadr = f0 < 0 ? -1 : m->flex_vertadr[f0];
mjtNum* xpos = f0 < 0 ? d->xpos + 3*i0 : d->flexvert_xpos + 3*flex_vertadr;
mjtNum* qfrc = d->qfrc_passive + (f0 < 0 ? m->body_dofadr[i0] : 0);
int flex_vertadr = m->flex_vertadr[f0];
mjtNum* xpos = d->flexvert_xpos + 3*flex_vertadr;
mjtNum* qfrc = d->qfrc_passive;
ComputeForce<Stencil3D>(force, elements, metric, elongation, m, xpos);
// insert into passive force
if (f0 < 0) {
mju_addTo(qfrc, force.data(), force.size());
} else {
AddFlexForce(qfrc, force, m, d, xpos, f0);
}
AddFlexForce(qfrc, force, m, d, xpos, f0);
// update stored lengths
if (kD > 0) {
+11 -201
View File
@@ -301,6 +301,17 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
}
}
// check plugin compatibility
// TODO: move mujoco.elasticity.cable to the engine
if (plugin.active) {
if (type != mjCOMPTYPE_CABLE) {
return comperr(error, "Only cable composite supports plugins", error_sz);
}
if (plugin_name != "mujoco.elasticity.cable") {
return comperr(error, "Only mujoco.elasticity.cable is supported by composites", error_sz);
}
}
// overwrite plugin name
if (plugin_instance_name.empty() && plugin.active) {
plugin_instance_name = "composite" + prefix;
@@ -372,93 +383,6 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int
}
}
// create faces
if (userface.empty()) {
if (dim == 3) {
int cube2tets[6][4] = {{0, 3, 1, 7}, {0, 1, 4, 7},
{1, 3, 2, 7}, {1, 2, 6, 7},
{1, 5, 4, 7}, {1, 6, 5, 7}};
for (int ix = 0; ix < count[0]-1; ix++) {
for (int iy = 0; iy < count[1]-1; iy++) {
for (int iz = 0; iz < count[2]-1; iz++) {
int vert[8] = {
count[2]*count[1]*(ix+0) + count[2]*(iy+0) + iz+0,
count[2]*count[1]*(ix+1) + count[2]*(iy+0) + iz+0,
count[2]*count[1]*(ix+1) + count[2]*(iy+1) + iz+0,
count[2]*count[1]*(ix+0) + count[2]*(iy+1) + iz+0,
count[2]*count[1]*(ix+0) + count[2]*(iy+0) + iz+1,
count[2]*count[1]*(ix+1) + count[2]*(iy+0) + iz+1,
count[2]*count[1]*(ix+1) + count[2]*(iy+1) + iz+1,
count[2]*count[1]*(ix+0) + count[2]*(iy+1) + iz+1,
};
for (int s = 0; s < 6; s++) {
for (int v = 0; v < 4; v++) {
face.push_back(vert[cube2tets[s][v]]);
}
}
}
}
}
} else if (dim == 2) {
int quad2tri[2][3] = {{0, 1, 2}, {0, 2, 3}};
for (int ix = 0; ix < count[0]-1; ix++) {
for (int iy = 0; iy < count[1]-1; iy++) {
int vert[4] = {
count[2]*count[1]*(ix+0) + count[2]*(iy+0),
count[2]*count[1]*(ix+1) + count[2]*(iy+0),
count[2]*count[1]*(ix+1) + count[2]*(iy+1),
count[2]*count[1]*(ix+0) + count[2]*(iy+1),
};
for (int s = 0; s < 2; s++) {
for (int v = 0; v < 3; v++) {
face.push_back(vert[quad2tri[s][v]]);
}
}
}
}
}
userface = VectorToString(face);
} else {
dim = 2; // can only load a surface for now
face = StringToVector<int>(userface);
for (int i=0; i<face.size(); face[i++]--) {};
userface = VectorToString(face);
}
// compute volume
std::vector<double> volume(uservert.size()/3);
double thickness = 1;
if (dim == 2 && plugin.active) {
try {
mjCPlugin* pplugin = static_cast<mjCPlugin*>(plugin.instance);
thickness = std::stod(pplugin->config_attribs["thickness"], nullptr);
} catch (const std::invalid_argument& e) {
return comperr(error, "Invalid thickness attribute", error_sz);
}
}
if (!userface.empty()) {
face = StringToVector<int>(userface);
for (int j=0; j<face.size()/3; j++) {
double area[3];
double edge1[3];
double edge2[3];
for (int i=0; i<3; i++) {
edge1[i] = uservert[3*face[3*j+1]+i] - uservert[3*face[3*j]+i];
edge2[i] = uservert[3*face[3*j+2]+i] - uservert[3*face[3*j]+i];
}
mjuu_crossvec(area, edge1, edge2);
for (int i=0; i<3; i++) {
volume[face[3*j+i]] += sqrt(mjuu_dot3(area, area)) / 2 * thickness;
}
}
} else {
for (int i=0; i<uservert.size()/3; i++) {
volume[i] = 6 * spacing * spacing / 2 * thickness;
}
}
// create bodies and geoms
for (int i=0; i<uservert.size()/3; i++) {
// create body
@@ -506,83 +430,6 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int
s->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sS%d", prefix.c_str(), i);
mjs_setString(s->name, txt);
// add plugin
if (plugin.active) {
mjsPlugin* pplugin = &b->plugin;
mjCPlugin* cplugin = static_cast<mjCPlugin*>(plugin.instance);
pplugin->active = true;
pplugin->instance = plugin.instance;
mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
mjs_setString(pplugin->name, mjs_getString(plugin.name));
if (i==0 && !cplugin->config_attribs["face"].empty()) {
return comperr(error, "Face attribute already exists in plugin", error_sz);
}
cplugin->config_attribs["face"] = userface;
cplugin->config_attribs["edge"] = "";
// update density
if (dim == 2) {
g->density *= volume[i] / (4./3. * mjPI * pow(g->size[0], 3));
}
}
}
// add isometry constraints
if (dim==2) {
char txt0[100], txt1[100], txt2[100];
std::vector<std::pair<int, int>> edge;
// create edges
for (int i=0; i<face.size()/3; i++) {
for (int j=0; j<3; j++) {
int v0 = face[3*i+(j+0)%3];
int v1 = face[3*i+(j+1)%3];
edge.push_back(v0 < v1 ? std::pair(v0, v1) : std::pair(v1, v0));
}
}
std::sort(edge.begin(), edge.end());
auto last = std::unique(edge.begin(), edge.end());
edge.erase(last, edge.end());
// create constraints
for (int i=0; i<edge.size(); i++) {
int v0 = edge[i].first;
int v1 = edge[i].second;
mju::sprintf_arr(txt0, "%sT%d_%d", prefix.c_str(), v0, v1);
mju::sprintf_arr(txt1, "%sS%d", prefix.c_str(), v0);
mju::sprintf_arr(txt2, "%sS%d", prefix.c_str(), v1);
// create tendon
mjsTendon* ten = mjs_addTendon(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjs_setDefault(ten->element, &model->Default()->spec);
mjs_setString(ten->name, txt0);
ten->group = 4;
mjs_wrapSite(ten, txt1);
mjs_wrapSite(ten, txt2);
// add equality constraint
mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjs_setDefault(eq->element, &model->Default()->spec);
eq->type = mjEQ_TENDON;
mjs_setString(eq->name1, mjs_getString(ten->name));
}
}
if (skin && dim==3) {
MakeSkin3(model);
}
if (skin && dim==2) {
if (skinsubgrid>0) {
MakeSkin2Subgrid(model, skininflate);
} else {
MakeSkin2(model, skininflate);
}
}
return true;
@@ -1303,43 +1150,6 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
skin->inflate = inflate;
skin->group = skingroup;
// copy skin from existing mesh
if (type==mjCOMPTYPE_PARTICLE && username.empty()) {
std::vector<int> skinface;
skinface = StringToVector<int>(userface);
int nvert = uservert.size()/3;
for (int j=0; j<2; j++) {
for (int i=0; i<nvert; i++) {
vert.push_back(0);
vert.push_back(0);
vert.push_back(0);
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
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);
vertid.push_back({j*nvert+i});
vertweight.push_back({1});
}
for (int i=0; i<skinface.size()/3; i++) {
face.push_back(j*nvert+skinface[3*i]);
face.push_back(j*nvert+skinface[3*i+(j==0 ? 1 : 2)]);
face.push_back(j*nvert+skinface[3*i+(j==0 ? 2 : 1)]);
}
}
CopyIntoSkin(skin);
return;
}
// populate mesh: two sides
for (int i=0; i<2; i++) {
for (int ix=0; ix<count[0]; ix++) {
-1
View File
@@ -106,7 +106,6 @@ class mjCComposite {
// currently used only for cable
std::string initial; // root boundary type
std::vector<float> uservert; // user-specified vertex positions
std::string userface; // connectivity
double size[3]; // rope size (meaning depends on the shape)
mjtCompShape curve[3]; // geometric shape
+2 -5
View File
@@ -296,8 +296,8 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"<"},
{"config", "*", "2", "key", "value"},
{">"},
{"composite", "*", "13", "prefix", "type", "count", "spacing", "offset",
"flatinertia", "solrefsmooth", "solimpsmooth", "vertex", "face",
{"composite", "*", "12", "prefix", "type", "count", "spacing", "offset",
"flatinertia", "solrefsmooth", "solimpsmooth", "vertex",
"initial", "curve", "size"},
{"<"},
{"joint", "*", "17", "kind", "group", "stiffness", "damping", "armature",
@@ -2371,9 +2371,6 @@ void mjXReader::OneComposite(XMLElement* elem, mjsBody* body, mjsDefault* def) {
comp.uservert = std::move(uservert.value());
}
// shell
ReadAttrTxt(elem, "face", comp.userface);
// process curve string
std::istringstream iss(curves);
int i = 0;
@@ -348,7 +348,7 @@ void ABSL_ATTRIBUTE_NOINLINE mulMatVecSparse_8(mjtNum* res,
// ----------------------------- benchmark ------------------------------------
static void BM_MatVecSparse(benchmark::State& state, int unroll) {
static mjModel* m = LoadModelFromPath("plugin/elasticity/flag.xml");
static mjModel* m = LoadModelFromPath("plugin/elasticity/flag_flex.xml");
mjData* d = mj_makeData(m);
// warm-up rollout to get a typical state
+1 -1
View File
@@ -70,7 +70,7 @@ static void run_parse_benchmark(const std::string xml_path,
// run_parse_benchmark).
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_ParseFlagPlugin(benchmark::State& state) {
run_parse_benchmark(GetModelPath("plugin/elasticity/flag.xml"), state);
run_parse_benchmark(GetModelPath("plugin/elasticity/flag_flex.xml"), state);
}
BENCHMARK(BM_ParseFlagPlugin);
+1 -1
View File
@@ -74,7 +74,7 @@ static void run_step_benchmark(const mjModel* model, benchmark::State& state) {
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepFlagPlugin(benchmark::State& state) {
MujocoErrorTestGuard guard;
static mjModel* model = LoadModelFromPath("plugin/elasticity/flag.xml");
static mjModel* model = LoadModelFromPath("plugin/elasticity/flag_flex.xml");
run_step_benchmark(model, state);
}
BENCHMARK(BM_StepFlagPlugin);
+5 -3
View File
@@ -184,12 +184,13 @@ TEST_F(ElasticityTest, InvalidThickness) {
</extension>
<worldbody>
<composite type="particle" count="2 2 1" spacing="1">
<geom size=".025"/>
<flexcomp type="grid" count="2 2 1" spacing="1 1 1"
radius=".025" name="test" dim="2">
<plugin plugin="mujoco.elasticity.shell">
<config key="thickness" value="hello"/>
</plugin>
</composite>
<edge equality="false"/>
</flexcomp>
</worldbody>
</mujoco>
)";
@@ -197,6 +198,7 @@ TEST_F(ElasticityTest, InvalidThickness) {
char error[1024] = {0};
mjModel* m = LoadModelFromString(xml, error, sizeof(error));
ASSERT_THAT(m, testing::IsNull());
EXPECT_THAT(error, ::testing::HasSubstr("Invalid parameter"));
}
// -------------------------------- solid -----------------------------------