What is Xacro? URDF macros explained
Xacro is the XML macro language that makes URDF maintainable: properties, math expressions, macros, and includes that expand into plain URDF — here's how it works and how to expand it without ROS.
Xacro (XML Macros) is a preprocessor for URDF. You write a parameterized template; the xacro processor expands it into plain URDF that simulators consume. It exists because raw URDF has no variables, no math, and no reuse — and real robots are full of repetition.
The problem it solves
A four-wheeled robot in raw URDF means writing four nearly identical wheel links and four nearly identical joints — around 100 lines of copy-paste where changing the wheel radius means editing eight places, and computing the inertia of a cylinder means doing m·r²/2 on a calculator and pasting the result. In xacro that's one macro and four one-line instantiations:
<xacro:property name="wheel_radius" value="0.1"/>
<xacro:property name="wheel_mass" value="0.5"/>
<xacro:macro name="wheel" params="prefix x y">
<link name="${prefix}_wheel">
<inertial>
<mass value="${wheel_mass}"/>
<inertia ixx="${wheel_mass*wheel_radius*wheel_radius/2}" ... />
</inertial>
</link>
<joint name="${prefix}_axle" type="continuous">
<origin xyz="${x} ${y} 0"/>
...
</joint>
</xacro:macro>
<xacro:wheel prefix="front_left" x="0.2" y="0.15"/>
<xacro:wheel prefix="front_right" x="0.2" y="-0.15"/> The feature set
| Feature | Syntax | What it does |
|---|---|---|
| Properties | <xacro:property name="w" value="0.2"/> | Named constants, usable anywhere |
| Expressions | ${mass*len*len/12} | Python-style math — pi, trig, arithmetic — evaluated at expansion |
| Macros | <xacro:macro name="m" params="a b:=1 *block"> | Reusable fragments with required, defaulted, and block parameters |
| Conditionals | <xacro:if value="$(arg use_gripper)"> | Build variants (with/without sensor, arm, gripper) from one file |
| Arguments | <xacro:arg name="x" default="true"/> + $(arg x) | Values injected at expansion time, e.g. from a launch file |
| Includes | <xacro:include filename="materials.xacro"/> | Split a robot across files: materials, sensors, subassemblies |
How expansion works — and how to do it without ROS
The reference processor ships as a ROS package: xacro robot.xacro > robot.urdf. That's fine on a ROS machine, but many consumers of the expanded URDF — MuJoCo importers, Isaac Sim, CI runners, web viewers — live on machines with no ROS installed, which historically meant Docker containers just to expand one file.
The free Xacro → URDF converter runs the expansion entirely in your browser: properties, math, macros, conditionals, args, and multi-file includes (select the included files together with the main one). Constructs that genuinely can't resolve outside ROS — like $(find package) — are reported as explicit warnings, never silently dropped.
Good xacro hygiene
- Name every dimension as a property — magic numbers in geometry are future bugs.
- Compute inertias in expressions from mass and dimensions instead of pasting numbers (see why inertia matters).
- One macro per repeated physical assembly (wheel, finger, leg segment); one include per concern (materials, sensors).
- After any change, expand and validate the output — xacro syntax being correct says nothing about the resulting robot being physically sane.