Files
OneCAD/docs/urdf.md
Mateusz Sych 17db109c5d URDF export for robot simulators (#719) (#942)
A design with components and joints exports as a URDF robot description (file.export to .urdf, the MCP export tool, solidcraft-cli run --out, File > Export URDF...). It writes one binary STL per component in metres, links with mass, centre of mass and inertia from material density, and maps rigid, revolute, slider, cylindrical, pin-slot, planar and ball joints to URDF joints or short chains. Loops, broken joints and loose parts are reported as warnings. Options: mesh_prefix, effort, velocity. Docs in docs/urdf.md.
2026-10-13 21:52:30 -04:00

6.3 KiB

URDF export

A design with components and joints exports as a robot description in URDF (Unified Robot Description Format), the format ROS, Gazebo, Isaac Sim, PyBullet and MuJoCo read. Each part becomes a link with its mesh, mass and inertia. Each joint becomes a URDF joint, or a short chain of them, that moves the parts the way SolidCraft does.

  • Desktop: File → Export URDF…
  • Commands: file.export {"path": "robot.urdf"} (or "format": "urdf")
  • MCP: the export tool with a .urdf path or format: "urdf"
  • CLI: solidcraft-cli run script.json --out robot.urdf

URDF always exports the whole assembly, so bodies is refused.

Files

Next to robot.urdf the export writes one binary STL per component, in metres:

  • robot-<component>.stl holds all of the component's bodies. The root component's bodies go in robot-base.stl.
  • robot-<component>-collision.stl appears only when a component mixes closed solids with open surfaces: it holds the closed ones, which are the collision geometry.

Every path is checked before anything is written, including against the folders an agent may use (allow_paths). The meshes are written first and the .urdf last. If a write fails part way, the error names the files already written and the one that failed.

Parameters

Parameter Default Meaning
mesh_prefix none Put before each mesh file name. Leave it empty for loaders that resolve against the URDF's folder (Isaac Sim, PyBullet, MuJoCo, yourdfpy). RViz and other ROS tools need package://<pkg>/meshes/ or an absolute folder.
effort 1000 Joint effort limit, in N (sliding) or N m (turning).
velocity 10 Joint velocity limit, in m/s or rad/s.

URDF requires effort and velocity on every moving joint. When they are not given, the defaults are written and a warning says so. A value that is not a positive number is refused.

  • base_link holds the root component's bodies and stays fixed in the world. Every grounded occurrence hangs on it by a fixed joint at its current place.
  • One link per placement of a component. A component placed once gives its name to the link (Gripper). One placed several times gives the occurrence names (Finger:1 becomes Finger_1).
  • Names use only A-Z a-z 0-9 _ (mesh files also keep -). Links, joints and files share one set of names, because Gazebo refuses a link and a joint with the same name. A name already taken gets _2, _3 and so on. Joint names are taken first, so a joint keeps the name you gave it. Mesh file names are compared without case, since Windows and macOS ignore it.
  • Mass and inertia come from each body's mesh and material density: the mass in kg, the centre of mass and the inertia tensor about it in the link frame, in kg m². Bodies of the same link combine with the parallel-axis theorem.
  • Open surfaces are drawn but add no mass or collision, with a warning naming them.
  • A link with no mass (only surfaces, no bodies, or a chain's in-between link) gets a token mass of 1e-6 kg and inertia of 1e-12 kg m², because Gazebo drops massless links and breaks the chain there.
  • Colour: the first body's colour, as the visual's material.

Joints

SolidCraft joint URDF
Rigid fixed
Revolute revolute about z with limits, or continuous without
Slider prismatic along z
Cylindrical revolute z, then prismatic z
Pin-slot prismatic x, then revolute z
Planar prismatic x, prismatic y, then revolute z
Ball revolute z, revolute y, then revolute z
  • Chains: a joint with several values becomes one URDF joint per value. Between them sit links named <joint>_link1, <joint>_link2. The steps before the last are named <joint>_dof1, <joint>_dof2, and the last one keeps the joint's name.
  • Values: each URDF joint value equals the SolidCraft value it comes from: the same angle (in radians) or distance (in metres). This holds whichever side of the joint is nearer the base. When the tree reaches a joint from its B side, the chain runs backwards with its axes reversed, so the values still match.
  • Limits are written as lower <= upper in radians or metres. A sliding step without a limit gets ±1000 m, since URDF requires one, with a warning.
  • Motion links are not written as <mimic>. Each joint's own value is free in the URDF.

The URDF is written at the design's current joint values, with every part where it is shown, including moves not captured yet. The exception is a part the joints place: it exports where its joints put it, since they put it back as soon as one moves, and a warning says so. Moving a joint in a simulator puts the parts the joint solver places where SolidCraft's Drive Joints would.

The tree

URDF is a tree hanging from base_link. The export builds it the way the joint solver walks the assembly.

  1. From base_link and the grounded occurrences, it follows the joints outwards.
  2. A group of parts joined to each other but to nothing grounded is fixed where it is by the A side of its first joint, as the solver does when nothing is grounded. A warning says the part is not grounded.
  3. A part no joint reaches is fixed where it is. A nested one hangs on its parent part, so it moves with it, as in SolidCraft. A top-level one hangs on base_link, with a warning.
  4. A joint that would close a loop is left out, with a warning, since a tree cannot hold it.
  5. A joint whose snap points no longer resolve (for example, the face it was on is gone) is left out, with a warning naming it.

When a component is placed several times, what is nested in it appears in each placement. In the URDF the first placement is the one its joints move; the others are copies fixed in their parent at their current pose, with a warning when the copied part has a joint. (In SolidCraft the copies move together, which a URDF could only express with <mimic>.) The export stops copying past 64 levels or 100 000 placements, with a warning.

Not covered

  • <mimic> for motion links.
  • Simplified collision shapes: the collision mesh is the visual mesh.
  • SDF and MJCF export, and URDF import.
  • Joint motion inside the copies of a component placed several times.
  • Drive dynamics: effort and velocity are limits you choose.