How to Generate URDF Robot Descriptions from Python with `gen_urdf()`
Use the genurdf() function in skills/urdf/scripts/urdf/source.py to parse, validate, and inspect URDF files, returning a typed UrdfSource object with full programmatic access to links, joints, and mesh resources.
Generating URDF robot descriptions from Python is essential for robotics workflows that require automated validation, inspection, or transformation of robot models. The text-to-CAD repository provides a purpose-built URDF skill that exposes genurdf()—a robust parser that handles XML validation, mesh URI resolution, and kinematic tree verification in a single call.
What genurdf() Does
The genurdf() function serves as the primary entry point for the URDF skill. It wraps read_urdf_source to provide a complete analysis pipeline:
- Parses XML structure using
ET.fromstring, requiring a root<robot>element with anameattribute - Validates link definitions, checking for duplicate names and consistent inertial properties via
_validate_link_inertials - Processes geometry elements, classifying and resolving mesh URIs through
classify_mesh_uriandresolve_mesh_uri - Verifies joint integrity, ensuring supported types (
fixed,continuous,revolute,prismatic), valid parent/child references, and proper axis/limit specifications - Confirms tree connectivity, enforcing a single root link and acyclic structure through depth-first traversal
All errors raise UrdfSourceError; warnings emit UrdfSourceWarning for non-critical issues.
Function Signature and Parameters
def genurdf(
path: Path,
package_map: dict[str, Path] | None = None
) -> UrdfSource
| Parameter | Type | Description |
|---|---|---|
path |
Path |
Absolute or relative path to the .urdf file |
package_map |
dict[str, Path] | None |
Optional mapping of ROS package names to local directories for resolving package:// mesh URIs |
The function returns a frozen UrdfSource dataclass containing:
file_ref,source_path,robot_name,root_linklinks: tuple[str, …]— all link names in declaration orderjoints: tuple[UrdfJoint, …]— validated joint objects with limit informationmesh_paths,visual_mesh_paths,collision_mesh_paths— resolved filesystem paths
Complete Python Example
from pathlib import Path
from skills.urdf.scripts.urdf.source import read_urdf_source as genurdf
# Load a URDF file (absolute or relative to repo root)
urdf_path = Path("models/my_robot.urdf")
# Optional: map ROS package names to local directories
package_map = {"my_robot_description": Path("models/my_robot_description")}
# Parse & validate
robot = genurdf(urdf_path, package_map=package_map)
# Inspect the robot description
print(f"Robot name: {robot.robot_name}")
print(f"Root link: {robot.root_link}")
print("\nLinks:")
for link in robot.links:
print(f" - {link}")
print("\nJoints:")
for joint in robot.joints:
print(
f" - {joint.name} ({joint.joint_type}) "
f"parent={joint.parent_link} child={joint.child_link} "
f"limits=[{joint.min_value_deg}, {joint.max_value_deg}]"
)
print("\nVisual meshes:")
for mesh in robot.visual_mesh_paths:
print(f" • {mesh}")
print("\nCollision meshes:")
for mesh in robot.collision_mesh_paths:
print(f" • {mesh}")
Source File Architecture
The URDF skill maintains clean separation between core logic and interfaces:
| File | Purpose | Key Components |
|---|---|---|
skills/urdf/scripts/urdf/source.py |
Parser and validator implementation | genurdf(), read_urdf_source(), UrdfSource dataclass, _validate_link_inertials(), _joint_limits_deg() |
skills/urdf/scripts/urdf/cli.py |
Command-line frontend | Thin wrapper exposing text-to-cad urdf ... commands |
Functions in source.py follow a strict validation hierarchy: XML parsing → link collection → geometry extraction → joint processing → tree validation. This ordering ensures that structural errors surface early with precise UrdfSourceError messages.
Mesh URI Resolution
The genurdf() function handles three mesh URI types through classify_mesh_uri:
package://— Resolved againstpackage_mapentriesfile://— Converted to absolute filesystem paths- Relative paths — Interpreted relative to
source_path
Unsupported geometry tags trigger immediate UrdfSourceError exceptions, preventing downstream processing of invalid robot descriptions.
Integration with text-to-CAD
The URDF skill adheres to repository-wide isolation principles:
- No cross-skill imports — All dependencies live within
skills/urdf/or shared utilities inpackages/cadpy_metadata - Reusable geometry utilities —
resolve_mesh_uriandclassify_mesh_urileveragepackages/cadpy_metadatafor consistent mesh handling across skills - Test coverage — Unit tests in
tests/python/skills/urdf/test_source.pyandtest_cli.pyverify parser behavior against malformed inputs
Extending genurdf() for Custom Workflows
To adapt genurdf() for specialized requirements:
- Custom package resolution — Pass an expanded
package_mapwith additional URI scheme handlers - Serialization pipelines — The frozen
UrdfSourcedataclass supports direct JSON conversion for MoveIt! SRDF generation or Gazebo SDF export - Validation overrides — Subclass
UrdfSourceErrorto capture specific failure modes in automated CI/CD pipelines
Summary
genurdf()inskills/urdf/scripts/urdf/source.pyprovides complete URDF parsing, validation, and inspection from Python- Returns an immutable
UrdfSourcedataclass with full access to kinematic structure and resolved mesh paths - Handles ROS package URI resolution through the optional
package_mapparameter - Enforces strict validation—duplicate links, cyclic joints, and unsupported geometry types raise
UrdfSourceError - Integrates cleanly with the text-to-CAD ecosystem while maintaining skill isolation
Frequently Asked Questions
What Python version does genurdf() require?
The text-to-CAD repository uses Python 3.10+ features including union type syntax (dict[str, Path] | None) and the match statement in related skills. Ensure your environment matches the repository's pyproject.toml specifications.
How do I resolve package:// URIs without ROS installed?
Provide a package_map dictionary mapping package names to local directories. The genurdf() function intercepts these URIs before any ROS infrastructure is invoked, making pure-Python URDF processing possible without a full ROS installation.
Can genurdf() export modified URDF files?
The current implementation focuses on ingestion and validation. To generate modified URDF XML, access the UrdfSource fields programmatically and reconstruct the XML using xml.etree.ElementTree or template engines. The dataclass structure provides all necessary data for faithful reconstruction.
What's the difference between genurdf() and read_urdf_source()?
They are aliases for the same function—genurdf() is the preferred public name, while read_urdf_source appears in internal import statements. Both reside in skills/urdf/scripts/urdf/source.py and exhibit identical behavior.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →