Add mjs_getParent to retrieve the parent body of an object.
PiperOrigin-RevId: 715794859 Change-Id: Ib9792787cdb966f579938dde3f94ebabca8ef1fc
This commit is contained in:
committed by
Copybara-Service
parent
10c7207cea
commit
05d4c3d670
@@ -4175,6 +4175,15 @@ Find element in spec by name.
|
|||||||
|
|
||||||
Find child body by name.
|
Find child body by name.
|
||||||
|
|
||||||
|
.. _mjs_getParent:
|
||||||
|
|
||||||
|
`mjs_getParent <#mjs_getParent>`__
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. mujoco-include:: mjs_getParent
|
||||||
|
|
||||||
|
Get parent body.
|
||||||
|
|
||||||
.. _mjs_findFrame:
|
.. _mjs_findFrame:
|
||||||
|
|
||||||
`mjs_findFrame <#mjs_findFrame>`__
|
`mjs_findFrame <#mjs_findFrame>`__
|
||||||
|
|||||||
@@ -3607,6 +3607,7 @@ 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);
|
||||||
|
mjsBody* mjs_getParent(mjsElement* element);
|
||||||
mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
|
mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
|
||||||
mjsDefault* mjs_getDefault(mjsElement* element);
|
mjsDefault* mjs_getDefault(mjsElement* element);
|
||||||
const mjsDefault* mjs_findDefault(mjSpec* s, const char* classname);
|
const mjsDefault* mjs_findDefault(mjSpec* s, const char* classname);
|
||||||
|
|||||||
@@ -591,6 +591,8 @@ Recursive search:
|
|||||||
``body.find_all(mujoco.mjtObj.mjOBJ_SITE)`` or ``body.find_all('site')`` will return a list of all sites under the
|
``body.find_all(mujoco.mjtObj.mjOBJ_SITE)`` or ``body.find_all('site')`` will return a list of all sites under the
|
||||||
body.
|
body.
|
||||||
|
|
||||||
|
Additionally, the parent body of a given element - including bodies and frames - can be accessed via the ``parent``
|
||||||
|
property. For example, the parent of a site can be accessed via ``site.parent``.
|
||||||
|
|
||||||
Relationship to ``PyMJCF``
|
Relationship to ``PyMJCF``
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|||||||
@@ -1546,6 +1546,9 @@ MJAPI mjsElement* mjs_findElement(mjSpec* s, mjtObj type, const char* name);
|
|||||||
// Find child body by name.
|
// Find child body by name.
|
||||||
MJAPI mjsBody* mjs_findChild(mjsBody* body, const char* name);
|
MJAPI mjsBody* mjs_findChild(mjsBody* body, const char* name);
|
||||||
|
|
||||||
|
// Get parent body.
|
||||||
|
MJAPI mjsBody* mjs_getParent(mjsElement* element);
|
||||||
|
|
||||||
// Find frame by name.
|
// Find frame by name.
|
||||||
MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
|
MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
|
||||||
|
|
||||||
|
|||||||
@@ -9828,6 +9828,22 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
|
|||||||
),
|
),
|
||||||
doc='Find child body by name.',
|
doc='Find child body by name.',
|
||||||
)),
|
)),
|
||||||
|
('mjs_getParent',
|
||||||
|
FunctionDecl(
|
||||||
|
name='mjs_getParent',
|
||||||
|
return_type=PointerType(
|
||||||
|
inner_type=ValueType(name='mjsBody'),
|
||||||
|
),
|
||||||
|
parameters=(
|
||||||
|
FunctionParameterDecl(
|
||||||
|
name='element',
|
||||||
|
type=PointerType(
|
||||||
|
inner_type=ValueType(name='mjsElement'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
doc='Get parent body.',
|
||||||
|
)),
|
||||||
('mjs_findFrame',
|
('mjs_findFrame',
|
||||||
FunctionDecl(
|
FunctionDecl(
|
||||||
name='mjs_findFrame',
|
name='mjs_findFrame',
|
||||||
|
|||||||
@@ -680,6 +680,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
return mjs_getSpec(self.element);
|
return mjs_getSpec(self.element);
|
||||||
},
|
},
|
||||||
py::return_value_policy::reference_internal);
|
py::return_value_policy::reference_internal);
|
||||||
|
mjsBody.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsBody& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsBody.def(
|
mjsBody.def(
|
||||||
"attach_frame",
|
"attach_frame",
|
||||||
[](raw::MjsBody& self, raw::MjsFrame& frame,
|
[](raw::MjsBody& self, raw::MjsFrame& frame,
|
||||||
@@ -713,6 +719,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
mjsFrame.def("set_frame", [](raw::MjsFrame& self, raw::MjsFrame& frame) {
|
mjsFrame.def("set_frame", [](raw::MjsFrame& self, raw::MjsFrame& frame) {
|
||||||
mjs_setFrame(self.element, &frame);
|
mjs_setFrame(self.element, &frame);
|
||||||
});
|
});
|
||||||
|
mjsFrame.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsFrame& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsFrame.def(
|
mjsFrame.def(
|
||||||
"attach_body",
|
"attach_body",
|
||||||
[](raw::MjsFrame& self, raw::MjsBody& body,
|
[](raw::MjsFrame& self, raw::MjsBody& body,
|
||||||
@@ -760,6 +772,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
mjsGeom.def("set_default", [](raw::MjsGeom& self, raw::MjsDefault& def) {
|
mjsGeom.def("set_default", [](raw::MjsGeom& self, raw::MjsDefault& def) {
|
||||||
mjs_setDefault(self.element, &def);
|
mjs_setDefault(self.element, &def);
|
||||||
});
|
});
|
||||||
|
mjsGeom.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsGeom& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsGeom.def(
|
mjsGeom.def(
|
||||||
"default",
|
"default",
|
||||||
[](raw::MjsGeom& self) -> raw::MjsDefault* {
|
[](raw::MjsGeom& self) -> raw::MjsDefault* {
|
||||||
@@ -775,6 +793,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
mjsJoint.def("set_default", [](raw::MjsJoint& self, raw::MjsDefault& def) {
|
mjsJoint.def("set_default", [](raw::MjsJoint& self, raw::MjsDefault& def) {
|
||||||
mjs_setDefault(self.element, &def);
|
mjs_setDefault(self.element, &def);
|
||||||
});
|
});
|
||||||
|
mjsJoint.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsJoint& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsJoint.def(
|
mjsJoint.def(
|
||||||
"default",
|
"default",
|
||||||
[](raw::MjsJoint& self) -> raw::MjsDefault* {
|
[](raw::MjsJoint& self) -> raw::MjsDefault* {
|
||||||
@@ -790,6 +814,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
mjsSite.def("set_default", [](raw::MjsSite& self, raw::MjsDefault& def) {
|
mjsSite.def("set_default", [](raw::MjsSite& self, raw::MjsDefault& def) {
|
||||||
mjs_setDefault(self.element, &def);
|
mjs_setDefault(self.element, &def);
|
||||||
});
|
});
|
||||||
|
mjsSite.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsSite& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsSite.def(
|
mjsSite.def(
|
||||||
"default",
|
"default",
|
||||||
[](raw::MjsSite& self) -> raw::MjsDefault* {
|
[](raw::MjsSite& self) -> raw::MjsDefault* {
|
||||||
@@ -845,6 +875,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
mjsCamera.def("set_default", [](raw::MjsCamera& self, raw::MjsDefault& def) {
|
mjsCamera.def("set_default", [](raw::MjsCamera& self, raw::MjsDefault& def) {
|
||||||
mjs_setDefault(self.element, &def);
|
mjs_setDefault(self.element, &def);
|
||||||
});
|
});
|
||||||
|
mjsCamera.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsCamera& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsCamera.def(
|
mjsCamera.def(
|
||||||
"default",
|
"default",
|
||||||
[](raw::MjsCamera& self) -> raw::MjsDefault* {
|
[](raw::MjsCamera& self) -> raw::MjsDefault* {
|
||||||
@@ -860,6 +896,12 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
mjsLight.def("set_default", [](raw::MjsLight& self, raw::MjsDefault& def) {
|
mjsLight.def("set_default", [](raw::MjsLight& self, raw::MjsDefault& def) {
|
||||||
mjs_setDefault(self.element, &def);
|
mjs_setDefault(self.element, &def);
|
||||||
});
|
});
|
||||||
|
mjsLight.def_property_readonly(
|
||||||
|
"parent",
|
||||||
|
[](raw::MjsLight& self) -> raw::MjsBody* {
|
||||||
|
return mjs_getParent(self.element);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
mjsLight.def(
|
mjsLight.def(
|
||||||
"default",
|
"default",
|
||||||
[](raw::MjsLight& self) -> raw::MjsDefault* {
|
[](raw::MjsLight& self) -> raw::MjsDefault* {
|
||||||
|
|||||||
@@ -646,6 +646,10 @@ class SpecsTest(absltest.TestCase):
|
|||||||
self.assertEqual(spec.bodies[2].name, 'body2')
|
self.assertEqual(spec.bodies[2].name, 'body2')
|
||||||
self.assertEqual(spec.bodies[3].name, 'body3')
|
self.assertEqual(spec.bodies[3].name, 'body3')
|
||||||
self.assertEqual(spec.bodies[4].name, 'body4')
|
self.assertEqual(spec.bodies[4].name, 'body4')
|
||||||
|
self.assertEqual(spec.bodies[1].parent, spec.worldbody)
|
||||||
|
self.assertEqual(spec.bodies[2].parent, spec.worldbody)
|
||||||
|
self.assertEqual(spec.bodies[3].parent, spec.bodies[1])
|
||||||
|
self.assertEqual(spec.bodies[4].parent, spec.bodies[3])
|
||||||
self.assertLen(spec.worldbody.find_all(bodytype), 4)
|
self.assertLen(spec.worldbody.find_all(bodytype), 4)
|
||||||
self.assertLen(spec.bodies[1].find_all(bodytype), 2)
|
self.assertLen(spec.bodies[1].find_all(bodytype), 2)
|
||||||
self.assertLen(spec.bodies[3].find_all(bodytype), 1)
|
self.assertLen(spec.bodies[3].find_all(bodytype), 1)
|
||||||
@@ -671,6 +675,11 @@ class SpecsTest(absltest.TestCase):
|
|||||||
self.assertEqual(spec.bodies[3].sites[2].name, 'site3')
|
self.assertEqual(spec.bodies[3].sites[2].name, 'site3')
|
||||||
self.assertEqual(spec.bodies[3].sites[3].name, 'site4')
|
self.assertEqual(spec.bodies[3].sites[3].name, 'site4')
|
||||||
self.assertEqual(spec.bodies[4].sites[0].name, 'site5')
|
self.assertEqual(spec.bodies[4].sites[0].name, 'site5')
|
||||||
|
self.assertEqual(spec.bodies[3].sites[0].parent, spec.bodies[3])
|
||||||
|
self.assertEqual(spec.bodies[3].sites[1].parent, spec.bodies[3])
|
||||||
|
self.assertEqual(spec.bodies[3].sites[2].parent, spec.bodies[3])
|
||||||
|
self.assertEqual(spec.bodies[3].sites[3].parent, spec.bodies[3])
|
||||||
|
self.assertEqual(spec.bodies[4].sites[0].parent, spec.bodies[4])
|
||||||
with self.assertRaises(ValueError) as cm:
|
with self.assertRaises(ValueError) as cm:
|
||||||
spec.worldbody.find_all('actuator')
|
spec.worldbody.find_all('actuator')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|||||||
@@ -649,6 +649,30 @@ mjsBody* mjs_findChild(mjsBody* bodyspec, const char* name) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// get parent body
|
||||||
|
mjsBody* mjs_getParent(mjsElement* element) {
|
||||||
|
switch (element->elemtype) {
|
||||||
|
case mjOBJ_BODY:
|
||||||
|
return &(static_cast<mjCBody*>(element)->GetParent()->spec);
|
||||||
|
case mjOBJ_FRAME:
|
||||||
|
return &(static_cast<mjCFrame*>(element)->GetParent()->spec);
|
||||||
|
case mjOBJ_JOINT:
|
||||||
|
return &(static_cast<mjCJoint*>(element)->GetParent()->spec);
|
||||||
|
case mjOBJ_GEOM:
|
||||||
|
return &(static_cast<mjCGeom*>(element)->GetParent()->spec);
|
||||||
|
case mjOBJ_SITE:
|
||||||
|
return &(static_cast<mjCSite*>(element)->GetParent()->spec);
|
||||||
|
case mjOBJ_CAMERA:
|
||||||
|
return &(static_cast<mjCCamera*>(element)->GetParent()->spec);
|
||||||
|
case mjOBJ_LIGHT:
|
||||||
|
return &(static_cast<mjCLight*>(element)->GetParent()->spec);
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// find frame by name
|
// find frame by name
|
||||||
mjsFrame* mjs_findFrame(mjSpec* s, const char* name) {
|
mjsFrame* mjs_findFrame(mjSpec* s, const char* name) {
|
||||||
mjsElement* frame = mjs_findElement(s, mjOBJ_FRAME, name);
|
mjsElement* frame = mjs_findElement(s, mjOBJ_FRAME, name);
|
||||||
|
|||||||
@@ -201,6 +201,9 @@ MJAPI mjsElement* mjs_findElement(mjSpec* s, mjtObj type, const char* name);
|
|||||||
// Find child body by name.
|
// Find child body by name.
|
||||||
MJAPI mjsBody* mjs_findChild(mjsBody* body, const char* name);
|
MJAPI mjsBody* mjs_findChild(mjsBody* body, const char* name);
|
||||||
|
|
||||||
|
// Get parent body.
|
||||||
|
MJAPI mjsBody* mjs_getParent(mjsElement* element);
|
||||||
|
|
||||||
// Find frame by name.
|
// Find frame by name.
|
||||||
MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
|
MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name);
|
||||||
|
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ class mjCBody : public mjCBody_, private mjsBody {
|
|||||||
|
|
||||||
// set parent of this body
|
// set parent of this body
|
||||||
void SetParent(mjCBody* _body) { parent = _body; }
|
void SetParent(mjCBody* _body) { parent = _body; }
|
||||||
|
mjCBody* GetParent() const { return parent; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mjCBody(const mjCBody& other, mjCModel* _model); // copy constructor
|
mjCBody(const mjCBody& other, mjCModel* _model); // copy constructor
|
||||||
@@ -411,6 +412,7 @@ class mjCFrame : public mjCFrame_, private mjsFrame {
|
|||||||
void CopyFromSpec(void);
|
void CopyFromSpec(void);
|
||||||
void PointToLocal(void);
|
void PointToLocal(void);
|
||||||
void SetParent(mjCBody* _body) { body = _body; }
|
void SetParent(mjCBody* _body) { body = _body; }
|
||||||
|
mjCBody* GetParent() const { return body; }
|
||||||
|
|
||||||
mjCFrame& operator+=(const mjCBody& other);
|
mjCFrame& operator+=(const mjCBody& other);
|
||||||
|
|
||||||
@@ -462,6 +464,7 @@ class mjCJoint : public mjCJoint_, private mjsJoint {
|
|||||||
|
|
||||||
void CopyFromSpec(void);
|
void CopyFromSpec(void);
|
||||||
void SetParent(mjCBody* _body) { body = _body; }
|
void SetParent(mjCBody* _body) { body = _body; }
|
||||||
|
mjCBody* GetParent() const { return body; }
|
||||||
|
|
||||||
// used by mjXWriter and mjCModel
|
// used by mjXWriter and mjCModel
|
||||||
const std::vector<double>& get_userdata() const { return userdata_; }
|
const std::vector<double>& get_userdata() const { return userdata_; }
|
||||||
@@ -543,6 +546,7 @@ class mjCGeom : public mjCGeom_, private mjsGeom {
|
|||||||
bool IsVisual(void) const { return visual_; }
|
bool IsVisual(void) const { return visual_; }
|
||||||
void SetNotVisual(void) { visual_ = false; }
|
void SetNotVisual(void) { visual_ = false; }
|
||||||
void SetParent(mjCBody* _body) { body = _body; }
|
void SetParent(mjCBody* _body) { body = _body; }
|
||||||
|
mjCBody* GetParent() const { return body; }
|
||||||
mjtGeom Type() const { return type; }
|
mjtGeom Type() const { return type; }
|
||||||
|
|
||||||
// Compute all coefs modeling the interaction with the surrounding fluid.
|
// Compute all coefs modeling the interaction with the surrounding fluid.
|
||||||
@@ -608,6 +612,7 @@ class mjCSite : public mjCSite_, private mjsSite {
|
|||||||
// site's body
|
// site's body
|
||||||
mjCBody* Body() const { return body; }
|
mjCBody* Body() const { return body; }
|
||||||
void SetParent(mjCBody* _body) { body = _body; }
|
void SetParent(mjCBody* _body) { body = _body; }
|
||||||
|
mjCBody* GetParent() const { return body; }
|
||||||
|
|
||||||
// use strings from mjCBase rather than mjStrings from mjsSite
|
// use strings from mjCBase rather than mjStrings from mjsSite
|
||||||
using mjCBase::name;
|
using mjCBase::name;
|
||||||
@@ -661,6 +666,7 @@ class mjCCamera : public mjCCamera_, private mjsCamera {
|
|||||||
const std::vector<double>& get_userdata() const { return userdata_; }
|
const std::vector<double>& get_userdata() const { return userdata_; }
|
||||||
|
|
||||||
void SetParent(mjCBody* _body) { body = _body; }
|
void SetParent(mjCBody* _body) { body = _body; }
|
||||||
|
mjCBody* GetParent() const { return body; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Compile(void); // compiler
|
void Compile(void); // compiler
|
||||||
@@ -701,6 +707,7 @@ class mjCLight : public mjCLight_, private mjsLight {
|
|||||||
const std::string& get_targetbody() const { return targetbody_; }
|
const std::string& get_targetbody() const { return targetbody_; }
|
||||||
|
|
||||||
void SetParent(mjCBody* _body) { body = _body; }
|
void SetParent(mjCBody* _body) { body = _body; }
|
||||||
|
mjCBody* GetParent() const { return body; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Compile(void); // compiler
|
void Compile(void); // compiler
|
||||||
|
|||||||
Reference in New Issue
Block a user