Example #1
0
def test_namespaces_to_string():
    xml = XML.from_string(
        """<?xml version="1.0" encoding="UTF-8"?><robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="panda"><xacro:bamboo/></robot>"""
    )
    xml_string = xml.to_string(prettify=True)
    assert b'xmlns:xacro="http://www.ros.org/wiki/xacro"' in xml_string
    assert b'<xacro:bamboo' in xml_string or b'<ns0:bamboo' in xml_string
Example #2
0
def test_namespace_expansion_from_file(namespaces_file):
    xml = XML.from_file(namespaces_file)

    assert xml.root.tag == '{https://ethz.ch}main'
    assert list(xml.root)[0].tag == '{https://ethz.ch}item'
    assert list(list(xml.root)[0])[0].tag == '{https://ethz.ch}subitem'
    assert list(list(list(
        xml.root)[0])[0])[0].tag == '{https://sub.ethz.ch}cat'
Example #3
0
def test_nested_default_namespaces_from_file(default_nested_namespace_file):
    xml = XML.from_file(default_nested_namespace_file)

    assert xml.root.attrib['xmlns'] == 'https://ita.arch.ethz.ch/'
    assert xml.root.attrib[
        'xmlns:xsi'] == 'http://www.w3.org/2001/XMLSchema-instance'

    # first element redefines default namespace
    assert list(xml.root)[1].attrib['xmlns'] == 'https://ethz.ch'
    assert list(xml.root)[1].attrib['name'] == 'item2'
Example #4
0
def test_no_root_default_namespace():
    xml = XML.from_string("""<?xml version="1.0"?>
        <main name="test-xml">
            <item name="item1"><subitem /></item>
            <item xmlns="https://ethz.ch" name="item2"><subitem /></item>
        </main>""")

    assert not xml.root.attrib.get('xmlns')
    assert list(xml.root)[1].attrib['xmlns'] == 'https://ethz.ch'
    assert list(xml.root)[1].attrib['name'] == 'item2'
Example #5
0
def test_nested_default_namespaces():
    xml = XML.from_string("""<?xml version="1.0"?>
        <main xmlns="https://ita.arch.ethz.ch/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="test-xml">
            <item name="item1"><subitem /></item>
            <item xmlns="https://ethz.ch" name="item2"><subitem /></item>
        </main>""")

    assert xml.root.attrib['xmlns'] == 'https://ita.arch.ethz.ch/'
    assert xml.root.attrib[
        'xmlns:xsi'] == 'http://www.w3.org/2001/XMLSchema-instance'

    # first element redefines default namespace
    assert list(xml.root)[1].attrib['xmlns'] == 'https://ethz.ch'
    assert list(xml.root)[1].attrib['name'] == 'item2'
Example #6
0
def test_namespace_expansion():
    xml = XML.from_string("""<?xml version="1.0"?>
        <main xmlns="https://ethz.ch" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="test-xml">
            <item>
                <subitem xmlns:magic="https://sub.ethz.ch">
                    <magic:cat />
                </subitem>
            </item>
        </main>""")

    assert xml.root.tag == '{https://ethz.ch}main'
    assert list(xml.root)[0].tag == '{https://ethz.ch}item'
    assert list(list(xml.root)[0])[0].tag == '{https://ethz.ch}subitem'
    assert list(list(list(
        xml.root)[0])[0])[0].tag == '{https://sub.ethz.ch}cat'
Example #7
0
def _dae_mesh_importer(filename):
    """This is a very simple implementation of a DAE/Collada parser.
    It merges all solids of the DAE file into one mesh, because
    several other parts of the framework don't support multi-meshes per file."""
    dae = XML.from_file(filename)
    meshes = []

    for mesh_xml in dae.root.findall('.//mesh'):
        for triangle_set in mesh_xml.findall('triangles'):
            triangle_set_data = triangle_set.find('p').text.split()

            # Parse vertices
            vertices_input = triangle_set.find('input[@semantic="VERTEX"]')
            vertices_link = mesh_xml.find('vertices[@id="{}"]/input'.format(vertices_input.attrib['source'][1:]))
            positions = mesh_xml.find('source[@id="{}"]/float_array'.format(vertices_link.attrib['source'][1:]))
            positions = positions.text.split()

            vertices = list(map(float, positions[i:i + 3]) for i in range(0, len(positions), 3))

            # Parse faces
            faces = list(map(int, triangle_set_data[::2]))  # Ignore normals (ever second item is normal index)
            faces = list(faces[i:i + 3] for i in range(0, len(faces), 3))

            mesh = Mesh.from_vertices_and_faces(vertices, faces)

            meshes.append(mesh)

    combined_mesh = meshes_join(meshes)

    # from compas.datastructures import mesh_transform
    # from compas.geometry import Frame
    # from compas.geometry import Transformation

    # former DAE files have yaxis and zaxis swapped
    # frame = Frame([0, 0, 0], [1, 0, 0], [0, 0, 1])
    # T = Transformation.from_frame(frame)
    # mesh_transform(combined_mesh, T)
    return combined_mesh
