# How to Set Up Joint Limits and Inertial Parameters in URDF for text-to-cad

> Learn to set up joint limits and inertial parameters in URDF for text-to-cad. Define `<limit>` and `<inertial>` tags with precise bounds and mass values to optimize your robot models.

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

---

**To set up joint limits and inertial parameters in URDF for text-to-cad, define `<limit>` elements with finite `lower` and `upper` bounds for revolute and prismatic joints, and specify positive mass values with inertia matrices satisfying the triangle inequality inside `<inertial>` blocks for each dynamic link.**

The text-to-cad repository validates robot descriptions through a strict Python parser located at [`plugins/cad/skills/urdf/scripts/urdf/source.py`](https://github.com/earthtojake/text-to-cad/blob/main/plugins/cad/skills/urdf/scripts/urdf/source.py). Understanding the specific validation logic in `_joint_limits_deg` and `_validate_inertia_values` ensures your URDF files pass inspection for downstream CAD generation and MoveIt2 integration.

## Joint Limit Validation Logic

The `_joint_limits_deg` method (lines 402-450 in [`source.py`](https://github.com/earthtojake/text-to-cad/blob/main/source.py)) processes every `<joint>` element and applies type-specific validation rules.

### Fixed and Continuous Joint Handling

- **Fixed joints** automatically receive limit values of `0/0`
- **Continuous joints** default to `-180°/180°` limits regardless of URDF content

### Revolute and Prismatic Joint Requirements

Both joint types must contain a `<limit>` element with numeric attributes:

- **`lower` and `upper`** must be finite values satisfying `lower ≤ upper`
- **Revolute joints**: Values are interpreted as radians and converted to degrees internally
- **Prismatic joints**: Raw values are returned as-is (typically meters in standard URDF)
- **Optional attributes**: `effort` and `velocity` are parsed when present

Missing `<limit>` tags on revolute or prismatic joints raise `UrdfSourceError` with a path-relative message referencing the specific joint name.

## Inertial Parameter Constraints

Inertial validation occurs in two stages: `_validate_link_inertials` (lines 220-250) checks structural presence, while `_validate_inertia_values` (lines 332-388) enforces physical validity.

### Mass and Origin Requirements

Each `<link>` containing an `<inertial>` block must specify:

- A `<mass>` element with a strictly positive `value` (non-positive values trigger `UrdfSourceError`)
- An optional `<origin>` element defining the center of mass reference frame

### Inertia Matrix Triangle Inequality

The `<inertia>` element must provide six components where the diagonal entries satisfy physical constraints:

- **`ixx`**, **`iyy`**, and **`izz`** must be positive values
- The **triangle inequality** must hold: `ixx + iyy > izz`, `ixx + izz > iyy`, and `iyy + izz > ixx`
- Off-diagonal elements (`ixy`, `ixz`, `iyz`) are parsed but not validated for sign

These checks ensure the inertia tensor represents a physically valid rigid body.

## Complete URDF Example

The following structure demonstrates valid joint limits and inertial parameters accepted by the text-to-cad parser:

```xml
<robot name="validated_robot">
  <link name="base_link">
    <inertial>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <mass value="1.0"/>
      <inertia ixx="0.01" ixy="0.0" ixz="0.0"
               iyy="0.01" iyz="0.0" izz="0.02"/>
    </inertial>
  </link>

  <joint name="shoulder_joint" type="revolute">
    <parent link="base_link"/>
    <child link="arm_link"/>
    <origin xyz="0 0 0.1" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-1.57" upper="1.57" effort="10" velocity="1.0"/>
  </joint>

  <link name="arm_link">
    <inertial>
      <mass value="0.5"/>
      <inertia ixx="0.002" ixy="0.0" ixz="0.0"
               iyy="0.002" iyz="0.0" izz="0.001"/>
    </inertial>
  </link>

  <joint name="linear_actuator" type="prismatic">
    <parent link="arm_link"/>
    <child link="tool_link"/>
    <origin xyz="0 0 0.2"/>
    <axis xyz="1 0 0"/>
    <limit lower="0.0" upper="0.05" effort="5" velocity="0.2"/>
  </joint>

  <link name="tool_link"/>
</robot>

```

## Debugging Validation Errors

When validation fails, the parser raises `UrdfSourceError` with descriptive messages:

- `<path> joint "name" requires <limit>` — Indicates missing limit elements on revolute or prismatic joints
- `<path> link "name" inertial mass must be positive` — Mass value is zero or negative
- Triangle inequality violations — Detected in `_validate_inertia_values` when diagonal inertia components violate geometric constraints

The test suite in [`tests/python/skills/urdf/test_source.py`](https://github.com/earthtojake/text-to-cad/blob/main/tests/python/skills/urdf/test_source.py) contains reference implementations demonstrating valid configurations for both joint limits and inertial parameters.

## MoveIt2 Integration

Validated URDF data flows to [`viewer/moveit2_server/moveit2_server/context.py`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/moveit2_server/moveit2_server/context.py), which consumes the processed limits for trajectory planning. Ensuring compliance at the parsing stage prevents runtime validation failures in MoveIt2 servers.

Note that [`skills/urdf/scripts/urdf/source.py`](https://github.com/earthtojake/text-to-cad/blob/main/skills/urdf/scripts/urdf/source.py) is symlinked to the main parser; edits should target [`plugins/cad/skills/urdf/scripts/urdf/source.py`](https://github.com/earthtojake/text-to-cad/blob/main/plugins/cad/skills/urdf/scripts/urdf/source.py) to affect both the plugin and skill runtimes.

## Summary

- **Joint limits** for revolute and prismatic joints require explicit `<limit>` tags with finite, ordered bounds validated by `_joint_limits_deg` in [`plugins/cad/skills/urdf/scripts/urdf/source.py`](https://github.com/earthtojake/text-to-cad/blob/main/plugins/cad/skills/urdf/scripts/urdf/source.py)
- **Fixed joints** use `0/0` limits automatically, while **continuous joints** default to `±180°`
- **Inertial parameters** require positive mass values and inertia matrices satisfying the triangle inequality (`ixx + iyy > izz`, etc.) as enforced by `_validate_inertia_values`
- Validation raises `UrdfSourceError` with path-specific messages, making debugging straightforward
- Compliant URDF files integrate seamlessly with MoveIt2 planning via [`viewer/moveit2_server/moveit2_server/context.py`](https://github.com/earthtojake/text-to-cad/blob/main/viewer/moveit2_server/moveit2_server/context.py)

## Frequently Asked Questions

### What units does text-to-cad use for joint limits?

Revolute joint limits are specified in radians in the URDF file but converted to degrees internally by `_joint_limits_deg`. Prismatic joint limits preserve the raw values from the URDF (typically meters) without unit conversion.

### Why does my URDF fail with a triangle inequality error?

The `_validate_inertia_values` method (lines 332-388) validates that diagonal inertia components satisfy `ixx + iyy > izz`, `ixx + izz > iyy`, and `iyy + izz > ixx`. This ensures the inertia matrix represents a physically valid rigid body. Adjust your `ixx`, `iyy`, and `izz` values to satisfy these three inequalities simultaneously.

### Can I omit the `<inertial>` block for static links?

Yes. The `_validate_link_inertials` method only validates links that explicitly include an `<inertial>` block. Static links without mass requirements may omit the inertial definition entirely, though empty or malformed `<inertial>` tags will raise validation errors.

### How do I debug URDF validation errors in text-to-cad?

The parser raises `UrdfSourceError` with path-relative messages identifying the specific joint or link causing the failure. Review the validation logic in `_joint_limits_deg` for joint issues or `_validate_inertia_values` for mass/inertia problems, and consult [`tests/python/skills/urdf/test_source.py`](https://github.com/earthtojake/text-to-cad/blob/main/tests/python/skills/urdf/test_source.py) for examples of valid URDF structures.