# Handling Inertial Data, Mesh Scales, and Units in URDF Generation with text-to-cad

> Generate accurate URDF files with text-to-cad. Learn to handle inertial data, mesh scales, and units for seamless robotic simulation imports using SI-compliant formats.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: how-to-guide
- Published: 2026-08-04

---

**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`](https://github.com/earthtojake/text-to-cad/blob/main/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`](https://github.com/earthtojake/text-to-cad/blob/main/generator.py), this function accepts:

- `mass`: Float value in kilograms
- `inertia_tensor`: 3×3 NumPy array representing the rotational inertia
- `com`: 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.

1. Prepare inertial data using SI base units (kilograms for mass, meters for COM position).
2. Convert mesh units by calling `mesh_units_to_meters` with the source unit designation.
3. Generate inertial dictionaries via `generate_inertia` to obtain properly keyed values.
4. Inject into URDF templates, referencing the rescaled mesh paths for `<visual>` and `<collision>` elements.

### Complete Python Example

```python
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:**

```python
{
    '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`](https://github.com/earthtojake/text-to-cad/blob/main/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_inertia`** function in [`packages/cadpy_metadata/src/cadpy_metadata/generator.py`](https://github.com/earthtojake/text-to-cad/blob/main/packages/cadpy_metadata/src/cadpy_metadata/generator.py) converts raw mass, inertia tensors, and COM vectors into URDF-compliant dictionary structures.
- **`mesh_units_to_meters`** provides explicit conversion from millimeters or centimeters to meters, the canonical URDF unit, while **`scale_mesh`** reserves 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-cad` repository 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.