Remove cloth and rope composites and deprecate loop.
PiperOrigin-RevId: 568168329 Change-Id: Ida4a5236bef74828c7bf59affdc28adea3db53b1
This commit is contained in:
committed by
Copybara-Service
parent
cbb07a4c32
commit
d3d46e16a4
+14
-10
@@ -84,35 +84,39 @@ General
|
|||||||
:ref:`conaffinity<body-geom-conaffinity>` attributes in the model and then setting them globally to ``0`` using
|
:ref:`conaffinity<body-geom-conaffinity>` attributes in the model and then setting them globally to ``0`` using
|
||||||
|br| ``<default> <geom contype="0" conaffinity="0"/> </default>``.
|
|br| ``<default> <geom contype="0" conaffinity="0"/> </default>``.
|
||||||
|
|
||||||
11. Added a new :ref:`dyntype<actuator-general-dyntype>`, ``filterexact``, which updates first-order filter states with
|
11. Removed the :at:`rope` and :at:`cloth` composite objects.
|
||||||
|
|
||||||
|
**Migration:** Users should use the :at:`cable` and :at:`shell` elasticity plugins.
|
||||||
|
|
||||||
|
12. Added a new :ref:`dyntype<actuator-general-dyntype>`, ``filterexact``, which updates first-order filter states with
|
||||||
the exact formula rather than with Euler integration.
|
the exact formula rather than with Euler integration.
|
||||||
12. Added an actuator attribute, :ref:`actearly<actuator-general-actearly>`, which uses semi-implicit integration for
|
13. Added an actuator attribute, :ref:`actearly<actuator-general-actearly>`, which uses semi-implicit integration for
|
||||||
actuator forces: using the next step's actuator state to compute the current actuator forces at the current timestep.
|
actuator forces: using the next step's actuator state to compute the current actuator forces at the current timestep.
|
||||||
13. Renamed ``actuatorforcerange`` and ``actuatorforcelimited``, introduced in the previous version to
|
14. Renamed ``actuatorforcerange`` and ``actuatorforcelimited``, introduced in the previous version to
|
||||||
:ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` and
|
:ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` and
|
||||||
:ref:`actuatorfrclimited<body-joint-actuatorfrclimited>`, respectively.
|
:ref:`actuatorfrclimited<body-joint-actuatorfrclimited>`, respectively.
|
||||||
14. Added the flag :ref:`eulerdamp<option-flag-eulerdamp>`, which disables implicit integration of joint damping in the
|
15. Added the flag :ref:`eulerdamp<option-flag-eulerdamp>`, which disables implicit integration of joint damping in the
|
||||||
Euler integrator. See the :ref:`Numerical Integration<geIntegration>` section for more details.
|
Euler integrator. See the :ref:`Numerical Integration<geIntegration>` section for more details.
|
||||||
15. Added the flag :ref:`invdiscrete<option-flag-invdiscrete>`, which enables discrete-time inverse dynamics for all
|
16. Added the flag :ref:`invdiscrete<option-flag-invdiscrete>`, which enables discrete-time inverse dynamics for all
|
||||||
:ref:`integrators<option-integrator>` other than ``RK4``. See the flag documentation for more details.
|
:ref:`integrators<option-integrator>` other than ``RK4``. See the flag documentation for more details.
|
||||||
16. Added :ref:`ls_iterations<option-ls_iterations>` and :ref:`ls_tolerance<option-ls_tolerance>` options for adjusting
|
17. Added :ref:`ls_iterations<option-ls_iterations>` and :ref:`ls_tolerance<option-ls_tolerance>` options for adjusting
|
||||||
linesearch stopping criteria in CG and Newton solvers. These can be useful for performance tuning.
|
linesearch stopping criteria in CG and Newton solvers. These can be useful for performance tuning.
|
||||||
17. Added ``mesh_pos`` and ``mesh_quat`` fields to :ref:`mjModel` to store the normalizing transformation applied to
|
18. Added ``mesh_pos`` and ``mesh_quat`` fields to :ref:`mjModel` to store the normalizing transformation applied to
|
||||||
mesh assets. Fixes `#409 <https://github.com/google-deepmind/mujoco/issues/409>`__ .
|
mesh assets. Fixes `#409 <https://github.com/google-deepmind/mujoco/issues/409>`__ .
|
||||||
18. Added camera :ref:`resolution<body-camera-resolution>` attribute and :ref:`camprojection<sensor-camprojection>`
|
19. Added camera :ref:`resolution<body-camera-resolution>` attribute and :ref:`camprojection<sensor-camprojection>`
|
||||||
sensor. If camera resolution is set to positive values, the camera projection sensor will report the location of a
|
sensor. If camera resolution is set to positive values, the camera projection sensor will report the location of a
|
||||||
target site, projected onto the camera image, in pixel coordinates.
|
target site, projected onto the camera image, in pixel coordinates.
|
||||||
|
|
||||||
Python bindings
|
Python bindings
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
19. Fixed `#870 <https://github.com/google-deepmind/mujoco/issues/870>`__ where calling ``update_scene`` with an invalid
|
20. Fixed `#870 <https://github.com/google-deepmind/mujoco/issues/870>`__ where calling ``update_scene`` with an invalid
|
||||||
camera name used the default camera.
|
camera name used the default camera.
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
20. Fixed a bug that was causing :ref:`geom margin<body-geom-margin>` to be ignored during the construction of
|
21. Fixed a bug that was causing :ref:`geom margin<body-geom-margin>` to be ignored during the construction of
|
||||||
midphase collision trees.
|
midphase collision trees.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +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="Cloth">
|
|
||||||
<include file="scene.xml"/>
|
|
||||||
|
|
||||||
<option timestep="0.002" solver="CG" tolerance="1e-6"/>
|
|
||||||
|
|
||||||
<size memory="10M"/>
|
|
||||||
|
|
||||||
<worldbody>
|
|
||||||
|
|
||||||
<body name="B3_5" pos="0 0 1">
|
|
||||||
<freejoint/>
|
|
||||||
<composite type="cloth" count="9 9 1" spacing="0.05" flatinertia="0.01">
|
|
||||||
<joint kind="main" damping="0.001"/>
|
|
||||||
<skin material="matcarpet" texcoord="true" inflate="0.005" subgrid="2"/>
|
|
||||||
<geom type="capsule" size="0.015 0.01" rgba=".8 .2 .1 1"/>
|
|
||||||
</composite>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</worldbody>
|
|
||||||
</mujoco>
|
|
||||||
@@ -1,32 +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="Loop">
|
|
||||||
<include file="scene.xml"/>
|
|
||||||
|
|
||||||
<option timestep="0.002" jacobian="dense"/>
|
|
||||||
|
|
||||||
<size memory="2M"/>
|
|
||||||
|
|
||||||
<worldbody>
|
|
||||||
<body name="B0" pos="0 0 1">
|
|
||||||
<freejoint/>
|
|
||||||
<composite type="loop" count="20 1 1" spacing="0.04" offset="0 0 2">
|
|
||||||
<joint kind="main" damping="0.005"/>
|
|
||||||
<geom type="capsule" size=".01 .015" rgba=".8 .2 .1 1"/>
|
|
||||||
</composite>
|
|
||||||
</body>
|
|
||||||
</worldbody>
|
|
||||||
</mujoco>
|
|
||||||
@@ -23,22 +23,33 @@
|
|||||||
-->
|
-->
|
||||||
<statistic center=".4 0 .8" extent="1.3"/>
|
<statistic center=".4 0 .8" extent="1.3"/>
|
||||||
|
|
||||||
<option wind="5 5 0" density="10">
|
<option wind="5 5 0" density="10" solver="CG" tolerance="1e-6">
|
||||||
<flag constraint="disable"/>
|
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
<extension>
|
||||||
|
<plugin plugin="mujoco.elasticity.shell"/>
|
||||||
|
</extension>
|
||||||
|
|
||||||
<worldbody>
|
<worldbody>
|
||||||
<geom name="floor" type="plane" size="0 0 .1"/>
|
<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"/>
|
<light diffuse=".6 .6 .6" specular="0.2 0.2 0.2" pos="0 0 4" dir="0 0 -1"/>
|
||||||
<body name="B0_0" pos="0 0 1">
|
<body pos="0 0 1">
|
||||||
<composite type="cloth" count="9 19 1" spacing="0.05" flatinertia="0.01">
|
<composite type="particle" count="9 19 1" spacing="0.05" flatinertia="0.01">
|
||||||
<joint kind="main" damping="0.001" stiffness=".1"/>
|
|
||||||
<skin texcoord="true" inflate="0.005" subgrid="4"/>
|
<skin texcoord="true" inflate="0.005" subgrid="4"/>
|
||||||
<geom type="ellipsoid" size="0.025 0.01 0.025" rgba=".8 .2 .1 1"/>
|
<geom type="ellipsoid" size="0.025 0.01 0.025" rgba=".8 .2 .1 1" group="4"/>
|
||||||
<tendon kind="main" stiffness="100" damping=".001"/>
|
<plugin plugin="mujoco.elasticity.shell">
|
||||||
<tendon kind="shear" stiffness="100" damping=".001"/>
|
<config key="poisson" value="0"/>
|
||||||
|
<config key="damping" value="0.001"/>
|
||||||
|
<config key="thickness" value="1e-2"/>
|
||||||
|
<!--Units are in Pa (SI)-->
|
||||||
|
<config key="young" value="3e6"/>
|
||||||
|
</plugin>
|
||||||
</composite>
|
</composite>
|
||||||
</body>
|
</body>
|
||||||
</worldbody>
|
</worldbody>
|
||||||
|
|
||||||
|
<equality>
|
||||||
|
<connect body1="B0_0_0" anchor="0 0 0" solref="0.0002 1"/>
|
||||||
|
</equality>
|
||||||
</mujoco>
|
</mujoco>
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<composite type="particle" count="16 16 1" spacing="0.05" offset="0 0 1">
|
<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"
|
<geom size=".02" rgba=".8 .2 .1 1" group="4" density="1000"
|
||||||
condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
|
condim="3" solref="0.01 1" solimp=".95 .99 .0001"/>
|
||||||
<skin inflate="0.01" rgba=".4 0 .3 1" subgrid="4"/>
|
<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="damping" value="0.001"/>
|
||||||
|
|||||||
+74
-314
@@ -293,16 +293,25 @@ bool mjCComposite::Make(mjCModel* model, mjCBody* body, char* error, int error_s
|
|||||||
return MakeGrid(model, body, error, error_sz);
|
return MakeGrid(model, body, error, error_sz);
|
||||||
|
|
||||||
case mjCOMPTYPE_ROPE:
|
case mjCOMPTYPE_ROPE:
|
||||||
mju_warning("The \"rope\" composite type is deprecated. Please use \"cable\" instead.");
|
return comperr(error,
|
||||||
[[fallthrough]];
|
"The \"rope\" composite type is deprecated. Please use "
|
||||||
|
"\"cable\" instead.",
|
||||||
|
error_sz);
|
||||||
|
|
||||||
case mjCOMPTYPE_LOOP:
|
case mjCOMPTYPE_LOOP:
|
||||||
|
mju_warning(
|
||||||
|
"The \"loop\" composite type is deprecated. Please use \"cable\" "
|
||||||
|
"instead.");
|
||||||
return MakeRope(model, body, error, error_sz);
|
return MakeRope(model, body, error, error_sz);
|
||||||
|
|
||||||
case mjCOMPTYPE_CABLE:
|
case mjCOMPTYPE_CABLE:
|
||||||
return MakeCable(model, body, error, error_sz);
|
return MakeCable(model, body, error, error_sz);
|
||||||
|
|
||||||
case mjCOMPTYPE_CLOTH:
|
case mjCOMPTYPE_CLOTH:
|
||||||
return MakeCloth(model, body, error, error_sz);
|
return comperr(error,
|
||||||
|
"The \"cloth\" composite type is deprecated. Please use "
|
||||||
|
"\"shell\" instead.",
|
||||||
|
error_sz);
|
||||||
|
|
||||||
case mjCOMPTYPE_BOX:
|
case mjCOMPTYPE_BOX:
|
||||||
case mjCOMPTYPE_CYLINDER:
|
case mjCOMPTYPE_CYLINDER:
|
||||||
@@ -531,10 +540,18 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjCBody* body, char* error, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skin) {
|
if (skin && dim==3) {
|
||||||
MakeSkin3(model);
|
MakeSkin3(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skin && dim==2) {
|
||||||
|
if (skinsubgrid>0) {
|
||||||
|
MakeSkin2Subgrid(model, skininflate);
|
||||||
|
} else {
|
||||||
|
MakeSkin2(model, skininflate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,273 +1036,6 @@ mjCBody* mjCComposite::AddRopeBody(mjCModel* model, mjCBody* body, int ix, int i
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// make 2d cloth
|
|
||||||
bool mjCComposite::MakeCloth(mjCModel* model, mjCBody* body, char* error, int error_sz) {
|
|
||||||
// check dim
|
|
||||||
if (dim!=2) {
|
|
||||||
return comperr(error, "Cloth must be two-dimensional", error_sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check root body name prefix
|
|
||||||
char txt[200];
|
|
||||||
mju::sprintf_arr(txt, "%sB", prefix.c_str());
|
|
||||||
if (std::strncmp(txt, body->name.substr(0, strlen(txt)).c_str(), mju::sizeof_arr(txt))) {
|
|
||||||
mju::strcat_arr(txt, " must be the beginning of root body name");
|
|
||||||
return comperr(error, txt, error_sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// read origin coordinate from root body
|
|
||||||
mju::strcpy_arr(txt, body->name.substr(strlen(txt)).c_str());
|
|
||||||
int ox = -1, oy = -1;
|
|
||||||
char c;
|
|
||||||
if (sscanf(txt, "%d%c%d", &ox, &c, &oy)!=3 || c!='_') {
|
|
||||||
return comperr(error, "Root body name must contain X_Y coordinates", error_sz);
|
|
||||||
}
|
|
||||||
if (ox<0 || ox>=count[0] || oy<0 || oy>=count[1]) {
|
|
||||||
return comperr(error, "Root body coordinates out of range", error_sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add origin
|
|
||||||
AddClothBody(model, body, ox, oy, ox, oy);
|
|
||||||
|
|
||||||
// add row: both directions
|
|
||||||
for (int i=-2; i<=2; i+=2) {
|
|
||||||
// init at origin
|
|
||||||
int ix = ox;
|
|
||||||
|
|
||||||
// process row to end
|
|
||||||
mjCBody* pbodyx = body;
|
|
||||||
while (1) {
|
|
||||||
// candidate neighbor
|
|
||||||
int ix1 = ix;
|
|
||||||
if (i==0) {
|
|
||||||
ix1 = mjMIN(count[0]-1, ix+1);
|
|
||||||
} else if (i==2) {
|
|
||||||
ix1 = mjMAX(0, ix-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// regular column
|
|
||||||
if (i!=-2) {
|
|
||||||
// stop if same
|
|
||||||
if (ix1==ix) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add body, assign counter
|
|
||||||
pbodyx = AddClothBody(model, pbodyx, ix, oy, ix1, oy);
|
|
||||||
ix = ix1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add column: regular or center
|
|
||||||
for (int j=1; j<=3; j+=2) {
|
|
||||||
// init at row
|
|
||||||
int iy = oy;
|
|
||||||
|
|
||||||
// process column to end
|
|
||||||
mjCBody* pbodyy = pbodyx;
|
|
||||||
while (1) {
|
|
||||||
// candidate neighbor
|
|
||||||
int iy1;
|
|
||||||
if (j==1) {
|
|
||||||
iy1 = mjMIN(count[1]-1, iy+1);
|
|
||||||
} else {
|
|
||||||
iy1 = mjMAX(0, iy-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// stop if same
|
|
||||||
if (iy1==iy) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add body, assign counter
|
|
||||||
pbodyy = AddClothBody(model, pbodyy, ix, iy, ix, iy1);
|
|
||||||
iy = iy1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// center column added
|
|
||||||
if (i==-2) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add main tendons
|
|
||||||
for (int iy=0; iy<count[1]; iy++) {
|
|
||||||
if (iy!=oy) {
|
|
||||||
for (int ix=0; ix<count[0]-1; ix++) {
|
|
||||||
char txt1[100], txt2[100];
|
|
||||||
|
|
||||||
// recover site names
|
|
||||||
mju::sprintf_arr(txt1, "%sS%d_%d", prefix.c_str(), ix, iy);
|
|
||||||
mju::sprintf_arr(txt2, "%sS%d_%d", prefix.c_str(), ix+1, iy);
|
|
||||||
|
|
||||||
// create tendon
|
|
||||||
mjCTendon* ten = model->AddTendon(def + mjCOMPKIND_TENDON);
|
|
||||||
ten->def = model->defaults[0];
|
|
||||||
mju::sprintf_arr(txt, "%sT%d_%d", prefix.c_str(), ix, iy);
|
|
||||||
ten->name = txt;
|
|
||||||
ten->WrapSite(txt1);
|
|
||||||
ten->WrapSite(txt2);
|
|
||||||
|
|
||||||
// add equality constraint
|
|
||||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_TENDON);
|
|
||||||
eq->def = model->defaults[0];
|
|
||||||
eq->type = mjEQ_TENDON;
|
|
||||||
eq->name1 = ten->name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// shear for 2D
|
|
||||||
if (add[mjCOMPKIND_SHEAR]) {
|
|
||||||
MakeShear(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
// skin
|
|
||||||
if (skin) {
|
|
||||||
if (skinsubgrid>0) {
|
|
||||||
MakeSkin2Subgrid(model, skininflate);
|
|
||||||
} else {
|
|
||||||
MakeSkin2(model, skininflate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// add child body for cloth
|
|
||||||
mjCBody* mjCComposite::AddClothBody(mjCModel* model, mjCBody* body,
|
|
||||||
int ix, int iy, int ix1, int iy1) {
|
|
||||||
char txt[100];
|
|
||||||
bool isroot = (ix==ix1 && iy==iy1);
|
|
||||||
double dx = spacing*(ix1-ix);
|
|
||||||
double dy = spacing*(iy1-iy);
|
|
||||||
|
|
||||||
// add child if not root
|
|
||||||
if (!isroot) {
|
|
||||||
body = body->AddBody();
|
|
||||||
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix1, iy1);
|
|
||||||
body->name = txt;
|
|
||||||
mjuu_setvec(body->pos, dx, dy, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add geom, alternating rotations
|
|
||||||
mjCGeom* geom = body->AddGeom(def);
|
|
||||||
geom->def = body->def;
|
|
||||||
mju::sprintf_arr(txt, "%sG%d_%d", prefix.c_str(), ix1, iy1);
|
|
||||||
geom->name = txt;
|
|
||||||
mjuu_setvec(geom->pos, 0, 0, 0);
|
|
||||||
if ((ix1+iy1)%2) {
|
|
||||||
mjuu_setvec(geom->quat, sqrt(0.5), sqrt(0.5), 0, 0);
|
|
||||||
} else {
|
|
||||||
mjuu_setvec(geom->quat, 0.5, 0.5, 0.5, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make inertia flat
|
|
||||||
if (flatinertia>0) {
|
|
||||||
// set body mass = geom mass
|
|
||||||
body->mass = mjuu_defined(geom->_mass) ? geom->_mass :
|
|
||||||
geom->density * geom->GetVolume();
|
|
||||||
|
|
||||||
// set body i-frame
|
|
||||||
mjuu_setvec(body->ipos, 0, 0, 0);
|
|
||||||
mjuu_setvec(body->iquat, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
// desired equivalent inertia box
|
|
||||||
double size[3] = {0.5*spacing, 0.5*spacing, 0.5*spacing*flatinertia};
|
|
||||||
|
|
||||||
// convert to inertia
|
|
||||||
body->inertia[0] = body->mass*(size[1]*size[1]+size[2]*size[2])/3;
|
|
||||||
body->inertia[1] = body->mass*(size[0]*size[0]+size[2]*size[2])/3;
|
|
||||||
body->inertia[2] = body->mass*(size[0]*size[0]+size[1]*size[1])/3;
|
|
||||||
|
|
||||||
body->MakeInertialExplicit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// add site
|
|
||||||
mjCSite* site = body->AddSite(def);
|
|
||||||
site->def = body->def;
|
|
||||||
site->type = mjGEOM_SPHERE;
|
|
||||||
mju::sprintf_arr(txt, "%sS%d_%d", prefix.c_str(), ix1, iy1);
|
|
||||||
site->name = txt;
|
|
||||||
mjuu_setvec(site->pos, 0, 0, 0);
|
|
||||||
mjuu_setvec(site->quat, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
// root: no joints
|
|
||||||
if (isroot) {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add main joint
|
|
||||||
for (int i=0; i<2; i++) {
|
|
||||||
// add joint
|
|
||||||
mjCJoint* jnt = body->AddJoint(&defjoint[mjCOMPKIND_JOINT][0]);
|
|
||||||
jnt->def = body->def;
|
|
||||||
mju::sprintf_arr(txt, "%sJ%d_%d_%d", prefix.c_str(), i, ix1, iy1);
|
|
||||||
jnt->name = txt;
|
|
||||||
jnt->type = mjJNT_HINGE;
|
|
||||||
mjuu_setvec(jnt->pos, -dx, -dy, 0);
|
|
||||||
|
|
||||||
// set universal axis depending on parent direction
|
|
||||||
mjuu_setvec(jnt->axis, 0, 0, 0);
|
|
||||||
if (ix!=ix1) {
|
|
||||||
jnt->axis[i+1] = 1;
|
|
||||||
} else {
|
|
||||||
jnt->axis[2*i] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add twist joint
|
|
||||||
if (add[mjCOMPKIND_TWIST]) {
|
|
||||||
mjCJoint* jnt = body->AddJoint(&defjoint[mjCOMPKIND_TWIST][0]);
|
|
||||||
jnt->def = body->def;
|
|
||||||
mju::sprintf_arr(txt, "%sJT%d_%d", prefix.c_str(), ix1, iy1);
|
|
||||||
jnt->name = txt;
|
|
||||||
jnt->type = mjJNT_HINGE;
|
|
||||||
mjuu_setvec(jnt->pos, -dx, -dy, 0);
|
|
||||||
if (ix!=ix1) {
|
|
||||||
mjuu_setvec(jnt->axis, 1, 0, 0);
|
|
||||||
} else {
|
|
||||||
mjuu_setvec(jnt->axis, 0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add constraint
|
|
||||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_TWIST);
|
|
||||||
eq->def = model->defaults[0];
|
|
||||||
eq->type = mjEQ_JOINT;
|
|
||||||
eq->name1 = jnt->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add stretch joint
|
|
||||||
if (add[mjCOMPKIND_STRETCH]) {
|
|
||||||
// add joint
|
|
||||||
mjCJoint* jnt = body->AddJoint(&defjoint[mjCOMPKIND_STRETCH][0]);
|
|
||||||
jnt->def = body->def;
|
|
||||||
mju::sprintf_arr(txt, "%sJS%d_%d", prefix.c_str(), ix1, iy1);
|
|
||||||
jnt->name = txt;
|
|
||||||
jnt->type = mjJNT_SLIDE;
|
|
||||||
mjuu_setvec(jnt->pos, -dx, -dy, 0);
|
|
||||||
if (ix!=ix1) {
|
|
||||||
mjuu_setvec(jnt->axis, 1, 0, 0);
|
|
||||||
} else {
|
|
||||||
mjuu_setvec(jnt->axis, 0, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add constraint
|
|
||||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_STRETCH);
|
|
||||||
eq->def = model->defaults[0];
|
|
||||||
eq->type = mjEQ_JOINT;
|
|
||||||
eq->name1 = jnt->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// project from box to other shape
|
// project from box to other shape
|
||||||
void mjCComposite::BoxProject(double* pos) {
|
void mjCComposite::BoxProject(double* pos) {
|
||||||
// determine sizes
|
// determine sizes
|
||||||
@@ -1490,6 +1240,46 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
|||||||
skin->inflate = inflate;
|
skin->inflate = inflate;
|
||||||
skin->group = skingroup;
|
skin->group = skingroup;
|
||||||
|
|
||||||
|
// copy skin from existing mesh
|
||||||
|
if (type==mjCOMPTYPE_PARTICLE && username.empty()) {
|
||||||
|
std::vector<int> face;
|
||||||
|
mjXUtil::String2Vector(userface, face);
|
||||||
|
int nvert = uservert.size()/3;
|
||||||
|
|
||||||
|
for (int j=0; j<2; j++) {
|
||||||
|
for (int i=0; i<nvert; i++) {
|
||||||
|
skin->vert.push_back(0);
|
||||||
|
skin->vert.push_back(0);
|
||||||
|
skin->vert.push_back(0);
|
||||||
|
|
||||||
|
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
|
||||||
|
skin->bodyname.push_back(txt);
|
||||||
|
skin->bindpos.push_back(0);
|
||||||
|
skin->bindpos.push_back(0);
|
||||||
|
skin->bindpos.push_back(0);
|
||||||
|
skin->bindquat.push_back(1);
|
||||||
|
skin->bindquat.push_back(0);
|
||||||
|
skin->bindquat.push_back(0);
|
||||||
|
skin->bindquat.push_back(0);
|
||||||
|
|
||||||
|
vector<int> vertid;
|
||||||
|
vector<float> vertweight;
|
||||||
|
vertid.push_back(j*nvert+i);
|
||||||
|
vertweight.push_back(1);
|
||||||
|
skin->vertid.push_back(vertid);
|
||||||
|
skin->vertweight.push_back(vertweight);
|
||||||
|
}
|
||||||
|
|
||||||
|
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+(j==0 ? 1 : 2)]-1);
|
||||||
|
skin->face.push_back(j*nvert+face[3*i+(j==0 ? 2 : 1)]-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// populate mesh: two sides
|
// populate mesh: two sides
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
for (int ix=0; ix<count[0]; ix++) {
|
for (int ix=0; ix<count[0]; ix++) {
|
||||||
@@ -1564,7 +1354,7 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// couple with bones
|
// couple with bones
|
||||||
if (type==mjCOMPTYPE_CLOTH || type==mjCOMPTYPE_GRID) {
|
if (type==mjCOMPTYPE_PARTICLE || type==mjCOMPTYPE_GRID) {
|
||||||
MakeClothBones(model, skin);
|
MakeClothBones(model, skin);
|
||||||
} else if (type==mjCOMPTYPE_CABLE) {
|
} else if (type==mjCOMPTYPE_CABLE) {
|
||||||
MakeCableBones(model, skin);
|
MakeCableBones(model, skin);
|
||||||
@@ -1582,7 +1372,11 @@ void mjCComposite::MakeClothBones(mjCModel* model, mjCSkin* skin) {
|
|||||||
for (int ix=0; ix<count[0]; ix++) {
|
for (int ix=0; ix<count[0]; ix++) {
|
||||||
for (int iy=0; iy<count[1]; iy++) {
|
for (int iy=0; iy<count[1]; iy++) {
|
||||||
// body name
|
// body name
|
||||||
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
|
if (type==mjCOMPTYPE_GRID) {
|
||||||
|
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
|
||||||
|
} else {
|
||||||
|
mju::sprintf_arr(txt, "%sB%d_%d_0", prefix.c_str(), ix, iy);
|
||||||
|
}
|
||||||
|
|
||||||
// bind pose
|
// bind pose
|
||||||
skin->bodyname.push_back(txt);
|
skin->bodyname.push_back(txt);
|
||||||
@@ -1616,7 +1410,11 @@ void mjCComposite::MakeClothBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
|||||||
for (int ix=0; ix<count[0]; ix++) {
|
for (int ix=0; ix<count[0]; ix++) {
|
||||||
for (int iy=0; iy<count[1]; iy++) {
|
for (int iy=0; iy<count[1]; iy++) {
|
||||||
// body name
|
// body name
|
||||||
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
|
if (type==mjCOMPTYPE_GRID) {
|
||||||
|
mju::sprintf_arr(txt, "%sB%d_%d", prefix.c_str(), ix, iy);
|
||||||
|
} else {
|
||||||
|
mju::sprintf_arr(txt, "%sB%d_%d_0", prefix.c_str(), ix, iy);
|
||||||
|
}
|
||||||
|
|
||||||
// bind pose
|
// bind pose
|
||||||
skin->bodyname.push_back(txt);
|
skin->bodyname.push_back(txt);
|
||||||
@@ -2121,7 +1919,7 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) {
|
|||||||
skin->face.push_back(NN + iy+1 + (C0-1)*C1);
|
skin->face.push_back(NN + iy+1 + (C0-1)*C1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type==mjCOMPTYPE_CLOTH || type==mjCOMPTYPE_GRID) {
|
if (type==mjCOMPTYPE_PARTICLE || type==mjCOMPTYPE_GRID) {
|
||||||
MakeClothBonesSubgrid(model, skin);
|
MakeClothBonesSubgrid(model, skin);
|
||||||
} else if (type==mjCOMPTYPE_CABLE) {
|
} else if (type==mjCOMPTYPE_CABLE) {
|
||||||
MakeCableBonesSubgrid(model, skin);
|
MakeCableBonesSubgrid(model, skin);
|
||||||
@@ -2197,46 +1995,8 @@ void mjCComposite::MakeSkin3(mjCModel* model) {
|
|||||||
skin->inflate = skininflate;
|
skin->inflate = skininflate;
|
||||||
skin->group = skingroup;
|
skin->group = skingroup;
|
||||||
|
|
||||||
// copy skin from existing mesh
|
|
||||||
if (type==mjCOMPTYPE_PARTICLE && username.empty()) {
|
|
||||||
std::vector<int> face;
|
|
||||||
mjXUtil::String2Vector(userface, face);
|
|
||||||
int nvert = uservert.size()/3;
|
|
||||||
|
|
||||||
for (int j=0; j<2; j++) {
|
|
||||||
for (int i=0; i<nvert; i++) {
|
|
||||||
skin->vert.push_back(0);
|
|
||||||
skin->vert.push_back(0);
|
|
||||||
skin->vert.push_back(0);
|
|
||||||
|
|
||||||
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
|
|
||||||
skin->bodyname.push_back(txt);
|
|
||||||
skin->bindpos.push_back(0);
|
|
||||||
skin->bindpos.push_back(0);
|
|
||||||
skin->bindpos.push_back(0);
|
|
||||||
skin->bindquat.push_back(1);
|
|
||||||
skin->bindquat.push_back(0);
|
|
||||||
skin->bindquat.push_back(0);
|
|
||||||
skin->bindquat.push_back(0);
|
|
||||||
|
|
||||||
vector<int> vertid;
|
|
||||||
vector<float> vertweight;
|
|
||||||
vertid.push_back(j*nvert+i);
|
|
||||||
vertweight.push_back(1);
|
|
||||||
skin->vertid.push_back(vertid);
|
|
||||||
skin->vertweight.push_back(vertweight);
|
|
||||||
}
|
|
||||||
|
|
||||||
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+(j==0 ? 1 : 2)]-1);
|
|
||||||
skin->face.push_back(j*nvert+face[3*i+(j==0 ? 2 : 1)]-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// box
|
// box
|
||||||
else if (type==mjCOMPTYPE_BOX || type==mjCOMPTYPE_PARTICLE) {
|
if (type==mjCOMPTYPE_BOX || type==mjCOMPTYPE_PARTICLE) {
|
||||||
// z-faces
|
// z-faces
|
||||||
MakeSkin3Box(skin, count[0], count[1], 1, vcnt, "%sB%d_%d_0");
|
MakeSkin3Box(skin, count[0], count[1], 1, vcnt, "%sB%d_%d_0");
|
||||||
fmt = "%sB%d_%d_" + string(cnt2);
|
fmt = "%sB%d_%d_" + string(cnt2);
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ class mjCComposite {
|
|||||||
bool MakeGrid(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
bool MakeGrid(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
||||||
bool MakeRope(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
bool MakeRope(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
||||||
bool MakeCable(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
bool MakeCable(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
||||||
bool MakeCloth(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
|
||||||
bool MakeBox(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
bool MakeBox(mjCModel* model, mjCBody* body, char* error, int error_sz);
|
||||||
void MakeShear(mjCModel* model);
|
void MakeShear(mjCModel* model);
|
||||||
|
|
||||||
@@ -138,7 +137,6 @@ class mjCComposite {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
mjCBody* AddRopeBody(mjCModel* model, mjCBody* body, int ix, int ix1);
|
mjCBody* AddRopeBody(mjCModel* model, mjCBody* body, int ix, int ix1);
|
||||||
mjCBody* AddClothBody(mjCModel* model, mjCBody* body, int ix, int iy, int ix1, int iy1);
|
|
||||||
mjCBody* AddCableBody(mjCModel* model, mjCBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]);
|
mjCBody* AddCableBody(mjCModel* model, mjCBody* body, int ix, mjtNum normal[3], mjtNum prev_quat[4]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace mujoco {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// number of steps to roll out before benhmarking
|
// number of steps to roll out before benhmarking
|
||||||
static const int kNumWarmupSteps = 500;
|
static const int kNumWarmupSteps = 200;
|
||||||
|
|
||||||
// number of steps to benchmark
|
// number of steps to benchmark
|
||||||
static const int kNumBenchmarkSteps = 50;
|
static const int kNumBenchmarkSteps = 50;
|
||||||
@@ -102,7 +102,7 @@ void solveM_baseline(const mjModel* m, mjData* d, mjtNum* x, const mjtNum* y) {
|
|||||||
// ----------------------------- benchmark ------------------------------------
|
// ----------------------------- benchmark ------------------------------------
|
||||||
|
|
||||||
static void BM_solveLD(benchmark::State& state, bool new_function) {
|
static void BM_solveLD(benchmark::State& state, bool new_function) {
|
||||||
static mjModel* m = LoadModelFromPath("composite/cloth.xml");
|
static mjModel* m = LoadModelFromPath("plugin/elasticity/coil.xml");
|
||||||
mjData* d = mj_makeData(m);
|
mjData* d = mj_makeData(m);
|
||||||
|
|
||||||
// warm-up rollout to get a typical state
|
// warm-up rollout to get a typical state
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ void ABSL_ATTRIBUTE_NOINLINE mulMatVecSparse_8(mjtNum* res,
|
|||||||
// ----------------------------- benchmark ------------------------------------
|
// ----------------------------- benchmark ------------------------------------
|
||||||
|
|
||||||
static void BM_MatVecSparse(benchmark::State& state, int unroll) {
|
static void BM_MatVecSparse(benchmark::State& state, int unroll) {
|
||||||
static mjModel* m = LoadModelFromPath("composite/cloth.xml");
|
static mjModel* m = LoadModelFromPath("plugin/elasticity/flag.xml");
|
||||||
mjData* d = mj_makeData(m);
|
mjData* d = mj_makeData(m);
|
||||||
|
|
||||||
// warm-up rollout to get a typical state
|
// warm-up rollout to get a typical state
|
||||||
|
|||||||
@@ -48,13 +48,14 @@ static void run_parse_benchmark(const std::string xml_path, benchmark::State& st
|
|||||||
// separately in CPU profiles (and don't get replaced with raw calls to
|
// separately in CPU profiles (and don't get replaced with raw calls to
|
||||||
// run_parse_benchmark).
|
// run_parse_benchmark).
|
||||||
|
|
||||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_ParseCloth(benchmark::State& state) {
|
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_ParseCable(benchmark::State& state) {
|
||||||
run_parse_benchmark(GetModelPath("composite/cloth.xml"), state);
|
run_parse_benchmark(GetModelPath("plugin/elasticity/flag.xml"), state);
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_ParseCloth);
|
BENCHMARK(BM_ParseCable);
|
||||||
|
|
||||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_ParseFlag(benchmark::State& state) {
|
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_ParseFlag(benchmark::State& state) {
|
||||||
run_parse_benchmark(GetModelPath("flag/flag.xml"), state);
|
run_parse_benchmark(GetModelPath("../test/benchmark/testdata/flag.xml"),
|
||||||
|
state);
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_ParseFlag);
|
BENCHMARK(BM_ParseFlag);
|
||||||
|
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ static void run_step_benchmark(const mjModel* model, benchmark::State& state) {
|
|||||||
// separately in CPU profiles (and don't get replaced with raw calls to
|
// separately in CPU profiles (and don't get replaced with raw calls to
|
||||||
// run_step_benchmark).
|
// run_step_benchmark).
|
||||||
|
|
||||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepCloth(benchmark::State& state) {
|
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepCable(benchmark::State& state) {
|
||||||
MujocoErrorTestGuard guard;
|
MujocoErrorTestGuard guard;
|
||||||
static mjModel* model = LoadModelFromPath("composite/cloth.xml");
|
static mjModel* model = LoadModelFromPath("plugin/elasticity/flag.xml");
|
||||||
run_step_benchmark(model, state);
|
run_step_benchmark(model, state);
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_StepCloth);
|
BENCHMARK(BM_StepCable);
|
||||||
|
|
||||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepParticle(benchmark::State& state) {
|
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepParticle(benchmark::State& state) {
|
||||||
MujocoErrorTestGuard guard;
|
MujocoErrorTestGuard guard;
|
||||||
@@ -95,7 +95,8 @@ BENCHMARK(BM_StepParticle);
|
|||||||
|
|
||||||
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepFlag(benchmark::State& state) {
|
void ABSL_ATTRIBUTE_NO_TAIL_CALL BM_StepFlag(benchmark::State& state) {
|
||||||
MujocoErrorTestGuard guard;
|
MujocoErrorTestGuard guard;
|
||||||
static mjModel* model = LoadModelFromPath("flag/flag.xml");
|
static mjModel* model =
|
||||||
|
LoadModelFromPath("../test/benchmark/testdata/flag.xml");
|
||||||
run_step_benchmark(model, state);
|
run_step_benchmark(model, state);
|
||||||
}
|
}
|
||||||
BENCHMARK(BM_StepFlag);
|
BENCHMARK(BM_StepFlag);
|
||||||
|
|||||||
Vendored
+5582
File diff suppressed because one or more lines are too long
@@ -57,34 +57,6 @@ TEST_F(UserCompositeTest, MultipleJointsNotAllowedUnlessParticle) {
|
|||||||
HasSubstr("Only particles are allowed to have multiple joints"));
|
HasSubstr("Only particles are allowed to have multiple joints"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(UserCompositeTest, StretchAndTwistAllowed) {
|
|
||||||
static constexpr char xml[] = R"(
|
|
||||||
<mujoco>
|
|
||||||
<worldbody>
|
|
||||||
<body name="B10">
|
|
||||||
<freejoint/>
|
|
||||||
<composite type="rope" count="21 1 1" spacing="0.04">
|
|
||||||
<joint kind="main" damping="0.005"/>
|
|
||||||
<joint kind="stretch" damping="0.005"/>
|
|
||||||
<joint kind="twist" damping="0.005"/>
|
|
||||||
<geom type="capsule" size=".01 .015"/>
|
|
||||||
</composite>
|
|
||||||
</body>
|
|
||||||
</worldbody>
|
|
||||||
</mujoco>
|
|
||||||
)";
|
|
||||||
static char warning[1024];
|
|
||||||
warning[0] = '\0';
|
|
||||||
mju_user_warning = [](const char* msg) {
|
|
||||||
util::strcpy_arr(warning, msg);
|
|
||||||
};
|
|
||||||
std::array<char, 1024> error;
|
|
||||||
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
|
|
||||||
EXPECT_THAT(m, NotNull());
|
|
||||||
EXPECT_THAT(warning, HasSubstr("deprecated"));
|
|
||||||
mj_deleteModel(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(UserCompositeTest, SpacingGreaterThanGeometry) {
|
TEST_F(UserCompositeTest, SpacingGreaterThanGeometry) {
|
||||||
static constexpr char xml[] = R"(
|
static constexpr char xml[] = R"(
|
||||||
<mujoco>
|
<mujoco>
|
||||||
|
|||||||
@@ -795,12 +795,10 @@ TEST_F(XMLWriterTest, WritesSkin) {
|
|||||||
static constexpr char xml[] = R"(
|
static constexpr char xml[] = R"(
|
||||||
<mujoco>
|
<mujoco>
|
||||||
<worldbody>
|
<worldbody>
|
||||||
<body name="B0_0" pos="0 0 0">
|
<composite type="grid" count="2 2 1" spacing="0.05">
|
||||||
<composite type="cloth" count="2 2 1" spacing="0.05">
|
<skin texcoord="true"/>
|
||||||
<skin texcoord="true"/>
|
<geom size=".01"/>
|
||||||
<geom type="ellipsoid" size="1 1 1"/>
|
</composite>
|
||||||
</composite>
|
|
||||||
</body>
|
|
||||||
</worldbody>
|
</worldbody>
|
||||||
</mujoco>
|
</mujoco>
|
||||||
)";
|
)";
|
||||||
@@ -1085,7 +1083,8 @@ TEST_F(PluginTest, WriteReadCompare) {
|
|||||||
|
|
||||||
if (!mtemp) {
|
if (!mtemp) {
|
||||||
// if failing because assets are missing, accept the test
|
// if failing because assets are missing, accept the test
|
||||||
ASSERT_THAT(error.data(), HasSubstr("file")) << error.data();
|
ASSERT_THAT(error.data(), HasSubstr("file"))
|
||||||
|
<< error.data() << " from " << xml.c_str();
|
||||||
} else {
|
} else {
|
||||||
// for a particularly difficult example, relax the tolerance
|
// for a particularly difficult example, relax the tolerance
|
||||||
mjtNum tol =
|
mjtNum tol =
|
||||||
|
|||||||
Reference in New Issue
Block a user