Fixed a bug that caused dim to be necessary in flexcomp even when it was inferred from GMSH files.
Fixes #2107. Co-authored-by: Alessio Quaglino <quaglino@google.com> PiperOrigin-RevId: 684419740 Change-Id: Ia73e719bd37503563223ed92f4dbe0ae07eef300
This commit is contained in:
committed by
Copybara-Service
parent
22e4f7fc31
commit
694bdebc19
+17
-17
@@ -101,7 +101,7 @@ mjCFlexcomp::mjCFlexcomp(void) {
|
||||
bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
mjCModel* model = (mjCModel*)spec->element;
|
||||
mjsFlex* dflex = def.spec.flex;
|
||||
int dim = dflex->dim;
|
||||
|
||||
bool radial = (type == mjFCOMPTYPE_BOX ||
|
||||
type == mjFCOMPTYPE_CYLINDER ||
|
||||
type == mjFCOMPTYPE_ELLIPSOID);
|
||||
@@ -115,13 +115,13 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
}
|
||||
|
||||
// check dim
|
||||
if (dim < 1 || dim > 3) {
|
||||
if (dflex->dim < 1 || dflex->dim > 3) {
|
||||
return comperr(error, "Invalid dim, must be between 1 and 3", error_sz);
|
||||
}
|
||||
|
||||
// check counts
|
||||
for (int i=0; i < 3; i++) {
|
||||
if (count[i] < 1 || ((radial && count[i] < 2) && dim == 3)) {
|
||||
if (count[i] < 1 || ((radial && count[i] < 2) && dflex->dim == 3)) {
|
||||
return comperr(error, "Count too small", error_sz);
|
||||
}
|
||||
}
|
||||
@@ -191,7 +191,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
|
||||
// force flatskin shading for box, cylinder and 3D grid
|
||||
if (type == mjFCOMPTYPE_BOX || type == mjFCOMPTYPE_CYLINDER ||
|
||||
(type == mjFCOMPTYPE_GRID && dim == 3)) {
|
||||
(type == mjFCOMPTYPE_GRID && dflex->dim == 3)) {
|
||||
dflex->flatskin = true;
|
||||
}
|
||||
|
||||
@@ -199,16 +199,16 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
if (pinrange.size()%2) {
|
||||
return comperr(error, "Pin range number must be multiple of 2", error_sz);
|
||||
}
|
||||
if (pingrid.size()%dim) {
|
||||
if (pingrid.size()%dflex->dim) {
|
||||
return comperr(error, "Pin grid number must be multiple of dim", error_sz);
|
||||
}
|
||||
if (pingridrange.size()%(2*dim)) {
|
||||
if (pingridrange.size()%(2*dflex->dim)) {
|
||||
return comperr(error, "Pin grid range number of must be multiple of 2*dim", error_sz);
|
||||
}
|
||||
if (type != mjFCOMPTYPE_GRID && !(pingrid.empty() && pingridrange.empty())) {
|
||||
return comperr(error, "Pin grid(range) can only be used with grid type", error_sz);
|
||||
}
|
||||
if (dim == 1 && !(pingrid.empty() && pingridrange.empty())) {
|
||||
if (dflex->dim == 1 && !(pingrid.empty() && pingridrange.empty())) {
|
||||
return comperr(error, "Pin grid(range) cannot be used with dim=1", error_sz);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
}
|
||||
|
||||
// check element size
|
||||
if (element.size()%(dim+1)) {
|
||||
if (element.size()%(dflex->dim+1)) {
|
||||
return comperr(error, "Element size must be a multiple of dim+1", error_sz);
|
||||
}
|
||||
|
||||
@@ -289,41 +289,41 @@ bool mjCFlexcomp::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz) {
|
||||
}
|
||||
|
||||
// process pingrid
|
||||
for (int i=0; i < (int)pingrid.size(); i+=dim) {
|
||||
for (int i=0; i < (int)pingrid.size(); i+=dflex->dim) {
|
||||
// check range
|
||||
for (int k=0; k < dim; k++) {
|
||||
for (int k=0; k < dflex->dim; k++) {
|
||||
if (pingrid[i+k] < 0 || pingrid[i+k] >= count[k]) {
|
||||
return comperr(error, "pingrid out of range", error_sz);
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
if (dim == 2) {
|
||||
if (dflex->dim == 2) {
|
||||
pinned[GridID(pingrid[i], pingrid[i+1])] = true;
|
||||
}
|
||||
else if (dim == 3) {
|
||||
else if (dflex->dim == 3) {
|
||||
pinned[GridID(pingrid[i], pingrid[i+1], pingrid[i+2])] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// process pingridrange
|
||||
for (int i=0; i < (int)pingridrange.size(); i+=2*dim) {
|
||||
for (int i=0; i < (int)pingridrange.size(); i+=2*dflex->dim) {
|
||||
// check range
|
||||
for (int k=0; k < 2*dim; k++) {
|
||||
if (pingridrange[i+k] < 0 || pingridrange[i+k] >= count[k%dim]) {
|
||||
for (int k=0; k < 2*dflex->dim; k++) {
|
||||
if (pingridrange[i+k] < 0 || pingridrange[i+k] >= count[k%dflex->dim]) {
|
||||
return comperr(error, "pingridrange out of range", error_sz);
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
if (dim == 2) {
|
||||
if (dflex->dim == 2) {
|
||||
for (int ix=pingridrange[i]; ix <= pingridrange[i+2]; ix++) {
|
||||
for (int iy=pingridrange[i+1]; iy <= pingridrange[i+3]; iy++) {
|
||||
pinned[GridID(ix, iy)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dim==3) {
|
||||
else if (dflex->dim==3) {
|
||||
for (int ix=pingridrange[i]; ix <= pingridrange[i+3]; ix++) {
|
||||
for (int iy=pingridrange[i+1]; iy <= pingridrange[i+4]; iy++) {
|
||||
for (int iz=pingridrange[i+2]; iz <= pingridrange[i+5]; iz++) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<mujoco model="gmsh">
|
||||
<option timestep="0.01" integrator="implicitfast" solver="CG"/>
|
||||
|
||||
<asset>
|
||||
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="512" height="512"/>
|
||||
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
|
||||
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
|
||||
</asset>
|
||||
|
||||
<visual>
|
||||
<headlight diffuse="0.9 0.9 0.9" ambient="0.3 0.3 0.3" specular="0 0 0"/>
|
||||
<map force="0.1" zfar="30"/>
|
||||
<rgba haze="0.15 0.25 0.35 1"/>
|
||||
<quality shadowsize="4096"/>
|
||||
<global offwidth="800" offheight="800"/>
|
||||
</visual>
|
||||
|
||||
<worldbody>
|
||||
<geom name="floor" size="1 1 .05" type="plane" material="grid" condim="3"/>
|
||||
<light directional="false" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1"/>
|
||||
<flexcomp name="cube" type="gmsh" rgba=".8 .2 .2 1" radius="0.001" pos="0 0 0.3"
|
||||
mass="10" scale="1 1 1" file="cube_22_ascii_vol_gmshApp.msh">
|
||||
<edge equality="true"/>
|
||||
</flexcomp>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
Vendored
+30
-10
@@ -243,7 +243,7 @@ TEST_F(UserFlexTest, RigidFlex) {
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHBinaryGMSH_41_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHBinary_41_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_41_binary_vol_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -252,12 +252,13 @@ TEST_F(UserFlexTest, LoadMSHBinaryGMSH_41_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_step(m, d);
|
||||
mj_deleteModel(m);
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHBinaryGMSH_22_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHBinary_22_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_22_binary_vol_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -266,12 +267,13 @@ TEST_F(UserFlexTest, LoadMSHBinaryGMSH_22_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_step(m, d);
|
||||
mj_deleteModel(m);
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_41_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceBinary_41_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_41_binary_surf_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -280,6 +282,7 @@ TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_41_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 2);
|
||||
|
||||
// first node x y z
|
||||
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||
@@ -296,7 +299,7 @@ TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_41_Success) {
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_22_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceBinary_22_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_22_binary_surf_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -305,6 +308,7 @@ TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_22_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 2);
|
||||
|
||||
// first node x y z
|
||||
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||
@@ -323,19 +327,20 @@ TEST_F(UserFlexTest, LoadMSHSurfaceBinaryGMSH_22_Success) {
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHBinaryFTETWILD_22_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/shark_22_binary_fTetWild.xml");
|
||||
GetTestDataFilePath("user/testdata/shark_22_binary_vol_fTetWild.xml");
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||
ASSERT_THAT(m, NotNull()) << error.data();
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 429);
|
||||
EXPECT_EQ(m->nflexelem, 1073);
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_step(m, d);
|
||||
mj_deleteModel(m);
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHASCIIGMSH_41_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHASCII_41_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_41_ascii_vol_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -344,12 +349,13 @@ TEST_F(UserFlexTest, LoadMSHASCIIGMSH_41_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_step(m, d);
|
||||
mj_deleteModel(m);
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHASCIIGMSH_22_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHASCII_22_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_22_ascii_vol_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -358,12 +364,13 @@ TEST_F(UserFlexTest, LoadMSHASCIIGMSH_22_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_step(m, d);
|
||||
mj_deleteModel(m);
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_41_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceASCII_41_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_41_ascii_surf_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -372,6 +379,7 @@ TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_41_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 2);
|
||||
|
||||
// first node x y z
|
||||
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||
@@ -388,7 +396,7 @@ TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_41_Success) {
|
||||
mj_deleteData(d);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_22_Success) {
|
||||
TEST_F(UserFlexTest, LoadMSHSurfaceASCII_22_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/cube_22_ascii_surf_gmshApp.xml");
|
||||
std::array<char, 1024> error;
|
||||
@@ -397,6 +405,7 @@ TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_22_Success) {
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 14);
|
||||
EXPECT_EQ(m->nflexelem, 24);
|
||||
EXPECT_EQ(m->flex_dim[0], 2);
|
||||
|
||||
// first node x y z
|
||||
EXPECT_EQ(m->flex_xvert0[0], -0.5 );
|
||||
@@ -415,13 +424,14 @@ TEST_F(UserFlexTest, LoadMSHSurfaceASCIIGMSH_22_Success) {
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHASCIIFTETWILD_22_Success) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath("user/testdata/shark_22_ascii_fTetWild.xml");
|
||||
GetTestDataFilePath("user/testdata/shark_22_ascii_vol_fTetWild.xml");
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||
ASSERT_THAT(m, NotNull()) << error.data();
|
||||
mjData* d = mj_makeData(m);
|
||||
EXPECT_EQ(m->nflexvert, 425);
|
||||
EXPECT_EQ(m->nflexelem, 1070);
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_step(m, d);
|
||||
mj_deleteModel(m);
|
||||
mj_deleteData(d);
|
||||
@@ -517,5 +527,15 @@ TEST_F(UserFlexTest, LoadMSHASCII_22_MissingElement_Fail) {
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
TEST_F(UserFlexTest, LoadMSHASCII_dim_missing_in_xml) {
|
||||
const std::string xml_path =
|
||||
GetTestDataFilePath(
|
||||
"user/testdata/cube_22_ascii_vol_gmshApp_missing_dim.xml");
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
|
||||
EXPECT_EQ(m->flex_dim[0], 3);
|
||||
mj_deleteModel(m);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mujoco
|
||||
|
||||
Reference in New Issue
Block a user