예제 #1
0
  def testDefaultIdentifier(self):
    mujoco = element.RootElement(model='test')
    body = mujoco.worldbody.add('body')
    joint_0 = body.add('freejoint')
    joint_1 = body.add('joint', type='hinge')
    self.assertIsNone(body.name)
    self.assertIsNone(joint_0.name)
    self.assertIsNone(joint_1.name)
    self.assertEqual(str(body), '<body>...</body>')
    self.assertEqual(str(joint_0), '<freejoint/>')
    self.assertEqual(str(joint_1), '<joint class="/" type="hinge"/>')
    self.assertEqual(body.full_identifier, '//unnamed_body_0')
    self.assertStartsWith(body.to_xml_string(pretty_print=False),
                          '<body name="{:s}">'.format(body.full_identifier))
    self.assertEqual(joint_0.full_identifier, '//unnamed_joint_0')
    self.assertEqual(joint_0.to_xml_string(pretty_print=False),
                     '<freejoint name="{:s}"/>'.format(joint_0.full_identifier))
    self.assertEqual(joint_1.full_identifier, '//unnamed_joint_1')
    self.assertEqual(joint_1.to_xml_string(pretty_print=False),
                     '<joint name="{:s}" class="/" type="hinge"/>'.format(
                         joint_1.full_identifier))

    submujoco = copy.copy(mujoco)
    submujoco.model = 'submodel'
    mujoco.attach(submujoco)
    submujoco_body = submujoco.worldbody.body[0]
    self.assertEqual(submujoco_body.full_identifier,
                     'submodel//unnamed_body_0')
    self.assertEqual(submujoco_body.freejoint.full_identifier,
                     'submodel//unnamed_joint_0')
    self.assertEqual(submujoco_body.joint[0].full_identifier,
                     'submodel//unnamed_joint_1')
예제 #2
0
  def testSetAndGetAttributes(self):
    mujoco = element.RootElement(model='test')

    foo_attribs = dict(name='foo', pos=[1, 2, 3, 4], quat=[0, 1, 0, 0])
    with self.assertRaisesRegexp(ValueError, 'no more than 3 entries'):
      foo = mujoco.worldbody.add('body', **foo_attribs)

    # failed creationg should not cause the identifier 'foo' to be registered
    with self.assertRaises(KeyError):
      mujoco.namescope.get('body', 'foo')
    foo_attribs['pos'] = [1, 2, 3]
    foo = mujoco.worldbody.add('body', **foo_attribs)
    self._test_attributes(foo, expected_values=foo_attribs)

    foo_attribs['name'] = 'bar'
    foo_attribs['pos'] = [1, 2, 3, 4]
    foo_attribs['childclass'] = 'klass'
    with self.assertRaisesRegexp(ValueError, 'no more than 3 entries'):
      foo.set_attributes(**foo_attribs)

    # failed assignment should not cause the identifier 'bar' to be registered
    with self.assertRaises(KeyError):
      mujoco.namescope.get('body', 'bar')
    foo_attribs['pos'] = [1, 2, 3]
    foo.set_attributes(**foo_attribs)
    self._test_attributes(foo, expected_values=foo_attribs)

    actual_foo_attribs = foo.get_attributes()
    for attribute_name, value in six.iteritems(foo_attribs):
      np.testing.assert_array_equal(
          actual_foo_attribs.pop(attribute_name), value)
    for value in six.itervalues(actual_foo_attribs):
      self.assertIsNone(value)
예제 #3
0
 def setUp(self):
     super().setUp()
     schema.override_schema(os.path.join(ASSETS_DIR, FAKE_SCHEMA_FILENAME))
     self._alpha = namescope.NameScope('alpha', None)
     self._beta = namescope.NameScope('beta', None)
     self._beta.parent = self._alpha
     self._mujoco = element.RootElement()
     self._mujoco.namescope.parent = self._beta
예제 #4
0
 def setUp(self):
   schema.MUJOCO = FAKE_MUJOCO
   schema.FINDABLE_NAMESPACES = FAKE_FINDABLE_NAMESPACES
   self._alpha = namescope.NameScope('alpha', None)
   self._beta = namescope.NameScope('beta', None)
   self._beta.parent = self._alpha
   self._mujoco = element.RootElement()
   self._mujoco.namescope.parent = self._beta
