diff --git a/dm_control/mjcf/schema.xml b/dm_control/mjcf/schema.xml index cf376fa8..d9c13bd1 100644 --- a/dm_control/mjcf/schema.xml +++ b/dm_control/mjcf/schema.xml @@ -2193,7 +2193,7 @@ - + @@ -2232,7 +2232,7 @@ - + @@ -2260,7 +2260,7 @@ - + @@ -2291,7 +2291,7 @@ - + @@ -2322,7 +2322,7 @@ - + @@ -2372,7 +2372,7 @@ - + @@ -2400,7 +2400,7 @@ - + @@ -2431,7 +2431,7 @@ - + @@ -2486,7 +2486,7 @@ - + @@ -3128,6 +3128,28 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -3182,7 +3204,7 @@ - + diff --git a/dm_control/mjcf/schema_test.py b/dm_control/mjcf/schema_test.py index 1eda0e8c..6f52630d 100644 --- a/dm_control/mjcf/schema_test.py +++ b/dm_control/mjcf/schema_test.py @@ -187,5 +187,46 @@ def constructible(spec_node, path): + '\n'.join(failures[:20])) +class SchemaRegressionTest(absltest.TestCase): + """Declarations that MuJoCo accepts must stay representable in PyMJCF.""" + + def test_contact_sensor_parses_and_compiles(self): + xml_string = """ + + + + + + + + + + + """ + root = mjcf.from_xml_string(xml_string) + physics = mjcf.Physics.from_mjcf_model(root) + self.assertEqual(physics.model.nsensor, 1) + self.assertEqual(root.find('sensor', 'cs').geom1.name, 'g') + + def test_jointinparent_is_scoped_on_attach(self): + child = mjcf.RootElement(model='child') + body = child.worldbody.add('body', name='b') + body.add('joint', name='j', type='hinge') + body.add('geom', name='g', size=[0.1]) + child.actuator.add('general', name='a', jointinparent='j') + parent = mjcf.RootElement(model='parent') + parent.attach(child) + self.assertIn('jointinparent="child/j"', parent.to_xml_string()) + physics = mjcf.Physics.from_mjcf_model(parent) + self.assertEqual(physics.model.nu, 1) + + def test_custom_numeric_accepts_array_data(self): + root = mjcf.RootElement(model='m') + root.custom.add('numeric', name='x', data=[1, 2, 3]) + physics = mjcf.Physics.from_mjcf_model(root) + self.assertEqual(physics.model.nnumericdata, 3) + + if __name__ == '__main__': absltest.main()