Combine all mjs_attach functions into one.
PiperOrigin-RevId: 742702092 Change-Id: I89e35c59ada017cd061e2031584eeea71776743d
This commit is contained in:
committed by
Copybara-Service
parent
08d22baea1
commit
a02a27d4a4
@@ -3808,41 +3808,14 @@ Free all pointers with ``mju_free()``.
|
||||
|
||||
Attachment
|
||||
^^^^^^^^^^
|
||||
.. _mjs_attachBody:
|
||||
.. _mjs_attach:
|
||||
|
||||
`mjs_attachBody <#mjs_attachBody>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
`mjs_attach <#mjs_attach>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. mujoco-include:: mjs_attachBody
|
||||
.. mujoco-include:: mjs_attach
|
||||
|
||||
Attach child body to a parent frame, return the attached body if success or NULL otherwise.
|
||||
|
||||
.. _mjs_attachFrame:
|
||||
|
||||
`mjs_attachFrame <#mjs_attachFrame>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. mujoco-include:: mjs_attachFrame
|
||||
|
||||
Attach child frame to a parent body, return the attached frame if success or NULL otherwise.
|
||||
|
||||
.. _mjs_attachToSite:
|
||||
|
||||
`mjs_attachToSite <#mjs_attachToSite>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. mujoco-include:: mjs_attachToSite
|
||||
|
||||
Attach child body to a parent site, return the attached body if success or NULL otherwise.
|
||||
|
||||
.. _mjs_attachFrameToSite:
|
||||
|
||||
`mjs_attachFrameToSite <#mjs_attachFrameToSite>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. mujoco-include:: mjs_attachFrameToSite
|
||||
|
||||
Attach child frame to a parent site, return the attached frame if success or NULL otherwise.
|
||||
Attach child to a parent, return the attached element if success or NULL otherwise.
|
||||
|
||||
.. _mjs_detachBody:
|
||||
|
||||
|
||||
@@ -175,11 +175,10 @@ replicating 200 times, suffixes will be ``000, 001, ...`` etc). All referencing
|
||||
and namespaced appropriately. Detailed examples of models using replicate can be found in the
|
||||
`model/replicate/ <https://github.com/google-deepmind/mujoco/tree/main/model/replicate>`__ directory.
|
||||
|
||||
There is a caveat concerning :ref:`keyframes<keyframe>` when using replicate. Since :ref:`mjs_attachFrame` is used to
|
||||
There is a caveat concerning :ref:`keyframes<keyframe>` when using replicate. Since :ref:`mjs_attach` is used to
|
||||
self-attach multiple times the enclosed kinematic tree, if this tree contains further :ref:`attach<body-attach>`
|
||||
elements, keyframes will not be replicated nor namespaced by :ref:`replicate<replicate>`, but they will be attached and
|
||||
namespaced once by the innermost call of :ref:`mjs_attachFrame` or :ref:`mjs_attachBody`. See the limitations discussed
|
||||
in :ref:`attach<body-attach>`.
|
||||
namespaced once by the innermost call of :ref:`mjs_attach`. See the limitations discussed in :ref:`attach<body-attach>`.
|
||||
|
||||
.. _replicate-count:
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ Upcoming version (not yet released)
|
||||
|
||||
- The default value of the flag for toggling :ref:`internal flex contacts<flex-contact-internal>` was changed from
|
||||
"true" to "false". This feature has proven to be counterintuitive for users.
|
||||
- All of the attach functions (``mjs_attachBody``, ``mjs_attachFrame``, ``mjs_attachToSite``,
|
||||
``mjs_attachFrameToSite``) have been removed and replaced by a single function :ref:`mjs_attach`.
|
||||
|
||||
General
|
||||
^^^^^^^
|
||||
|
||||
@@ -3613,14 +3613,8 @@ void mju_threadPoolEnqueue(mjThreadPool* thread_pool, mjTask* task);
|
||||
void mju_threadPoolDestroy(mjThreadPool* thread_pool);
|
||||
void mju_defaultTask(mjTask* task);
|
||||
void mju_taskJoin(mjTask* task);
|
||||
mjsBody* mjs_attachBody(mjsFrame* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix);
|
||||
mjsFrame* mjs_attachFrame(mjsBody* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix);
|
||||
mjsBody* mjs_attachToSite(mjsSite* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix);
|
||||
mjsFrame* mjs_attachFrameToSite(mjsSite* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix);
|
||||
mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||
const char* prefix, const char* suffix);
|
||||
int mjs_detachBody(mjSpec* s, mjsBody* b);
|
||||
int mjs_detachDefault(mjSpec* s, mjsDefault* d);
|
||||
mjsBody* mjs_addBody(mjsBody* body, const mjsDefault* def);
|
||||
|
||||
@@ -111,9 +111,10 @@ This framework introduces a powerful new feature: attaching and detaching model
|
||||
to power the :ref:`attach<body-attach>` an :ref:`replicate<replicate>` meta-elements in MJCF. Attachment allows the user
|
||||
to move or copy a subtree from one model into another, while also copying or moving related referenced assets and
|
||||
referencing elements from outside the kinematic tree (e.g., actuators and sensors). Similarly, detaching a subtree will
|
||||
remove all associated elements from the model. The default behavior is to move during attach. The user can select to
|
||||
instead copy by passing the corresponding flag to ``mjs_setDeepCopy``. This flag is temporary set to true while parsing
|
||||
XMLs. It is possible to :ref:`attach a body to a frame<mjs_attachBody>`:
|
||||
remove all associated elements from the model. The default behavior is to move the child into the parent while
|
||||
attaching, so subsequent changes to the child will also change the parent. Alternatively, the user can choose to make an
|
||||
entirely new copy during attach using :ref:`mjs_setDeepCopy`. This flag is temporarily set to true while parsing XMLs.
|
||||
It is possible to :ref:`attach a body to a frame<mjs_attach>`:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
@@ -121,29 +122,29 @@ XMLs. It is possible to :ref:`attach a body to a frame<mjs_attachBody>`:
|
||||
mjSpec* child = mj_makeSpec();
|
||||
parent->compiler.degree = 0;
|
||||
child->compiler.degree = 1;
|
||||
mjsFrame* frame = mjs_addFrame(mjs_findBody(parent, "world"), NULL);
|
||||
mjsBody* body = mjs_addBody(mjs_findBody(child, "world"), NULL);
|
||||
mjsBody* attached_body_1 = mjs_attachBody(frame, body, "attached-", "-1");
|
||||
mjsElement* frame = mjs_addFrame(mjs_findBody(parent, "world"), NULL)->element;
|
||||
mjsElement* body = mjs_addBody(mjs_findBody(child, "world"), NULL)->element;
|
||||
mjsBody* attached_body_1 = mjs_asBody(mjs_attach(frame, body, "attached-", "-1"));
|
||||
|
||||
or :ref:`attach a body to a site<mjs_attachToSite>`:
|
||||
or :ref:`attach a body to a site<mjs_attach>`:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
mjSpec* parent = mj_makeSpec();
|
||||
mjSpec* child = mj_makeSpec();
|
||||
mjsSite* site = mjs_addSite(mjs_findBody(parent, "world"), NULL);
|
||||
mjsBody* body = mjs_addBody(mjs_findBody(child, "world"), NULL);
|
||||
mjsBody* attached_body_2 = mjs_attachToSite(site, body, "attached-", "-2");
|
||||
mjsElement* site = mjs_addSite(mjs_findBody(parent, "world"), NULL)->element;
|
||||
mjsElement* body = mjs_addBody(mjs_findBody(child, "world"), NULL)->element;
|
||||
mjsBody* attached_body_2 = mjs_asBody(mjs_attach(site, body, "attached-", "-2"));
|
||||
|
||||
or :ref:`attach a frame to a body<mjs_attachFrame>`:
|
||||
or :ref:`attach a frame to a body<mjs_attach>`:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
mjSpec* parent = mj_makeSpec();
|
||||
mjSpec* child = mj_makeSpec();
|
||||
mjsBody* body = mjs_addBody(mjs_findBody(parent, "world"), NULL);
|
||||
mjsFrame* frame = mjs_addFrame(mjs_findBody(child, "world"), NULL);
|
||||
mjsFrame* attached_frame = mjs_attachFrame(body, frame, "attached-", "-1");
|
||||
mjsElement* body = mjs_addBody(mjs_findBody(parent, "world"), NULL)->element;
|
||||
mjsElement* frame = mjs_addFrame(mjs_findBody(child, "world"), NULL)->element;
|
||||
mjsFrame* attached_frame = mjs_asFrame(mjs_attach(body, frame, "attached-", "-1"));
|
||||
|
||||
Note that in the above examples, the parent and child models have different values for ``compiler.degree``,
|
||||
corresponding to the :ref:`compiler/angle<compiler-angle>` attribute, specifying the units in which angles are
|
||||
|
||||
+3
-15
@@ -1414,21 +1414,9 @@ MJAPI void mju_taskJoin(mjTask* task);
|
||||
|
||||
//---------------------------------- Attachment ----------------------------------------------------
|
||||
|
||||
// Attach child body to a parent frame, return the attached body if success or NULL otherwise.
|
||||
MJAPI mjsBody* mjs_attachBody(mjsFrame* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Attach child frame to a parent body, return the attached frame if success or NULL otherwise.
|
||||
MJAPI mjsFrame* mjs_attachFrame(mjsBody* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Attach child body to a parent site, return the attached body if success or NULL otherwise.
|
||||
MJAPI mjsBody* mjs_attachToSite(mjsSite* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Attach child frame to a parent site, return the attached frame if success or NULL otherwise.
|
||||
MJAPI mjsFrame* mjs_attachFrameToSite(mjsSite* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix);
|
||||
// Attach child to a parent, return the attached element if success or NULL otherwise.
|
||||
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Delete body and descendants from mjSpec, remove all references, return 0 on success.
|
||||
MJAPI int mjs_detachBody(mjSpec* s, mjsBody* b);
|
||||
|
||||
@@ -9000,23 +9000,23 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
||||
),
|
||||
doc='Wait for a task to complete.',
|
||||
)),
|
||||
('mjs_attachBody',
|
||||
('mjs_attach',
|
||||
FunctionDecl(
|
||||
name='mjs_attachBody',
|
||||
name='mjs_attach',
|
||||
return_type=PointerType(
|
||||
inner_type=ValueType(name='mjsBody'),
|
||||
inner_type=ValueType(name='mjsElement'),
|
||||
),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='parent',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsFrame'),
|
||||
inner_type=ValueType(name='mjsElement'),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='child',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsBody', is_const=True),
|
||||
inner_type=ValueType(name='mjsElement', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
@@ -9032,109 +9032,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Attach child body to a parent frame, return the attached body if success or NULL otherwise.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mjs_attachFrame',
|
||||
FunctionDecl(
|
||||
name='mjs_attachFrame',
|
||||
return_type=PointerType(
|
||||
inner_type=ValueType(name='mjsFrame'),
|
||||
),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='parent',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsBody'),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='child',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsFrame', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='prefix',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='suffix',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Attach child frame to a parent body, return the attached frame if success or NULL otherwise.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mjs_attachToSite',
|
||||
FunctionDecl(
|
||||
name='mjs_attachToSite',
|
||||
return_type=PointerType(
|
||||
inner_type=ValueType(name='mjsBody'),
|
||||
),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='parent',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsSite'),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='child',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsBody', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='prefix',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='suffix',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Attach child body to a parent site, return the attached body if success or NULL otherwise.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mjs_attachFrameToSite',
|
||||
FunctionDecl(
|
||||
name='mjs_attachFrameToSite',
|
||||
return_type=PointerType(
|
||||
inner_type=ValueType(name='mjsFrame'),
|
||||
),
|
||||
parameters=(
|
||||
FunctionParameterDecl(
|
||||
name='parent',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsSite'),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='child',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='mjsFrame', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='prefix',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
FunctionParameterDecl(
|
||||
name='suffix',
|
||||
type=PointerType(
|
||||
inner_type=ValueType(name='char', is_const=True),
|
||||
),
|
||||
),
|
||||
),
|
||||
doc='Attach child frame to a parent site, return the attached frame if success or NULL otherwise.', # pylint: disable=line-too-long
|
||||
doc='Attach child to a parent, return the attached element if success or NULL otherwise.', # pylint: disable=line-too-long
|
||||
)),
|
||||
('mjs_detachBody',
|
||||
FunctionDecl(
|
||||
|
||||
+13
-11
@@ -540,7 +540,7 @@ PYBIND11_MODULE(_specs, m) {
|
||||
SetFrame(worldbody, mjOBJ_CAMERA, worldframe);
|
||||
const char* p = prefix.has_value() ? prefix.value().c_str() : "";
|
||||
const char* s = suffix.has_value() ? suffix.value().c_str() : "";
|
||||
raw::MjsFrame* attached_frame = nullptr;
|
||||
raw::MjsElement* attached_frame = nullptr;
|
||||
if (frame.has_value()) {
|
||||
raw::MjsFrame* frame_ptr = nullptr;
|
||||
try {
|
||||
@@ -560,11 +560,12 @@ PYBIND11_MODULE(_specs, m) {
|
||||
if (!parent_body) {
|
||||
throw pybind11::value_error("Frame does not have a parent body.");
|
||||
}
|
||||
attached_frame = mjs_attachFrame(parent_body, worldframe, p, s);
|
||||
attached_frame =
|
||||
mjs_attach(parent_body->element, worldframe->element, p, s);
|
||||
if (!attached_frame) {
|
||||
throw pybind11::value_error(mjs_getError(self.ptr));
|
||||
}
|
||||
if (mjs_setFrame(attached_frame->element, frame_ptr) != 0) {
|
||||
if (mjs_setFrame(attached_frame, frame_ptr) != 0) {
|
||||
throw pybind11::value_error(mjs_getError(self.ptr));
|
||||
}
|
||||
}
|
||||
@@ -583,7 +584,8 @@ PYBIND11_MODULE(_specs, m) {
|
||||
throw pybind11::value_error(
|
||||
"Site spec does not match parent spec.");
|
||||
}
|
||||
attached_frame = mjs_attachFrameToSite(site_ptr, worldframe, p, s);
|
||||
attached_frame =
|
||||
mjs_attach(site_ptr->element, worldframe->element, p, s);
|
||||
if (!attached_frame) {
|
||||
throw pybind11::value_error(mjs_getError(self.ptr));
|
||||
}
|
||||
@@ -597,7 +599,7 @@ PYBIND11_MODULE(_specs, m) {
|
||||
self.assets[asset.first] = asset.second;
|
||||
}
|
||||
child.parent = &self;
|
||||
return attached_frame;
|
||||
return mjs_asFrame(attached_frame);
|
||||
},
|
||||
py::arg("child"), py::arg("prefix") = py::none(),
|
||||
py::arg("suffix") = py::none(), py::arg("site") = py::none(),
|
||||
@@ -829,11 +831,11 @@ PYBIND11_MODULE(_specs, m) {
|
||||
std::optional<std::string>& suffix) -> raw::MjsFrame* {
|
||||
const char* p = prefix.has_value() ? prefix.value().c_str() : "";
|
||||
const char* s = suffix.has_value() ? suffix.value().c_str() : "";
|
||||
auto new_frame = mjs_attachFrame(&self, &frame, p, s);
|
||||
auto new_frame = mjs_attach(self.element, frame.element, p, s);
|
||||
if (!new_frame) {
|
||||
throw pybind11::value_error(mjs_getError(mjs_getSpec(self.element)));
|
||||
}
|
||||
return new_frame;
|
||||
return mjs_asFrame(new_frame);
|
||||
},
|
||||
py::arg("frame"), py::arg("prefix") = py::none(),
|
||||
py::arg("suffix") = py::none(),
|
||||
@@ -870,12 +872,12 @@ PYBIND11_MODULE(_specs, m) {
|
||||
std::optional<std::string>& suffix) -> raw::MjsBody* {
|
||||
const char* p = prefix.has_value() ? prefix.value().c_str() : "";
|
||||
const char* s = suffix.has_value() ? suffix.value().c_str() : "";
|
||||
auto new_body = mjs_attachBody(&self, &body, p, s);
|
||||
auto new_body = mjs_attach(self.element, body.element, p, s);
|
||||
if (!new_body) {
|
||||
throw pybind11::value_error(
|
||||
mjs_getError(mjs_getSpec(self.element)));
|
||||
}
|
||||
return new_body;
|
||||
return mjs_asBody(new_body);
|
||||
},
|
||||
py::arg("body"), py::arg("prefix") = py::none(),
|
||||
py::arg("suffix") = py::none(),
|
||||
@@ -953,12 +955,12 @@ PYBIND11_MODULE(_specs, m) {
|
||||
std::optional<std::string>& suffix) -> raw::MjsBody* {
|
||||
const char* p = prefix.has_value() ? prefix.value().c_str() : "";
|
||||
const char* s = suffix.has_value() ? suffix.value().c_str() : "";
|
||||
auto new_body = mjs_attachToSite(&self, &body, p, s);
|
||||
auto new_body = mjs_attach(self.element, body.element, p, s);
|
||||
if (!new_body) {
|
||||
throw pybind11::value_error(
|
||||
mjs_getError(mjs_getSpec(self.element)));
|
||||
}
|
||||
return new_body;
|
||||
return mjs_asBody(new_body);
|
||||
},
|
||||
py::arg("body"), py::arg("prefix") = py::none(),
|
||||
py::arg("suffix") = py::none(),
|
||||
|
||||
+92
-67
@@ -73,7 +73,7 @@ mjSpec* mj_copySpec(const mjSpec* s) {
|
||||
try {
|
||||
modelC = new mjCModel(*static_cast<mjCModel*>(s->element));
|
||||
} catch (mjCError& e) {
|
||||
mju_error("Failed to copy spec: %s", e.message);
|
||||
modelC->SetError(e);
|
||||
return nullptr;
|
||||
}
|
||||
return &modelC->spec;
|
||||
@@ -121,100 +121,125 @@ mjModel* mj_compile(mjSpec* s, const mjVFS* vfs) {
|
||||
|
||||
|
||||
// attach body to a frame of the parent
|
||||
mjsBody* mjs_attachBody(mjsFrame* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
if (!parent) {
|
||||
mju_error("parent frame is null");
|
||||
return nullptr;
|
||||
}
|
||||
mjCFrame* frame_parent = static_cast<mjCFrame*>(parent->element);
|
||||
mjCBody* child_body = static_cast<mjCBody*>(child->element);
|
||||
static mjsElement* attachBody(mjCFrame* parent, const mjCBody* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
try {
|
||||
*frame_parent += std::string(prefix) + *child_body + std::string(suffix);
|
||||
*parent += std::string(prefix) + *(mjCBody*)child + std::string(suffix);
|
||||
} catch (mjCError& e) {
|
||||
frame_parent->model->SetError(e);
|
||||
parent->model->SetError(e);
|
||||
return nullptr;
|
||||
}
|
||||
mjsBody* attached_body = frame_parent->last_attached;
|
||||
frame_parent->last_attached = nullptr;
|
||||
return attached_body;
|
||||
mjsBody* attached_body = parent->last_attached;
|
||||
parent->last_attached = nullptr;
|
||||
return attached_body->element;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// attach frame to a parent body
|
||||
mjsFrame* mjs_attachFrame(mjsBody* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
if (!parent) {
|
||||
mju_error("parent body is null");
|
||||
return nullptr;
|
||||
}
|
||||
mjCBody* body_parent = static_cast<mjCBody*>(parent->element);
|
||||
mjCFrame* child_frame = static_cast<mjCFrame*>(child->element);
|
||||
static mjsElement* attachFrame(mjCBody* parent, const mjCFrame* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
try {
|
||||
*body_parent += std::string(prefix) + *child_frame + std::string(suffix);
|
||||
*parent += std::string(prefix) + *(mjCFrame*)child + std::string(suffix);
|
||||
} catch (mjCError& e) {
|
||||
body_parent->model->SetError(e);
|
||||
parent->model->SetError(e);
|
||||
return nullptr;
|
||||
}
|
||||
mjsFrame* attached_frame = body_parent->last_attached;
|
||||
body_parent->last_attached = nullptr;
|
||||
return attached_frame;
|
||||
mjsFrame* attached_frame = parent->last_attached;
|
||||
parent->last_attached = nullptr;
|
||||
return attached_frame->element;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// attach child body to a parent site
|
||||
mjsBody* mjs_attachToSite(mjsSite* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
if (!parent) {
|
||||
mju_error("parent site is null");
|
||||
return nullptr;
|
||||
}
|
||||
mjSpec* spec = mjs_getSpec(parent->element);
|
||||
mjCSite* site = static_cast<mjCSite*>(parent->element);
|
||||
mjCBody* body = site->Body();
|
||||
mjCFrame* frame = body->AddFrame(site->frame);
|
||||
static mjsElement* attachToSite(mjCSite* parent, const mjCBody* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
mjSpec* spec = mjs_getSpec(parent->spec.element);
|
||||
mjCBody* body = parent->Body();
|
||||
mjCFrame* frame = body->AddFrame(parent->frame);
|
||||
frame->SetParent(body);
|
||||
frame->spec.pos[0] = site->spec.pos[0];
|
||||
frame->spec.pos[1] = site->spec.pos[1];
|
||||
frame->spec.pos[2] = site->spec.pos[2];
|
||||
frame->spec.quat[0] = site->spec.quat[0];
|
||||
frame->spec.quat[1] = site->spec.quat[1];
|
||||
frame->spec.quat[2] = site->spec.quat[2];
|
||||
frame->spec.quat[3] = site->spec.quat[3];
|
||||
frame->spec.pos[0] = parent->spec.pos[0];
|
||||
frame->spec.pos[1] = parent->spec.pos[1];
|
||||
frame->spec.pos[2] = parent->spec.pos[2];
|
||||
frame->spec.quat[0] = parent->spec.quat[0];
|
||||
frame->spec.quat[1] = parent->spec.quat[1];
|
||||
frame->spec.quat[2] = parent->spec.quat[2];
|
||||
frame->spec.quat[3] = parent->spec.quat[3];
|
||||
mjs_resolveOrientation(frame->spec.quat, spec->compiler.degree,
|
||||
spec->compiler.eulerseq, &site->spec.alt);
|
||||
return mjs_attachBody(&frame->spec, child, prefix, suffix);
|
||||
spec->compiler.eulerseq, &parent->spec.alt);
|
||||
return attachBody(frame, child, prefix, suffix);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// attach child frame to a parent site
|
||||
mjsFrame* mjs_attachFrameToSite(mjsSite* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
static mjsElement* attachFrameToSite(mjCSite* parent, const mjCFrame* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
mjSpec* spec = mjs_getSpec(parent->spec.element);
|
||||
mjCBody* body = parent->Body();
|
||||
mjCFrame* frame = body->AddFrame(parent->frame);
|
||||
frame->SetParent(body);
|
||||
frame->spec.pos[0] = parent->spec.pos[0];
|
||||
frame->spec.pos[1] = parent->spec.pos[1];
|
||||
frame->spec.pos[2] = parent->spec.pos[2];
|
||||
frame->spec.quat[0] = parent->spec.quat[0];
|
||||
frame->spec.quat[1] = parent->spec.quat[1];
|
||||
frame->spec.quat[2] = parent->spec.quat[2];
|
||||
frame->spec.quat[3] = parent->spec.quat[3];
|
||||
mjs_resolveOrientation(frame->spec.quat, spec->compiler.degree,
|
||||
spec->compiler.eulerseq, &parent->spec.alt);
|
||||
|
||||
mjsElement* attached_frame = attachFrame(body, child, prefix, suffix);
|
||||
mjs_setFrame(attached_frame, &frame->spec);
|
||||
return attached_frame;
|
||||
}
|
||||
|
||||
|
||||
mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||
const char* prefix, const char* suffix) {
|
||||
if (!parent) {
|
||||
mju_error("parent site is null");
|
||||
mju_error("parent element is null");
|
||||
return nullptr;
|
||||
}
|
||||
mjSpec* spec = mjs_getSpec(parent->element);
|
||||
mjCSite* site = static_cast<mjCSite*>(parent->element);
|
||||
mjCBody* body = site->Body();
|
||||
mjCFrame* frame = body->AddFrame(site->frame);
|
||||
frame->SetParent(body);
|
||||
frame->spec.pos[0] = site->spec.pos[0];
|
||||
frame->spec.pos[1] = site->spec.pos[1];
|
||||
frame->spec.pos[2] = site->spec.pos[2];
|
||||
frame->spec.quat[0] = site->spec.quat[0];
|
||||
frame->spec.quat[1] = site->spec.quat[1];
|
||||
frame->spec.quat[2] = site->spec.quat[2];
|
||||
frame->spec.quat[3] = site->spec.quat[3];
|
||||
mjs_resolveOrientation(frame->spec.quat, spec->compiler.degree,
|
||||
spec->compiler.eulerseq, &site->spec.alt);
|
||||
|
||||
mjsFrame* attached_frame = mjs_attachFrame(&body->spec, child, prefix, suffix);
|
||||
mjs_setFrame(attached_frame->element, &frame->spec);
|
||||
return attached_frame;
|
||||
if (!child) {
|
||||
mju_error("child element is null");
|
||||
return nullptr;
|
||||
}
|
||||
mjCModel* model = static_cast<mjCModel*>(mjs_getSpec(parent)->element);
|
||||
switch (parent->elemtype) {
|
||||
case mjOBJ_FRAME:
|
||||
if (child->elemtype == mjOBJ_BODY) {
|
||||
return attachBody(static_cast<mjCFrame*>(parent),
|
||||
static_cast<const mjCBody*>(child), prefix, suffix);
|
||||
} else {
|
||||
model->SetError(mjCError(0, "child element is not a body"));
|
||||
return nullptr;
|
||||
}
|
||||
case mjOBJ_BODY:
|
||||
if (child->elemtype == mjOBJ_FRAME) {
|
||||
return attachFrame(static_cast<mjCBody*>(parent),
|
||||
static_cast<const mjCFrame*>(child), prefix, suffix);
|
||||
} else {
|
||||
model->SetError(mjCError(0, "child element is not a frame"));
|
||||
return nullptr;
|
||||
}
|
||||
case mjOBJ_SITE:
|
||||
if (child->elemtype == mjOBJ_BODY) {
|
||||
return attachToSite(static_cast<mjCSite*>(parent),
|
||||
static_cast<const mjCBody*>(child), prefix, suffix);
|
||||
} else if (child->elemtype == mjOBJ_FRAME) {
|
||||
return attachFrameToSite(static_cast<mjCSite*>(parent),
|
||||
static_cast<const mjCFrame*>(child), prefix, suffix);
|
||||
} else {
|
||||
model->SetError(mjCError(0, "child element is not a body or frame"));
|
||||
return nullptr;
|
||||
}
|
||||
default:
|
||||
model->SetError(mjCError(0, "parent element is not a frame, body or site"));
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+3
-15
@@ -69,21 +69,9 @@ MJAPI int mjs_setDeepCopy(mjSpec* s, int deepcopy);
|
||||
|
||||
//---------------------------------- Attachment ----------------------------------------------------
|
||||
|
||||
// Attach child body to a parent frame, return the attached body if success or NULL otherwise.
|
||||
MJAPI mjsBody* mjs_attachBody(mjsFrame* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Attach child frame to a parent body, return the attached frame if success or NULL otherwise.
|
||||
MJAPI mjsFrame* mjs_attachFrame(mjsBody* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Attach child body to a parent site, return the attached body if success or NULL otherwise.
|
||||
MJAPI mjsBody* mjs_attachToSite(mjsSite* parent, const mjsBody* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Attach child frame to a parent site, return the attached frame if success or NULL otherwise.
|
||||
MJAPI mjsFrame* mjs_attachFrameToSite(mjsSite* parent, const mjsFrame* child,
|
||||
const char* prefix, const char* suffix);
|
||||
// Attach child to a parent, return the attached element if success or NULL otherwise.
|
||||
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
|
||||
const char* prefix, const char* suffix);
|
||||
|
||||
// Detach body from mjSpec, remove all references and delete the body, return 0 on success.
|
||||
MJAPI int mjs_detachBody(mjSpec* s, mjsBody* b);
|
||||
|
||||
@@ -3566,7 +3566,7 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
|
||||
UpdateString(suffix, count, i);
|
||||
|
||||
// attach to parent
|
||||
if (!mjs_attachFrame(body, pframe, /*prefix=*/"", suffix.c_str())) {
|
||||
if (!mjs_attach(body->element, pframe->element, /*prefix=*/"", suffix.c_str())) {
|
||||
throw mjXError(elem, mjs_getError(spec));
|
||||
}
|
||||
}
|
||||
@@ -3642,7 +3642,7 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
|
||||
if (!child) {
|
||||
throw mjXError(elem, "could not find body '%s''%s'", body_name.c_str());
|
||||
}
|
||||
if (!mjs_attachBody(pframe, child, prefix.c_str(), "")) {
|
||||
if (!mjs_attach(pframe->element, child->element, prefix.c_str(), "")) {
|
||||
throw mjXError(elem, mjs_getError(spec));
|
||||
}
|
||||
} else {
|
||||
|
||||
+56
-43
@@ -279,20 +279,23 @@ TEST_F(PluginTest, AttachPlugin) {
|
||||
EXPECT_THAT(body_1, NotNull());
|
||||
mjsFrame* attachment_frame = mjs_addFrame(body_1, 0);
|
||||
EXPECT_THAT(attachment_frame, NotNull());
|
||||
mjs_attachBody(attachment_frame, mjs_findBody(spec_1, "body"), "child-", "");
|
||||
mjs_attach(attachment_frame->element, mjs_findBody(spec_1, "body")->element,
|
||||
"child-", "");
|
||||
mjModel* model_1 = mj_compile(parent, nullptr);
|
||||
EXPECT_THAT(model_1, NotNull());
|
||||
EXPECT_THAT(model_1->nbody, 3);
|
||||
|
||||
// attach it a second time to test namespacing and compile
|
||||
ASSERT_THAT(spec_2, NotNull()) << err.data();
|
||||
mjs_attachBody(attachment_frame, mjs_findBody(spec_2, "body"), "copy-", "");
|
||||
mjs_attach(attachment_frame->element, mjs_findBody(spec_2, "body")->element,
|
||||
"copy-", "");
|
||||
mjModel* model_2 = mj_compile(parent, nullptr);
|
||||
EXPECT_THAT(model_2, NotNull());
|
||||
EXPECT_THAT(model_2->nbody, 4);
|
||||
|
||||
// attach a body not referencing the plugin and compile
|
||||
mjs_attachBody(attachment_frame, mjs_findBody(spec_3, "empty"), "empty-", "");
|
||||
mjs_attach(attachment_frame->element, mjs_findBody(spec_3, "empty")->element,
|
||||
"empty-", "");
|
||||
mjModel* model_3 = mj_compile(parent, nullptr);
|
||||
EXPECT_THAT(model_3, NotNull());
|
||||
EXPECT_THAT(model_3->nbody, 5);
|
||||
@@ -314,9 +317,9 @@ TEST_F(PluginTest, DetachPlugin) {
|
||||
ASSERT_THAT(child, NotNull()) << err.data();
|
||||
|
||||
// attach a body referencing the plugin to the frame
|
||||
mjsFrame* frame = mjs_addFrame(mjs_findBody(parent, "world"), 0);
|
||||
mjsBody* body = mjs_findBody(child, "body");
|
||||
EXPECT_THAT(mjs_attachBody(frame, body, "child-", ""), NotNull());
|
||||
mjsElement* frame = mjs_addFrame(mjs_findBody(parent, "world"), 0)->element;
|
||||
mjsElement* body = mjs_findBody(child, "body")->element;
|
||||
EXPECT_THAT(mjs_attach(frame, body, "child-", ""), NotNull());
|
||||
|
||||
// detach the body and compile
|
||||
mjsBody* body_to_detach = mjs_findBody(parent, "child-body");
|
||||
@@ -372,7 +375,8 @@ TEST_F(PluginTest, AttachExplicitPlugin) {
|
||||
mjsFrame* attachment_frame = mjs_addFrame(body_parent, 0);
|
||||
EXPECT_THAT(attachment_frame, NotNull());
|
||||
|
||||
mjs_attachBody(attachment_frame, mjs_findBody(child, "body"), "child-", "");
|
||||
mjs_attach(attachment_frame->element, mjs_findBody(child, "body")->element,
|
||||
"child-", "");
|
||||
mjModel* model = mj_compile(parent, nullptr);
|
||||
EXPECT_THAT(model, NotNull());
|
||||
EXPECT_THAT(model->nplugin, 1);
|
||||
@@ -937,7 +941,8 @@ TEST_F(MujocoTest, AttachSame) {
|
||||
EXPECT_THAT(body, NotNull());
|
||||
|
||||
// attach child to parent frame
|
||||
mjsBody* attached = mjs_attachBody(frame, body, "attached-", "-1");
|
||||
mjsBody* attached =
|
||||
mjs_asBody(mjs_attach(frame->element, body->element, "attached-", "-1"));
|
||||
EXPECT_THAT(attached, mjs_findBody(parent, "attached-body-1"));
|
||||
|
||||
// check that the spec was not copied
|
||||
@@ -1073,7 +1078,8 @@ TEST_F(MujocoTest, AttachDifferent) {
|
||||
EXPECT_THAT(body, NotNull());
|
||||
|
||||
// attach child to parent frame
|
||||
mjsBody* attached = mjs_attachBody(frame, body, "attached-", "-1");
|
||||
mjsBody* attached =
|
||||
mjs_asBody(mjs_attach(frame->element, body->element, "attached-", "-1"));
|
||||
EXPECT_THAT(attached, mjs_findBody(parent, "attached-body-1"));
|
||||
|
||||
// check that the spec was copied
|
||||
@@ -1212,7 +1218,8 @@ TEST_F(MujocoTest, AttachFrame) {
|
||||
EXPECT_THAT(frame, NotNull());
|
||||
|
||||
// attach child frame to parent body
|
||||
mjsFrame* attached = mjs_attachFrame(body, frame, "attached-", "-1");
|
||||
mjsFrame* attached =
|
||||
mjs_asFrame(mjs_attach(body->element, frame->element, "attached-", "-1"));
|
||||
EXPECT_THAT(attached, mjs_findFrame(parent, "attached-pframe-1"));
|
||||
|
||||
// check that the spec was copied
|
||||
@@ -1286,7 +1293,7 @@ TEST_F(MujocoTest, AttachCompiled) {
|
||||
// attach child body to the frame
|
||||
mjsBody* to_attach = mjs_findBody(child, "base");
|
||||
EXPECT_THAT(to_attach, NotNull()) << mjs_getError(child);
|
||||
mjs_attachBody(frame, to_attach, "", "");
|
||||
mjs_attach(frame->element, to_attach->element, "", "");
|
||||
|
||||
// check that attached model can be compiled
|
||||
mjModel* m_attached = mj_compile(parent, 0);
|
||||
@@ -1433,7 +1440,8 @@ TEST_F(MujocoTest, AttachToSite) {
|
||||
EXPECT_THAT(site, NotNull());
|
||||
mjsBody* body = mjs_findBody(child, "sphere");
|
||||
EXPECT_THAT(body, NotNull());
|
||||
mjsBody* attached = mjs_attachToSite(site, body, "attached-", "-1");
|
||||
mjsBody* attached =
|
||||
mjs_asBody(mjs_attach(site->element, body->element, "attached-", "-1"));
|
||||
EXPECT_THAT(attached, NotNull());
|
||||
|
||||
mjModel* model = mj_compile(parent, 0);
|
||||
@@ -1498,7 +1506,8 @@ TEST_F(MujocoTest, AttachFrameToSite) {
|
||||
EXPECT_THAT(site, NotNull());
|
||||
mjsFrame* frame = mjs_findFrame(child, "frame");
|
||||
EXPECT_THAT(frame, NotNull());
|
||||
mjsFrame* attached = mjs_attachFrameToSite(site, frame, "attached-", "-1");
|
||||
mjsFrame* attached =
|
||||
mjs_asFrame(mjs_attach(site->element, frame->element, "attached-", "-1"));
|
||||
EXPECT_THAT(attached, NotNull());
|
||||
|
||||
mjModel* model = mj_compile(parent, 0);
|
||||
@@ -1573,7 +1582,8 @@ TEST_F(MujocoTest, BodyToFrame) {
|
||||
EXPECT_THAT(frame, NotNull());
|
||||
mjsBody* body = mjs_findBody(child1, "sphere");
|
||||
EXPECT_THAT(body, NotNull());
|
||||
mjsBody* attached = mjs_attachBody(frame, body, "attached-", "-1");
|
||||
mjsBody* attached =
|
||||
mjs_asBody(mjs_attach(frame->element, body->element, "attached-", "-1"));
|
||||
EXPECT_THAT(attached, NotNull());
|
||||
mjModel* model1 = mj_compile(parent, 0);
|
||||
EXPECT_THAT(model1, NotNull());
|
||||
@@ -1581,7 +1591,8 @@ TEST_F(MujocoTest, BodyToFrame) {
|
||||
// attach the world to the same frame and convert it to a frame
|
||||
mjsBody* world = mjs_findBody(child2, "world");
|
||||
EXPECT_THAT(world, NotNull());
|
||||
mjsBody* child_world = mjs_attachBody(frame, world, "attached-", "-2");
|
||||
mjsBody* child_world =
|
||||
mjs_asBody(mjs_attach(frame->element, world->element, "attached-", "-2"));
|
||||
EXPECT_THAT(child_world, NotNull());
|
||||
mjsFrame* frame_world = mjs_bodyToFrame(&child_world);
|
||||
EXPECT_THAT(frame_world, NotNull());
|
||||
@@ -1662,7 +1673,8 @@ TEST_F(MujocoTest, AttachSpecToSite) {
|
||||
mjs_setFrame(mjs_firstChild(world, mjOBJ_CAMERA, 0), frame);
|
||||
|
||||
// attach the entire spec to the site
|
||||
mjsFrame* worldframe = mjs_attachFrameToSite(site, frame, "attached-", "-1");
|
||||
mjsFrame* worldframe =
|
||||
mjs_asFrame(mjs_attach(site->element, frame->element, "attached-", "-1"));
|
||||
EXPECT_THAT(worldframe, NotNull());
|
||||
|
||||
// compile and compare
|
||||
@@ -1739,7 +1751,8 @@ TEST_F(MujocoTest, AttachSpecToBody) {
|
||||
mjs_setFrame(mjs_firstChild(world, mjOBJ_CAMERA, 0), frame);
|
||||
|
||||
// attach the entire spec to the site
|
||||
mjsFrame* worldframe = mjs_attachFrame(body, frame, "attached-", "-1");
|
||||
mjsFrame* worldframe =
|
||||
mjs_asFrame(mjs_attach(body->element, frame->element, "attached-", "-1"));
|
||||
EXPECT_THAT(worldframe, NotNull());
|
||||
worldframe->pos[0] = 1;
|
||||
worldframe->pos[1] = 2;
|
||||
@@ -1937,8 +1950,8 @@ TEST_F(MujocoTest, RecompileAttach) {
|
||||
mjSpec* child2 = mj_parseXMLString(xml, 0, er.data(), er.size());
|
||||
EXPECT_THAT(child2, NotNull());
|
||||
|
||||
mjsFrame* frame1 = mjs_addFrame(mjs_findBody(parent, "world"), 0);
|
||||
mjs_attachBody(frame1, mjs_findBody(child1, "body"), "child-", "-1");
|
||||
mjsElement* frame1 = mjs_addFrame(mjs_findBody(parent, "world"), 0)->element;
|
||||
mjs_attach(frame1, mjs_findBody(child1, "body")->element, "child-", "-1");
|
||||
|
||||
mjModel* model = mj_compile(parent, 0);
|
||||
EXPECT_THAT(model, NotNull());
|
||||
@@ -1950,8 +1963,8 @@ TEST_F(MujocoTest, RecompileAttach) {
|
||||
mj_step(model, data);
|
||||
}
|
||||
|
||||
mjsFrame* frame2 = mjs_addFrame(mjs_findBody(parent, "world"), 0);
|
||||
mjs_attachBody(frame2, mjs_findBody(child2, "body"), "child-", "-2");
|
||||
mjsElement* frame2 = mjs_addFrame(mjs_findBody(parent, "world"), 0)->element;
|
||||
mjs_attach(frame2, mjs_findBody(child2, "body")->element, "child-", "-2");
|
||||
|
||||
EXPECT_EQ(mj_recompile(parent, 0, model, data), 0);
|
||||
EXPECT_THAT(model, NotNull());
|
||||
@@ -2003,8 +2016,8 @@ TEST_F(MujocoTest, AttachMocap) {
|
||||
mjsBody* world = mjs_findBody(spec, "world");
|
||||
EXPECT_THAT(world, NotNull());
|
||||
|
||||
mjsFrame* frame = mjs_addFrame(world, NULL);
|
||||
mjs_attachBody(frame, body, "attached-", "-1");
|
||||
mjsElement* frame = mjs_addFrame(world, NULL)->element;
|
||||
mjs_attach(frame, body->element, "attached-", "-1");
|
||||
|
||||
mjsBody* attached_body = mjs_findBody(spec, "attached-mocap-1");
|
||||
EXPECT_THAT(attached_body, NotNull());
|
||||
@@ -2083,7 +2096,7 @@ TEST_F(MujocoTest, AttachUnnamedAssets) {
|
||||
geom->type = mjGEOM_MESH;
|
||||
|
||||
mjSpec* spec = mj_makeSpec();
|
||||
mjs_attachFrame(mjs_findBody(spec, "world"), frame, "_", "");
|
||||
mjs_attach(mjs_findBody(spec, "world")->element, frame->element, "_", "");
|
||||
|
||||
mjModel* model = mj_compile(spec, vfs.get());
|
||||
EXPECT_THAT(model, NotNull());
|
||||
@@ -2229,8 +2242,8 @@ void AttachNestedKeyframe(bool compile) {
|
||||
mjs_setDeepCopy(child, true);
|
||||
|
||||
// attach gchild to child
|
||||
mjs_attachBody(mjs_findFrame(child, "frame"),
|
||||
mjs_findBody(gchild, "body"), "gchild-", "");
|
||||
mjs_attach(mjs_findFrame(child, "frame")->element,
|
||||
mjs_findBody(gchild, "body")->element, "gchild-", "");
|
||||
|
||||
// compile required before further attachment
|
||||
mjModel* m_child = compile ? mj_compile(child, 0) : nullptr;
|
||||
@@ -2243,8 +2256,8 @@ void AttachNestedKeyframe(bool compile) {
|
||||
};
|
||||
|
||||
// attach child to parent
|
||||
mjs_attachBody(mjs_findFrame(parent, "frame"),
|
||||
mjs_findBody(child, "body"), "child-", "");
|
||||
mjs_attach(mjs_findFrame(parent, "frame")->element,
|
||||
mjs_findBody(child, "body")->element, "child-", "");
|
||||
|
||||
EXPECT_THAT(warning, HasSubstr(compile ? "" : "model has pending keyframes"));
|
||||
|
||||
@@ -2305,11 +2318,11 @@ TEST_F(MujocoTest, RepeatedAttachKeyframe) {
|
||||
EXPECT_THAT(child, NotNull()) << er.data();
|
||||
|
||||
mjsBody* body_1 = mjs_findBody(parent, "body");
|
||||
mjsFrame* attachment_frame = mjs_addFrame(body_1, 0);
|
||||
mjs_attachBody(attachment_frame, mjs_findBody(child, "b1"), "b1-", "");
|
||||
mjsElement* attachment_frame = mjs_addFrame(body_1, 0)->element;
|
||||
mjs_attach(attachment_frame, mjs_findBody(child, "b1")->element, "b1-", "");
|
||||
mjModel* model_1 = mj_compile(parent, 0);
|
||||
EXPECT_THAT(model_1, NotNull());
|
||||
mjs_attachBody(attachment_frame, mjs_findBody(child, "b2"), "b2-", "");
|
||||
mjs_attach(attachment_frame, mjs_findBody(child, "b2")->element, "b2-", "");
|
||||
mjModel* model_2 = mj_compile(parent, 0);
|
||||
EXPECT_THAT(model_2, NotNull());
|
||||
|
||||
@@ -2374,8 +2387,8 @@ TEST_F(MujocoTest, ResizeParentKeyframe) {
|
||||
mjSpec* child = mj_parseXMLString(xml_child, 0, er.data(), er.size());
|
||||
EXPECT_THAT(child, NotNull()) << er.data();
|
||||
|
||||
mjs_attachBody(mjs_findFrame(parent, "frame"), mjs_findBody(child, "body"),
|
||||
"child-", "");
|
||||
mjs_attach(mjs_findFrame(parent, "frame")->element,
|
||||
mjs_findBody(child, "body")->element, "child-", "");
|
||||
|
||||
mjModel* model = mj_compile(parent, 0);
|
||||
EXPECT_THAT(model, NotNull());
|
||||
@@ -2466,12 +2479,10 @@ TEST_F(MujocoTest, DifferentUnitsAllowed) {
|
||||
mjSpec* child = mj_parseXMLString(child_xml, 0, error.data(), error.size());
|
||||
mjSpec* spec = mj_parseXMLString(parent_xml, 0, error.data(), error.size());
|
||||
ASSERT_THAT(spec, NotNull()) << error.data();
|
||||
mjs_attachBody(mjs_findFrame(child, "frame"),
|
||||
mjs_findBody(gchild, "gchild"),
|
||||
"gchild_", "");
|
||||
mjs_attachBody(mjs_findFrame(spec, "frame"),
|
||||
mjs_findBody(child, "child"),
|
||||
"child_", "");
|
||||
mjs_attach(mjs_findFrame(child, "frame")->element,
|
||||
mjs_findBody(gchild, "gchild")->element, "gchild_", "");
|
||||
mjs_attach(mjs_findFrame(spec, "frame")->element,
|
||||
mjs_findBody(child, "child")->element, "child_", "");
|
||||
|
||||
mjModel* model = mj_compile(spec, 0);
|
||||
EXPECT_THAT(model, NotNull());
|
||||
@@ -2544,7 +2555,8 @@ TEST_F(MujocoTest, DifferentOptionsInAttachedFrame) {
|
||||
EXPECT_THAT(world, NotNull());
|
||||
mjsFrame* child_frame = mjs_findFrame(child, "child");
|
||||
EXPECT_THAT(child_frame, NotNull());
|
||||
mjsFrame* attached_frame = mjs_attachFrame(world, child_frame, "child-", "");
|
||||
mjsElement* attached_frame =
|
||||
mjs_attach(world->element, child_frame->element, "child-", "");
|
||||
EXPECT_THAT(attached_frame, NotNull());
|
||||
|
||||
// wrap the child frame in the parent frame and compile
|
||||
@@ -2659,8 +2671,9 @@ TEST_F(MujocoTest, ApplyNameSpaceToDefaults) {
|
||||
mjSpec* parent = mj_parseXMLString(xml_p, 0, err.data(), err.size());
|
||||
EXPECT_THAT(parent, NotNull()) << err.data();
|
||||
|
||||
mjsBody* attached = mjs_attachBody(mjs_findFrame(parent, "parent"),
|
||||
mjs_findBody(child, "body"), "child-", "");
|
||||
mjsElement* attached =
|
||||
mjs_attach(mjs_findFrame(parent, "parent")->element,
|
||||
mjs_findBody(child, "body")->element, "child-", "");
|
||||
EXPECT_THAT(attached, NotNull());
|
||||
|
||||
mjModel* model = mj_compile(parent, vfs.get());
|
||||
@@ -2774,7 +2787,7 @@ TEST_F(MujocoTest, ErrorWhenCompilingOrphanedSpec) {
|
||||
EXPECT_THAT(body, NotNull());
|
||||
mjsFrame* frame = mjs_addFrame(mjs_findBody(parent, "world"), nullptr);
|
||||
EXPECT_THAT(frame, NotNull());
|
||||
mjs_attachBody(frame, body, "child-", "");
|
||||
mjs_attach(frame->element, body->element, "child-", "");
|
||||
mj_deleteSpec(parent);
|
||||
mjModel* model = mj_compile(child, 0);
|
||||
EXPECT_THAT(model, IsNull());
|
||||
|
||||
@@ -623,7 +623,7 @@ TEST_F(MujocoTest, Modeldir) {
|
||||
mjSpec* spec = mj_makeSpec();
|
||||
mjs_setDeepCopy(spec, true);
|
||||
mjs_setString(spec->meshdir, "asset");
|
||||
mjs_attachFrame(mjs_findBody(spec, "world"), frame, "_", "");
|
||||
mjs_attach(mjs_findBody(spec, "world")->element, frame->element, "_", "");
|
||||
mjModel* model = mj_compile(spec, vfs.get());
|
||||
EXPECT_THAT(model, NotNull());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user