google-deepmind / mujoco

Multi-Joint dynamics with Contact. A general purpose physics simulator.
https://mujoco.org
Apache License 2.0
8.25k stars 823 forks source link

Loading an XML model with MjSpec broken since v3.2.4 #2205

Closed jonasweihing closed 2 weeks ago

jonasweihing commented 2 weeks ago

Intro

Hi!

I am a masters' student at the University of Tübingen, Germany, and I use MuJoCo/MJX for my research on robotic manipulation.

My setup

MuJoCo/MJX 3.2.4, Python 3.12, Ubuntu 20.04

What's happening? What did you expect?

Loading an xml model (string or file) with MjSpec is broken since MuJoCo 3.2.4.

The loaded and compiled model does not contain any objects, geoms or anything else within the world body. However, if you build the same model with MjSpec manually, it compiles correctly and loading the xml with the old 'mujoco.MjModel.from_xml_string()' method also works correctly. Therefore, I suspect it has to do with the loading of the xml model in MjSpec and not the compilation. In MuJoCo 3.2.3 it worked fine and I have seen some changes in 3.2.4 in the way the xml is loaded in this commit.

I expect that in my example code, the number of geoms in the model (in this example case: 1) loaded with MjSpecs from_string() or from_file() method is the same as in the manually created model and also the old 'mujoco.MjModel.from_xml_string()'.

I wonder why this is happening, as the 'test_body_list()' test in specs_test.py should cover this issue and therefore should have failed.

Steps for reproduction

  1. Add the model from below to the code as a string or load it with MjSpec from a file.
  2. Run the code below.
  3. The number of geoms should equal in all 3 models.

Minimal model for reproduction


<mujoco>
  <worldbody>
    <geom type="sphere" size="1" rgba="1 0 0 1"/>
  </worldbody>
</mujoco>

Code required for reproduction


import mujoco

spec1 = mujoco.MjSpec()
spec1.from_string(xml)
model1 = spec1.compile()

spec2 = mujoco.MjSpec()
geom = spec2.worldbody.add_geom()
geom.type = mujoco.mjtGeom.mjGEOM_SPHERE
geom.size=[1, 1, 1]
geom.rgba=[1, 0, 0, 1]
model2 = spec2.compile()

model3 = mujoco.MjModel.from_xml_string(xml)

if model1.ngeom != model2.ngeom:
  print("Missmatch between xml model loaded with MjSpec 'from_string()' and custom built model with MjSpec.")

if model1.ngeom != model3.ngeom:
  print("Missmatch between xml model loaded with MjSpec 'from_string()' and old 'mujoco.MjModel.from_xml_string()'.")

Confirmations

quagla commented 2 weeks ago

Hi, it's a change in API. The method from_string is now static, so you need to do spec1 = mujoco.MjSpec.from_string(xml) without first initializing an empty spec.

jonasweihing commented 2 weeks ago

I'm sorry I didn't see that. That solves the problem. Thank you.