Example #8
0
def test_xml_to_string(sample_xml):
    xml = XML.from_string(sample_xml)
    strxml = xml.to_string('utf-8')
    assert strxml.startswith(b'<Tests>')
Example #9
0
def test_xml_from_string(sample_xml):
    xml = XML.from_string(sample_xml)
    assert xml.root.tag == 'Tests'
Example #10
0
def test_xml_from_file(sample_file):
    xml = XML.from_file(sample_file)
    assert xml.root.tag == 'Tests'
Example #11
0
 def from_srdf_string(cls, text, robot_model):
     """Create an instance of semantics based on an SRDF string."""
     xml = XML.from_string(text)
     return cls.from_xml(xml, robot_model)
Example #12
0
 def from_srdf_file(cls, file, robot_model):
     """Create an instance of semantics based on an SRDF file path or file-like object."""
     xml = XML.from_file(file)
     return cls.from_xml(xml, robot_model)
Example #13
0
def test_no_default_namespace():
    xml = XML.from_string(
        """<?xml version="1.0"?><main name="test-xml"></main>""")

    assert not xml.root.attrib.get('xmlns')
    assert xml.root.attrib['name'] == 'test-xml'
Example #14
0
 def from_srdf_file(cls, file, urdf_robot):
     xml = XML.from_file(file)
     return cls(xml.root, urdf_robot)
Example #15
0
 def _read_robot_name(self, robot_description):
     # TODO: Optimize this. We really don't need to parse the full URDF
     # only to read the robot's name (only used for local caching)
     xml = XML.from_string(robot_description)
     return xml.root.attrib['name']
Example #16
0
def test_xml_from_string(basic_xml):
    xml = XML.from_string(basic_xml)
    assert xml.root.tag == 'Tests'
Example #17
0
def test_xml_from_url(basic_file_url):
    xml = XML.from_file(basic_file_url)
    assert xml.root.tag == 'Tests'
