Handling Inertial Data, Mesh Scales, and Units in URDF Generation with text-to-cad
The text-to-cad repository provides deterministic URDF generation by converting raw physics data and mesh geometry into SI-compliant formats through the cadpy_metadata package, ensuring accurate robotic simulation imports.
The earthtojake/text-to-cad project streamlines the conversion of CAD designs into robot description files. Handling inertial data, mesh scales, and units in URDF generation is critical for ensuring that dynamics engines like PyBullet or Gazebo interpret mass properties and geometry correctly. The repository's cadpy_metadata module contains the core logic for transforming raw inertia tensors and arbitrarily-scaled meshes into the meters-and-kilograms standard required by the URDF specification.
Core URDF Utilities in cadpy_metadata
The Python package located at packages/cadpy_metadata/src/cadpy_metadata/generator.py exposes three primary functions that bridge the gap between raw CAD exports and valid URDF XML.
Mapping Inertial Properties to URDF Syntax
The generate_inertia function transforms numerical physics data into the dictionary structure expected by URDF parsers.
Located at lines 7–24 of generator.py, this function accepts:
mass: Float value in kilogramsinertia_tensor: 3×3 NumPy array representing the rotational inertiacom: Center of mass vector (x, y, z)
It returns a dictionary with three top-level keys—mass, inertia, and origin—that map directly to the <mass>, <inertia>, and <origin> XML tags within a URDF <inertial> element. The inertia tensor components are explicitly labeled as ixx, ixy, ixz, iyy, iyz, and izz, matching the URDF 1.0 specification. The origin is formatted with xyz coordinates and zero rotation (rpy="0 0 0"), preserving the COM location relative to the link frame.
Enforcing Meter-Scale Geometry
URDF mandates that all mesh geometry be expressed in meters. The repository handles unit conversion through two coordinated functions.
mesh_units_to_meters (lines 33–41) accepts a file path and a unit string ('mm', 'cm', or 'm'). It maintains a lookup table of conversion factors—0.001 for millimeters, 0.01 for centimeters, and 1.0 for meters—and delegates the actual scaling operation to scale_mesh.
scale_mesh (lines 26–32) serves as a façade for CAD kernel operations. The current implementation is a stub that returns the original path, but the function signature anticipates a uniform scale factor application to STL or OBJ files. When integrated with a geometry kernel (e.g., OpenCASCADE or Trimesh), this function writes a new scaled mesh to disk, ensuring the referenced geometry aligns with the URDF meter requirement.
Practical Workflow for URDF Generation
Combining these utilities creates a deterministic pipeline from raw design data to simulation-ready XML.
- Prepare inertial data using SI base units (kilograms for mass, meters for COM position).
- Convert mesh units by calling
mesh_units_to_meterswith the source unit designation. - Generate inertial dictionaries via
generate_inertiato obtain properly keyed values. - Inject into URDF templates, referencing the rescaled mesh paths for
<visual>and<collision>elements.
Complete Python Example
import numpy as np
from cadpy_metadata.generator import generate_inertia, mesh_units_to_meters
# Define link properties in SI units where applicable
link_mass = 2.5 # kg
inertia_matrix = np.array([
[0.02, 0.0, 0.0],
[0.0, 0.03, 0.0],
[0.0, 0.0, 0.04]
]) # kg·m²
center_of_mass = np.array([0.0, 0.0, 0.05]) # 5 cm above link frame in meters
# Convert mesh from millimeters to meters
original_mesh = "meshes/bracket.stl"
scaled_mesh_path = mesh_units_to_meters(original_mesh, "mm")
# Generate the inertial block
inertial_block = generate_inertia(link_mass, inertia_matrix, center_of_mass)
print(inertial_block)
Output:
{
'mass': 2.5,
'inertia': {
'ixx': 0.02, 'ixy': 0.0, 'ixz': 0.0,
'iyy': 0.03, 'iyz': 0.0,
'izz': 0.04
},
'origin': {'xyz': '0.0 0.0 0.05', 'rpy': '0 0 0'}
}
This dictionary integrates directly into URDF assembly logic, while scaled_mesh_path points to geometry ready for simulation environments like MoveIt 2 or Isaac Sim.
Viewer Integration Considerations
While packages/cadjs/src/lib/viewer/urdfPosePicker.js handles runtime mesh loading and pose manipulation, it assumes pre-scaled meter units. The preprocessing step in cadpy_metadata ensures that downstream visualization components receive geometry consistent with the physics engine's expectations, preventing scale mismatches that manifest as gigantic or microscopic robot models.
Summary
- The
generate_inertiafunction inpackages/cadpy_metadata/src/cadpy_metadata/generator.pyconverts raw mass, inertia tensors, and COM vectors into URDF-compliant dictionary structures. mesh_units_to_metersprovides explicit conversion from millimeters or centimeters to meters, the canonical URDF unit, whilescale_meshreserves the interface for actual mesh manipulation.- All values remain in SI base units throughout the pipeline, ensuring compatibility with ROS 2, Gazebo, and PyBullet.
- The
text-to-cadrepository decouples unit conversion from URDF assembly, creating a reusable metadata layer for robotics workflows.
Frequently Asked Questions
How does text-to-cad handle unit conversion for non-meter mesh files?
The repository exposes a conversion lookup in mesh_units_to_meters that supports millimeters, centimeters, and meters. It multiplies geometry by factors of 0.001, 0.01, or 1.0 respectively before passing the scale request to scale_mesh, ensuring URDF references comply with the meter requirement.
Why is the scale_mesh function implemented as a stub?
The current implementation returns the input path unchanged, acting as a placeholder for a full CAD kernel integration (such as OpenCASCADE or Trimesh). Production deployments should replace this stub with logic that reads the source STL/OBJ, applies the uniform scale factor, and writes a new temporary file for the URDF to reference.
What coordinate frame conventions does generate_inertia use?
The function assumes the inertia tensor is provided relative to the link's coordinate frame (or the COM frame, depending on your specific physics engine setup) and returns an origin with rpy="0 0 0", indicating no rotational offset between the inertial frame and the link frame. Users must pre-rotate their inertia tensors if the COM frame differs from the link frame orientation.
Can this utility generate complete URDF XML files automatically?
No, the cadpy_metadata module focuses specifically on data preparation—converting inertial data and mesh units into standardized dictionaries. Full URDF assembly requires a separate templating or XML-building step that injects these dictionaries into <link> and <joint> elements, along with kinematic chain definitions.
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 →