예제 #5
0
 def testAddWithInvalidAttribute(self):
     mujoco = element.RootElement(model='test')
     with self.assertRaisesRegexp(AttributeError, 'not a valid attribute'):
         mujoco.worldbody.add('body',
                              name='foo',
                              invalid_attribute='some_value')
     self.assertFalse(mujoco.worldbody.body)
     self.assertIsNone(mujoco.worldbody.find('body', 'foo'))
예제 #6
0
 def testDictLikeInterface(self):
   mujoco = element.RootElement(model='test')
   elem = mujoco.worldbody.add('body')
   with self.assertRaisesRegex(TypeError, 'object is not subscriptable'):
     _ = elem['foo']
   with self.assertRaisesRegex(TypeError, 'does not support item assignment'):
     elem['foo'] = 'bar'
   with self.assertRaisesRegex(TypeError, 'does not support item deletion'):
     del elem['foo']
    def testAssetInheritance(self):
        parent = element.RootElement(model='parent')
        child = element.RootElement(model='child')
        grandchild = element.RootElement(model='grandchild')

        ext = '.png'
        parent_str = b'I belong to the parent'
        child_str = b'I belong to the child'
        grandchild_str = b'I belong to the grandchild'
        parent_vfs_name, child_vfs_name, grandchild_vfs_name = (
            hashlib.sha1(s).hexdigest() + ext
            for s in (parent_str, child_str, grandchild_str))

        parent_ph = mjcf.Asset(contents=parent_str, extension=ext)
        child_ph = mjcf.Asset(contents=child_str, extension=ext)
        grandchild_ph = mjcf.Asset(contents=grandchild_str, extension=ext)

        parent.asset.add('texture', name='parent_tex', file=parent_ph)
        child.asset.add('texture', name='child_tex', file=child_ph)
        grandchild.asset.add('texture',
                             name='grandchild_tex',
                             file=grandchild_ph)

        parent.attach(child)
        child.attach(grandchild)

        # The grandchild should only return its own assets.
        self.assertDictEqual({grandchild_vfs_name: grandchild_str},
                             grandchild.get_assets())

        # The child should return its own assets plus those of the grandchild.
        self.assertDictEqual(
            {
                child_vfs_name: child_str,
                grandchild_vfs_name: grandchild_str
            }, child.get_assets())

        # The parent should return everything.
        self.assertDictEqual(
            {
                parent_vfs_name: parent_str,
                child_vfs_name: child_str,
                grandchild_vfs_name: grandchild_str
            }, parent.get_assets())
예제 #8
0
 def testFileFromAssetsDict(self):
   prefix = 'fake_filename'
   extension = '.whatever'
   path = 'invalid/path/' + prefix + extension
   contents = 'Fake contents'
   assets = {path: contents}
   mujoco = element.RootElement(assets=assets)
   text_file = mujoco.files.add('text', file=path)
   expected_value = attribute.Asset(
       contents=contents, extension=extension, prefix=prefix)
   self.assertEqual(text_file.file, expected_value)
예제 #9
0
 def testDictLikeInterface(self):
   mujoco = element.RootElement(model='test')
   elem = mujoco.worldbody.add('body')
   if six.PY3:
     subscript_error_regex = 'object is not subscriptable'
   else:
     subscript_error_regex = 'no attribute \'__getitem__\''
   with self.assertRaisesRegexp(TypeError, subscript_error_regex):
     _ = elem['foo']
   with self.assertRaisesRegexp(TypeError, 'does not support item assignment'):
     elem['foo'] = 'bar'
   with self.assertRaisesRegexp(TypeError, 'does not support item deletion'):
     del elem['foo']
예제 #10
0
 def testInvalidAttr(self):
   mujoco = element.RootElement(model='test')
   invalid_attrib_name = 'foobar'
   def test_invalid_attr_recursively(mjcf_element):
     self.assertNotHasAttr(mjcf_element, invalid_attrib_name)
     self.assertNotIn(invalid_attrib_name, dir(mjcf_element))
     with self.assertRaisesRegexp(AttributeError, 'object has no attribute'):
       getattr(mjcf_element, invalid_attrib_name)
     with self.assertRaisesRegexp(AttributeError, 'can\'t set attribute'):
       setattr(mjcf_element, invalid_attrib_name, 'value')
     with self.assertRaisesRegexp(AttributeError, 'object has no attribute'):
       delattr(mjcf_element, invalid_attrib_name)
     for child in mjcf_element.all_children():
       test_invalid_attr_recursively(child)
   test_invalid_attr_recursively(mujoco)
