Skip to content

Commit f791599

Browse files
committed
Added get_materials to URDFParser
1 parent 23a2dec commit f791599

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

tests/data/verifying_elements.urdf

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@
5959
<geometry>
6060
<cylinder radius="0.5" length="1"/>
6161
</geometry>
62-
<material name="blue"/>
62+
<material name="yellow"> <!-- New materials that do not exist in the global materials -->
63+
<color rgba="1.0 1.0 0.0 1"/>
64+
</material>
6365
</visual>
6466
<collision>
6567
<origin xyz="2 0 0.5"/> <!-- Omit rpy -->

tests/test_parser.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ def test_get_basic_information(self):
237237
self.assertEqual(root_robot_name, "verifying_elements")
238238
self.assertEqual(root_element.get_with_default("version"), "1.0")
239239

240-
def test_get_materials(self):
240+
def test_find_materials(self):
241241
# Get the root element.
242242
root_element = self.parser.get_root_element()
243243

@@ -373,7 +373,7 @@ def test_get_links(self):
373373
self.assertEqual(geometry.geometry.get_with_default("length"), 1.0)
374374
material = visual.material
375375
self.assertTrue(material)
376-
self.assertEqual(material.get_with_default("name"), "blue")
376+
self.assertEqual(material.get_with_default("name"), "yellow")
377377

378378
collision = link.collision
379379
self.assertTrue(collision)
@@ -453,6 +453,41 @@ def test_get_meshes(self):
453453
self.assertEqual(mesh[0], "assets/box.stl")
454454
self.assertEqual(mesh[1], (0.5, 0.6, 1.0))
455455

456+
def test_get_materials(self):
457+
materials = self.parser.get_materials()
458+
459+
self.assertEqual(len(materials), 6)
460+
461+
material = materials[0]
462+
self.assertEqual(material[0], "red")
463+
self.assertEqual(material[1], (1.0, 0.0, 0.0, 1.0))
464+
self.assertEqual(material[2], None)
465+
466+
material = materials[1]
467+
self.assertEqual(material[0], "green")
468+
self.assertEqual(material[1], (0.0, 1.0, 0.0, 1.0))
469+
self.assertEqual(material[2], None)
470+
471+
material = materials[2]
472+
self.assertEqual(material[0], "blue")
473+
self.assertEqual(material[1], (0.0, 0.0, 1.0, 1.0))
474+
self.assertEqual(material[2], None)
475+
476+
material = materials[3]
477+
self.assertEqual(material[0], "black")
478+
self.assertEqual(material[1], (0.0, 0.0, 0.0, 0.0))
479+
self.assertEqual(material[2], None)
480+
481+
material = materials[4]
482+
self.assertEqual(material[0], "texture")
483+
self.assertEqual(material[1], (0.0, 0.0, 0.0, 0.0))
484+
self.assertEqual(material[2], "assets/grid.png")
485+
486+
material = materials[5]
487+
self.assertEqual(material[0], "yellow")
488+
self.assertEqual(material[1], (1.0, 1.0, 0.0, 1.0))
489+
self.assertEqual(material[2], None)
490+
456491
def test_get_transmissions(self):
457492
# Get the root element.
458493
root_element = self.parser.get_root_element()

urdf_usd_converter/_impl/urdf_parser/parser.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ def __init__(self, input_file: Path):
5454
# A list of mesh file paths and scales.
5555
self.meshes: list[tuple[str, tuple[float, float, float]]] = []
5656

57+
# A list of material colors and file paths.
58+
# However, this does not include materials used in mesh(dae, obj).
59+
self.materials: list[tuple[str, tuple[float, float, float, float], str]] = []
60+
5761
self.texture_paths: list[str] = []
5862

5963
def parse(self):
@@ -75,6 +79,9 @@ def parse(self):
7579
# Store the meshes data.
7680
self._store_meshes()
7781

82+
# Store the materials data.
83+
self._store_materials()
84+
7885
except Exception as e:
7986
raise RuntimeError(f"Error parsing XML: {e}")
8087

@@ -120,6 +127,15 @@ def get_meshes(self) -> list[tuple[str, tuple[float, float, float]]]:
120127
"""
121128
return self.meshes
122129

130+
def get_materials(self) -> list[tuple[str, tuple[float, float, float, float], str]]:
131+
"""
132+
Get the materials.
133+
134+
Returns:
135+
A list of tuples containing the material name, color, and file path.
136+
"""
137+
return self.materials
138+
123139
def get_undefined_elements(self) -> list[UndefinedData]:
124140
"""
125141
Get undefined elements.
@@ -225,6 +241,7 @@ def _parse_xml_elements(self, node: ET.Element, prev_element: ElementBase = None
225241
element,
226242
ElementRobot
227243
| ElementMaterialGlobal
244+
| ElementMaterial
228245
| ElementLink
229246
| ElementJoint
230247
| ElementTransmission
@@ -568,6 +585,29 @@ def _store_meshes(self):
568585
else:
569586
self.meshes.append((geometry.filename, scale))
570587

588+
def _store_materials(self):
589+
"""
590+
Store the materials.
591+
A material has a name, color, and file path.
592+
"""
593+
# Global material names are unique, so they are stored as is.
594+
for material in self.root_element.materials:
595+
color = material.color.get_with_default("rgba") if material.color else (0.0, 0.0, 0.0, 0.0)
596+
texture = material.texture.get_with_default("filename") if material.texture else None
597+
self.materials.append((material.name, color, texture))
598+
599+
for link in self.root_element.links:
600+
if link.visual and link.visual.material:
601+
visual_material = link.visual.material
602+
603+
# If the material name is already stored, skip it.
604+
if visual_material.name in [material[0] for material in self.materials]:
605+
continue
606+
607+
color = visual_material.color.get_with_default("rgba") if visual_material.color else (0.0, 0.0, 0.0, 0.0)
608+
texture = visual_material.texture.get_with_default("filename") if visual_material.texture else None
609+
self.materials.append((visual_material.name, color, texture))
610+
571611
def _get_undefined_elements_nested(self, element: ElementBase, undefined_elements: list[UndefinedData]):
572612
"""
573613
Get undefined elements nested in an element.

0 commit comments

Comments
 (0)