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.
|
Get spec from body.
|
||||||
|
|
||||||
|
.. _mjs_findSpec:
|
||||||
|
|
||||||
|
mjs_findSpec
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. mujoco-include:: mjs_findSpec
|
||||||
|
|
||||||
|
Find spec (model asset) by name.
|
||||||
|
|
||||||
.. _mjs_findBody:
|
.. _mjs_findBody:
|
||||||
|
|
||||||
mjs_findBody
|
mjs_findBody
|
||||||
|
|||||||
@@ -3600,6 +3600,7 @@ mjsSkin* mjs_addSkin(mjSpec* s);
|
|||||||
mjsTexture* mjs_addTexture(mjSpec* s);
|
mjsTexture* mjs_addTexture(mjSpec* s);
|
||||||
mjsMaterial* mjs_addMaterial(mjSpec* s, mjsDefault* def);
|
mjsMaterial* mjs_addMaterial(mjSpec* s, mjsDefault* def);
|
||||||
mjSpec* mjs_getSpec(mjsElement* element);
|
mjSpec* mjs_getSpec(mjsElement* element);
|
||||||
|
mjSpec* mjs_findSpec(mjSpec* spec, const char* name);
|
||||||
mjsBody* mjs_findBody(mjSpec* s, const char* name);
|
mjsBody* mjs_findBody(mjSpec* s, const char* name);
|
||||||
mjsElement* mjs_findElement(mjSpec* s, mjtObj type, const char* name);
|
mjsElement* mjs_findElement(mjSpec* s, mjtObj type, const char* name);
|
||||||
mjsBody* mjs_findChild(mjsBody* body, 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.
|
// Get spec from body.
|
||||||
MJAPI mjSpec* mjs_getSpec(mjsElement* element);
|
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.
|
// Find body in spec by name.
|
||||||
MJAPI mjsBody* mjs_findBody(mjSpec* s, const char* name);
|
MJAPI mjsBody* mjs_findBody(mjSpec* s, const char* name);
|
||||||
|
|
||||||
|
|||||||
@@ -9742,6 +9742,28 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
),
|
),
|
||||||
doc='Get spec from body.',
|
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',
|
('mjs_findBody',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
name='mjs_findBody',
|
name='mjs_findBody',
|
||||||
|
|||||||
@@ -388,6 +388,9 @@ mjCModel& mjCModel::operator+=(const mjCModel& other) {
|
|||||||
}
|
}
|
||||||
CopyList(numerics_, other.numerics_);
|
CopyList(numerics_, other.numerics_);
|
||||||
CopyList(texts_, other.texts_);
|
CopyList(texts_, other.texts_);
|
||||||
|
for (const auto* s : other.specs_) {
|
||||||
|
specs_.push_back(mj_copySpec(s));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CopyList(flexes_, other.flexes_);
|
CopyList(flexes_, other.flexes_);
|
||||||
CopyList(pairs_, other.pairs_);
|
CopyList(pairs_, other.pairs_);
|
||||||
@@ -3648,12 +3651,6 @@ mjModel* mjCModel::Compile(const mjVFS* vfs, mjModel** m) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy attached specs
|
|
||||||
for (auto spec : specs_) {
|
|
||||||
mj_deleteSpec(spec);
|
|
||||||
}
|
|
||||||
specs_.clear();
|
|
||||||
|
|
||||||
// restore error handler, mark as compiled, return mjModel
|
// restore error handler, mark as compiled, return mjModel
|
||||||
_mjPRIVATE__set_tls_error_fn(save_error);
|
_mjPRIVATE__set_tls_error_fn(save_error);
|
||||||
_mjPRIVATE__set_tls_warning_fn(save_warning);
|
_mjPRIVATE__set_tls_warning_fn(save_warning);
|
||||||
|
|||||||
+2
-2
@@ -387,11 +387,11 @@ mjSpec* ParseXML(const char* filename, const mjVFS* vfs,
|
|||||||
return spec;
|
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();
|
RegisterResourceProvider();
|
||||||
std::string xml2 = {xml.begin(), xml.end()};
|
std::string xml2 = {xml.begin(), xml.end()};
|
||||||
std::string str = "LoadModelFromString:" + xml2;
|
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
|
// 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.
|
// Returns a newly-allocated mjSpec, loaded from the contents of xml.
|
||||||
// On failure returns nullptr and populates the error array if present.
|
// 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
|
// Main writer function
|
||||||
std::string WriteXML(const mjModel* m, const mjSpec* spec, char* error, int nerror);
|
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
|
// parse spec from string
|
||||||
mjSpec* mj_parseXMLString(const char* xml, const mjVFS* vfs, char* error, int error_sz) {
|
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);
|
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
|
||||||
} // namespace mujoco
|
} // namespace mujoco
|
||||||
|
|||||||
Reference in New Issue
Block a user