예제 #11
0
 def testAttributeError(self):
     mjcf_model = element.RootElement(model='test')
     mjcf_model.worldbody._spec = None
     try:
         _ = mjcf_model.worldbody.tag
     except AttributeError:
         _, err, tb = sys.exc_info()
     else:
         self.fail('AttributeError was not raised.')
     # Test that the error comes from the fact that we've set `_spec = None`.
     self.assertEqual(str(err),
                      '\'NoneType\' object has no attribute \'name\'')
     _, _, func_name, _ = traceback.extract_tb(tb)[-1]
     # Test that the error comes from the `root` property, not `__getattr__`.
     self.assertEqual(func_name, 'tag')
예제 #12
0
    def testSameness(self):
        mujoco = element.RootElement(model='test')

        body_1 = mujoco.worldbody.add('body', pos=[0, 1, 2], quat=[0, 1, 0, 1])
        site_1 = body_1.add('site', pos=[0, 1, 2], quat=[0, 1, 0, 1])
        geom_1 = body_1.add('geom', pos=[0, 1, 2], quat=[0, 1, 0, 1])

        for elem in (body_1, site_1, geom_1):
            self.assertIsSame(elem, elem)

        # strict ordering NOT required: adding geom and site is different order
        body_2 = mujoco.worldbody.add('body', pos=[0, 1, 2], quat=[0, 1, 0, 1])
        geom_2 = body_2.add('geom', pos=[0, 1, 2], quat=[0, 1, 0, 1])
        site_2 = body_2.add('site', pos=[0, 1, 2], quat=[0, 1, 0, 1])

        elems_1 = (body_1, site_1, geom_1)
        elems_2 = (body_2, site_2, geom_2)
        for i, j in itertools.product(range(len(elems_1)),
                                      range(len(elems_2))):
            if i == j:
                self.assertIsSame(elems_1[i], elems_2[j])
            else:
                self.assertIsNotSame(elems_1[i], elems_2[j])

        # on-demand child
        body_1.add('inertial', pos=[0, 0, 0], mass=1)
        self.assertIsNotSame(body_1, body_2)

        body_2.add('inertial', pos=[0, 0, 0], mass=1)
        self.assertIsSame(body_1, body_2)

        # different number of children
        subbody_1 = body_1.add('body', pos=[0, 0, 1])
        self.assertIsNotSame(body_1, body_2)

        # attribute mismatch
        subbody_2 = body_2.add('body')
        self.assertIsNotSame(subbody_1, subbody_2)
        self.assertIsNotSame(body_1, body_2)

        subbody_2.pos = [0, 0, 1]
        self.assertIsSame(subbody_1, subbody_2)
        self.assertIsSame(body_1, body_2)

        # grandchild attribute mismatch
        subbody_1.add('joint', type='hinge')
        subbody_2.add('joint', type='ball')
        self.assertIsNotSame(body_1, body_2)
예제 #13
0
    def testAdd(self):
        mujoco = element.RootElement(model='test')

        # repeated elements
        body_foo_attributes = dict(name='foo',
                                   pos=[0, 1, 0],
                                   quat=[0, 1, 0, 0])
        body_foo = mujoco.worldbody.add('body', **body_foo_attributes)
        self.assertEqual(body_foo.tag, 'body')
        joint_foo_attributes = dict(name='foo', type='free')
        joint_foo = body_foo.add('joint', **joint_foo_attributes)
        self.assertEqual(joint_foo.tag, 'joint')
        self._test_properties(body_foo, parent=mujoco.worldbody, root=mujoco)
        self._test_attributes(body_foo, expected_values=body_foo_attributes)
        self._test_children(body_foo)
        self._test_properties(joint_foo, parent=body_foo, root=mujoco)
        self._test_attributes(joint_foo, expected_values=joint_foo_attributes)
        self._test_children(joint_foo)

        # non-repeated, on-demand elements
        self.assertIsNone(body_foo.inertial)
        body_foo_inertial_attributes = dict(mass=1.0, pos=[0, 0, 0])
        body_foo_inertial = body_foo.add('inertial',
                                         **body_foo_inertial_attributes)
        self._test_properties(body_foo_inertial, parent=body_foo, root=mujoco)
        self._test_attributes(body_foo_inertial,
                              expected_values=body_foo_inertial_attributes)
        self._test_children(body_foo_inertial)

        with six.assertRaisesRegex(self, ValueError,
                                   '<inertial> child already exists'):
            body_foo.add('inertial', **body_foo_inertial_attributes)

        # non-repeated, non-on-demand elements
        with six.assertRaisesRegex(self, ValueError,
                                   '<compiler> child already exists'):
            mujoco.add('compiler')
        self.assertIsNotNone(mujoco.compiler)
        with six.assertRaisesRegex(self, ValueError,
                                   '<default> child already exists'):
            mujoco.add('default')
        self.assertIsNotNone(mujoco.default)
