Prevent bodies from overwriting the frame names in xml_native_writer.

PiperOrigin-RevId: 625632369
Change-Id: If3bd048ac40e116fcb97beb3dca3d99826fe4ad0
This commit is contained in:
Alessio Quaglino
2024-04-17 04:06:40 -07:00
committed by Copybara-Service
parent b33230210a
commit 4b6c07cd7d
3 changed files with 19 additions and 7 deletions
+1
View File
@@ -19,6 +19,7 @@ MJX
Bug fixes Bug fixes
^^^^^^^^^ ^^^^^^^^^
4. Defaults of lights were not being saved, now fixed. 4. Defaults of lights were not being saved, now fixed.
5. Prevent overwriting of frame names by body names when saving an XML. Bug introduced in 3.1.4.
Version 3.1.4 (April 10th, 2024) Version 3.1.4 (April 10th, 2024)
+13 -5
View File
@@ -1454,7 +1454,7 @@ void mjXWriter::Asset(XMLElement* root) {
// recursive body writer // recursive body and frame writer
void mjXWriter::Body(XMLElement* elem, mjCBody* body, mjCFrame* frame) { void mjXWriter::Body(XMLElement* elem, mjCBody* body, mjCFrame* frame) {
double unitq[4] = {1, 0, 0, 0}; double unitq[4] = {1, 0, 0, 0};
@@ -1462,14 +1462,14 @@ void mjXWriter::Body(XMLElement* elem, mjCBody* body, mjCFrame* frame) {
throw mjXError(0, "missing body in XML write"); // SHOULD NOT OCCUR throw mjXError(0, "missing body in XML write"); // SHOULD NOT OCCUR
} }
// write frame if classname is defined // write frame if defined
if (frame) { if (frame) {
WriteAttrTxt(elem, "name", frame->name); WriteAttrTxt(elem, "name", frame->name);
WriteAttrTxt(elem, "childclass", frame->classname); WriteAttrTxt(elem, "childclass", frame->classname);
} }
// write body attributes and inertial // write body attributes and inertial
if (body!=model->GetWorld()) { else if (body!=model->GetWorld()) {
WriteAttrTxt(elem, "name", body->name); WriteAttrTxt(elem, "name", body->name);
WriteAttrTxt(elem, "childclass", body->classname); WriteAttrTxt(elem, "childclass", body->classname);
@@ -1537,10 +1537,18 @@ void mjXWriter::Body(XMLElement* elem, mjCBody* body, mjCFrame* frame) {
// write frames // write frames
for (int i=0; i<body->frames.size(); i++) { for (int i=0; i<body->frames.size(); i++) {
if (body->frames[i]->frame != frame) continue; // skip current frame
if (body->frames[i]->frame != frame) {
continue;
}
// write frame if named or has defaults
if (!body->frames[i]->name.empty() || !body->frames[i]->classname.empty()) { if (!body->frames[i]->name.empty() || !body->frames[i]->classname.empty()) {
Body(InsertEnd(elem, "frame"), body, body->frames[i]); Body(InsertEnd(elem, "frame"), body, body->frames[i]);
} else { }
// otherwise skip
else {
Body(elem, body, body->frames[i]); Body(elem, body, body->frames[i]);
} }
} }
+5 -2
View File
@@ -736,7 +736,7 @@ TEST_F(XMLWriterTest, WritesFrameDefaults) {
<geom size=".5" euler="0 0 20"/> <geom size=".5" euler="0 0 20"/>
</frame> </frame>
<body> <body name="body">
<frame pos="0 1 0" name="f2" childclass="dframe"> <frame pos="0 1 0" name="f2" childclass="dframe">
<geom pos="0 1 0"/> <geom pos="0 1 0"/>
<body pos="1 0 0"> <body pos="1 0 0">
@@ -752,7 +752,10 @@ TEST_F(XMLWriterTest, WritesFrameDefaults) {
EXPECT_THAT(model, NotNull()) << error.data(); EXPECT_THAT(model, NotNull()) << error.data();
std::string saved_xml = SaveAndReadXml(model); std::string saved_xml = SaveAndReadXml(model);
EXPECT_THAT(saved_xml, HasSubstr("frame name=\"f1\"")); EXPECT_THAT(saved_xml, HasSubstr("frame name=\"f1\""));
EXPECT_THAT(saved_xml, HasSubstr("frame name=\"f2\" childclass=\"dframe\"")); EXPECT_THAT(saved_xml, HasSubstr("frame name=\"f2\" childclass=\"dframe\">"));
EXPECT_THAT(saved_xml, HasSubstr("geom pos=\"0 2 0\""));
EXPECT_THAT(saved_xml, HasSubstr("body pos=\"1 1 0\""));
EXPECT_THAT(saved_xml, HasSubstr("geom pos=\"0 0 1\""));
EXPECT_THAT(saved_xml, Not(HasSubstr("<frame>"))); EXPECT_THAT(saved_xml, Not(HasSubstr("<frame>")));
mj_deleteModel(model); mj_deleteModel(model);
} }