Do not delete attached specs after compilation.
Also, copy them when copying the spec. PiperOrigin-RevId: 688998464 Change-Id: I7229fd8032eafede582194ccf73ab4160fe06768
This commit is contained in:
committed by
Copybara-Service
parent
e14aebfd16
commit
d17d9e835c
@@ -4139,6 +4139,15 @@ mjs_getSpec
|
||||
|
||||
Get spec from body.
|
||||
|
||||
.. _mjs_findSpec:
|
||||
|
||||
mjs_findSpec
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. mujoco-include:: mjs_findSpec
|
||||
|
||||
Find spec (model asset) by name.
|
||||
|
||||
.. _mjs_findBody:
|
||||
|
||||
mjs_findBody
|
||||
|
||||
@@ -3600,6 +3600,7 @@ mjsSkin* mjs_addSkin(mjSpec* s);
|
||||
mjsTexture* mjs_addTexture(mjSpec* s);
|
||||
mjsMaterial* mjs_addMaterial(mjSpec* s, mjsDefault* def);
|
||||
mjSpec* mjs_getSpec(mjsElement* element);
|
||||
mjSpec* mjs_findSpec(mjSpec* spec, const char* name);
|
||||
mjsBody* mjs_findBody(mjSpec* s, const char* name);
|
||||
mjsElement* mjs_findElement(mjSpec* s, mjtObj type, const char* name);
|
||||
mjsBody* mjs_findChild(mjsBody* body, const char* name);
|
||||
|
||||
@@ -1534,6 +1534,9 @@ MJAPI mjsMaterial* mjs_addMaterial(mjSpec* s, mjsDefault* def);
|
||||
// Get spec from body.
|
||||
MJAPI mjSpec* mjs_getSpec(mjsElement* element);
|
||||
|
||||
// Find spec (model asset) by name.
|
||||
MJAPI mjSpec* mjs_findSpec(mjSpec* spec, const char* name);
|
||||
|
||||
// Find body in spec by name.
|
||||
MJAPI mjsBody* mjs_findBody(mjSpec* s, const char* name);
|
||||
|
||||
|
||||
@@ -9742,6 +9742,28 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
||||
),
|
||||
doc='Get spec from body.',
|
||||
)),
|
||||
('mjs_findSpec',
|
||||
FunctionDecl(
|
||||
name='mjs_findSpec',
|
||||
return_type=PointerType(
|
||||
inner_type=ValueType(name='mjSpec'),
|
||||
),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='spec',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjSpec'),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='name',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Find spec (model asset) by name.',
|
||||
)),
|
||||
('mjs_findBody',
|
||||
FunctionDecl(
|
||||
name='mjs_findBody',
|
||||
|
||||
@@ -388,6 +388,9 @@ mjCModel& mjCModel::operator+=(const mjCModel& other) {
|
||||
}
|
||||
CopyList(numerics_, other.numerics_);
|
||||
CopyList(texts_, other.texts_);
|
||||
for (const auto* s : other.specs_) {
|
||||
specs_.push_back(mj_copySpec(s));
|
||||
}
|
||||
}
|
||||
CopyList(flexes_, other.flexes_);
|
||||
CopyList(pairs_, other.pairs_);
|
||||
@@ -3648,12 +3651,6 @@ mjModel* mjCModel::Compile(const mjVFS* vfs, mjModel** m) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// destroy attached specs
|
||||
for (auto spec : specs_) {
|
||||
mj_deleteSpec(spec);
|
||||
}
|
||||
specs_.clear();
|
||||
|
||||
// restore error handler, mark as compiled, return mjModel
|
||||
_mjPRIVATE__set_tls_error_fn(save_error);
|
||||
_mjPRIVATE__set_tls_warning_fn(save_warning);
|
||||
|
||||
+2
-2
@@ -387,11 +387,11 @@ mjSpec* ParseXML(const char* filename, const mjVFS* vfs,
|
||||
return spec;
|
||||
}
|
||||
|
||||
mjSpec* ParseSpecFromString(std::string_view xml, char* error, int nerror) {
|
||||
mjSpec* ParseSpecFromString(std::string_view xml, const mjVFS* vfs, char* error, int nerror) {
|
||||
RegisterResourceProvider();
|
||||
std::string xml2 = {xml.begin(), xml.end()};
|
||||
std::string str = "LoadModelFromString:" + xml2;
|
||||
return ParseXML(str.c_str(), nullptr, error, nerror);
|
||||
return ParseXML(str.c_str(), vfs, error, nerror);
|
||||
}
|
||||
|
||||
// Main writer function - calls mjXWrite
|
||||
|
||||
+2
-1
@@ -26,7 +26,8 @@ mjSpec* ParseXML(const char* filename, const mjVFS* vfs, char* error, int nerror
|
||||
|
||||
// Returns a newly-allocated mjSpec, loaded from the contents of xml.
|
||||
// On failure returns nullptr and populates the error array if present.
|
||||
mjSpec* ParseSpecFromString(std::string_view xml, char* error = nullptr, int nerror = 0);
|
||||
mjSpec* ParseSpecFromString(std::string_view xml, const mjVFS* vfs = nullptr,
|
||||
char* error = nullptr, int nerror = 0);
|
||||
|
||||
// Main writer function
|
||||
std::string WriteXML(const mjModel* m, const mjSpec* spec, char* error, int nerror);
|
||||
|
||||
+1
-1
@@ -221,7 +221,7 @@ mjSpec* mj_parseXML(const char* filename, const mjVFS* vfs, char* error, int err
|
||||
|
||||
// parse spec from string
|
||||
mjSpec* mj_parseXMLString(const char* xml, const mjVFS* vfs, char* error, int error_sz) {
|
||||
return ParseSpecFromString(xml, error, error_sz);
|
||||
return ParseSpecFromString(xml, vfs, error, error_sz);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1849,5 +1849,57 @@ TEST_F(MujocoTest, DifferentUnitsNotAllowed) {
|
||||
mj_deleteSpec(spec_2);
|
||||
}
|
||||
|
||||
TEST_F(MujocoTest, CopyAttachedSpec) {
|
||||
static constexpr char xml_parent[] = R"(
|
||||
<mujoco>
|
||||
<asset>
|
||||
<model name="child" file="xml_child.xml"/>
|
||||
</asset>
|
||||
<worldbody>
|
||||
<body name="parent">
|
||||
<geom name="geom" size="2"/>
|
||||
<attach model="child" body="body" prefix="other"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
static constexpr char xml_child[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body name="body">
|
||||
<geom name="geom" size="1" pos="2 0 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
auto vfs = std::make_unique<mjVFS>();
|
||||
mj_defaultVFS(vfs.get());
|
||||
mj_addBufferVFS(vfs.get(), "xml_child.xml", xml_child, sizeof(xml_child));
|
||||
|
||||
std::array<char, 1024> er;
|
||||
mjSpec* spec = mj_parseXMLString(xml_parent, vfs.get(), er.data(), er.size());
|
||||
EXPECT_THAT(spec, NotNull()) << er.data();
|
||||
|
||||
mjModel* model = mj_compile(spec, vfs.get());
|
||||
EXPECT_THAT(model, NotNull()) << er.data();
|
||||
|
||||
mjSpec* child = mjs_findSpec(spec, "child");
|
||||
EXPECT_THAT(child, NotNull());
|
||||
|
||||
mjSpec* copy = mj_copySpec(spec);
|
||||
EXPECT_THAT(copy, NotNull());
|
||||
|
||||
mjSpec* child_copy = mjs_findSpec(copy, "child");
|
||||
EXPECT_THAT(child_copy, NotNull());
|
||||
EXPECT_NE(child_copy, child);
|
||||
|
||||
mj_deleteSpec(spec);
|
||||
mj_deleteSpec(copy);
|
||||
mj_deleteModel(model);
|
||||
mj_deleteVFS(vfs.get());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mujoco
|
||||
|
||||
Reference in New Issue
Block a user