You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been using the new MjSpec's Python api quite a lot recently, and find the object- and name-based data structure accessors super useful. The interfaces between MjSpec, Mj{Model,Data}, and mjx.{Model,Data}, however, are quite inconsistent, which decreases the user experience quite a bit. I think making the different interfaces consistent with each other and polishing some of the rough edges could improve the usability significantly. For some examples of what I mean exactly, see the code snippet and the inlined comments below.
Alternatives
All these have workarounds.
Additional context
Examples
fromabslimportappimportmujocofrommujocoimportmjxdefmain(args):
xml=r"""<mujoco> <worldbody> <body name="main"> <geom name="main" size="0.15 0.15 0.15" mass="1" type="box"/> <freejoint/> <body name="box"> <joint name="box" type="hinge" range="-1 +1"/> <geom name="box" size="0.15 0.15 0.15" mass="1" type="box"/> </body> <body name="sphere"> <joint name="sphere" type="hinge" range="-1 +1"/> <geom name="sphere" size="0.15 0.15 0.15" mass="1" type="box"/> </body> </body> </worldbody></mujoco>"""spec=mujoco.MjSpec.from_string(xml)
sphere_body=spec.find_body("main")
box_body=spec.find_body("box")
# Why can't I do `spec.find_geom("sphere")` as I can do with bodies? Their names are unique, after all.# Or even better: `spec.geom("sphere")` as can be done with `Mj{Model,Data}`.sphere_geom=next(gforginspec.geomsifg.name=="sphere")
box_geom=next(gforginspec.geomsifg.name=="box")
# Again, why can't I do `spec.joint("box")`? This feels inconsistent with `Mj{Model,Data}`.joint_box=next(jforjinspec.jointsifj.name=="box")
joint_sphere=next(jforjinspec.jointsifj.name=="sphere")
joints= [joint_box, joint_sphere]
mj_model=spec.compile()
mj_data=mujoco.MjData(mj_model)
mjx_model=mjx.put_model(mj_model)
mjx_data=mjx.put_data(mj_model, mj_data)
mj_data.bind(joint_sphere).qpos# This works.mj_data.bind(joint_sphere).qvel# This too.mj_data.bind(joints).qpos# Doesn't work with multiple joints though.mjx_data.bind(mjx_model, joint_sphere).qpos# This doesn't, but I believe it's fixed in https://github.com/google-deepmind/mujoco/commit/3dcfad3293522f564eeeb68bc178edb5ffe9c823mjx_data.bind(mjx_model, joint_sphere).qvel# This doesn't either. I don't think it's fixed like `qpos`.mjx_data.bind(mjx_model, joints).qpos# Neither does this.mj_model.bind(joint_box).qposadr# This works.mj_model.bind(joints).qposadr# This does not: "TypeError: bind(): incompatible function arguments."mjx_model.bind(joint_box).qposadr# Neither does this: "IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed"mjx_model.bind(joints).qposadr# Same here: "IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed"# None of these work. Why not? Why can I access `MjData` fields with `MjSpec`# objects but not `MjModel` objects?mj_data.bind(mj_model.joint("sphere")).qposmj_data.bind([mj_model.joint("sphere"), mj_model.joint("box")]).qpos# This does not work. Why not? Why can I do `MjModel.{joint,geom,body}` but not# `mjx.Model.{joint,geom,body}`?mjx_data.bind(mjx_model.joint("sphere")).qposmjx_data.bind([mjx_model.joint("sphere"), mjx_model.joint("box")]).qpos# Neither of these works. They might be a nice user-friendly feature to have. Not# sure though.mj_model.joint(["sphere", "box"])
mjx_model.joint(["sphere", "box"])
if__name__=="__main__":
app.run(main)
The text was updated successfully, but these errors were encountered:
hartikainen
changed the title
Python data structure inconsistensies and usability improvements
Python data structure inconsistencies and usability improvements
Feb 4, 2025
The feature, motivation and pitch
Hey folks,
I've been using the new
MjSpec
's Python api quite a lot recently, and find the object- and name-based data structure accessors super useful. The interfaces betweenMjSpec
,Mj{Model,Data}
, andmjx.{Model,Data}
, however, are quite inconsistent, which decreases the user experience quite a bit. I think making the different interfaces consistent with each other and polishing some of the rough edges could improve the usability significantly. For some examples of what I mean exactly, see the code snippet and the inlined comments below.Alternatives
All these have workarounds.
Additional context
Examples
The text was updated successfully, but these errors were encountered: