RDF, ROS, and Sim-to-Real: Understanding Robot Description Files
2nd March 2026
When you start working with robot simulation — whether it’s Isaac Sim, Gazebo, or MoveIt — you immediately run into a file called something.urdf. It’s one of those things that seems simple on the surface but connects to everything in the robotics stack. Here’s a clear breakdown of what URDF is, what it isn’t, and how it fits alongside ROS.
What is URDF?
URDF stands for Unified Robot Description Format. It’s an XML file that describes what a robot physically is:
- Links — rigid bodies (the physical segments of the arm)
- Joints — connections between links (how they move relative to each other)
- Mass & inertia — how heavy each part is and how it resists rotation
- Collision shapes — simplified geometry for physics engines
- Visual meshes — detailed 3D models for rendering
The critical distinction: URDF does NOT control the robot. It only describes what the robot is. Think of it as a blueprint, not a control system.
URDF Structure: The Kinematic Tree
A URDF file defines a tree of links connected by joints:
base_link
↓ (joint_1: revolute)
link_1
↓ (joint_2: revolute)
link_2
↓ (joint_3: revolute)
gripper
Each link includes:
| Property | What It Defines |
|---|---|
| Mass | Weight of the link (kg) |
| Inertia | Rotational inertia tensor (3x3 matrix) |
| Collision mesh | Simplified shape for physics calculations |
| Visual mesh | Detailed 3D model for rendering (STL/DAE files) |
Each joint includes:
| Property | What It Defines |
|---|---|
| Type | revolute, prismatic, fixed, continuous |
| Axis | Which axis the joint rotates/slides around |
| Limits | Min/max angle, max effort, max velocity |
| Parent link | The link “above” in the tree |
| Child link | The link “below” in the tree |
Example URDF Snippet
Here’s what a simplified SO-101 arm URDF looks like:
<link name="base_link">
<inertial>
<mass value="1.5"/>
<inertia ixx="0.01" ixy="0" ixz="0"
iyy="0.01" iyz="0" izz="0.01"/>
</inertial>
<visual>
<geometry>
<mesh filename="meshes/base.stl"/>
</geometry>
</visual>
<collision>
<geometry>
<cylinder radius="0.05" length="0.1"/>
</geometry>
</collision>
</link>
<joint name="joint_1" type="revolute">
<parent link="base_link"/>
<child link="link_1"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57"
effort="10" velocity="2.0"/>
</joint>
This tells any simulator or visualization tool: what moves, how it moves, how heavy it is, and what shape it has.
URDF in the Robotics Ecosystem
URDF is primarily associated with the ROS (Robot Operating System) ecosystem. It enables:
- RViz — 3D visualization of the robot model and sensor data
- MoveIt — motion planning and inverse kinematics
- Gazebo — physics simulation
- Isaac Sim — NVIDIA’s simulator imports URDF and converts it to USD internally
URDF is NOT Physics
This is an important distinction. URDF describes structure. Physics engines use URDF as input to build their internal representation:
URDF (structure blueprint)
→ Physics Engine (Isaac / Gazebo / MuJoCo)
→ Internal Physics Model (collisions, gravity, friction, contacts)
The actual physics behavior — how objects collide, how friction works, how gravity affects motion — depends entirely on the simulator. Two simulators given the same URDF can produce different physics behavior because they use different solvers and contact models.
URDF vs Other Robot Description Formats
| Format | Used In | Purpose |
|---|---|---|
| URDF | ROS ecosystem | Robot structure (kinematic tree) |
| USD | Omniverse / Isaac Sim | Full 3D scene description |
| MJCF (XML) | MuJoCo | Physics + control definition |
| SDF | Gazebo | Advanced simulation (extends URDF) |
For an SO-101 arm, the GitHub repo typically includes both SO101.urdf (for ROS tools) and SO101.xml (MJCF format for MuJoCo). Isaac Sim cannot open URDF directly as a scene file — it imports the URDF and converts it to USD internally.
Now, What About ROS?
This is where confusion often creeps in. People see URDF files, launch files, rosbag files, and assume ROS is some kind of file-based system. It’s not.
ROS is middleware — a communication framework for robots. Think of it as a message bus:
Node A (camera driver)
publishes → /camera/image → 30 fps live stream
Node B (motor driver)
publishes → /joint_states → 50 Hz joint angles
subscribes ← /joint_commands ← target positions
Node C (VLA controller)
subscribes ← /camera/image
subscribes ← /joint_states
publishes → /joint_commands
Nodes send and receive messages via topics. This is live streaming data, not file I/O. No files are required for ROS to operate.
ROS: Streaming vs Files
Topics = Live Streams
/joint_states → publishing 50 times/sec → live data, no file
/camera/image → publishing 30 times/sec → live data, no file
This is a live data stream. No file is required.
Files Are Optional (For Recording)
If you want to record demo data, debug later, or train ML models, you use:
ros2 bag record /joint_states /camera/image
That writes the live topic stream into a file on disk. But ROS itself does not need it to function.
Where URDF Fits With ROS
URDF is separate from ROS. ROS uses URDF so it knows the robot’s structure:
- What joints exist?
- What are their names?
- What are their limits?
Without URDF, ROS can still stream topics — but it won’t understand the robot’s structure. You lose visualization, motion planning, and collision checking.
| Thing | Required? | What It Does |
|---|---|---|
| ROS | Yes (if using ROS) | Communication layer between nodes |
| URDF | No (optional but common) | Robot structure blueprint |
| rosbag | No | Records topic data to disk |
| Launch file | No | Auto-starts multiple nodes |
For the SO-101: Why URDF Matters for Sim-to-Real
If you own a real SO-101 and want to do sim-to-real transfer — train a VLA in simulation and deploy on the physical arm — URDF alignment is critical:
- Same joint names in sim and real — so commands map correctly
- Same joint limits — so the policy never commands impossible positions
- Same kinematic tree — so the model’s internal representation matches reality
If your simulation URDF says joint_1 has a range of [-1.57, 1.57] radians but your real motor only supports [-1.0, 1.0], your trained policy will try to move past the physical limit. That misalignment is where sim-to-real breaks down.
URDF (shared blueprint)
├── Simulation (Isaac Sim / Gazebo)
│ → trains VLA policy
│ → uses URDF joint names + limits
│
└── Real Robot (SO-101 hardware)
→ executes VLA policy
→ same joint names + limits
→ policy transfers cleanly
Putting It All Together
Three separate concepts, three different roles:
URDF = Robot structure file (what the robot IS)
ROS = Communication layer (how nodes TALK)
rosbag = Recording file (saving streams to DISK)
URDF tells tools what your robot looks like. ROS lets your robot’s software components communicate in real time. Rosbag lets you record that communication for later analysis or training. They’re complementary but independent — and understanding where each one starts and stops will save you hours of confusion as you build out your robotics stack.
More recent articles
- OpenUSD: Advanced Patterns and Common Gotchas. - 28th March 2026
- OpenUSD Mastery: From Composition to Pipeline — A SO-101 Arm Journey - 25th March 2026
- Learning OpenUSD — From Curious Questions to Real Understanding - 19th March 2026