예제 #14
0
  def testTendonSameness(self):
    mujoco = element.RootElement(model='test')

    spatial_1 = mujoco.tendon.add('spatial')
    spatial_1.add('site', site='foo')
    spatial_1.add('geom', geom='bar')

    spatial_2 = mujoco.tendon.add('spatial')
    spatial_2.add('site', site='foo')
    spatial_2.add('geom', geom='bar')

    self.assertIsSame(spatial_1, spatial_2)

    # strict ordering is required
    spatial_3 = mujoco.tendon.add('spatial')
    spatial_3.add('site', site='foo')
    spatial_3.add('geom', geom='bar')

    spatial_4 = mujoco.tendon.add('spatial')
    spatial_4.add('geom', geom='bar')
    spatial_4.add('site', site='foo')

    self.assertIsNotSame(spatial_3, spatial_4)
예제 #15
0
def _parse(xml_root,
           escape_separators=False,
           model_dir='',
           resolve_references=True,
           assets=None):
    """Parses a complete MJCF model from an XML.

  Args:
    xml_root: An `etree.Element` object.
    escape_separators: (optional) A boolean, whether to replace '/' characters
      in element identifiers. If `False`, any '/' present in the XML causes
      a ValueError to be raised.
    model_dir: (optional) Path to the directory containing the model XML file.
      This is used to prefix the paths of all asset files.
    resolve_references: (optional) A boolean indicating whether the parser
      should attempt to resolve reference attributes to a corresponding element.
    assets: (optional) A dictionary of pre-loaded assets, of the form
      `{filename: bytestring}`. If present, PyMJCF will search for assets in
      this dictionary before attempting to load them from the filesystem.

  Returns:
    An `mjcf.RootElement`.

  Raises:
    ValueError: If `xml_root`'s tag is not 'mujoco.*'.
  """

    assets = assets or {}

    if not xml_root.tag.startswith('mujoco'):
        raise ValueError(
            'Root element of the XML should be <mujoco.*>: got <{}>'.format(
                xml_root.tag))

    with debugging.freeze_current_stack_trace():
        # Recursively parse any included XML files.
        to_include = []
        for include_tag in xml_root.findall('include'):
            try:
                # First look for the path to the included XML file in the assets dict.
                path_or_xml_string = assets[include_tag.attrib['file']]
                parsing_func = from_xml_string
            except KeyError:
                # If it's not present in the assets dict then attempt to load the XML
                # from the filesystem.
                path_or_xml_string = os.path.join(model_dir,
                                                  include_tag.attrib['file'])
                parsing_func = from_path
            included_mjcf = parsing_func(path_or_xml_string,
                                         escape_separators=escape_separators,
                                         resolve_references=resolve_references,
                                         assets=assets)
            to_include.append(included_mjcf)
            # We must remove <include/> tags before parsing the main XML file, since
            # these are a schema violation.
            xml_root.remove(include_tag)

        # Parse the main XML file.
        try:
            model = xml_root.attrib.pop('model')
        except KeyError:
            model = None
        mjcf_root = element.RootElement(model=model,
                                        model_dir=model_dir,
                                        assets=assets)
        _parse_children(xml_root, mjcf_root, escape_separators)

        # Merge in the included XML files.
        for included_mjcf in to_include:
            # The included MJCF might have been automatically assigned a model name
            # that conficts with that of `mjcf_root`, so we override it here.
            included_mjcf.model = mjcf_root.model
            mjcf_root.include_copy(included_mjcf)

        if resolve_references:
            mjcf_root.resolve_references()
        return mjcf_root
예제 #16
0
 def testChildren(self):
   mujoco = element.RootElement(model='test')
   self._test_children(mujoco, recursive=True)
예제 #17
0
 def testAttributes(self):
   mujoco = element.RootElement(model='test')
   mujoco.default.dclass = 'main'
   self._test_attributes(mujoco, recursive=True)
예제 #18
0
 def testProperties(self):
   mujoco = element.RootElement(model='test')
   self.assertIsInstance(mujoco.namescope, namescope.NameScope)
   self._test_properties(mujoco, parent=None, root=mujoco, recursive=True)