Exemple #1
0
    def test_parse_scalar_sdf_strings(self):
        def generate_scalar_test_obj(name, value=None):
            if value is None:
                value = random.random()
            sdf_str = '<{}>{}</{}>'.format(name, value, name)
            expected_sdf = create_sdf_element(name)
            self.assertIsNotNone(expected_sdf, '{} returned None'.format(name))
            expected_sdf.value = value
            return sdf_str, expected_sdf

        scalar_test_cases = list()

        for c in XMLScalar.__subclasses__():
            if c._TYPE == 'sdf':
                scalar_test_cases.append(c._NAME)

        # Exclude special cases
        exclude = ['friction', 'range', 'poissons_ratio']

        for tag in scalar_test_cases:
            if tag in exclude:
                continue
            sdf_str, expected_sdf = generate_scalar_test_obj(tag)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # TODO Add tests for friction and range
        sdf_str, expected_sdf = generate_scalar_test_obj(
            'poissons_ratio', random.uniform(-1, 0.5))
        sdf = parse_sdf(sdf_str)
        self.assertIsNotNone(sdf)
        self.assertEqual(parse_sdf(sdf_str), expected_sdf)
Exemple #2
0
    def test_parse_integer_sdf_strings(self):
        def generate_integer_test_obj(name, value=None):
            if value is None:
                value = random.randint(1, 10)
            sdf_str = '<{}>{}</{}>'.format(name, value, name)
            expected_sdf = create_sdf_element(name)
            self.assertIsNotNone(expected_sdf, '{} returned None'.format(name))
            expected_sdf.value = value
            return sdf_str, expected_sdf

        int_test_cases = list()

        for c in XMLInteger.__subclasses__():
            if c._TYPE == 'sdf':
                int_test_cases.append(c._NAME)

        # Exclude special cases
        exclude = []

        for tag in int_test_cases:
            if tag in exclude:
                continue
            sdf_str, expected_sdf = generate_integer_test_obj(tag)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)
    def test_add_light(self):
        sdf = """
        <light type="point" name="point_light">
            <pose>0 2 2 0 0 0</pose>
            <diffuse>1 0 0 1</diffuse>
            <specular>.1 .1 .1 1</specular>
            <attenuation>
                <range>20</range>
                <linear>0.2</linear>
                <constant>0.8</constant>
                <quadratic>0.01</quadratic>
            </attenuation>
            <cast_shadows>false</cast_shadows>
        </light>
        """

        light = Light.from_sdf(parse_sdf(sdf))
        group = ModelGroup()

        group.add_light('light', light)
        self.assertEqual(group.n_lights, 1)
        self.assertIsNotNone(group.get_light('light'))

        group_light = group.get_light('light')

        self.assertIsNotNone(group_light)
