Skip to content

Commit e7a7154

Browse files
powertjcopybara-github
authored andcommitted
Write mesh inertia to defaults when exporting to xml. Fixes #2478
PiperOrigin-RevId: 735338748 Change-Id: Id0b71d06c77baef417f7968ae8a14154243a1f83
1 parent adc3cc0 commit e7a7154

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

src/xml/xml_native_writer.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,6 @@ void mjXWriter::OneMesh(XMLElement* elem, const mjCMesh* mesh, mjCDef* def) {
220220
}
221221
WriteAttrTxt(elem, "content_type", mesh->ContentType());
222222
WriteAttrTxt(elem, "file", mesh->File());
223-
if (mesh->Inertia() != def->Mesh().Inertia()) {
224-
WriteAttrTxt(elem, "inertia", FindValue(meshinertia_map, 4, mesh->Inertia()));
225-
}
226223

227224
// write vertex data
228225
if (!mesh->UserVert().empty()) {
@@ -250,6 +247,9 @@ void mjXWriter::OneMesh(XMLElement* elem, const mjCMesh* mesh, mjCDef* def) {
250247
}
251248

252249
// defaults and regular
250+
if (mesh->Inertia() != def->Mesh().Inertia()) {
251+
WriteAttrTxt(elem, "inertia", FindValue(meshinertia_map, 4, mesh->Inertia()));
252+
}
253253
WriteAttr(elem, "refpos", 3, mesh->Refpos(), def->Mesh().Refpos());
254254
WriteAttr(elem, "refquat", 4, mesh->Refquat(), def->Mesh().Refquat());
255255
WriteAttr(elem, "scale", 3, mesh->Scale(), def->Mesh().Scale());

test/xml/xml_api_test.cc

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace {
3434
using ::testing::IsNull;
3535
using ::testing::NotNull;
3636
using ::testing::StartsWith;
37+
using ::testing::HasSubstr;
3738

3839
static constexpr char xml[] = R"(
3940
<mujoco>
@@ -151,11 +152,46 @@ TEST_F(MujocoTest, SaveXml) {
151152
mjModel* saved_model = mj_compile(saved_spec, 0);
152153
EXPECT_THAT(saved_model, NotNull()) << "Invalid model: " << error.data();
153154

154-
mjtNum tol = 0;
155-
std::string field = "";
156-
EXPECT_LE(CompareModel(model, saved_model, field), tol)
157-
<< "Expected and attached models are different!\n"
158-
<< "Different field: " << field << '\n';
155+
mj_deleteSpec(spec);
156+
mj_deleteSpec(saved_spec);
157+
mj_deleteModel(model);
158+
mj_deleteModel(saved_model);
159+
}
160+
161+
TEST_F(MujocoTest, SaveXmlWithDefaultMesh) {
162+
static constexpr char xml[] = R"(
163+
<mujoco>
164+
<default>
165+
<mesh inertia="shell"/>
166+
</default>
167+
<asset>
168+
<mesh name="test_mesh" vertex="0 0 0 1 0 0 0 1 0 0 0 1"/>
169+
</asset>
170+
<worldbody>
171+
<body>
172+
<geom mesh="test_mesh" type="mesh"/>
173+
</body>
174+
</worldbody>
175+
</mujoco>
176+
)";
177+
178+
std::array<char, 1024> error;
179+
mjSpec* spec = mj_parseXMLString(xml, 0, error.data(), error.size());
180+
EXPECT_THAT(spec, NotNull()) << "Failed to parse spec: " << error.data();
181+
mjModel* model = mj_compile(spec, 0);
182+
EXPECT_THAT(model, NotNull()) << "Failed to compile model: " << error.data();
183+
184+
std::array<char, 1024> out;
185+
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(), error.data(),
186+
error.size()), 0) << error.data();
187+
188+
mjSpec* saved_spec = mj_parseXMLString(xml, 0, error.data(), error.size());
189+
EXPECT_THAT(saved_spec, NotNull()) << "Invalid saved spec: " << error.data();
190+
mjModel* saved_model = mj_compile(saved_spec, 0);
191+
EXPECT_THAT(saved_model, NotNull()) << "Invalid model: " << error.data();
192+
193+
// check that the mesh has inertia="shell"
194+
EXPECT_THAT(out.data(), HasSubstr(R"(<mesh inertia="shell"/>)"));
159195

160196
mj_deleteSpec(spec);
161197
mj_deleteSpec(saved_spec);

0 commit comments

Comments
 (0)