Example #18
0
def _dae_mesh_importer(filename, precision):
    """This is a very simple implementation of a DAE/Collada parser.

    Collada specification: https://www.khronos.org/files/collada_spec_1_5.pdf
    """
    dae = XML.from_file(filename)
    meshes = []
    visual_scenes = dae.root.find('library_visual_scenes')
    materials = dae.root.find('library_materials')
    effects = dae.root.find('library_effects')

    for geometry in dae.root.findall('library_geometries/geometry'):
        mesh_xml = geometry.find('mesh')
        mesh_id = geometry.attrib['id']
        matrix_node = visual_scenes.find('visual_scene/node/instance_geometry[@url="#{}"]/../matrix'.format(mesh_id))
        transform = None

        if matrix_node is not None:
            M = [float(i) for i in matrix_node.text.split()]

            # If it's the identity matrix, then ignore, we don't need to transform it
            if M != [1., 0., 0., 0.,
                     0., 1., 0., 0.,
                     0., 0., 1., 0.,
                     0., 0., 0., 1.]:
                M = M[0:4], M[4:8], M[8:12], M[12:16]
                transform = Transformation.from_matrix(M)

        # primitive elements can be any combination of:
        # lines, linestrips, polygons, polylist, triangles, trifans, tristrips
        # The current implementation only supports triangles and polylist of triangular meshes
        primitive_element_sets = []
        primitive_element_sets.extend(mesh_xml.findall('triangles'))
        primitive_element_sets.extend(mesh_xml.findall('polylist'))

        if len(primitive_element_sets) == 0:
            raise Exception('No primitive elements found (currently only triangles and polylist are supported)')

        for primitive_element_set in primitive_element_sets:
            primitive_tag = primitive_element_set.tag
            primitive_set_data = primitive_element_set.find('p').text.split()

            # Try to retrieve mesh colors
            mesh_colors = {}

            if materials is not None and effects is not None:
                try:
                    instance_effect = None
                    material_id = primitive_element_set.attrib.get('material')
                    primitive_count = int(primitive_element_set.attrib['count'])

                    if material_id is not None:
                        instance_effect = materials.find('material[@id="{}"]/instance_effect'.format(material_id))

                    if instance_effect is not None:
                        instance_effect_id = instance_effect.attrib['url'][1:]
                        colors = effects.findall('effect[@id="{}"]/profile_COMMON/technique/phong/*/color'.format(instance_effect_id))
                        for color_node in colors:
                            rgba = [float(i) for i in color_node.text.split()]
                            mesh_colors['mesh_color.{}'.format(color_node.attrib['sid'])] = rgba
                except Exception:
                    LOGGER.exception('Exception while loading materials, all materials of mesh file %s will be ignored ', filename)

            # Parse vertices
            all_offsets = sorted([int(i.attrib['offset']) for i in primitive_element_set.findall('input[@offset]')])
            if not all_offsets:
                raise Exception('Primitive element node does not contain offset information! Primitive tag={}'.format(primitive_tag))

            vertices_input = primitive_element_set.find('input[@semantic="VERTEX"]')
            vertices_id = vertices_input.attrib['source'][1:]
            vertices_link = mesh_xml.find('vertices[@id="{}"]/input'.format(vertices_id))
            positions = mesh_xml.find('source[@id="{}"]/float_array'.format(vertices_link.attrib['source'][1:]))
            positions = positions.text.split()

            vertices = [[float(p) for p in positions[i:i + 3]] for i in range(0, len(positions), 3)]

            # Parse faces
            # Every nth element is a vertex key, we ignore the rest based on the offsets defined
            # Usually, every second item is the normal, but there can be other items offset in there (vertex tangents, etc)
            skip_step = 1 + all_offsets[-1]

            if primitive_tag == 'triangles':
                vcount = [3] * primitive_count
            elif primitive_tag == 'polylist':
                vcount = [int(v) for v in primitive_element_set.find('vcount').text.split()]

            if len(vcount) != primitive_count:
                raise Exception('Primitive count does not match vertex per face count, vertex input id={}'.format(vertices_id))

            fkeys = [int(f) for f in primitive_set_data[::skip_step]]
            faces = []
            for i in range(primitive_count):
                a = i * vcount[i]
                b = a + vcount[i]
                faces.append(fkeys[a:b])

            # Rebuild vertices and faces using the same logic that other importers
            # use remapping everything based on a selected precision
            index_key = OrderedDict()
            vertex = OrderedDict()

            for i, xyz in enumerate(vertices):
                key = geometric_key(xyz, precision)
                index_key[i] = key
                vertex[key] = xyz

            key_index = {key: index for index, key in enumerate(vertex)}
            index_index = {index: key_index[key] for index, key in iter(index_key.items())}
            vertices = [xyz for xyz in iter(vertex.values())]
            faces = [[index_index[index] for index in face] for face in faces]

            mesh = Mesh.from_vertices_and_faces(vertices, faces)

            if mesh_colors:
                mesh.attributes.update(mesh_colors)

            if transform:
                mesh_transform(mesh, transform)

            meshes.append(mesh)

    return meshes
Example #19
0
def test_xml_to_pretty_string(sample_xml):
    xml = XML.from_string(sample_xml)
    prettyxml = xml.to_string(prettify=True)
    assert b"\n  " in prettyxml
Example #20
0
 def from_srdf_string(cls, text, urdf_robot):
     xml = XML.from_string(text)
     return cls(xml.root, urdf_robot)
Example #21
0
 def read_robot_name_and_uris_from_urdf(self, robot_description):
     xml = XML.from_string(robot_description)
     robot_name = xml.root.attrib['name']
     uris = [mesh.attrib['filename'] for mesh in xml.root.iter('mesh')
         if mesh.attrib['filename'] != '']
     return robot_name, uris