Open XinyuWang2 opened 1 year ago
From the MJCF documentation, it seems that the following is the only way at the moment to add a freejoint:
attachment_frame = parent_model.attach(child_model)
attachment_frame.add('freejoint', name=...)
UPDATE: But this still may produce child_name/...
namespace (e.g., <freejoint name="child_name/some_body" />
), and when instantiating a Physics
from the MJCF-generated xml the error will happen due to the nested namespace.
Have you considered doing the combination in the XML, using the <include />
element? See the hammock.xml file in the example models, which can be thought of as the arena, and the humanoid.xml it includes, which could be thought of as the objects.
For easy reference, the "hammock.xml"/"humanoid_body.xml" mentioned: https://github.com/deepmind/mujoco/tree/main/model/hammock
@Balint-H: My problem is that even though the <include />
format in your "hammock.xml" example works and is necessary when testing in "mujoco.viewer", once I try to programmatically attach the "humanoid_body.xml" to a different scene (e.g. when using dm_control.composer
), then I get the error.
For example, this does not work:
from dm_control import mjcf, composer
from dm_control.locomotion import arenas
HUMANOID_XML_PATH = 'test/humanoid_body.xml'
class Humanoid(composer.Entity):
def _build(self):
self._mjcf_model = mjcf.from_path(HUMANOID_XML_PATH)
@property
def mjcf_model(self):
return self._mjcf_model
robot = Humanoid() # composer.Entity
arena = arenas.Floor() # composer.Entity
arena.attach(robot)
print(arena.mjcf_model.to_xml_string())
because it produces:
...
<worldbody>
<geom name="groundplane" class="/" type="plane" size="8 8 0.25" material="groundplane"/>
<camera name="top_camera" class="/" fovy="10.058147163570894" pos="0 0 100" quat="1 0 0 0"/>
<body name="Humanoid body/">
<body name="Humanoid body/torso" childclass="Humanoid body/body" pos="0 0 1.5">
<camera name="Humanoid body/back" mode="trackcom" pos="-3 0 1" xyaxes="0 -1 0 1 0 2"/>
<camera name="Humanoid body/side" mode="trackcom" pos="0 -3 1" xyaxes="1 0 0 0 1 2"/>
<freejoint name="Humanoid body/root"/>
...
resulting in:
Error: free joint can only be used on top level
So the problem is what works for (1) mujoco.viewer
doesn't work for (2) dm_control.composer
. If I remove the <freejoint/>
in the XML file, then use arena.add_free_entity(robot)
then (2) works but (1) shows a fixed humanoid. Ideally, would like to find a solution for both to work. Any ideas?
I want to create separate xml files for robot, object, arena and combine them together later. Because all the objects are very similar, I decided to put all of them in one xml file. Each object are should move freely. Something like this:
Then I use .attach to combine two models: modelArena.attach(modelObject)
But, this will create an outside <body that wraps all <body from modelObject. Something like this:
Then I will get a problem "Error: free joint can only be used on top level".
I know one solution would be to create xml file for each object individually and let the attachment frame add('freejoint'). But this is not very elegant, and it will create many redundant attributes (like <default, because each xml file has the same default setting)
So is there any better way to achieve the same result? I tried to find a way to do without creating another <body that wraps all these but still haven't found one. Thanks!