Exemple #4
0
    def test_heightmap_generator_to_gazebo_model(self):
        hg = HeightmapGenerator()
        hg.biome = WhittakerBiome()
        model_name = generate_random_string(10)
        output_dir = os.path.join(os.path.expanduser('~'), '.gazebo', 'models')
        if not os.path.isdir(output_dir):
            os.makedirs(output_dir)

        model = hg.as_model()
        model.name = model_name

        model.to_gazebo_model(output_dir=output_dir, copy_resources=True)

        self.assertTrue(os.path.isdir(os.path.join(output_dir, model_name)))

        sdf = parse_sdf(os.path.join(output_dir, model_name, 'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertIsNotNone(sdf.models[0])

        heightmap = \
            sdf.models[0].links[0].visuals[0].geometry.heightmap
        self.assertIsNotNone(heightmap.uri)
        self.assertIn('model://{}'.format(model_name), heightmap.uri.value)
        self.assertIn('/materials/textures/', heightmap.uri.value)
        self.assertTrue(heightmap.uri.value.endswith('.png'))

        heightmap = \
            sdf.models[0].links[0].collisions[0].geometry.heightmap
        self.assertIsNotNone(heightmap.uri)
        self.assertIn('model://{}'.format(model_name), heightmap.uri.value)
        self.assertIn('/materials/textures/', heightmap.uri.value)
        self.assertTrue(heightmap.uri.value.endswith('.png'))

        shutil.rmtree(os.path.join(output_dir, model_name))
Exemple #5
0
    def test_actor_walking(self):
        add_custom_gazebo_resource_path(os.path.join(CUR_DIR, 'gazebo_models'))
        sdf = parse_sdf(
            os.path.join(CUR_DIR, 'gazebo_models', 'test_actor_walking',
                         'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertIsNotNone(sdf.actors)
        self.assertEqual(len(sdf.actors), 1)

        actor = Actor.from_sdf(sdf.actors[0])
        self.assertIsNotNone(actor)

        self.assertEqual(actor.name, 'actor')
        self.assertEqual(actor.pose.position[0], 0)
        self.assertEqual(actor.pose.position[1], 0)
        self.assertEqual(actor.pose.position[2], 0)

        self.assertEqual(len(actor.animations), 1)
        self.assertEqual(actor.animations[0].name, 'walking')
        self.assertEqual(actor.animations[0].filename,
                         'model://test_actor_walking/meshes/walk.dae')
        self.assertEqual(actor.animations[0].scale, 1)
        self.assertEqual(actor.animations[0].interpolate_x, True)

        self.assertEqual(len(actor.script.trajectories), 1)
        self.assertEqual(actor.script.trajectories[0].id, 0)
        self.assertEqual(actor.script.trajectories[0].type, 'walking')

        self.assertEqual(len(actor.script.trajectories[0].waypoints), 32)
Exemple #6
0
 def test_parse_gazebo_models(self):
     gazebo_models_dir = \
         os.path.join(CUR_DIR, 'gazebo_models')
     for item in os.listdir(gazebo_models_dir):
         sdf = parse_sdf(
             os.path.join(gazebo_models_dir, item, 'model.sdf'))
         self.assertIsNotNone(sdf)
         if '_actor_' in item:
             self.assertIsNotNone(sdf.actors)
         else:
             self.assertIsNotNone(sdf.models)
Exemple #7
0
    def test_parse_actor_relative_paths(self):
        sdf = parse_sdf(os.path.join(
            CUR_DIR,
            'gazebo_models',
            'test_actor_relative_paths',
            'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertIsNotNone(sdf.actors)
        self.assertEqual(len(sdf.actors), 1)

        self.assertEqual(len(sdf.actors[0].animations), 8)
        self.assertEqual(len(sdf.actors[0].script.trajectories), 13)
Exemple #8
0
    def test_template_world_gen(self):
        root_path = os.path.join(CWD, 'templates', 'world_generator')

        for template_file in os.listdir(root_path):
            if not os.path.isfile(os.path.join(root_path, template_file)):
                continue
            output_xml = process_jinja_template(
                os.path.join(root_path, template_file))
            sdf = parse_sdf(output_xml)
            self.assertIsNotNone(sdf)
            self.assertEqual(sdf.xml_element_name, 'sdf')
            self.assertIsNotNone(sdf.world)
Exemple #9
0
    def test_export_model_to_sdf(self):
        box = self.create_random_box()

        sdf = box.to_sdf('model')
        filename = '/tmp/box.sdf'
        sdf.export_xml(filename, version='1.6')

        self.assertTrue(os.path.isfile(filename))

        # Parse the exported file
        parsed_sdf = parse_sdf(filename)
        self.assertIsNotNone(parsed_sdf)
        self.assertEqual(sdf, parsed_sdf)
    def test_kobuki_robot_description(self):
        template_dir = os.path.abspath(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), '..',
                         'examples', 'robot_description', 'kobuki', 'sdf'))

        template = os.path.join(template_dir, 'kobuki.sdf.jinja')
        xml = process_jinja_template(template)
        sdf = parse_sdf(xml)

        self.assertIsNotNone(sdf)
        self.assertEqual(sdf.xml_element_name, 'sdf')
        self.assertIsNotNone(sdf.models)
        self.assertEqual(len(sdf.models), 1)
        self.assertEqual(sdf.models[0].name, 'kobuki')
    def test_parse_world_files(self):
        world_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                 'worlds')
        for item in os.listdir(world_dir):
            world_file = os.path.join(world_dir, item)
            if not os.path.isfile(world_file) or \
                    not world_file.endswith('.world'):
                continue
            sdf = parse_sdf(world_file)
            self.assertIsNotNone(sdf)
            self.assertEqual(sdf.xml_element_name, 'sdf')
            self.assertIsNotNone(
                sdf.world,
                'No world element was parsed from file {}'.format(world_file))

            if sdf.world.includes is None:
                world = World.from_sdf(sdf)
                self.assertIsNotNone(world)

                w_sdf = world.to_sdf(type='sdf')
                self.assertIsNotNone(w_sdf.world)

                for tag in sdf.world.children:
                    if sdf.world.children[tag] is None:
                        continue

                    if isinstance(sdf.world.children[tag], list):
                        if tag == 'model':
                            for model in sdf.world.children[tag]:
                                self.assertTrue(world.model_exists(model.name))
                        if tag == 'light':
                            for light in sdf.world.children[tag]:
                                self.assertTrue(world.light_exists(light.name))
                    elif tag == 'physics':
                        self.assertEqual(sdf.world.physics.type,
                                         w_sdf.world.physics.type)
                        for physics_tag in sdf.world.physics.children:
                            obj = getattr(sdf.world.physics, physics_tag)
                            self.assertIn(physics_tag,
                                          w_sdf.world.physics.children)
                            if obj.has_value():
                                self.assertEqual(
                                    obj,
                                    getattr(w_sdf.world.physics, physics_tag))
                    else:
                        obj = getattr(sdf.world, tag)
                        if obj.has_value():
                            self.assertEqual(obj, getattr(w_sdf.world, tag))
Exemple #12
0
 def test_parse_world_files(self):
     world_dir = os.path.join(
         os.path.dirname(os.path.abspath(__file__)),
         'worlds'
     )
     for item in os.listdir(world_dir):
         world_file = os.path.join(world_dir, item)
         if not os.path.isfile(world_file) or \
                 not world_file.endswith('.world'):
             continue
         sdf = parse_sdf(world_file)
         self.assertIsNotNone(sdf)
         self.assertEqual(sdf.xml_element_name, 'sdf')
         self.assertIsNotNone(
             sdf.world,
             'No world element was parsed from file {}'.format(world_file))
Exemple #13
0
    def test_parse_vector_sdf_strings(self):
        def generate_array_test_obj(name, vec=None):
            expected_sdf = create_sdf_element(name)
            self.assertIsNotNone(expected_sdf, '{} returned None'.format(name))
            if vec is None:
                vec = [random.random() for _ in range(expected_sdf._size)]
            sdf_str = '<{}>{}</{}>'.format(name,
                                           ' '.join(str(x) for x in vec), name)
            expected_sdf.value = vec
            return sdf_str, expected_sdf

        array_test_cases = list()

        for c in XMLVector.__subclasses__():
            if c._TYPE == 'sdf':
                array_test_cases.append(c._NAME)

        exclude = ['xyz']

        for tag in array_test_cases:
            if tag in exclude:
                continue
            sdf_str, expected_sdf = generate_array_test_obj(tag)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # Test for XYZ vectors
        sdf_str, expected_sdf = generate_array_test_obj('xyz', [1, 0, 0])
        sdf = parse_sdf(sdf_str)
        self.assertIsNotNone(sdf)
        self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        sdf_str, expected_sdf = generate_array_test_obj('xyz', [0, 1, 0])
        sdf = parse_sdf(sdf_str)
        self.assertIsNotNone(sdf)
        self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        sdf_str, expected_sdf = generate_array_test_obj('xyz', [0, 0, 1])
        sdf = parse_sdf(sdf_str)
        self.assertIsNotNone(sdf)
        self.assertEqual(parse_sdf(sdf_str), expected_sdf)
Exemple #14
0
    def test_actor_relative_paths(self):
        add_custom_gazebo_resource_path(os.path.join(CUR_DIR, 'gazebo_models'))
        sdf = parse_sdf(
            os.path.join(CUR_DIR, 'gazebo_models', 'test_actor_relative_paths',
                         'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertIsNotNone(sdf.actors)
        self.assertEqual(len(sdf.actors), 1)

        actor = Actor.from_sdf(sdf.actors[0])
        self.assertIsNotNone(actor)

        self.assertEqual(actor.name, 'actor_test')
        self.assertEqual(actor.pose.position[0], 0)
        self.assertEqual(actor.pose.position[1], 0)
        self.assertEqual(actor.pose.position[2], 1)

        self.assertEqual(len(actor.animations), 8)
        self.assertEqual(len(actor.script.trajectories), 13)
    def test_xml_input_random(self):
        urdf_elements = [
            'mass', 'child', 'parent', 'origin', 'box', 'cylinder', 'sphere',
            'mesh', 'limit', 'inertial', 'inertia', 'dynamics'
        ]

        for urdf_name in urdf_elements:
            obj = create_urdf_element(urdf_name)
            assert obj is not None
            obj.random()
            output = subprocess.check_output(
                ['pcg-urdf2sdf', '--xml',
                 obj.to_xml_as_str(), '--print'])

            urdf = parse_sdf(output.decode('utf-8'))
            assert urdf is not None

            response_urdf = sdf2urdf(urdf)
            assert obj == response_urdf
Exemple #16
0
    def test_parse_biome_from_heightmap(self):
        add_custom_gazebo_resource_path(
            os.path.join(CUR_DIR, '..', 'examples', 'models'))

        # Parse the SDF file
        sdf = parse_sdf(
            os.path.join(CUR_DIR, '..', 'examples', 'models',
                         'pcg_winding_valley_heightmap', 'model.sdf'))
        self.assertIsNotNone(sdf)

        sdf_heightmap = sdf.models[0].links[0].visuals[0].geometry.heightmap
        biome = Biome.from_sdf(sdf_heightmap)

        self.assertIsNotNone(biome)
        self.assertEqual(biome.n_elevation_zones, 3)
        self.assertEqual(biome.n_moisture_zones, 1)

        for i in range(biome.n_elevation_zones):
            tag = biome.get_biome(i, 0)
            self.assertIsNotNone(tag)
            self.assertIsNotNone(biome.get_diffuse(tag))
            self.assertIsNotNone(biome.get_normal(tag))
    def randomize_configured_model(self,
                                   model_path,
                                   min_scale=0.05,
                                   max_scale=0.25,
                                   min_mass=0.1,
                                   max_mass=3.0,
                                   min_friction=0.75,
                                   max_friction=1.5):

        # Get path to the configured SDF file
        configured_sdf_path = self.get_configured_sdf_path(model_path)

        # Parse the configured SDF that needs to be randomized
        sdf = parse_sdf(configured_sdf_path)

        # Process the model(s) contained in the SDF
        for model in sdf.models:

            # Process the link(s) of each model
            for link in model.links:

                # Randomize scale of the link
                self.randomize_scale(model_path,
                                     link,
                                     min_scale=min_scale,
                                     max_scale=max_scale)

                # Randomize inertial properties of the link
                self.randomize_inertial(link,
                                        min_mass=min_mass,
                                        max_mass=max_mass)

                # Randomize friction of the link
                self.randomize_friction(link,
                                        min_friction=min_friction,
                                        max_friction=max_friction)

        # Overwrite the configured SDF file with randomized values
        sdf.export_xml(configured_sdf_path)
Exemple #18
0
    def test_parse_heightmap_model(self):
        add_custom_gazebo_resource_path(
            os.path.join(CUR_DIR, '..', 'examples', 'models'))

        # Parse the SDF file
        sdf = parse_sdf(
            os.path.join(CUR_DIR, '..', 'examples', 'models',
                         'pcg_winding_valley_heightmap', 'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertIsNotNone(sdf.models)
        self.assertEqual(len(sdf.models[0].links[0].visuals), 1)
        self.assertEqual(len(sdf.models[0].links[0].collisions), 1)

        sdf_heightmap = sdf.models[0].links[0].visuals[0].geometry.heightmap
        self.assertIsNotNone(sdf_heightmap)

        uri_path_prefix = \
            'model://pcg_winding_valley_heightmap/materials/textures'
        self.assertIn(uri_path_prefix, sdf_heightmap.uri.value)
        self.assertEqual(len(sdf_heightmap.textures), 3)
        for texture in sdf_heightmap.textures:
            self.assertIn(uri_path_prefix, texture.diffuse.value)
            self.assertIn(uri_path_prefix, texture.normal.value)
            self.assertEqual(texture.size.value, [10])
        self.assertEqual(len(sdf_heightmap.blends), 2)
        for blend in sdf_heightmap.blends:
            self.assertGreater(blend.min_height.value, 0)
            self.assertGreater(blend.fade_dist.value, 0)
        self.assertEqual(sdf_heightmap.size.value, [1000, 1000, 25])
        self.assertEqual(sdf_heightmap.pos.value, [0, 0, -4])

        sdf_heightmap = \
            sdf.models[0].links[0].collisions[0].geometry.heightmap
        self.assertIsNotNone(sdf_heightmap)

        self.assertIn(uri_path_prefix, sdf_heightmap.uri.value)
        self.assertEqual(sdf_heightmap.size.value, [1000, 1000, 25])
        self.assertEqual(sdf_heightmap.pos.value, [0, 0, -4])
    def test_xml_input_visual_collision(self):
        for urdf_tag in ['visual', 'collision']:
            obj = create_urdf_element(urdf_tag)
            assert obj is not None

            obj.origin = create_urdf_element('origin')
            obj.origin.random()
            obj.geometry = create_urdf_element('geometry')

            geometries = ['box', 'cylinder', 'sphere', 'mesh']

            for geo_name in geometries:
                obj.geometry.reset(mode=geo_name)
                obj.geometry.random()

                output = subprocess.check_output(
                    ['pcg-urdf2sdf', '--xml',
                     obj.to_xml_as_str(), '--print'])
                urdf = parse_sdf(output.decode('utf-8'))
                assert urdf is not None

                response_urdf = sdf2urdf(urdf)

                assert obj == response_urdf
Exemple #20
0
    def test_parse_string_sdf_strings(self):
        def generate_string_test_obj(name, value=None):
            if value is None:
                value = generate_random_string(5)
            sdf_str = '<{}>{}</{}>'.format(name, value, name)
            expected_sdf = create_sdf_element(name)
            self.assertIsNotNone(expected_sdf, '{} returned None'.format(name))
            expected_sdf.value = value
            return sdf_str, expected_sdf

        string_test_cases = list()

        for c in XMLString.__subclasses__():
            if c._TYPE == 'sdf':
                string_test_cases.append(c._NAME)

        # Exclude special cases
        exclude = ['empty', 'format', 'friction_model', 'collision',
                   'measure_direction', 'localization', 'view_controller',
                   'projection_type', 'surface_model',
                   'world_frame_orientation']

        for tag in string_test_cases:
            if tag in exclude:
                continue
            sdf_str, expected_sdf = generate_string_test_obj(tag)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # Add tests for measure_direction
        values = ['child_to_parent', 'parent_to_link']
        for value in values:
            sdf_str, expected_sdf = generate_string_test_obj(
                'measure_direction', value)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # Add tests for format
        values = ['L8', 'R8G8B8', 'B8G8R8', 'BAYER_RGGB8',
                  'BAYER_BGGR8', 'BAYER_GBRG8', 'BAYER_GRBG8']
        for value in values:
            sdf_str, expected_sdf = generate_string_test_obj('format', value)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # Add tests for friction_model
        values = ['pyramid_model', 'box_model', 'cone_model']
        for value in values:
            sdf_str, expected_sdf = generate_string_test_obj(
                'friction_model', value)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # Add tests for localization
        values = ['CUSTOM', 'NED', 'ENU', 'NWU', 'GRAV_UP', 'GRAV_DOWN']
        for value in values:
            sdf_str, expected_sdf = generate_string_test_obj(
                'localization', value)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)

        # Add tests for projection_type
        values = ['perspective', 'orthographic']
        for value in values:
            sdf_str, expected_sdf = generate_string_test_obj(
                'projection_type', value)
            sdf = parse_sdf(sdf_str)
            self.assertIsNotNone(sdf)
            self.assertEqual(parse_sdf(sdf_str), expected_sdf)
    def test_model_group_to_sdf(self):
        sdf_light = """
        <light type="point" name="point_light">
            <pose>0 2 2 0 0 0</pose>
            <diffuse>1 0 0 1</diffuse>
            <specular>.1 .1 .1 1</specular>
            <attenuation>
                <range>20</range>
                <linear>0.2</linear>
                <constant>0.8</constant>
                <quadratic>0.01</quadratic>
            </attenuation>
            <cast_shadows>false</cast_shadows>
        </light>
        """
        light = Light.from_sdf(parse_sdf(sdf_light))
        box = box_factory(size=[[1, 1, 1]],
                          mass=1,
                          use_permutation=True,
                          name='box')[0]

        group = ModelGroup(name='test')
        group.add_light('light', light)
        group.add_model('box', box)

        sdf_models, sdf_lights, sdf_includes = group.to_sdf(use_include=False)

        self.assertEqual(len(sdf_models), 1)
        self.assertEqual(len(sdf_lights), 1)
        self.assertEqual(len(sdf_includes), 0)

        group_box = group.get_model('box', with_group_prefix=False)
        self.assertIsNotNone(group_box)
        self.assertEqual(group_box.name, 'box')

        group_box = group.get_model('box', with_group_prefix=True)
        self.assertIsNotNone(group_box)
        self.assertEqual(group_box.name, 'test/box')

        group_models = group.get_models(with_group_prefix=False)
        self.assertIsInstance(group_models, dict)
        self.assertEqual(len(group_models), 1)
        self.assertIn('box', group_models)

        group_models = group.get_models(with_group_prefix=True)
        self.assertIsInstance(group_models, dict)
        self.assertEqual(len(group_models), 1)
        self.assertIn('test/box', group_models)

        group_light = group.get_light('light', with_group_prefix=False)
        self.assertIsNotNone(group_light)
        self.assertEqual(group_light.name, 'light')

        group_light = group.get_light('light', with_group_prefix=True)
        self.assertIsNotNone(group_light)
        self.assertEqual(group_light.name, 'test/light')

        group_lights = group.get_lights(with_group_prefix=False)
        self.assertIsInstance(group_lights, dict)
        self.assertEqual(len(group_lights), 1)
        self.assertIn('light', group_lights)

        group_lights = group.get_lights(with_group_prefix=True)
        self.assertIsInstance(group_lights, dict)
        self.assertEqual(len(group_lights), 1)
        self.assertIn('test/light', group_lights)
    def test_nested_model_groups(self):
        sdf_light = """
        <light type="point" name="point_light">
            <pose>0 2 2 0 0 0</pose>
            <diffuse>1 0 0 1</diffuse>
            <specular>.1 .1 .1 1</specular>
            <attenuation>
                <range>20</range>
                <linear>0.2</linear>
                <constant>0.8</constant>
                <quadratic>0.01</quadratic>
            </attenuation>
            <cast_shadows>false</cast_shadows>
        </light>
        """
        light = Light.from_sdf(parse_sdf(sdf_light))

        box_1 = box_factory(size=[[1, 1, 1]],
                            mass=1,
                            use_permutation=True,
                            name='box')[0]

        box_2 = box_factory(size=[[2, 2, 2]],
                            mass=2,
                            use_permutation=True,
                            name='box')[0]

        nested_group = ModelGroup(name='nested')
        root_group = ModelGroup(name='root')

        nested_group.add_light('light', light)
        nested_group.add_model('box', box_1)

        root_group.add_model('box', box_2)
        root_group.add_model('nested', nested_group)

        # Trying to get light from the root group, should return None
        gl = root_group.get_light('light')
        self.assertIsNone(gl)
        gl = root_group.get_light('nested/light')
        self.assertIsNotNone(gl)

        # Trying to get boxes from both groups
        gb = root_group.get_model('box')
        self.assertIsNotNone(gb)
        self.assertEqual(gb.links[gb.link_names[0]].inertial.mass, 2)

        gb = root_group.get_model('nested/box')
        self.assertIsNotNone(gb)
        self.assertEqual(gb.links[gb.link_names[0]].inertial.mass, 1)

        # Request all models from nested group (with and without prefix)
        group_models = nested_group.get_models(with_group_prefix=False)
        self.assertIsInstance(group_models, dict)
        self.assertEqual(len(group_models), 1)
        self.assertIn('box', group_models)

        group_models = nested_group.get_models(with_group_prefix=True)
        self.assertIsInstance(group_models, dict)
        self.assertEqual(len(group_models), 1)
        self.assertIn('nested/box', group_models)

        # Request all lights from nested group (with and without prefix)
        group_lights = nested_group.get_lights(with_group_prefix=False)
        self.assertIsInstance(group_lights, dict)
        self.assertEqual(len(group_lights), 1)
        self.assertIn('light', group_lights)

        group_lights = nested_group.get_lights(with_group_prefix=True)
        self.assertIsInstance(group_lights, dict)
        self.assertEqual(len(group_lights), 1)
        self.assertIn('nested/light', group_lights)

        # Request all models from root group (with and without prefix)
        group_models = root_group.get_models(with_group_prefix=False)
        self.assertIsInstance(group_models, dict)
        self.assertEqual(len(group_models), 2)
        self.assertIn('box', group_models)
        self.assertIn('nested/box', group_models)

        group_models = root_group.get_models(with_group_prefix=True)
        self.assertIsInstance(group_models, dict)
        self.assertEqual(len(group_models), 2)
        self.assertIn('root/box', group_models)
        self.assertIn('root/nested/box', group_models)

        # Request all lights from root group (with and without prefix)
        group_lights = root_group.get_lights(with_group_prefix=False)
        self.assertIsInstance(group_lights, dict)
        self.assertEqual(len(group_lights), 1)
        self.assertIn('nested/light', group_lights)

        group_lights = root_group.get_lights(with_group_prefix=True)
        self.assertIsInstance(group_lights, dict)
        self.assertEqual(len(group_lights), 1)
        self.assertIn('root/nested/light', group_lights)
    def test_export_models_to_gazebo_model(self):
        models = [
            SimulationModel(name=generate_random_string(5)) for _ in range(2)
        ]
        model_names = [obj.name for obj in models]
        sdf_elements = [model.to_sdf() for model in models]

        group = ModelGroup.from_sdf(sdf_elements)
        group.name = generate_random_string(5)
        group.pose = Pose.random()
        self.assertIsNotNone(group)
        self.assertEqual(group.n_models, len(models))
        self.assertEqual(group.n_lights, 0)

        # Convert to separate SDF elements
        sdf_models, sdf_lights, sdf_includes = group.to_sdf()
        self.assertEqual(len(sdf_models), len(models))
        for tag in sdf_models:
            self.assertIn(
                sdf_models[tag].name.replace('{}/'.format(group.name), ''),
                model_names)
        self.assertEqual(len(sdf_lights), 0)
        self.assertEqual(len(sdf_includes), 0)

        # Convert to default Gazebo model
        self.assertIsNotNone(group.to_gazebo_model())
        default_dir = os.path.join(os.path.expanduser('~'), '.gazebo',
                                   'models')
        model_dir = os.path.join(default_dir, group.name)

        # Check if all model files were created
        self.assertTrue(os.path.isdir(model_dir))
        self.assertTrue(os.path.isfile(os.path.join(model_dir,
                                                    'model.config')))
        self.assertTrue(os.path.isfile(os.path.join(model_dir, 'model.sdf')))

        # Parse model config file
        sdf_config = parse_sdf_config(os.path.join(model_dir, 'model.config'))
        self.assertIsNotNone(sdf_config)

        # Get name of current user, used in default model metadata input
        username = getpass.getuser()

        self.assertEqual(sdf_config.name.value, group.name)
        self.assertEqual(len(sdf_config.authors), 1)
        self.assertEqual(sdf_config.authors[0].name.value, username)
        self.assertEqual(sdf_config.authors[0].email.value,
                         '{}@email.com'.format(username))
        self.assertEqual(sdf_config.description.value, '')
        self.assertEqual(sdf_config.version.value, '1.6')
        self.assertEqual(len(sdf_config.sdfs), 1)
        self.assertEqual(sdf_config.sdfs[0].value, 'model.sdf')
        self.assertEqual(sdf_config.sdfs[0].version, '1.6')

        # Parse the SDF file
        sdf = parse_sdf(os.path.join(model_dir, 'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertEqual(sdf.xml_element_name, 'sdf')
        self.assertIsNotNone(sdf.models)
        self.assertEqual(len(sdf.models), 1)
        for i, j in zip(sdf.models[0].pose.value, group.pose.to_sdf().value):
            self.assertTrue(numpy.isclose(i, j))
        self.assertEqual(len(sdf.models[0].models), len(models))

        for i in range(len(sdf.models[0].models)):
            self.assertEqual(sdf.models[0].models[i].pose.value,
                             [0 for _ in range(6)])
            self.assertIn(sdf.models[0].models[i].name, model_names)

        # Delete generated Gazebo model directory
        shutil.rmtree(model_dir)

        # Rename group
        group.name = generate_random_string(5)

        # Export group with individually exported models
        self.assertIsNotNone(group.to_gazebo_model(nested=False))

        # Check if model folders exist
        self.assertTrue(os.path.isdir(os.path.join(default_dir, group.name)))
        for name in model_names:
            self.assertTrue(os.path.isdir(os.path.join(default_dir, name)))

        # Parse the SDF file for the main model
        sdf = parse_sdf(os.path.join(default_dir, group.name, 'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertEqual(sdf.xml_element_name, 'sdf')
        self.assertIsNotNone(sdf.models)
        self.assertEqual(len(sdf.models), 1)

        self.assertIsNone(sdf.models[0].models)
        self.assertIsNotNone(sdf.models[0].includes)
        self.assertEqual(len(sdf.models[0].includes), len(models))

        for i, j in zip(sdf.models[0].pose.value, group.pose.to_sdf().value):
            self.assertTrue(numpy.isclose(i, j))

        for i in range(len(sdf.models[0].includes)):
            self.assertEqual(sdf.models[0].includes[i].pose.value,
                             [0 for _ in range(6)])
            self.assertIn(sdf.models[0].includes[i].name.value, model_names)
            self.assertEqual(
                sdf.models[0].includes[i].uri.value,
                'model://{}'.format(sdf.models[0].includes[i].name.value))

        shutil.rmtree(os.path.join(default_dir, group.name))
        for name in model_names:
            shutil.rmtree(os.path.join(default_dir, name))
def generate_sdf(test_case, params):
    xml = process_jinja_template(
        os.path.join(CUR_DIR, 'jinja_sdf', '{}.jinja'.format(test_case)),
        params)
    return parse_sdf(xml)
    def process_model(self,
                      model_path,
                      decimation_fraction_of_visual=0.25,
                      decimation_min_faces=40,
                      decimation_max_faces=200,
                      max_faces=40000,
                      max_vertices=None,
                      component_min_faces_fraction=0.05,
                      component_max_volume_fraction=0.1,
                      fix_mtl_texture_paths=True) -> bool:

        # Parse the SDF of the model
        sdf = parse_sdf(self.get_sdf_path(model_path))

        # Process the model(s) contained in the SDF
        for model in sdf.models:

            # Process the link(s) of each model
            for link in model.links:

                # Get rid of the existing collisions prior to simplifying it
                link.collisions.clear()

                # Values for the total inertial properties of current link
                # These values will be updated for each body that the link contains
                total_mass = 0.0
                total_inertia = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0],
                                 [0.0, 0.0, 0.0]]
                common_centre_of_mass = [0.0, 0.0, 0.0]

                # Go through the visuals and process them
                for visual in link.visuals:

                    # Get path to the mesh of the link's visual
                    mesh_path = self.get_mesh_path(model_path, visual)

                    # If desired, fix texture path in 'mtl' files for '.obj' mesh format
                    if fix_mtl_texture_paths:
                        self.fix_mtl_texture_paths(model_path, mesh_path,
                                                   model.attributes['name'])

                    # Load the mesh (without materials)
                    mesh = trimesh.load(mesh_path,
                                        force='mesh',
                                        skip_materials=True)

                    # Check if model has too much geometry (blacklist if needed)
                    if not self.check_excessive_geometry(
                            mesh,
                            model_path,
                            max_faces=max_faces,
                            max_vertices=max_vertices):
                        return False

                    # Check if model has disconnected geometry/components (blacklist if needed)
                    if not self.check_disconnected_components(
                            mesh,
                            model_path,
                            component_min_faces_fraction=
                            component_min_faces_fraction,
                            component_max_volume_fraction=
                            component_max_volume_fraction):
                        return False

                    # Compute inertial properties for this mesh
                    total_mass, total_inertia, common_centre_of_mass = \
                        self.sum_inertial_properties(mesh,
                                                     total_mass,
                                                     total_inertia,
                                                     common_centre_of_mass)

                    # Add decimated collision geometry to the SDF
                    self.add_collision(
                        mesh,
                        link,
                        model_path,
                        fraction_of_visual=decimation_fraction_of_visual,
                        min_faces=decimation_min_faces,
                        max_faces=decimation_max_faces)

                    # Write original scale (size) into the SDF
                    # This is used for later reference during randomization (for scale limits)
                    self.write_original_scale(mesh, model_path)

                # Make sure the link has valid inertial properties (blacklist if needed)
                if not self.check_inertial_properties(model_path, total_mass,
                                                      total_inertia):
                    return False

                # Write inertial properties to the SDF of the link
                self.write_inertial_properties(link, total_mass, total_inertia,
                                               common_centre_of_mass)

        # Write the configured SDF into a file
        sdf.export_xml(self.get_configured_sdf_path(model_path))
        return True
Exemple #26
0
    def test_export_model_to_gazebo_model(self):
        box = self.create_random_box()
        model = SimulationModel.from_sdf(box.to_sdf())

        self.assertIsNotNone(model)

        # Export Gazebo model with default parameters
        model.to_gazebo_model()
        default_dir = os.path.join(os.path.expanduser('~'), '.gazebo',
                                   'models')
        model_dir = os.path.join(default_dir, box.name)
        # Check if all model files were created
        self.assertTrue(os.path.isdir(model_dir))
        self.assertTrue(os.path.isfile(os.path.join(model_dir,
                                                    'model.config')))
        self.assertTrue(os.path.isfile(os.path.join(model_dir, 'model.sdf')))

        # Parse model config file
        sdf_config = parse_sdf_config(os.path.join(model_dir, 'model.config'))
        self.assertIsNotNone(sdf_config)

        # Get name of current user, used in default model metadata input
        username = getpass.getuser()

        self.assertEqual(sdf_config.name.value, box.name)
        self.assertEqual(len(sdf_config.authors), 1)
        self.assertEqual(sdf_config.authors[0].name.value, username)
        self.assertEqual(sdf_config.authors[0].email.value,
                         '{}@email.com'.format(username))
        self.assertEqual(sdf_config.description.value, '')
        self.assertEqual(sdf_config.version.value, '1.6')
        self.assertEqual(len(sdf_config.sdfs), 1)
        self.assertEqual(sdf_config.sdfs[0].value, 'model.sdf')
        self.assertEqual(sdf_config.sdfs[0].version, '1.6')

        sdf = parse_sdf(os.path.join(model_dir, 'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertEqual(sdf.xml_element_name, 'sdf')
        self.assertIsNotNone(sdf.models)
        self.assertEqual(len(sdf.models), 1)

        # Export Gazebo model with default parameters
        author = generate_random_string(5)
        email = generate_random_string(5)
        description = generate_random_string(10)
        model_metaname = generate_random_string(10)

        model.to_gazebo_model(author=author,
                              email=email,
                              description=description,
                              model_metaname=model_metaname,
                              overwrite=True)

        # Check if all model files were created
        self.assertTrue(os.path.isdir(model_dir))
        self.assertTrue(os.path.isfile(os.path.join(model_dir,
                                                    'model.config')))
        self.assertTrue(os.path.isfile(os.path.join(model_dir, 'model.sdf')))

        # Parse model config file
        sdf_config = parse_sdf_config(os.path.join(model_dir, 'model.config'))
        self.assertIsNotNone(sdf_config)

        self.assertEqual(sdf_config.name.value, model_metaname)
        self.assertEqual(len(sdf_config.authors), 1)
        self.assertEqual(sdf_config.authors[0].name.value, author)
        self.assertEqual(sdf_config.authors[0].email.value, email)
        self.assertEqual(sdf_config.description.value, description)
        self.assertEqual(sdf_config.version.value, '1.6')
        self.assertEqual(len(sdf_config.sdfs), 1)
        self.assertEqual(sdf_config.sdfs[0].value, 'model.sdf')
        self.assertEqual(sdf_config.sdfs[0].version, '1.6')

        # Parse the SDF file
        sdf = parse_sdf(os.path.join(model_dir, 'model.sdf'))
        self.assertIsNotNone(sdf)
        self.assertEqual(sdf.xml_element_name, 'sdf')
        self.assertIsNotNone(sdf.models)
        self.assertEqual(len(sdf.models), 1)

        # Delete generated Gazebo model directory
        shutil.rmtree(model_dir)
Exemple #27
0
    def test_from_sdf(self):
        add_custom_gazebo_resource_path(
            os.path.join(CUR_DIR, '..', 'examples', 'models'))

        # Parse the SDF file
        sdf = parse_sdf(
            os.path.join(CUR_DIR, '..', 'examples', 'models',
                         'pcg_winding_valley_heightmap', 'model.sdf'))
        self.assertIsNotNone(sdf)

        # Convert SDF heightmap element to simulation heightmap element
        sdf_heightmap = sdf.models[0].links[0].visuals[0].geometry.heightmap
        heightmap = Heightmap.from_sdf(sdf_heightmap)
        self.assertIsNotNone(heightmap)

        output_sdf = heightmap.to_sdf()
        self.assertIsNotNone(output_sdf)

        sdf_heightmap = \
            sdf.models[0].links[0].collisions[0].geometry.heightmap
        heightmap = Heightmap.from_sdf(sdf_heightmap)
        self.assertIsNotNone(heightmap)

        output_sdf = heightmap.to_sdf()
        self.assertIsNotNone(output_sdf)

        self.assertEqual(sdf_heightmap.size.value, output_sdf.size.value)
        self.assertEqual(sdf_heightmap.pos.value, output_sdf.pos.value)

        # Convert model to SimulationModel element
        model = SimulationModel.from_sdf(sdf.models[0])
        self.assertIsNotNone(model)
        output_sdf = model.to_sdf()
        self.assertIsNotNone(output_sdf)

        self.assertIsNotNone(output_sdf)
        self.assertEqual(len(output_sdf.links[0].visuals), 1)
        self.assertEqual(len(output_sdf.links[0].collisions), 1)

        sdf_heightmap = output_sdf.links[0].visuals[0].geometry.heightmap
        self.assertIsNotNone(sdf_heightmap)

        uri_path_prefix = \
            'model://pcg_winding_valley_heightmap/materials/textures'
        self.assertIn(uri_path_prefix, sdf_heightmap.uri.value)
        self.assertEqual(len(sdf_heightmap.textures), 3)
        for texture in sdf_heightmap.textures:
            self.assertIn(uri_path_prefix, texture.diffuse.value)
            self.assertIn(uri_path_prefix, texture.normal.value)
            self.assertEqual(texture.size.value, [10])
        self.assertEqual(len(sdf_heightmap.blends), 2)
        for blend in sdf_heightmap.blends:
            self.assertGreater(blend.min_height.value, 0)
            self.assertGreater(blend.fade_dist.value, 0)
        self.assertEqual(sdf_heightmap.size.value, [1000, 1000, 25])
        self.assertEqual(sdf_heightmap.pos.value, [0, 0, -4])

        sdf_heightmap = \
            output_sdf.links[0].collisions[0].geometry.heightmap
        self.assertIsNotNone(sdf_heightmap)

        self.assertIn(uri_path_prefix, sdf_heightmap.uri.value)
        self.assertEqual(sdf_heightmap.size.value, [1000, 1000, 25])
        self.assertEqual(sdf_heightmap.pos.value, [0, 0, -4])