Add mj_copyBack for copying real-valued arrays from mjModel back to mjSpec.
Also add `SaveAndReadXML` function to test fixture using `mjSpec` as input. PiperOrigin-RevId: 765393821 Change-Id: Ic257addd2fc89678fc11b226c168c077626cc51e
This commit is contained in:
committed by
Copybara-Service
parent
072c872deb
commit
84ad22a590
+16
-4
@@ -130,9 +130,7 @@ std::string GetFileContents(const char* path) {
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
std::string SaveAndReadXml(const mjModel* model) {
|
||||
EXPECT_THAT(model, testing::NotNull());
|
||||
|
||||
std::string SaveAndReadXmlImpl(const mjModel* model, const mjSpec* spec) {
|
||||
constexpr int kMaxPathLen = 1024;
|
||||
std::string path_template =
|
||||
std::filesystem::temp_directory_path().append("tmp.XXXXXX").string();
|
||||
@@ -148,7 +146,11 @@ std::string SaveAndReadXml(const mjModel* model) {
|
||||
EXPECT_NE(_mktemp_s(filepath), EINVAL);
|
||||
#endif
|
||||
|
||||
mj_saveLastXML(filepath, model, nullptr, 0);
|
||||
if (spec) {
|
||||
mj_saveXML(spec, filepath, nullptr, 0);
|
||||
} else if (model) {
|
||||
mj_saveLastXML(filepath, model, nullptr, 0);
|
||||
}
|
||||
std::string contents = GetFileContents(filepath);
|
||||
|
||||
#if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
|
||||
@@ -159,6 +161,16 @@ std::string SaveAndReadXml(const mjModel* model) {
|
||||
return contents;
|
||||
}
|
||||
|
||||
std::string SaveAndReadXml(const mjModel* model) {
|
||||
EXPECT_THAT(model, testing::NotNull());
|
||||
return SaveAndReadXmlImpl(model, nullptr);
|
||||
}
|
||||
|
||||
std::string SaveAndReadXml(const mjSpec* spec) {
|
||||
EXPECT_THAT(spec, testing::NotNull());
|
||||
return SaveAndReadXmlImpl(nullptr, spec);
|
||||
}
|
||||
|
||||
std::vector<mjtNum> GetCtrlNoise(const mjModel* m, int nsteps,
|
||||
mjtNum ctrlnoise) {
|
||||
std::vector<mjtNum> ctrl;
|
||||
|
||||
@@ -102,6 +102,9 @@ mjModel* LoadModelFromPath(const char* model_path);
|
||||
// Returns a string loaded from first saving the model given an input.
|
||||
std::string SaveAndReadXml(const mjModel* model);
|
||||
|
||||
// Returns a string loaded from first saving the spec given an input.
|
||||
std::string SaveAndReadXml(const mjSpec* spec);
|
||||
|
||||
// Adds control noise.
|
||||
std::vector<mjtNum> GetCtrlNoise(const mjModel* m, int nsteps,
|
||||
mjtNum ctrlnoise = 0.01);
|
||||
|
||||
@@ -1498,6 +1498,65 @@ TEST_F(DecompilerTest, SavesStatistics) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerTest, SaveAndReadXml) {
|
||||
static constexpr char xml1[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<geom size="1"/>
|
||||
<geom size="2"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
static constexpr char xml2[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<geom size="1"/>
|
||||
<geom size="2"/>
|
||||
<geom size="3"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* m1 = LoadModelFromString(xml1, error.data(), error.size());
|
||||
ASSERT_THAT(m1, NotNull()) << error.data();
|
||||
m1->geom_size[0] = 10;
|
||||
m1->geom_size[3] = 20;
|
||||
std::string saved_xml = SaveAndReadXml(m1);
|
||||
EXPECT_THAT(saved_xml, HasSubstr("geom size=\"10\""));
|
||||
EXPECT_THAT(saved_xml, HasSubstr("geom size=\"20\""));
|
||||
|
||||
// parse the mjSpec, save it and read it back
|
||||
mjSpec* spec = mj_parseXMLString(xml2, nullptr, error.data(), error.size());
|
||||
EXPECT_THAT(spec, NotNull()) << error.data();
|
||||
mjModel* m2 = mj_compile(spec, nullptr);
|
||||
std::string saved_xml1 = SaveAndReadXml(spec);
|
||||
EXPECT_THAT(saved_xml1, HasSubstr("geom size=\"1\""));
|
||||
EXPECT_THAT(saved_xml1, HasSubstr("geom size=\"2\""));
|
||||
EXPECT_THAT(saved_xml1, HasSubstr("geom size=\"3\""));
|
||||
|
||||
// modify the mjModel, save it and read it back
|
||||
m2->geom_size[0] = .1;
|
||||
m2->geom_size[3] = .2;
|
||||
m2->geom_size[6] = .3;
|
||||
EXPECT_EQ(mj_copyBack(spec, m1), 0);
|
||||
EXPECT_THAT(mjs_getError(spec), HasSubstr("CopyBack"));
|
||||
EXPECT_EQ(mj_copyBack(spec, m2), 1);
|
||||
std::string saved_xml2 = SaveAndReadXml(spec);
|
||||
EXPECT_THAT(saved_xml2, HasSubstr("geom size=\"0.1\""));
|
||||
EXPECT_THAT(saved_xml2, HasSubstr("geom size=\"0.2\""));
|
||||
EXPECT_THAT(saved_xml2, HasSubstr("geom size=\"0.3\""));
|
||||
|
||||
// check that using mjModel as argument writes in the wrong mjSpec
|
||||
std::string saved_xml3 = SaveAndReadXml(m2);
|
||||
EXPECT_THAT(saved_xml3, Not(HasSubstr("geom size=\"0.1\"")));
|
||||
EXPECT_THAT(saved_xml3, Not(HasSubstr("geom size=\"0.2\"")));
|
||||
EXPECT_THAT(saved_xml3, Not(HasSubstr("geom size=\"0.3\"")));
|
||||
|
||||
mj_deleteSpec(spec);
|
||||
mj_deleteModel(m1);
|
||||
mj_deleteModel(m2);
|
||||
}
|
||||
|
||||
TEST_F(DecompilerTest, DoesntSaveInferredStatistics) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
|
||||
Reference in New Issue
Block a user