Enable to attach a spec to a frame.
PiperOrigin-RevId: 699703988 Change-Id: Idbddcbce1e68286248458eb0bd24d5080451a58a
This commit is contained in:
committed by
Copybara-Service
parent
3a12db9ad2
commit
f909d63cdf
+1
-1
@@ -1284,7 +1284,7 @@ elastic structures.
|
|||||||
|
|
||||||
|
|
||||||
The box type, as well as the cylinder and ellipsoid types, are now deprecated in favor of 3D flex :ref:`deformable
|
The box type, as well as the cylinder and ellipsoid types, are now deprecated in favor of 3D flex :ref:`deformable
|
||||||
objects <CDeformable>``. element.
|
objects <CDeformable>`. element.
|
||||||
|
|
||||||
.. _CDeformable:
|
.. _CDeformable:
|
||||||
|
|
||||||
|
|||||||
@@ -503,6 +503,42 @@ The ``MjSpec`` object wraps the :ref:`mjSpec` struct and can be constructed in t
|
|||||||
|
|
||||||
Note the ``from_string()`` and ``from_file()`` methods can only be called at construction time.
|
Note the ``from_string()`` and ``from_file()`` methods can only be called at construction time.
|
||||||
|
|
||||||
|
Attachments
|
||||||
|
-----------
|
||||||
|
|
||||||
|
It is possible to combine multiple specs by using attachments. The following options are possible:
|
||||||
|
|
||||||
|
- Attach a body from the child spec to a frame in the parent spec: ``body.attach_body(body, prefix, suffix)``, returns
|
||||||
|
the newly createdbody in the parent spec.
|
||||||
|
- Attach a frame from the child spec to a body in the parent spec: ``body.attach_frame(frame, prefix, suffix)``,
|
||||||
|
returns the newly created frame in the parent spec.
|
||||||
|
- Attach a body from the child spec to a site in the parent spec: ``site.attach(body, prefix, suffix)``, returns the
|
||||||
|
newly created body in the parent spec.
|
||||||
|
- Attach the worldbody from the child spec to a frame in the parent spec and transform it to a frame:
|
||||||
|
``body.attach(spec, prefix, suffix)``, returns the newly created frame that the child worldbody was transformed
|
||||||
|
into.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import mujoco
|
||||||
|
|
||||||
|
# Create the parent spec.
|
||||||
|
parent = mujoco.MjSpec()
|
||||||
|
body = parent.worldbody.add_body()
|
||||||
|
frame = parent.worldbody.add_frame()
|
||||||
|
site = parent.worldbody.add_site()
|
||||||
|
|
||||||
|
# Create the child spec.
|
||||||
|
child = mujoco.MjSpec()
|
||||||
|
child_body = child.worldbody.add_body()
|
||||||
|
child_frame = child.worldbody.add_frame()
|
||||||
|
|
||||||
|
# Attach the child to the parent in different ways.
|
||||||
|
body_in_frame = frame.attach_body(child_body, 'child-', '')
|
||||||
|
frame_in_body = body.attach_frame(child_frame, 'child-', '')
|
||||||
|
body_in_site = site.attach(child_body, 'child-', '')
|
||||||
|
worldframe_in_frame = frame.attach(child, 'child-', '')
|
||||||
|
|
||||||
Convenience methods
|
Convenience methods
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -665,6 +665,24 @@ PYBIND11_MODULE(_specs, m) {
|
|||||||
return new_body;
|
return new_body;
|
||||||
},
|
},
|
||||||
py::return_value_policy::reference_internal);
|
py::return_value_policy::reference_internal);
|
||||||
|
mjsFrame.def(
|
||||||
|
"attach",
|
||||||
|
[](raw::MjsFrame& self, MjSpec& spec, std::string& prefix,
|
||||||
|
std::string& suffix) -> raw::MjsFrame* {
|
||||||
|
auto world = mjs_findBody(spec.ptr, "world");
|
||||||
|
if (!world) {
|
||||||
|
throw pybind11::value_error(
|
||||||
|
mjs_getError(mjs_getSpec(self.element)));
|
||||||
|
}
|
||||||
|
auto attached_world =
|
||||||
|
mjs_attachBody(&self, world, prefix.c_str(), suffix.c_str());
|
||||||
|
if (!attached_world) {
|
||||||
|
throw pybind11::value_error(
|
||||||
|
mjs_getError(mjs_getSpec(self.element)));
|
||||||
|
}
|
||||||
|
return mjs_bodyToFrame(&attached_world);
|
||||||
|
},
|
||||||
|
py::return_value_policy::reference_internal);
|
||||||
|
|
||||||
// ============================= MJSGEOM =====================================
|
// ============================= MJSGEOM =====================================
|
||||||
mjsGeom.def("delete", [](raw::MjsGeom& self) { mjs_delete(self.element); });
|
mjsGeom.def("delete", [](raw::MjsGeom& self) { mjs_delete(self.element); });
|
||||||
|
|||||||
@@ -884,6 +884,19 @@ class SpecsTest(absltest.TestCase):
|
|||||||
frame = body.to_frame()
|
frame = body.to_frame()
|
||||||
np.testing.assert_array_equal(frame.pos, [1, 2, 3])
|
np.testing.assert_array_equal(frame.pos, [1, 2, 3])
|
||||||
|
|
||||||
|
def test_attach_spec_to_frame(self):
|
||||||
|
child = mujoco.MjSpec()
|
||||||
|
child.worldbody.add_camera(name='camera')
|
||||||
|
parent = mujoco.MjSpec()
|
||||||
|
frame = parent.worldbody.add_frame(name='frame')
|
||||||
|
frame.attach(child, 'child-', '')
|
||||||
|
self.assertLen(child.cameras, 1)
|
||||||
|
self.assertLen(parent.bodies, 1)
|
||||||
|
self.assertLen(parent.frames, 2)
|
||||||
|
self.assertEqual(parent.cameras[0].name, 'child-camera')
|
||||||
|
self.assertEqual(parent.frames[0].name, 'frame')
|
||||||
|
self.assertEqual(parent.frames[1].name, '')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
absltest.main()
|
absltest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user