diff --git a/test/user/CMakeLists.txt b/test/user/CMakeLists.txt index d31037b1..1672d183 100644 --- a/test/user/CMakeLists.txt +++ b/test/user/CMakeLists.txt @@ -13,7 +13,7 @@ # limitations under the License. mujoco_test(user_model_test) -target_link_libraries(user_model_test fixture gmock) +target_link_libraries(user_model_test fixture gmock absl::str_format) mujoco_test(user_objects_test) target_link_libraries(user_objects_test fixture gmock) diff --git a/test/user/user_model_test.cc b/test/user/user_model_test.cc index 59abbcb3..3abae496 100644 --- a/test/user/user_model_test.cc +++ b/test/user/user_model_test.cc @@ -14,11 +14,11 @@ // Tests for user/user_model.cc. -#include #include #include #include +#include #include #include #include "test/fixture.h" @@ -26,7 +26,9 @@ namespace mujoco { namespace { +using ::testing::DoubleNear; using ::testing::ElementsAre; +using ::testing::NotNull; using UserDataTest = MujocoTest; static std::vector GetRow(const mjtNum* array, int ncolumn, int row) { @@ -188,5 +190,51 @@ TEST_F(UserDataTest, AutoNUserSensor) { mj_deleteModel(m); } +// ------------- test fusestatic ----------------------------------------------- + +using FuseStaticTest = MujocoTest; +TEST_F(FuseStaticTest, FuseStaticEquivalent) { + static constexpr char xml_template[] = R"( + + + + + + + + + + + + + )"; + + std::string fuse = absl::StrFormat(xml_template, "true"); + std::string no_fuse = absl::StrFormat(xml_template, "false"); + + mjModel* m_fuse = LoadModelFromString(fuse.c_str()); + mjModel* m_no_fuse = LoadModelFromString(no_fuse.c_str()); + ASSERT_THAT(m_fuse, NotNull()); + ASSERT_THAT(m_no_fuse, NotNull()); + + EXPECT_EQ(m_fuse->nbody, 2) << "Expecting a world body and one other body"; + EXPECT_EQ(m_no_fuse->nbody, 3) << "Expecting a world body and two others"; + + mjData* d_fuse = mj_makeData(m_fuse); + mjData* d_no_fuse = mj_makeData(m_no_fuse); + + mj_step(m_fuse, d_fuse); + mj_step(m_no_fuse, d_no_fuse); + + EXPECT_THAT(d_fuse->qvel[0], DoubleNear(d_no_fuse->qvel[0], 1e-17)) + << "Velocity should be the same after 1 step"; + EXPECT_NE(d_fuse->qvel[0], 0); + + mj_deleteData(d_fuse); + mj_deleteData(d_no_fuse); + mj_deleteModel(m_fuse); + mj_deleteModel(m_no_fuse); +} + } // namespace } // namespace mujoco