MCPcopy Create free account
hub / github.com/URLab-Sim/UnrealRoboticsLab / process_xml

Function process_xml

Scripts/clean_meshes.py:293–469  ·  view source on GitHub ↗

Parse MJCF XML, convert meshes, resolve conflicts, write updated XML.

(xml_path: Path)

Source from the content-addressed store, hash-verified

291
292
293def process_xml(xml_path: Path):
294 """Parse MJCF XML, convert meshes, resolve conflicts, write updated XML."""
295
296 if not xml_path.exists():
297 print(f"Error: XML file not found: {xml_path}")
298 return
299
300 xml_dir = xml_path.parent
301
302 print(f"XML: {xml_path}")
303 print(f"Dir: {xml_dir}")
304 print("=" * 60)
305
306 # Parse XML
307 tree = ET.parse(str(xml_path))
308 root = tree.getroot()
309
310 # Phase -1: Flatten <include> fragments (gym-aloha and friends split robots
311 # across <mujocoinclude> files, some referenced from inside <worldbody>).
312 # After this the tree is a single self-contained <mujoco> with no includes,
313 # so mesh conversion below sees every mesh and Unreal imports one flat model.
314 include_count = sum(1 for _ in root.iter("include"))
315 if include_count:
316 print(f"Flattening {include_count} <include> fragment(s)...")
317 root = flatten_includes(root, xml_dir.resolve())
318 tree = ET.ElementTree(root)
319 remaining = sum(1 for _ in root.iter("include"))
320 print(f" -> {remaining} include(s) remain after flatten")
321
322 # Find meshdir from compiler
323 meshdir = ""
324 for compiler in root.iter("compiler"):
325 md = compiler.get("meshdir", "")
326 if md:
327 meshdir = md
328
329 mesh_base = xml_dir / meshdir if meshdir else xml_dir
330 print(f"Mesh directory: {mesh_base}")
331
332 # Phase 0: Materialize inline ``<mesh vertex="..." face="...">`` entries.
333 # These get rewritten to file= entries before Phase 1 runs, so the rest
334 # of the pipeline treats them like any other on-disk mesh.
335 inline_count = materialize_inline_meshes(root, mesh_base)
336 if inline_count:
337 print(f"Materialized {inline_count} inline mesh(es) to {mesh_base}")
338
339 # Collect all mesh elements
340 mesh_elements = list(root.iter("mesh"))
341
342 # Also convert meshes referenced by <flexcomp file="...">
343 for flexcomp in root.iter("flexcomp"):
344 file_attr = flexcomp.get("file")
345 if file_attr:
346 source_path = mesh_base / file_attr
347 if source_path.exists():
348 output_glb = source_path.with_suffix(".glb")
349 if not output_glb.exists() or output_glb.stat().st_mtime < source_path.stat().st_mtime:
350 print(f"\n[flexcomp] Converting mesh: {source_path.name} -> {output_glb.name}")

Callers 1

mainFunction · 0.85

Calls 3

flatten_includesFunction · 0.85
convert_meshFunction · 0.85

Tested by

no test coverage detected