Add mj_parseXML and mj_saveXML to xml_api.
PiperOrigin-RevId: 640099466 Change-Id: I75f763523c5bc8f6f7c2f2de6806d82ba37ebd4e
This commit is contained in:
committed by
Saran Tunyasuvunakool
parent
1bf90af0e0
commit
b35ae973e1
@@ -25,7 +25,7 @@
|
||||
#include <absl/strings/match.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "src/user/user_api.h"
|
||||
#include "src/xml/xml.h"
|
||||
#include "src/xml/xml_api.h"
|
||||
#include "src/xml/xml_numeric_format.h"
|
||||
#include "test/fixture.h"
|
||||
|
||||
@@ -125,7 +125,7 @@ TEST_F(PluginTest, RecompileCompare) {
|
||||
|
||||
// load spec
|
||||
std::array<char, 1000> err;
|
||||
mjSpec* s = mjParseXML(xml.c_str(), nullptr, err.data(), err.size());
|
||||
mjSpec* s = mj_parseXML(xml.c_str(), 0, err.data(), err.size());
|
||||
|
||||
ASSERT_THAT(s, NotNull())
|
||||
<< "Failed to load " << xml << ": " << err.data();
|
||||
@@ -417,7 +417,7 @@ TEST_F(MujocoTest, AttachSame) {
|
||||
</mujoco>)";
|
||||
|
||||
// create parent
|
||||
mjSpec* parent = ParseSpecFromString(xml_child, er.data(), er.size());
|
||||
mjSpec* parent = mj_parseXMLString(xml_child, 0, er.data(), er.size());
|
||||
EXPECT_THAT(parent, NotNull()) << er.data();
|
||||
|
||||
// get frame
|
||||
@@ -530,7 +530,7 @@ TEST_F(MujocoTest, AttachDifferent) {
|
||||
</mujoco>)";
|
||||
|
||||
// model with one free sphere and a frame
|
||||
mjSpec* parent = ParseSpecFromString(xml_parent, er.data(), er.size());
|
||||
mjSpec* parent = mj_parseXMLString(xml_parent, 0, er.data(), er.size());
|
||||
EXPECT_THAT(parent, NotNull()) << er.data();
|
||||
|
||||
// get frame
|
||||
@@ -538,7 +538,7 @@ TEST_F(MujocoTest, AttachDifferent) {
|
||||
EXPECT_THAT(frame, NotNull());
|
||||
|
||||
// model with one cylinder and a hinge
|
||||
mjSpec* child = ParseSpecFromString(xml_child, er.data(), er.size());
|
||||
mjSpec* child = mj_parseXMLString(xml_child, 0, er.data(), er.size());
|
||||
EXPECT_THAT(child, NotNull()) << er.data();
|
||||
|
||||
// get subtree
|
||||
@@ -642,7 +642,7 @@ TEST_F(MujocoTest, AttachFrame) {
|
||||
</mujoco>)";
|
||||
|
||||
// model with one free sphere and a frame
|
||||
mjSpec* parent = ParseSpecFromString(xml_parent, er.data(), er.size());
|
||||
mjSpec* parent = mj_parseXMLString(xml_parent, 0, er.data(), er.size());
|
||||
EXPECT_THAT(parent, NotNull()) << er.data();
|
||||
|
||||
// get frame
|
||||
@@ -650,7 +650,7 @@ TEST_F(MujocoTest, AttachFrame) {
|
||||
EXPECT_THAT(body, NotNull());
|
||||
|
||||
// model with one cylinder and a hinge
|
||||
mjSpec* child = ParseSpecFromString(xml_child, er.data(), er.size());
|
||||
mjSpec* child = mj_parseXMLString(xml_child, 0, er.data(), er.size());
|
||||
EXPECT_THAT(child, NotNull()) << er.data();
|
||||
|
||||
// get subtree
|
||||
@@ -711,7 +711,7 @@ void TestDetachBody(bool compile) {
|
||||
</mujoco>)";
|
||||
|
||||
// model with one cylinder and a hinge
|
||||
mjSpec* child = ParseSpecFromString(xml_child, er.data(), er.size());
|
||||
mjSpec* child = mj_parseXMLString(xml_child, 0, er.data(), er.size());
|
||||
EXPECT_THAT(child, NotNull()) << er.data();
|
||||
|
||||
// compile model (for testing double compilation)
|
||||
|
||||
+63
-15
@@ -24,6 +24,8 @@
|
||||
#include <mujoco/mjdata.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include "src/user/user_api.h"
|
||||
#include "src/xml/xml_api.h"
|
||||
#include "test/fixture.h"
|
||||
|
||||
namespace mujoco {
|
||||
@@ -33,6 +35,21 @@ using ::testing::IsNull;
|
||||
using ::testing::NotNull;
|
||||
using ::testing::StartsWith;
|
||||
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint/>
|
||||
<geom size="1"/>
|
||||
</body>
|
||||
<body>
|
||||
<joint/>
|
||||
<geom size="0.5"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
// ---------------------------- test mj_loadXML --------------------------------
|
||||
|
||||
using LoadXmlTest = MujocoTest;
|
||||
@@ -66,20 +83,6 @@ TEST_F(LoadXmlTest, InvalidXmlFailsToLoad) {
|
||||
}
|
||||
|
||||
TEST_F(LoadXmlTest, MultipleBodies) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint/>
|
||||
<geom size="1"/>
|
||||
</body>
|
||||
<body>
|
||||
<joint/>
|
||||
<geom size="0.5"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1000> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
|
||||
@@ -92,7 +95,6 @@ TEST_F(LoadXmlTest, MultipleBodies) {
|
||||
mj_deleteData(data);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
using SaveLastXmlTest = MujocoTest;
|
||||
|
||||
TEST_F(SaveLastXmlTest, EmptyModel) {
|
||||
@@ -112,5 +114,51 @@ TEST_F(SaveLastXmlTest, EmptyModel) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, SaveXmlShortString) {
|
||||
std::array<char, 1000> error;
|
||||
|
||||
mjSpec* spec = mj_parseXMLString(xml, 0, error.data(), error.size());
|
||||
EXPECT_THAT(spec, NotNull()) << "Failed to parse spec: " << error.data();
|
||||
mjModel* model = mjs_compile(spec, 0);
|
||||
EXPECT_THAT(model, NotNull()) << "Failed to compile model: " << error.data();
|
||||
|
||||
std::array<char, 10> out;
|
||||
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(),
|
||||
error.data(), error.size()), 0);
|
||||
EXPECT_STREQ(error.data(), "Output string too short, should be at least 273");
|
||||
|
||||
mjs_deleteSpec(spec);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, SaveXml) {
|
||||
std::array<char, 1000> error;
|
||||
|
||||
mjSpec* spec = mj_parseXMLString(xml, 0, error.data(), error.size());
|
||||
EXPECT_THAT(spec, NotNull()) << "Failed to parse spec: " << error.data();
|
||||
mjModel* model = mjs_compile(spec, 0);
|
||||
EXPECT_THAT(model, NotNull()) << "Failed to compile model: " << error.data();
|
||||
|
||||
std::array<char, 273> out;
|
||||
EXPECT_THAT(mj_saveXMLString(spec, out.data(), out.size(), error.data(),
|
||||
error.size()), 1) << error.data();
|
||||
|
||||
mjSpec* saved_spec = mj_parseXMLString(xml, 0, error.data(), error.size());
|
||||
EXPECT_THAT(saved_spec, NotNull()) << "Invalid saved spec: " << error.data();
|
||||
mjModel* saved_model = mjs_compile(saved_spec, 0);
|
||||
EXPECT_THAT(saved_model, NotNull()) << "Invalid model: " << error.data();
|
||||
|
||||
mjtNum tol = 0;
|
||||
std::string field = "";
|
||||
EXPECT_LE(CompareModel(model, saved_model, field), tol)
|
||||
<< "Expected and attached models are different!\n"
|
||||
<< "Different field: " << field << '\n';
|
||||
|
||||
mjs_deleteSpec(spec);
|
||||
mjs_deleteSpec(saved_spec);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteModel(saved_model);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mujoco
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "src/cc/array_safety.h"
|
||||
#include "src/engine/engine_util_errmem.h"
|
||||
#include "src/user/user_api.h"
|
||||
#include "src/xml/xml.h"
|
||||
#include "src/xml/xml_api.h"
|
||||
#include "test/fixture.h"
|
||||
|
||||
namespace mujoco {
|
||||
@@ -1084,7 +1084,7 @@ TEST_F(XMLReaderTest, ParseReplicateDefaultPropagate) {
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjSpec* spec = ParseSpecFromString(xml, error.data(), error.size());
|
||||
mjSpec* spec = mj_parseXMLString(xml, 0, error.data(), error.size());
|
||||
EXPECT_THAT(spec, NotNull()) << error.data();
|
||||
|
||||
mjsBody* torso = mjs_findBody(spec, "torso-0");
|
||||
|
||||
Reference in New Issue
Block a user