diff --git a/src/user/user_flexcomp.cc b/src/user/user_flexcomp.cc index 3165d9e7..2f4aa428 100644 --- a/src/user/user_flexcomp.cc +++ b/src/user/user_flexcomp.cc @@ -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++) { diff --git a/test/user/testdata/cube_22_ascii_vol_gmshApp_missing_dim.xml b/test/user/testdata/cube_22_ascii_vol_gmshApp_missing_dim.xml new file mode 100644 index 00000000..3c08c9ef --- /dev/null +++ b/test/user/testdata/cube_22_ascii_vol_gmshApp_missing_dim.xml @@ -0,0 +1,26 @@ + + diff --git a/test/user/testdata/shark_22_ascii_fTetWild.xml b/test/user/testdata/shark_22_ascii_vol_fTetWild.xml similarity index 100% rename from test/user/testdata/shark_22_ascii_fTetWild.xml rename to test/user/testdata/shark_22_ascii_vol_fTetWild.xml diff --git a/test/user/testdata/shark_22_binary_fTetWild.xml b/test/user/testdata/shark_22_binary_vol_fTetWild.xml similarity index 100% rename from test/user/testdata/shark_22_binary_fTetWild.xml rename to test/user/testdata/shark_22_binary_vol_fTetWild.xml diff --git a/test/user/user_flex_test.cc b/test/user/user_flex_test.cc index d55f433e..1e2c168d 100644 --- a/test/user/user_flex_test.cc +++ b/test/user/user_flex_test.cc @@ -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 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 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 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 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 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 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 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 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 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 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 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