diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc index c3ae1016..436e4fbb 100644 --- a/src/xml/xml_native_writer.cc +++ b/src/xml/xml_native_writer.cc @@ -289,6 +289,11 @@ void mjXWriter::OneGeom(XMLElement* elem, mjCGeom* pgeom, mjCDef* def) { WriteAttr(elem, "margin", 1, &pgeom->margin, &def->geom.margin); WriteAttr(elem, "gap", 1, &pgeom->gap, &def->geom.gap); WriteAttr(elem, "gap", 1, &pgeom->gap, &def->geom.gap); + if (mjuu_defined(pgeom->_mass)) { + WriteAttr(elem, "mass", 1, &pgeom->mass, &def->geom.mass); + } else { + WriteAttr(elem, "density", 1, &pgeom->density, &def->geom.density); + } if (pgeom->material != def->geom.material) { WriteAttrTxt(elem, "material", pgeom->material); } diff --git a/test/xml/xml_native_writer_test.cc b/test/xml/xml_native_writer_test.cc index d7be6e65..7fe2a73a 100644 --- a/test/xml/xml_native_writer_test.cc +++ b/test/xml/xml_native_writer_test.cc @@ -143,6 +143,94 @@ TEST_F(XMLWriterTest, KeepsActlimited) { mj_deleteModel(model); } +TEST_F(XMLWriterTest, UndefinedMassDensity) { + static constexpr char xml[] = R"( + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + std::string saved_xml = SaveAndReadXml(model); + EXPECT_THAT(saved_xml, Not(HasSubstr("density"))); + EXPECT_THAT(saved_xml, Not(HasSubstr("mass"))); + mj_deleteModel(model); +} + +TEST_F(XMLWriterTest, WritesDefaults) { + static constexpr char xml[] = R"( + + + + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + std::string saved_xml = SaveAndReadXml(model); + EXPECT_THAT(saved_xml, Not(HasSubstr("mass"))); + EXPECT_THAT(saved_xml, HasSubstr("")); + mj_deleteModel(model); +} + +TEST_F(XMLWriterTest, WritesDensity) { + static constexpr char xml[] = R"( + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + std::string saved_xml = SaveAndReadXml(model); + EXPECT_THAT(saved_xml, HasSubstr("density=\"100\"")); + EXPECT_THAT(saved_xml, Not(HasSubstr("mass"))); + mj_deleteModel(model); +} + +TEST_F(XMLWriterTest, WritesMass) { + static constexpr char xml[] = R"( + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + std::string saved_xml = SaveAndReadXml(model); + EXPECT_THAT(saved_xml, Not(HasSubstr("density"))); + EXPECT_THAT(saved_xml, HasSubstr("mass=\"0.1\"")); + mj_deleteModel(model); +} + +TEST_F(XMLWriterTest, OverwritesDensity) { + static constexpr char xml[] = R"( + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + std::string saved_xml = SaveAndReadXml(model); + EXPECT_THAT(saved_xml, Not(HasSubstr("density"))); + EXPECT_THAT(saved_xml, HasSubstr("mass=\"100\"")); + mj_deleteModel(model); +} + TEST_F(XMLWriterTest, UsesTwoSpaces) { static constexpr char xml[] = R"(