Trim trailing default values in saved xmls.
For attributes which accept variable-length inputs. Currently used for `gainprm, biasprm, friction, solref, solimp` Example: - Saved before: `biasprm="0 -3 -4 0 0 0 0 0 0 0"`. - Saved after: `biasprm="0 -3 -4"`. PiperOrigin-RevId: 607609550 Change-Id: I0501348280663867693175236872e2aabc703601
This commit is contained in:
committed by
Copybara-Service
parent
6a346c42e8
commit
f9f7827a64
@@ -296,10 +296,12 @@ void mjXWriter::OneJoint(XMLElement* elem, mjCJoint* pjoint, mjCDef* def) {
|
||||
WriteAttrInt(elem, "group", pjoint->group, def->joint.group);
|
||||
WriteAttr(elem, "ref", 1, &pjoint->ref, &zero);
|
||||
WriteAttr(elem, "springref", 1, &pjoint->springref, &zero);
|
||||
WriteAttr(elem, "solreflimit", mjNREF, pjoint->solref_limit, def->joint.solref_limit);
|
||||
WriteAttr(elem, "solimplimit", mjNIMP, pjoint->solimp_limit, def->joint.solimp_limit);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, pjoint->solref_friction, def->joint.solref_friction);
|
||||
WriteAttr(elem, "solimpfriction", mjNIMP, pjoint->solimp_friction, def->joint.solimp_friction);
|
||||
WriteAttr(elem, "solreflimit", mjNREF, pjoint->solref_limit, def->joint.solref_limit, true);
|
||||
WriteAttr(elem, "solimplimit", mjNIMP, pjoint->solimp_limit, def->joint.solimp_limit, true);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, pjoint->solref_friction, def->joint.solref_friction,
|
||||
true);
|
||||
WriteAttr(elem, "solimpfriction", mjNIMP, pjoint->solimp_friction, def->joint.solimp_friction,
|
||||
true);
|
||||
WriteAttr(elem, "stiffness", 1, &pjoint->stiffness, &def->joint.stiffness);
|
||||
WriteAttrKey(elem, "limited", TFAuto_map, 3, pjoint->limited, def->joint.limited);
|
||||
WriteAttr(elem, "range", 2, pjoint->range, def->joint.range);
|
||||
@@ -373,10 +375,10 @@ void mjXWriter::OneGeom(XMLElement* elem, mjCGeom* pgeom, mjCDef* def) {
|
||||
WriteAttrInt(elem, "condim", pgeom->condim, def->geom.condim);
|
||||
WriteAttrInt(elem, "group", pgeom->group, def->geom.group);
|
||||
WriteAttrInt(elem, "priority", pgeom->priority, def->geom.priority);
|
||||
WriteAttr(elem, "friction", 3, pgeom->friction, def->geom.friction);
|
||||
WriteAttr(elem, "friction", 3, pgeom->friction, def->geom.friction, true);
|
||||
WriteAttr(elem, "solmix", 1, &pgeom->solmix, &def->geom.solmix);
|
||||
WriteAttr(elem, "solref", mjNREF, pgeom->solref, def->geom.solref);
|
||||
WriteAttr(elem, "solimp", mjNIMP, pgeom->solimp, def->geom.solimp);
|
||||
WriteAttr(elem, "solref", mjNREF, pgeom->solref, def->geom.solref, true);
|
||||
WriteAttr(elem, "solimp", mjNIMP, pgeom->solimp, def->geom.solimp, true);
|
||||
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);
|
||||
@@ -533,10 +535,11 @@ void mjXWriter::OnePair(XMLElement* elem, mjCPair* ppair, mjCDef* def) {
|
||||
WriteAttrInt(elem, "condim", ppair->condim, def->pair.spec.condim);
|
||||
WriteAttr(elem, "margin", 1, &ppair->margin, &def->pair.spec.margin);
|
||||
WriteAttr(elem, "gap", 1, &ppair->gap, &def->pair.spec.gap);
|
||||
WriteAttr(elem, "solref", mjNREF, ppair->solref, def->pair.spec.solref);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, ppair->solreffriction, def->pair.spec.solreffriction);
|
||||
WriteAttr(elem, "solimp", mjNIMP, ppair->solimp, def->pair.spec.solimp);
|
||||
WriteAttr(elem, "friction", 5, ppair->friction, def->pair.spec.friction);
|
||||
WriteAttr(elem, "solref", mjNREF, ppair->solref, def->pair.spec.solref, true);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, ppair->solreffriction, def->pair.spec.solreffriction,
|
||||
true);
|
||||
WriteAttr(elem, "solimp", mjNIMP, ppair->solimp, def->pair.spec.solimp, true);
|
||||
WriteAttr(elem, "friction", 5, ppair->friction, def->pair.spec.friction); // all 5 values
|
||||
}
|
||||
|
||||
|
||||
@@ -586,8 +589,8 @@ void mjXWriter::OneEquality(XMLElement* elem, mjCEquality* peq, mjCDef* def) {
|
||||
|
||||
// defaults and regular
|
||||
WriteAttrKey(elem, "active", bool_map, 2, peq->active, def->equality.active);
|
||||
WriteAttr(elem, "solref", mjNREF, peq->solref, def->equality.solref);
|
||||
WriteAttr(elem, "solimp", mjNIMP, peq->solimp, def->equality.solimp);
|
||||
WriteAttr(elem, "solref", mjNREF, peq->solref, def->equality.solref, true);
|
||||
WriteAttr(elem, "solimp", mjNIMP, peq->solimp, def->equality.solimp, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -604,10 +607,12 @@ void mjXWriter::OneTendon(XMLElement* elem, mjCTendon* pten, mjCDef* def) {
|
||||
|
||||
// defaults and regular
|
||||
WriteAttrInt(elem, "group", pten->group, def->tendon.group);
|
||||
WriteAttr(elem, "solreflimit", mjNREF, pten->solref_limit, def->tendon.solref_limit);
|
||||
WriteAttr(elem, "solimplimit", mjNIMP, pten->solimp_limit, def->tendon.solimp_limit);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, pten->solref_friction, def->tendon.solref_friction);
|
||||
WriteAttr(elem, "solimpfriction", mjNIMP, pten->solimp_friction, def->tendon.solimp_friction);
|
||||
WriteAttr(elem, "solreflimit", mjNREF, pten->solref_limit, def->tendon.solref_limit, true);
|
||||
WriteAttr(elem, "solimplimit", mjNIMP, pten->solimp_limit, def->tendon.solimp_limit, true);
|
||||
WriteAttr(elem, "solreffriction", mjNREF, pten->solref_friction, def->tendon.solref_friction,
|
||||
true);
|
||||
WriteAttr(elem, "solimpfriction", mjNIMP, pten->solimp_friction, def->tendon.solimp_friction,
|
||||
true);
|
||||
WriteAttrKey(elem, "limited", TFAuto_map, 3, pten->limited, def->tendon.limited);
|
||||
WriteAttr(elem, "range", 2, pten->range, def->tendon.range);
|
||||
WriteAttr(elem, "margin", 1, &pten->margin, &def->tendon.margin);
|
||||
@@ -711,8 +716,8 @@ void mjXWriter::OneActuator(XMLElement* elem, mjCActuator* pact, mjCDef* def) {
|
||||
}
|
||||
WriteAttrKey(elem, "gaintype", gain_map, gain_sz, pact->gaintype, def->actuator.gaintype);
|
||||
WriteAttrKey(elem, "biastype", bias_map, bias_sz, pact->biastype, def->actuator.biastype);
|
||||
WriteAttr(elem, "gainprm", mjNGAIN, pact->gainprm, def->actuator.gainprm);
|
||||
WriteAttr(elem, "biasprm", mjNBIAS, pact->biasprm, def->actuator.biasprm);
|
||||
WriteAttr(elem, "gainprm", mjNGAIN, pact->gainprm, def->actuator.gainprm, true);
|
||||
WriteAttr(elem, "biasprm", mjNBIAS, pact->biasprm, def->actuator.biasprm, true);
|
||||
}
|
||||
|
||||
// userdata
|
||||
|
||||
+13
-5
@@ -904,7 +904,8 @@ static int Round(double x) {
|
||||
|
||||
// write attribute
|
||||
template<typename T>
|
||||
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, const T* data, const T* def) {
|
||||
void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, const T* data, const T* def,
|
||||
bool trim) {
|
||||
// make sure all are defined
|
||||
if constexpr (std::is_floating_point_v<T>) {
|
||||
for (int i=0; i<n; i++) {
|
||||
@@ -919,6 +920,13 @@ void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, const T* data, con
|
||||
return;
|
||||
}
|
||||
|
||||
// trim identical trailing default values
|
||||
if (trim) {
|
||||
while (n > 0 && data[n-1] == def[n-1]) {
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
// increase precision for testing
|
||||
stringstream stream;
|
||||
stream.precision(mujoco::_mjPRIVATE__get_xml_precision());
|
||||
@@ -945,17 +953,17 @@ void mjXUtil::WriteAttr(XMLElement* elem, string name, int n, const T* data, con
|
||||
|
||||
|
||||
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||
const double* data, const double* def);
|
||||
const double* data, const double* def, bool trim);
|
||||
|
||||
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||
const float* data, const float* def);
|
||||
const float* data, const float* def, bool trim);
|
||||
|
||||
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||
const int* data, const int* def);
|
||||
const int* data, const int* def, bool trim);
|
||||
|
||||
template void mjXUtil::WriteAttr(XMLElement* elem, string name, int n,
|
||||
const unsigned char* data,
|
||||
const unsigned char* def);
|
||||
const unsigned char* def, bool trim);
|
||||
|
||||
|
||||
// write vector<double> attribute, default = zero array
|
||||
|
||||
+1
-1
@@ -195,7 +195,7 @@ class mjXUtil {
|
||||
// write attribute- any type
|
||||
template<typename T>
|
||||
static void WriteAttr(tinyxml2::XMLElement* elem, std::string name, int n, const T* data,
|
||||
const T* def = 0);
|
||||
const T* def = 0, bool trim = false);
|
||||
|
||||
// write vector<double> attribute, with and without default
|
||||
static void WriteVector(tinyxml2::XMLElement* elem, std::string name,
|
||||
|
||||
@@ -722,7 +722,7 @@ TEST_F(XMLWriterTest, WritesActuatorDefaults) {
|
||||
std::string saved_xml = SaveAndReadXml(model);
|
||||
EXPECT_THAT(saved_xml, Not(HasSubstr("mass")));
|
||||
EXPECT_THAT(saved_xml, HasSubstr(
|
||||
"<general biastype=\"affine\" gainprm=\"3 0 0 0 0 0 0 0 0 0\""));
|
||||
"<general biastype=\"affine\" gainprm=\"3\""));
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
@@ -999,6 +999,32 @@ TEST_F(XMLWriterTest, ActdimDefaults) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(XMLWriterTest, TrimsDefaults) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1" friction="0.9" solref="0.1" solimp="0.1 0.2"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="0 2"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<position joint="jnt" kp="3" kv="4"/>
|
||||
<damper joint="jnt" kv="10" ctrlrange="0 1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
mjModel* model = LoadModelFromString(xml);
|
||||
ASSERT_THAT(model, NotNull());
|
||||
std::string saved_xml = SaveAndReadXml(model);
|
||||
EXPECT_THAT(saved_xml, HasSubstr("friction=\"0.9\""));
|
||||
EXPECT_THAT(saved_xml, HasSubstr("solref=\"0.1\""));
|
||||
EXPECT_THAT(saved_xml, HasSubstr("solimp=\"0.1 0.2\""));
|
||||
EXPECT_THAT(saved_xml, HasSubstr("gainprm=\"3\" biasprm=\"0 -3 -4\""));
|
||||
EXPECT_THAT(saved_xml, HasSubstr("gainprm=\"0 0 -10\""));
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
// check that no precision is lost when saving XMLs with FullFloatPrecision
|
||||
TEST_F(XMLWriterTest, SetPrecision) {
|
||||
static constexpr char xml[] = R"(
|
||||
|
||||
Reference in New Issue
Block a user