Update Solid and Shell plugins to use FlexComp.

PiperOrigin-RevId: 573755821
Change-Id: I3b8d7fb27f0e940038fa9fd2b26ecc746df4f7ac
This commit is contained in:
Alessio Quaglino
2023-10-16 03:02:14 -07:00
committed by Copybara-Service
parent 93d1c3c92e
commit 110ade1435
26 changed files with 1988 additions and 177 deletions
+16 -1
View File
@@ -3765,7 +3765,7 @@ Associate this composite with an :ref:`engine plugin<exPlugin>`. Either :at:`plu
.. _body-flexcomp-euler: .. _body-flexcomp-euler:
.. _body-flexcomp-selfcollide: .. _body-flexcomp-group:
.. _body-flexcomp-flatskin: .. _body-flexcomp-flatskin:
@@ -3820,6 +3820,15 @@ Associate this composite with an :ref:`engine plugin<exPlugin>`. Either :at:`plu
.. _flex-contact-gap: .. _flex-contact-gap:
.. _flexcomp-contact-gap: .. _flexcomp-contact-gap:
.. _flex-contact-internal:
.. _flexcomp-contact-internal:
.. _flex-contact-selfcollide:
.. _flexcomp-contact-selfcollide:
.. _flex-contact-activelayers:
.. _flexcomp-contact-activelayers:
.. _flexcomp-pin: .. _flexcomp-pin:
.. _flexcomp-pin-id: .. _flexcomp-pin-id:
@@ -3830,6 +3839,12 @@ Associate this composite with an :ref:`engine plugin<exPlugin>`. Either :at:`plu
.. _flexcomp-pin-gridrange: .. _flexcomp-pin-gridrange:
.. _flexcomp-plugin:
.. _flexcomp-plugin-plugin:
.. _flexcomp-plugin-instance:
.. _deformable: .. _deformable:
+27 -9
View File
@@ -485,19 +485,19 @@
| :ref:`flexcomp | \* | :class: mjcf-attributes | | :ref:`flexcomp | \* | :class: mjcf-attributes |
| <body-flexcomp>` | | | | <body-flexcomp>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`name<body-flexcomp-name>` | :ref:`class<body-flexcomp-class>` | :ref:`type<body-flexcomp-type>` | :ref:`dim<body-flexcomp-dim>` | | | | | | :ref:`name<body-flexcomp-name>` | :ref:`class<body-flexcomp-class>` | :ref:`type<body-flexcomp-type>` | :ref:`group<body-flexcomp-group>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`flatskin<body-flexcomp-flatskin>` | :ref:`count<body-flexcomp-count>` | :ref:`spacing<body-flexcomp-spacing>` | :ref:`radius<body-flexcomp-radius>` | | | | | | :ref:`dim<body-flexcomp-dim>` | :ref:`count<body-flexcomp-count>` | :ref:`spacing<body-flexcomp-spacing>` | :ref:`radius<body-flexcomp-radius>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`rigid<body-flexcomp-rigid>` | :ref:`mass<body-flexcomp-mass>` | :ref:`inertiabox<body-flexcomp-inertiabox>` | :ref:`scale<body-flexcomp-scale>` | | | | | | :ref:`rigid<body-flexcomp-rigid>` | :ref:`mass<body-flexcomp-mass>` | :ref:`inertiabox<body-flexcomp-inertiabox>` | :ref:`scale<body-flexcomp-scale>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`file<body-flexcomp-file>` | :ref:`point<body-flexcomp-point>` | :ref:`element<body-flexcomp-element>` | :ref:`texcoord<body-flexcomp-texcoord>` | | | | | | :ref:`file<body-flexcomp-file>` | :ref:`point<body-flexcomp-point>` | :ref:`element<body-flexcomp-element>` | :ref:`texcoord<body-flexcomp-texcoord>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`material<body-flexcomp-material>` | :ref:`rgba<body-flexcomp-rgba>` | :ref:`selfcollide<body-flexcomp-selfcollide>` | :ref:`flatskin<body-flexcomp-flatskin>` | | | | | | :ref:`material<body-flexcomp-material>` | :ref:`rgba<body-flexcomp-rgba>` | :ref:`flatskin<body-flexcomp-flatskin>` | :ref:`pos<body-flexcomp-pos>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`pos<body-flexcomp-pos>` | :ref:`quat<body-flexcomp-quat>` | :ref:`axisangle<body-flexcomp-axisangle>` | :ref:`xyaxes<body-flexcomp-xyaxes>` | | | | | | :ref:`quat<body-flexcomp-quat>` | :ref:`axisangle<body-flexcomp-axisangle>` | :ref:`xyaxes<body-flexcomp-xyaxes>` | :ref:`zaxis<body-flexcomp-zaxis>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`zaxis<body-flexcomp-zaxis>` | :ref:`euler<body-flexcomp-euler>` | | | | | | | | :ref:`euler<body-flexcomp-euler>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| flexcomp |br| |_2| |L| | | .. table:: | | |_2| flexcomp |br| |_2| |L| | | .. table:: |
@@ -517,7 +517,9 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`friction<flexcomp-contact-friction>` | :ref:`solmix<flexcomp-contact-solmix>` | :ref:`solref<flexcomp-contact-solref>` | :ref:`solimp<flexcomp-contact-solimp>` | | | | | | :ref:`friction<flexcomp-contact-friction>` | :ref:`solmix<flexcomp-contact-solmix>` | :ref:`solref<flexcomp-contact-solref>` | :ref:`solimp<flexcomp-contact-solimp>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`margin<flexcomp-contact-margin>` | :ref:`gap<flexcomp-contact-gap>` | | | | | | | | :ref:`margin<flexcomp-contact-margin>` | :ref:`gap<flexcomp-contact-gap>` | :ref:`internal<flexcomp-contact-internal>` | :ref:`selfcollide<flexcomp-contact-selfcollide>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`activelayers<flexcomp-contact-activelayers>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| flexcomp |br| |_2| |L| | | .. table:: | | |_2| flexcomp |br| |_2| |L| | | .. table:: |
@@ -527,6 +529,20 @@
| | | | :ref:`id<flexcomp-pin-id>` | :ref:`range<flexcomp-pin-range>` | :ref:`grid<flexcomp-pin-grid>` | :ref:`gridrange<flexcomp-pin-gridrange>` | | | | | | :ref:`id<flexcomp-pin-id>` | :ref:`range<flexcomp-pin-range>` | :ref:`grid<flexcomp-pin-grid>` | :ref:`gridrange<flexcomp-pin-gridrange>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| flexcomp |br| |_2| |L| | | .. table:: |
| :ref:`plugin | \* | :class: mjcf-attributes |
| <flexcomp-plugin>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`plugin<flexcomp-plugin-plugin>` | :ref:`instance<flexcomp-plugin-instance>` | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_3| plugin |br| |_3| |L| | | .. table:: |
| :ref:`config | \* | :class: mjcf-attributes |
| <plugin-config>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`key<plugin-config-key>` | :ref:`value<plugin-config-value>` | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mujoco |br| |L| | | *no attributes* | | mujoco |br| |L| | | *no attributes* |
| :ref:`deformable<deformable>` | | | | :ref:`deformable<deformable>` | | |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -536,9 +552,9 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`name<deformable-flex-name>` | :ref:`group<deformable-flex-group>` | :ref:`dim<deformable-flex-dim>` | :ref:`radius<deformable-flex-radius>` | | | | | | :ref:`name<deformable-flex-name>` | :ref:`group<deformable-flex-group>` | :ref:`dim<deformable-flex-dim>` | :ref:`radius<deformable-flex-radius>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`material<deformable-flex-material>` | :ref:`rgba<deformable-flex-rgba>` | :ref:`flatskin<deformable-flex-flatskin>` | :ref:`selfcollide<deformable-flex-selfcollide>` | | | | | | :ref:`material<deformable-flex-material>` | :ref:`rgba<deformable-flex-rgba>` | :ref:`flatskin<deformable-flex-flatskin>` | :ref:`body<deformable-flex-body>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`body<deformable-flex-body>` | :ref:`vertex<deformable-flex-vertex>` | :ref:`element<deformable-flex-element>` | :ref:`texcoord<deformable-flex-texcoord>` | | | | | | :ref:`vertex<deformable-flex-vertex>` | :ref:`element<deformable-flex-element>` | :ref:`texcoord<deformable-flex-texcoord>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| flex |br| |_2| |L| | | .. table:: | | |_2| flex |br| |_2| |L| | | .. table:: |
@@ -549,7 +565,9 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`friction<flex-contact-friction>` | :ref:`solmix<flex-contact-solmix>` | :ref:`solref<flex-contact-solref>` | :ref:`solimp<flex-contact-solimp>` | | | | | | :ref:`friction<flex-contact-friction>` | :ref:`solmix<flex-contact-solmix>` | :ref:`solref<flex-contact-solref>` | :ref:`solimp<flex-contact-solimp>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`margin<flex-contact-margin>` | :ref:`gap<flex-contact-gap>` | | | | | | | | :ref:`margin<flex-contact-margin>` | :ref:`gap<flex-contact-gap>` | :ref:`internal<flex-contact-internal>` | :ref:`selfcollide<flex-contact-selfcollide>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`activelayers<flex-contact-activelayers>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_2| flex |br| |_2| |L| | | .. table:: | | |_2| flex |br| |_2| |L| | | .. table:: |
-1
View File
@@ -39,7 +39,6 @@
<geom type="ellipsoid" size="0.025 0.01 0.025" rgba=".8 .2 .1 1" group="4"/> <geom type="ellipsoid" size="0.025 0.01 0.025" rgba=".8 .2 .1 1" group="4"/>
<plugin plugin="mujoco.elasticity.shell"> <plugin plugin="mujoco.elasticity.shell">
<config key="poisson" value="0"/> <config key="poisson" value="0"/>
<config key="damping" value="0.001"/>
<config key="thickness" value="1e-2"/> <config key="thickness" value="1e-2"/>
<!--Units are in Pa (SI)--> <!--Units are in Pa (SI)-->
<config key="young" value="3e6"/> <config key="young" value="3e6"/>
+54
View File
@@ -0,0 +1,54 @@
<!-- 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 name="pin" pos="0 0 1.5">
<flexcomp type="grid" count="9 19 1" spacing=".05 .05 .05" mass="10"
name="flag" radius="0.001">
<edge equality="true" damping="0.001"/>
<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>
</flexcomp>
</body>
</worldbody>
<equality>
<connect body1="flag_0" anchor="0 0 0"/>
</equality>
</mujoco>
+54
View File
@@ -0,0 +1,54 @@
<!-- 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="CG" tolerance="1e-6" timestep=".001" integrator="implicitfast"/>
<size memory="100M"/>
<visual>
<map stiffness="100"/>
</visual>
<worldbody>
<flexcomp type="grid" count="24 4 4" spacing=".1 .1 .1" pos=".1 0 1.5"
radius=".0" rgba="0 .7 .7 1" name="softbody" dim="3" mass="7">
<contact condim="3" solref="0.01 1" solimp=".95 .99 .0001" selfcollide="none"/>
<edge damping="1"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0.2"/>
<!--Units are in Pa (SI)-->
<config key="young" value="5e4"/>
</plugin>
</flexcomp>
<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
@@ -0,0 +1,56 @@
<!-- 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" integrator="implicitfast"/>
<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"/>
<flexcomp type="grid" count="8 8 8" spacing=".07 .07 .07" pos="0 0 1" dim="3"
radius=".005" rgba="0 .7 .7 1" mass="5" name="softbody">
<edge damping="1"/>
<contact selfcollide="none"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0"/>
<!--Units are in Pa (SI)-->
<config key="young" value="5e4"/>
</plugin>
</flexcomp>
</worldbody>
</mujoco>
-1
View File
@@ -44,7 +44,6 @@
<skin inflate="0.0001" rgba=".4 0 .3 1" subgrid="1"/> <skin inflate="0.0001" rgba=".4 0 .3 1" subgrid="1"/>
<plugin plugin="mujoco.elasticity.shell"> <plugin plugin="mujoco.elasticity.shell">
<config key="poisson" value="0"/> <config key="poisson" value="0"/>
<config key="damping" value="0.001"/>
<config key="thickness" value="1e-2"/> <config key="thickness" value="1e-2"/>
<!--Units are in Pa (SI)--> <!--Units are in Pa (SI)-->
<config key="young" value="3e7"/> <config key="young" value="3e7"/>
+53
View File
@@ -0,0 +1,53 @@
<!-- 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" integrator="implicitfast"/>
<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>
<flexcomp type="grid" count="16 16 1" spacing=".05 .05 .05" pos="0 0 1"
radius=".001" mass="100" name="plate">
<contact condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
<edge equality="true" damping="0.001"/>
<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>
</flexcomp>
</worldbody>
</mujoco>
-1
View File
@@ -1407,7 +1407,6 @@
<skin inflate="0.001" rgba=".4 0 .3 1"/> <skin inflate="0.001" rgba=".4 0 .3 1"/>
<plugin plugin="mujoco.elasticity.shell"> <plugin plugin="mujoco.elasticity.shell">
<config key="poisson" value="0"/> <config key="poisson" value="0"/>
<config key="damping" value="0.001"/>
<config key="thickness" value="8e-3"/> <config key="thickness" value="8e-3"/>
<!--Units are in Pa (SI)--> <!--Units are in Pa (SI)-->
<config key="young" value="3e7"/> <config key="young" value="3e7"/>
File diff suppressed because it is too large Load Diff
+70
View File
@@ -0,0 +1,70 @@
<!-- 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" integrator="implicitfast"/>
<size memory="10M"/>
<visual>
<map stiffness="100"/>
</visual>
<worldbody>
<flexcomp name="A" type="grid" count="4 4 4" spacing=".2 .2 .2" pos="0 0 .5"
radius=".005" rgba="0 .7 .7 1" dim="3" mass="5">
<contact condim="3" solref="0.01 1" solimp=".95 .99 .0001" selfcollide="none"/>
<edge damping="1"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0.4"/>
<!--Units are in Pa (SI)-->
<config key="young" value="1e4"/>
</plugin>
</flexcomp>
<flexcomp name="B" type="grid" count="4 4 4" spacing=".2 .2 .2" pos="1 0 .5"
radius=".005" rgba="0 .7 .7 1" dim="3" mass="5">
<contact condim="3" solref="0.01 1" solimp=".95 .99 .0001" selfcollide="none"/>
<edge damping="1"/>
<plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0"/>
<!--Units are in Pa (SI)-->
<config key="young" value="5e4"/>
</plugin>
</flexcomp>
<body>
<joint name="soft" type="slide" axis="0 0 1" damping="500"/>
<geom type="box" size=".35 .35 0.05" pos=".1 .1 1" 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 1" 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>
-16
View File
@@ -18,7 +18,6 @@
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <utility>
#include <vector> #include <vector>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
@@ -47,19 +46,4 @@ bool CheckAttr(const char* name, const mjModel* m, int instance) {
return end == value.data() + value.size(); return end == value.data() + value.size();
} }
mjtNum SquaredDist3(const mjtNum pos1[3], const mjtNum pos2[3]) {
mjtNum dif[3] = {pos1[0]-pos2[0], pos1[1]-pos2[1], pos1[2]-pos2[2]};
return dif[0]*dif[0] + dif[1]*dif[1] + dif[2]*dif[2];
}
void UpdateSquaredLengths(std::vector<mjtNum>& len,
const std::vector<std::pair<int, int> >& edges,
const mjtNum* x) {
for (int e = 0; e < len.size(); e++) {
const mjtNum* p0 = x + 3*edges[e].first;
const mjtNum* p1 = x + 3*edges[e].second;
len[e] = SquaredDist3(p0, p1);
}
}
} // namespace mujoco::plugin::elasticity } // namespace mujoco::plugin::elasticity
+15 -8
View File
@@ -31,20 +31,27 @@ struct PairHash
} }
}; };
inline mjtNum SquaredDist3(const mjtNum pos1[3], const mjtNum pos2[3]) {
mjtNum dif[3] = {pos1[0]-pos2[0], pos1[1]-pos2[1], pos1[2]-pos2[2]};
return dif[0]*dif[0] + dif[1]*dif[1] + dif[2]*dif[2];
}
inline void UpdateSquaredLengths(std::vector<mjtNum>& len,
const std::vector<std::pair<int, int> >& edges,
const mjtNum* x) {
for (int e = 0; e < len.size(); e++) {
const mjtNum* p0 = x + 3*edges[e].first;
const mjtNum* p1 = x + 3*edges[e].second;
len[e] = SquaredDist3(p0, p1);
}
}
// copied from mjXUtil // copied from mjXUtil
void String2Vector(const std::string& txt, std::vector<int>& vec); void String2Vector(const std::string& txt, std::vector<int>& vec);
// reads numeric attributes // reads numeric attributes
bool CheckAttr(const char* name, const mjModel* m, int instance); bool CheckAttr(const char* name, const mjModel* m, int instance);
// Cartesian distance between 3D vectors
mjtNum SquaredDist3(const mjtNum pos1[3], const mjtNum pos2[3]);
// updates square lengths of edges
void UpdateSquaredLengths(std::vector<mjtNum>& len,
const std::vector<std::pair<int, int> >& edges,
const mjtNum* x);
} // namespace mujoco::plugin::elasticity } // namespace mujoco::plugin::elasticity
#endif // MUJOCO_PLUGIN_ELASTICITY_ELASTICITY_H_ #endif // MUJOCO_PLUGIN_ELASTICITY_ELASTICITY_H_
+21 -55
View File
@@ -13,13 +13,10 @@
// limitations under the License. // limitations under the License.
#include <algorithm> #include <algorithm>
#include <cctype> #include <cassert>
#include <cmath> #include <cmath>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <functional>
#include <sstream>
#include <optional> #include <optional>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
@@ -29,6 +26,7 @@
#include <mujoco/mjplugin.h> #include <mujoco/mjplugin.h>
#include <mujoco/mjtnum.h> #include <mujoco/mjtnum.h>
#include <mujoco/mujoco.h> #include <mujoco/mujoco.h>
#include "elasticity.h"
#include "shell.h" #include "shell.h"
@@ -40,22 +38,6 @@ constexpr int kNumEdges = Stencil2D::kNumEdges;
constexpr int kNumVerts = Stencil2D::kNumVerts; constexpr int kNumVerts = Stencil2D::kNumVerts;
constexpr int edge[kNumEdges][2] = {{1, 2}, {2, 0}, {0, 1}}; constexpr int edge[kNumEdges][2] = {{1, 2}, {2, 0}, {0, 1}};
// copied from void mjXUtil
void String2Vector(const std::string& txt, std::vector<int>& vec) {
std::stringstream strm(txt);
vec.clear();
while (!strm.eof()) {
int num;
strm >> num;
if (strm.fail()) {
break;
} else {
vec.push_back(num);
}
}
}
// cotangent between two edges // cotangent between two edges
mjtNum cot(mjtNum* x, int v0, int v1, int v2) { mjtNum cot(mjtNum* x, int v0, int v1, int v2) {
mjtNum normal[3]; mjtNum normal[3];
@@ -82,28 +64,12 @@ mjtNum ComputeVolume(const mjtNum* x, const int v[kNumVerts]) {
return mju_norm3(normal) / 2; return mju_norm3(normal) / 2;
} }
// reads numeric attributes
bool CheckAttr(const char* name, const mjModel* m, int instance) {
char* end;
std::string value = mj_getPluginConfig(m, instance, name);
value.erase(std::remove_if(value.begin(), value.end(), isspace), value.end());
strtod(value.c_str(), &end);
return end == value.data() + value.size();
}
struct PairHash
{
template <class T1, class T2>
std::size_t operator() (const std::pair<T1, T2>& pair) const {
return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);
}
};
} // namespace } // namespace
// factory function // factory function
std::optional<Shell> Shell::Create(const mjModel* m, mjData* d, int instance) { std::optional<Shell> Shell::Create(const mjModel* m, mjData* d, int instance) {
if (CheckAttr("face", m, instance) && if (CheckAttr("face", m, instance) &&
CheckAttr("edge", m, instance) &&
CheckAttr("poisson", m, instance) && CheckAttr("poisson", m, instance) &&
CheckAttr("young", m, instance) && CheckAttr("young", m, instance) &&
CheckAttr("thickness", m, instance)) { CheckAttr("thickness", m, instance)) {
@@ -111,11 +77,10 @@ std::optional<Shell> Shell::Create(const mjModel* m, mjData* d, int instance) {
mjtNum E = strtod(mj_getPluginConfig(m, instance, "young"), nullptr); mjtNum E = strtod(mj_getPluginConfig(m, instance, "young"), nullptr);
mjtNum thick = mjtNum thick =
strtod(mj_getPluginConfig(m, instance, "thickness"), nullptr); strtod(mj_getPluginConfig(m, instance, "thickness"), nullptr);
mjtNum damp = std::vector<int> face, edge;
strtod(mj_getPluginConfig(m, instance, "damping"), nullptr);
std::vector<int> face;
String2Vector(mj_getPluginConfig(m, instance, "face"), face); String2Vector(mj_getPluginConfig(m, instance, "face"), face);
return Shell(m, d, instance, nu, E, damp, thick, face); String2Vector(mj_getPluginConfig(m, instance, "edge"), edge);
return Shell(m, d, instance, nu, E, thick, face, edge);
} else { } else {
mju_warning("Invalid parameter specification in shell plugin"); mju_warning("Invalid parameter specification in shell plugin");
return std::nullopt; return std::nullopt;
@@ -123,13 +88,14 @@ std::optional<Shell> Shell::Create(const mjModel* m, mjData* d, int instance) {
} }
// create map from triangles to vertices and edges and from edges to vertices // create map from triangles to vertices and edges and from edges to vertices
void Shell::CreateStencils(const std::vector<int>& face) { void Shell::CreateStencils(const std::vector<int>& simplex,
const std::vector<int>& edgeidx) {
// populate stencil // populate stencil
nt = face.size() / kNumVerts; nt = simplex.size() / kNumVerts;
elements.resize(nt); elements.resize(nt);
for (int t = 0; t < nt; t++) { for (int t = 0; t < nt; t++) {
for (int v = 0; v < kNumVerts; v++) { for (int v = 0; v < kNumVerts; v++) {
elements[t].vertices[v] = face[kNumVerts*t+v]-1; elements[t].vertices[v] = simplex[kNumVerts*t+v];
} }
} }
@@ -162,14 +128,19 @@ void Shell::CreateStencils(const std::vector<int>& face) {
elements[t].edges[e] = it->second; elements[t].edges[e] = it->second;
flaps[it->second].vertices[3] = v[(edge[e][1]+1) % 3]; flaps[it->second].vertices[3] = v[(edge[e][1]+1) % 3];
} }
if (!edgeidx.empty()) {
assert(elements[t].edges[e] == edgeidx[kNumEdges*t+e]);
}
} }
} }
} }
// plugin constructor // plugin constructor
Shell::Shell(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E, Shell::Shell(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
mjtNum damp, mjtNum thick, const std::vector<int>& face) mjtNum thick, const std::vector<int>& face,
: damping(damp), thickness(thick) { const std::vector<int>& edgeidx)
: thickness(thick) {
// count plugin bodies // count plugin bodies
nv = ne = 0; nv = ne = 0;
for (int i = 1; i < m->nbody; i++) { for (int i = 1; i < m->nbody; i++) {
@@ -181,7 +152,7 @@ Shell::Shell(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
} }
// generate triangles from the vertices // generate triangles from the vertices
CreateStencils(face); CreateStencils(face, edgeidx);
// material parameters // material parameters
mjtNum mu = E / (2*(1+nu)); mjtNum mu = E / (2*(1+nu));
@@ -234,10 +205,6 @@ Shell::Shell(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
} }
void Shell::Compute(const mjModel* m, mjData* d, int instance) { void Shell::Compute(const mjModel* m, mjData* d, int instance) {
mjtNum kD = damping / m->opt.timestep;
// compute bending contribution
mjtNum embedding;
for (int e = 0; e < ne; e++) { for (int e = 0; e < ne; e++) {
int* v = flaps[e].vertices; int* v = flaps[e].vertices;
mjtNum force[12] = {0}; mjtNum force[12] = {0};
@@ -248,8 +215,7 @@ void Shell::Compute(const mjModel* m, mjData* d, int instance) {
for (int i = 0; i < StencilFlap::kNumVerts; i++) { for (int i = 0; i < StencilFlap::kNumVerts; i++) {
for (int j = 0; j < StencilFlap::kNumVerts; j++) { for (int j = 0; j < StencilFlap::kNumVerts; j++) {
for (int x = 0; x < 3; x++) { for (int x = 0; x < 3; x++) {
embedding = d->xpos[3*(i0+v[j])+x]*(kD+1) - position[3*v[j]+x]*kD; force[3*i+x] += bending[16*e+4*i+j] * d->xpos[3*(i0+v[j])+x];
force[3*i+x] += bending[16*e+4*i+j] * embedding;
} }
} }
} }
@@ -275,8 +241,8 @@ void Shell::RegisterPlugin() {
plugin.name = "mujoco.elasticity.shell"; plugin.name = "mujoco.elasticity.shell";
plugin.capabilityflags |= mjPLUGIN_PASSIVE; plugin.capabilityflags |= mjPLUGIN_PASSIVE;
const char* attributes[] = {"face", "young", "poisson", "damping", const char* attributes[] = {"face", "edge", "young",
"thickness"}; "poisson", "thickness"};
plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]); plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]);
plugin.attributes = attributes; plugin.attributes = attributes;
plugin.nstate = +[](const mjModel* m, int instance) { return 0; }; plugin.nstate = +[](const mjModel* m, int instance) { return 0; };
+4 -3
View File
@@ -64,14 +64,15 @@ class Shell {
std::vector<mjtNum> position; // previous-step positions (nv x 3) std::vector<mjtNum> position; // previous-step positions (nv x 3)
std::vector<mjtNum> bending; // bending Hessian (ne x 16) std::vector<mjtNum> bending; // bending Hessian (ne x 16)
mjtNum damping;
mjtNum thickness; mjtNum thickness;
private: private:
Shell(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E, Shell(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
mjtNum damp, mjtNum thick, const std::vector<int>& face); mjtNum thick, const std::vector<int>& face,
const std::vector<int>& edgeidx);
void CreateStencils(const std::vector<int>& face); void CreateStencils(const std::vector<int>& simplex,
const std::vector<int>& edgeidx);
}; };
} // namespace mujoco::plugin::elasticity } // namespace mujoco::plugin::elasticity
+43 -14
View File
@@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
#include <algorithm> #include <algorithm>
#include <cassert>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <optional> #include <optional>
@@ -100,15 +101,17 @@ void GradSquaredLengths(mjtNum gradient[kNumEdges][2][3],
// factory function // factory function
std::optional<Solid> Solid::Create(const mjModel* m, mjData* d, int instance) { std::optional<Solid> Solid::Create(const mjModel* m, mjData* d, int instance) {
if (CheckAttr("face", m, instance) && if (CheckAttr("face", m, instance) &&
CheckAttr("edge", m, instance) &&
CheckAttr("poisson", m, instance) && CheckAttr("poisson", m, instance) &&
CheckAttr("young", m, instance)) { CheckAttr("young", m, instance)) {
mjtNum nu = strtod(mj_getPluginConfig(m, instance, "poisson"), nullptr); mjtNum nu = strtod(mj_getPluginConfig(m, instance, "poisson"), nullptr);
mjtNum E = strtod(mj_getPluginConfig(m, instance, "young"), nullptr); mjtNum E = strtod(mj_getPluginConfig(m, instance, "young"), nullptr);
mjtNum damp = mjtNum damp =
strtod(mj_getPluginConfig(m, instance, "damping"), nullptr); strtod(mj_getPluginConfig(m, instance, "damping"), nullptr);
std::vector<int> face; std::vector<int> face, edge;
String2Vector(mj_getPluginConfig(m, instance, "face"), face); String2Vector(mj_getPluginConfig(m, instance, "face"), face);
return Solid(m, d, instance, nu, E, damp, face); String2Vector(mj_getPluginConfig(m, instance, "edge"), edge);
return Solid(m, d, instance, nu, E, damp, face, edge);
} else { } else {
mju_warning("Invalid parameter specification in solid plugin"); mju_warning("Invalid parameter specification in solid plugin");
return std::nullopt; return std::nullopt;
@@ -116,13 +119,14 @@ std::optional<Solid> Solid::Create(const mjModel* m, mjData* d, int instance) {
} }
// create map from tetrahedra to vertices and edges and from edges to vertices // create map from tetrahedra to vertices and edges and from edges to vertices
void Solid::CreateStencils(const std::vector<int>& simplex) { void Solid::CreateStencils(const std::vector<int>& simplex,
const std::vector<int>& edgeidx) {
// populate stencil // populate stencil
nt = simplex.size() / kNumVerts; nt = simplex.size() / kNumVerts;
elements.resize(nt); elements.resize(nt);
for (int t = 0; t < nt; t++) { for (int t = 0; t < nt; t++) {
for (int v = 0; v < kNumVerts; v++) { for (int v = 0; v < kNumVerts; v++) {
elements[t].vertices[v] = simplex[kNumVerts*t+v]-1; elements[t].vertices[v] = simplex[kNumVerts*t+v];
} }
} }
@@ -149,14 +153,19 @@ void Solid::CreateStencils(const std::vector<int>& simplex) {
} else { } else {
elements[t].edges[e] = it->second; elements[t].edges[e] = it->second;
} }
if (!edgeidx.empty()) {
assert(elements[t].edges[e] == edgeidx[kNumEdges*t+e]);
}
} }
} }
} }
// plugin constructor // plugin constructor
Solid::Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E, Solid::Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
mjtNum damp, const std::vector<int>& simplex) mjtNum damp, const std::vector<int>& simplex,
: damping(damp) { const std::vector<int>& edgeidx)
: f0(-1), damping(damp) {
// count plugin bodies // count plugin bodies
nv = ne = 0; nv = ne = 0;
for (int i = 1; i < m->nbody; i++) { for (int i = 1; i < m->nbody; i++) {
@@ -167,8 +176,16 @@ Solid::Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
} }
} }
// count flexes
for (int i = 0; i < m->nflex; i++) {
if (m->flex_vertbodyid[m->flex_vertadr[i]] == i0) {
f0 = i;
break;
}
}
// generate tetrahedra from the vertices // generate tetrahedra from the vertices
CreateStencils(simplex); CreateStencils(simplex, edgeidx);
// allocate arrays // allocate arrays
metric.assign(kNumEdges*kNumEdges*nt, 0); metric.assign(kNumEdges*kNumEdges*nt, 0);
@@ -238,7 +255,10 @@ Solid::Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
} }
void Solid::Compute(const mjModel* m, mjData* d, int instance) { void Solid::Compute(const mjModel* m, mjData* d, int instance) {
UpdateSquaredLengths(deformed, edges, d->xpos+3*i0); // update edges if no flex
if (f0 < 0) {
UpdateSquaredLengths(deformed, edges, d->xpos+3*i0);
}
// loop over all elements // loop over all elements
for (int t = 0; t < nt; t++) { for (int t = 0; t < nt; t++) {
@@ -254,11 +274,18 @@ void Solid::Compute(const mjModel* m, mjData* d, int instance) {
// compute elongation // compute elongation
mjtNum elongation[kNumEdges]; mjtNum elongation[kNumEdges];
mjtNum kD = damping / m->opt.timestep;
for (int e = 0; e < kNumEdges; e++) { for (int e = 0; e < kNumEdges; e++) {
int idx = elements[t].edges[e]; if (f0 < 0) {
elongation[e] = deformed[idx] - reference[idx] + int idx = elements[t].edges[e];
( deformed[idx] - previous[idx] ) * kD; mjtNum kD = damping / m->opt.timestep;
elongation[e] = deformed[idx] - reference[idx] +
( deformed[idx] - previous[idx] ) * kD;
} else {
int idx = elements[t].edges[e] + m->flex_edgeadr[f0];
mjtNum deformed = d->flexedge_length[idx]*d->flexedge_length[idx];
mjtNum reference = m->flexedge_length0[idx]*m->flexedge_length0[idx];
elongation[e] = deformed - reference;
}
} }
// we now multiply the elongations by the precomputed metric tensor, // we now multiply the elongations by the precomputed metric tensor,
@@ -289,7 +316,9 @@ void Solid::Compute(const mjModel* m, mjData* d, int instance) {
} }
// update stored lengths // update stored lengths
previous = deformed; if (f0 < 0) {
previous = deformed;
}
} }
@@ -301,7 +330,7 @@ void Solid::RegisterPlugin() {
plugin.name = "mujoco.elasticity.solid"; plugin.name = "mujoco.elasticity.solid";
plugin.capabilityflags |= mjPLUGIN_PASSIVE; plugin.capabilityflags |= mjPLUGIN_PASSIVE;
const char* attributes[] = {"face", "young", "poisson", "damping"}; const char* attributes[] = {"face", "edge", "young", "poisson", "damping"};
plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]); plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]);
plugin.attributes = attributes; plugin.attributes = attributes;
plugin.nstate = +[](const mjModel* m, int instance) { return 0; }; plugin.nstate = +[](const mjModel* m, int instance) { return 0; };
+5 -2
View File
@@ -44,6 +44,7 @@ class Solid {
static void RegisterPlugin(); static void RegisterPlugin();
int f0; // index of corresponding flex
int i0; // index of first body int i0; // index of first body
int nc; // number of cubes in the grid int nc; // number of cubes in the grid
int nv; // number of vertices (bodies) in the solid int nv; // number of vertices (bodies) in the solid
@@ -64,9 +65,11 @@ class Solid {
private: private:
Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E, Solid(const mjModel* m, mjData* d, int instance, mjtNum nu, mjtNum E,
mjtNum damp, const std::vector<int>& simplex); mjtNum damp, const std::vector<int>& simplex,
const std::vector<int>& edgeidx);
void CreateStencils(const std::vector<int>& simplex); void CreateStencils(const std::vector<int>& simplex,
const std::vector<int>& edgeidx);
}; };
} // namespace mujoco::plugin::elasticity } // namespace mujoco::plugin::elasticity
+6
View File
@@ -1814,6 +1814,8 @@ void mj_collideFlexSAP(const mjModel* m, mjData* d, int f) {
// test a geom and an elem for collision, add to contact list // test a geom and an elem for collision, add to contact list
void mj_collideGeomElem(const mjModel* m, mjData* d, int g, int f, int e) { void mj_collideGeomElem(const mjModel* m, mjData* d, int g, int f, int e) {
TM_START;
mjtNum margin = mj_assignMargin(m, mju_max(m->geom_margin[g], m->flex_margin[f])); mjtNum margin = mj_assignMargin(m, mju_max(m->geom_margin[g], m->flex_margin[f]));
int dim = m->flex_dim[f], type = m->geom_type[g]; int dim = m->flex_dim[f], type = m->geom_type[g];
int num; int num;
@@ -1927,6 +1929,9 @@ void mj_collideGeomElem(const mjModel* m, mjData* d, int g, int f, int e) {
// move arena pointer back to the end of the contact array // move arena pointer back to the end of the contact array
resetArena(d); resetArena(d);
// add duration without incrementing counter
TM_ADD(mjTIMER_COL_NARROW);
} }
@@ -1934,6 +1939,7 @@ void mj_collideGeomElem(const mjModel* m, mjData* d, int g, int f, int e) {
// test two elems for collision, add to contact list // test two elems for collision, add to contact list
void mj_collideElems(const mjModel* m, mjData* d, int f1, int e1, int f2, int e2) { void mj_collideElems(const mjModel* m, mjData* d, int f1, int e1, int f2, int e2) {
TM_START; TM_START;
mjtNum margin = mj_assignMargin(m, mju_max(m->flex_margin[f1], m->flex_margin[f2])); mjtNum margin = mj_assignMargin(m, mju_max(m->flex_margin[f1], m->flex_margin[f2]));
int dim1 = m->flex_dim[f1], dim2 = m->flex_dim[f2]; int dim1 = m->flex_dim[f1], dim2 = m->flex_dim[f2];
int num; int num;
+1 -3
View File
@@ -537,9 +537,7 @@ void mj_flex(const mjModel* m, mjData* d) {
// compute lengths and Jacobians of edges // compute lengths and Jacobians of edges
for (int f=0; f < m->nflex; f++) { for (int f=0; f < m->nflex; f++) {
// skip if edges cannot generate forces // skip if edges cannot generate forces
if (m->flex_rigid[f] || if (m->flex_rigid[f]) {
(m->flex_edgeequality[f] == 0 &&
m->flex_edgestiffness[f] == 0 && m->flex_edgedamping[f] == 0)) {
continue; continue;
} }
+2 -2
View File
@@ -948,11 +948,11 @@ void mj_energyPos(const mjModel* m, mjData* d) {
} }
} }
// add flex-level springs // add flex-level springs for dim=1 (dim>1 requires plugins)
if (!mjDISABLED(mjDSBL_PASSIVE)) { if (!mjDISABLED(mjDSBL_PASSIVE)) {
for (int i=0; i < m->nflex; i++) { for (int i=0; i < m->nflex; i++) {
stiffness = m->flex_edgestiffness[i]; stiffness = m->flex_edgestiffness[i];
if (m->flex_rigid[i] || stiffness == 0) { if (m->flex_rigid[i] || stiffness == 0 || m->flex_dim[i] > 1) {
continue; continue;
} }
+13 -10
View File
@@ -370,7 +370,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
}; };
for (int s = 0; s < 6; s++) { for (int s = 0; s < 6; s++) {
for (int v = 0; v < 4; v++) { for (int v = 0; v < 4; v++) {
face.push_back(vert[cube2tets[s][v]]+1); face.push_back(vert[cube2tets[s][v]]);
} }
} }
} }
@@ -388,7 +388,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
}; };
for (int s = 0; s < 2; s++) { for (int s = 0; s < 2; s++) {
for (int v = 0; v < 3; v++) { for (int v = 0; v < 3; v++) {
face.push_back(vert[quad2tri[s][v]]+1); face.push_back(vert[quad2tri[s][v]]);
} }
} }
} }
@@ -398,6 +398,8 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
} else { } else {
dim = 2; // can only load a surface for now dim = 2; // can only load a surface for now
mjXUtil::String2Vector(userface, face); mjXUtil::String2Vector(userface, face);
for (int i=0; i<face.size(); face[i++]--) {};
mjXUtil::Vector2String(userface, face);
} }
// compute volume // compute volume
@@ -414,13 +416,13 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
mjtNum edge2[3]; mjtNum edge2[3];
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
edge1[i] = uservert[3*(face[3*j+1]-1)+i] - uservert[3*(face[3*j]-1)+i]; edge1[i] = uservert[3*face[3*j+1]+i] - uservert[3*face[3*j]+i];
edge2[i] = uservert[3*(face[3*j+2]-1)+i] - uservert[3*(face[3*j]-1)+i]; edge2[i] = uservert[3*face[3*j+2]+i] - uservert[3*face[3*j]+i];
} }
mjuu_crossvec(area, edge1, edge2); mjuu_crossvec(area, edge1, edge2);
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
volume[face[3*j+i]-1] += sqrt(mjuu_dot3(area, area)) / 2 * t; volume[face[3*j+i]] += sqrt(mjuu_dot3(area, area)) / 2 * t;
} }
} }
} else { } else {
@@ -489,6 +491,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
} }
b->plugin_instance->config_attribs["face"] = userface; b->plugin_instance->config_attribs["face"] = userface;
b->plugin_instance->config_attribs["edge"] = "";
// update density // update density
if (dim == 2) { if (dim == 2) {
@@ -505,8 +508,8 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
// create edges // create edges
for (int i=0; i<face.size()/3; i++) { for (int i=0; i<face.size()/3; i++) {
for (int j=0; j<3; j++) { for (int j=0; j<3; j++) {
int v0 = face[3*i+(j+0)%3]-1; int v0 = face[3*i+(j+0)%3];
int v1 = face[3*i+(j+1)%3]-1; int v1 = face[3*i+(j+1)%3];
edge.push_back(v0 < v1 ? std::pair(v0, v1) : std::pair(v1, v0)); edge.push_back(v0 < v1 ? std::pair(v0, v1) : std::pair(v1, v0));
} }
} }
@@ -1271,9 +1274,9 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
} }
for (int i=0; i<face.size()/3; i++) { for (int i=0; i<face.size()/3; i++) {
skin->face.push_back(j*nvert+face[3*i]-1); skin->face.push_back(j*nvert+face[3*i]);
skin->face.push_back(j*nvert+face[3*i+(j==0 ? 1 : 2)]-1); skin->face.push_back(j*nvert+face[3*i+(j==0 ? 1 : 2)]);
skin->face.push_back(j*nvert+face[3*i+(j==0 ? 2 : 1)]-1); skin->face.push_back(j*nvert+face[3*i+(j==0 ? 2 : 1)]);
} }
} }
+10 -1
View File
@@ -65,11 +65,12 @@ mjCFlexcomp::mjCFlexcomp(void) {
mjuu_setvec(scale, 1, 1, 1); mjuu_setvec(scale, 1, 1, 1);
mass = 1; mass = 1;
inertiabox = 0.005; inertiabox = 0.005;
equality = true; equality = false;
mjuu_setvec(pos, 0, 0, 0); mjuu_setvec(pos, 0, 0, 0);
mjuu_setvec(quat, 1, 0, 0, 0); mjuu_setvec(quat, 1, 0, 0, 0);
rigid = false; rigid = false;
centered = false; centered = false;
plugin_instance = nullptr;
} }
@@ -453,6 +454,14 @@ bool mjCFlexcomp::Make(mjCModel* model, mjCBody* body, char* error, int error_sz
pf->vert[3*i+1] = 0; pf->vert[3*i+1] = 0;
pf->vert[3*i+2] = 0; pf->vert[3*i+2] = 0;
} }
// add plugin
if (plugin_instance) {
pb->is_plugin = true;
pb->plugin_name = plugin_name;
pb->plugin_instance = plugin_instance;
pb->plugin_instance_name = plugin_instance_name;
}
} }
} }
+6
View File
@@ -85,6 +85,12 @@ class mjCFlexcomp {
std::vector<bool> used; // is point used by any element (false: skip) std::vector<bool> used; // is point used by any element (false: skip)
std::vector<int> element; // flex elements std::vector<int> element; // flex elements
std::vector<float> texcoord; // vertex texture coordinates std::vector<float> texcoord; // vertex texture coordinates
// plugin support
bool is_plugin;
std::string plugin_name;
std::string plugin_instance_name;
mjCPlugin* plugin_instance;
}; };
#endif // MUJOCO_SRC_USER_USER_FLEXCOMP_H_ #endif // MUJOCO_SRC_USER_USER_FLEXCOMP_H_
+59 -31
View File
@@ -18,9 +18,11 @@
#include <cstddef> #include <cstddef>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <functional>
#include <memory> #include <memory>
#include <optional> #include <optional>
#include <string> #include <string>
#include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -59,6 +61,7 @@
#include "user/user_model.h" #include "user/user_model.h"
#include "user/user_objects.h" #include "user/user_objects.h"
#include "user/user_util.h" #include "user/user_util.h"
#include "xml/xml_util.h"
#include <tiny_obj_loader.h> #include <tiny_obj_loader.h>
extern "C" { extern "C" {
@@ -2157,6 +2160,24 @@ void mjCSkin::LoadSKN(mjResource* resource) {
//------------------ class mjCFlex implementation -------------------------------------------------- //------------------ class mjCFlex implementation --------------------------------------------------
// hash function for std::pair
struct PairHash
{
template <class T1, class T2>
std::size_t operator() (const std::pair<T1, T2>& pair) const {
return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);
}
};
// simplex connectivity
constexpr int kNumEdges[3] = {1, 3, 6};
constexpr int eledge[3][6][2] = {{{ 0, 1}, {-1, -1}, {-1, -1},
{-1, -1}, {-1, -1}, {-1, -1}},
{{ 1, 2}, { 2, 0}, { 0, 1},
{-1, -1}, {-1, -1}, {-1, -1}},
{{ 0, 1}, { 1, 2}, { 2, 0},
{ 2, 3}, { 0, 3}, { 1, 3}}};
// constructor // constructor
mjCFlex::mjCFlex(mjCModel* _model) { mjCFlex::mjCFlex(mjCModel* _model) {
// set model // set model
@@ -2216,6 +2237,9 @@ void mjCFlex::Compile(const mjVFS* vfs) {
if (vert.size() % 3) { if (vert.size() % 3) {
throw mjCError(this, "vert size must be a multiple of 3"); throw mjCError(this, "vert size must be a multiple of 3");
} }
if (edgestiffness>0 && dim>1) {
throw mjCError(this, "edge stiffness only available for dim=1, please use elasticity plugins");
}
nelem = (int)elem.size()/(dim+1); nelem = (int)elem.size()/(dim+1);
// set nvert, rigid, centered; check size // set nvert, rigid, centered; check size
@@ -2276,42 +2300,34 @@ void mjCFlex::Compile(const mjVFS* vfs) {
throw mjCError(this, "repeated vertex in element"); throw mjCError(this, "repeated vertex in element");
} }
} }
// make edges from sorted element
switch (dim) {
case 1: // line
edge.push_back(std::make_pair(el[0], el[1]));
break;
case 2: // triangle
edge.push_back(std::make_pair(el[0], el[1]));
edge.push_back(std::make_pair(el[1], el[2]));
edge.push_back(std::make_pair(el[0], el[2]));
break;
case 3: // tetrahedron
edge.push_back(std::make_pair(el[0], el[1]));
edge.push_back(std::make_pair(el[1], el[2]));
edge.push_back(std::make_pair(el[2], el[3]));
edge.push_back(std::make_pair(el[0], el[2]));
edge.push_back(std::make_pair(el[0], el[3]));
edge.push_back(std::make_pair(el[1], el[3]));
break;
}
} }
// sort edges // create edges
std::sort(edge.begin(), edge.end()); std::vector<int> edgeidx(elem.size()*kNumEdges[dim-1]);
// remove repeated edges // map from edge vertices to their index in `edges` vector
std::vector<std::pair<int,int>> edge1; std::unordered_map<std::pair<int, int>, int, PairHash> edge_indices;
edge1.push_back(edge[0]);
for (int i=1; i<(int)edge.size(); i++) { // insert local edges into global vector
if (edge1[edge1.size()-1]!=edge[i]) { for (int f = 0; f < (int)elem.size()/(dim+1); f++) {
edge1.push_back(edge[i]); int* v = elem.data() + f*(dim+1);
for (int e = 0; e < kNumEdges[dim-1]; e++) {
auto pair = std::pair(
std::min(v[eledge[dim-1][e][0]], v[eledge[dim-1][e][1]]),
std::max(v[eledge[dim-1][e][0]], v[eledge[dim-1][e][1]])
);
// if edge is already present in the vector only store its index
auto [it, inserted] = edge_indices.insert({pair, nedge});
if (inserted) {
edge.push_back(pair);
edgeidx[f*kNumEdges[dim-1]+e] = nedge++;
} else {
edgeidx[f*kNumEdges[dim-1]+e] = it->second;
}
} }
} }
edge = edge1;
// set size // set size
nedge = (int)edge.size(); nedge = (int)edge.size();
@@ -2378,6 +2394,18 @@ void mjCFlex::Compile(const mjVFS* vfs) {
} }
} }
// add plugins
std::string userface, useredge;
mjXUtil::Vector2String(userface, elem);
mjXUtil::Vector2String(useredge, edgeidx);
for (int i=0; i<(int)vertbodyid.size(); i++) {
if (model->bodies[vertbodyid[i]]->plugin_instance) {
model->bodies[vertbodyid[i]]->plugin_instance->config_attribs["face"] = userface;
model->bodies[vertbodyid[i]]->plugin_instance->config_attribs["edge"] = useredge;
}
}
// create shell fragments and element-vertex collision pairs // create shell fragments and element-vertex collision pairs
CreateShellPair(); CreateShellPair();
+30 -9
View File
@@ -78,7 +78,7 @@ void ReadPluginConfigs(tinyxml2::XMLElement* elem, mjCPlugin* pp) {
//---------------------------------- MJCF schema --------------------------------------------------- //---------------------------------- MJCF schema ---------------------------------------------------
static const int nMJCF = 223; static const int nMJCF = 227;
static const char* MJCF[nMJCF][mjXATTRNUM] = { static const char* MJCF[nMJCF][mjXATTRNUM] = {
{"mujoco", "!", "1", "model"}, {"mujoco", "!", "1", "model"},
{"<"}, {"<"},
@@ -293,25 +293,31 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
{"config", "*", "2", "key", "value"}, {"config", "*", "2", "key", "value"},
{">"}, {">"},
{">"}, {">"},
{"flexcomp", "*", "26", "name", "class", "type", "dim", "flatskin", {"flexcomp", "*", "25", "name", "class", "type", "group", "dim",
"count", "spacing", "radius", "rigid", "mass", "inertiabox", "count", "spacing", "radius", "rigid", "mass", "inertiabox",
"scale", "file", "point", "element", "texcoord", "material", "rgba", "selfcollide", "scale", "file", "point", "element", "texcoord", "material", "rgba",
"flatskin", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler"}, "flatskin", "pos", "quat", "axisangle", "xyaxes", "zaxis", "euler"},
{"<"}, {"<"},
{"edge", "?", "5", "equality", "solref", "solimp", "stiffness", "damping"}, {"edge", "?", "5", "equality", "solref", "solimp", "stiffness", "damping"},
{"contact", "?", "10", "contype", "conaffinity", "condim", "priority", {"contact", "?", "13", "contype", "conaffinity", "condim", "priority",
"friction", "solmix", "solref", "solimp", "margin", "gap"}, "friction", "solmix", "solref", "solimp", "margin", "gap",
"internal", "selfcollide", "activelayers"},
{"pin", "*", "4", "id", "range", "grid", "gridrange"}, {"pin", "*", "4", "id", "range", "grid", "gridrange"},
{"plugin", "*", "2", "plugin", "instance"},
{"<"},
{"config", "*", "2", "key", "value"},
{">"},
{">"}, {">"},
{">"}, {">"},
{"deformable", "*", "0"}, {"deformable", "*", "0"},
{"<"}, {"<"},
{"flex", "*", "12", "name", "group", "dim", "radius", "material", "rgba", "flatskin", {"flex", "*", "11", "name", "group", "dim", "radius", "material",
"selfcollide", "body", "vertex", "element", "texcoord"}, "rgba", "flatskin", "body", "vertex", "element", "texcoord"},
{"<"}, {"<"},
{"contact", "?", "10", "contype", "conaffinity", "condim", "priority", {"contact", "?", "13", "contype", "conaffinity", "condim", "priority",
"friction", "solmix", "solref", "solimp", "margin", "gap"}, "friction", "solmix", "solref", "solimp", "margin", "gap",
"internal", "selfcollide", "activelayers"},
{"edge", "?", "2", "stiffness", "damping"}, {"edge", "?", "2", "stiffness", "damping"},
{">"}, {">"},
{"skin", "*", "9", "name", "file", "material", "rgba", "inflate", {"skin", "*", "9", "name", "file", "material", "rgba", "inflate",
@@ -2366,6 +2372,21 @@ void mjXReader::OneFlexcomp(XMLElement* elem, mjCBody* pbody) {
epin = epin->NextSiblingElement("pin"); epin = epin->NextSiblingElement("pin");
} }
// plugin
XMLElement* eplugin = elem->FirstChildElement("plugin");
if (eplugin) {
ReadAttrTxt(eplugin, "plugin", fcomp.plugin_name);
ReadAttrTxt(eplugin, "instance", fcomp.plugin_instance_name);
if (fcomp.plugin_instance_name.empty()) {
fcomp.plugin_instance = model->AddPlugin();
fcomp.plugin_instance->name = "flexcomp_" + fcomp.name;
fcomp.plugin_instance_name = fcomp.plugin_instance->name;
} else {
model->hasImplicitPluginElem = true;
}
ReadPluginConfigs(eplugin, fcomp.plugin_instance);
}
// make flexcomp // make flexcomp
char error[200]; char error[200];
bool res = fcomp.Make(pbody->model, pbody, error, 200); bool res = fcomp.Make(pbody->model, pbody, error, 200);
+16 -10
View File
@@ -39,14 +39,14 @@ TEST_F(ElasticityTest, ElasticEnergyShell) {
</extension> </extension>
<worldbody> <worldbody>
<composite type="particle" count="8 8 1" spacing="1"> <flexcomp type="grid" count="8 8 1" spacing="1 1 1"
<geom size=".025" group="4"/> radius=".025" name="test" dim="2">
<plugin plugin="mujoco.elasticity.shell"> <plugin plugin="mujoco.elasticity.shell">
<config key="poisson" value="0"/> <config key="poisson" value="0"/>
<config key="young" value="2"/> <config key="young" value="2"/>
<config key="thickness" value="1"/> <config key="thickness" value="1"/>
</plugin> </plugin>
</composite> </flexcomp>
</worldbody> </worldbody>
</mujoco> </mujoco>
)"; )";
@@ -93,13 +93,14 @@ TEST_F(ElasticityTest, ElasticEnergySolid) {
</extension> </extension>
<worldbody> <worldbody>
<composite type="particle" count="8 8 8" spacing="1"> <flexcomp type="grid" count="8 8 8" spacing="1 1 1"
<geom size=".025" group="4"/> radius=".025" name="test" dim="3">
<plugin plugin="mujoco.elasticity.solid"> <plugin plugin="mujoco.elasticity.solid">
<config key="poisson" value="0"/> <config key="poisson" value="0"/>
<config key="young" value="2"/> <config key="young" value="2"/>
</plugin> </plugin>
</composite> <edge equality="false"/>
</flexcomp>
</worldbody> </worldbody>
</mujoco> </mujoco>
)"; )";
@@ -110,6 +111,9 @@ TEST_F(ElasticityTest, ElasticEnergySolid) {
mjData* d = mj_makeData(m); mjData* d = mj_makeData(m);
auto* solid = reinterpret_cast<plugin::elasticity::Solid*>(d->plugin_data[0]); auto* solid = reinterpret_cast<plugin::elasticity::Solid*>(d->plugin_data[0]);
mj_kinematics(m, d);
mj_flex(m, d);
// check that if the entire geometry is rescaled by a factor "scale", then // check that if the entire geometry is rescaled by a factor "scale", then
// trace(strain^2) = 3*scale^2 // trace(strain^2) = 3*scale^2
@@ -119,10 +123,12 @@ TEST_F(ElasticityTest, ElasticEnergySolid) {
mjtNum volume = 1./6.; mjtNum volume = 1./6.;
for (int e1 = 0; e1 < 6; e1++) { for (int e1 = 0; e1 < 6; e1++) {
for (int e2 = 0; e2 < 6; e2++) { for (int e2 = 0; e2 < 6; e2++) {
int idx1 = solid->elements[t].edges[e1]; int idx1 = solid->elements[t].edges[e1] + m->flex_edgeadr[0];
int idx2 = solid->elements[t].edges[e2]; int idx2 = solid->elements[t].edges[e2] + m->flex_edgeadr[0];
mjtNum elongation1 = scale*solid->reference[idx1]; mjtNum elongation1 =
mjtNum elongation2 = scale*solid->reference[idx2]; scale * m->flexedge_length0[idx1] * m->flexedge_length0[idx1];
mjtNum elongation2 =
scale * m->flexedge_length0[idx2] * m->flexedge_length0[idx2];
energy += solid->metric[36*t+6*e2+e1] * elongation1 * elongation2; energy += solid->metric[36*t+6*e2+e1] * elongation1 * elongation2;
} }
} }