Akshay Parkhi's Weblog

RDF, ROS, and Sim-to-Real: Understanding Robot Description Files

2nd March 2026

When you start to work with robot simulation, you immediately meet a file called something.urdf. This is true whether you use Isaac Sim, Gazebo, or MoveIt. 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:

PropertyWhat It Defines
MassWeight of the link (kg)
InertiaRotational inertia tensor (3x3 matrix)
Collision meshSimplified shape for physics calculations
Visual meshDetailed 3D model for rendering (STL/DAE files)

Each joint includes:

PropertyWhat It Defines
Typerevolute, prismatic, fixed, continuous
AxisWhich axis the joint rotates/slides around
LimitsMin/max angle, max effort, max velocity
Parent linkThe link “above” in the tree
Child linkThe 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
  • 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 depends entirely on the simulator. This includes how objects collide, how friction works, and how gravity affects motion. If two simulators receive the same URDF, they can produce different physics behavior. The reason is that they use different solvers and contact models.

URDF vs Other Robot Description Formats

FormatUsed InPurpose
URDFROS ecosystemRobot structure (kinematic tree)
USDOmniverse / Isaac SimFull 3D scene description
MJCF (XML)MuJoCoPhysics + control definition
SDFGazeboAdvanced 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 starts. 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. ROS does not need any files 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. It needs no file.

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.

ThingRequired?What It Does
ROSYes (if using ROS)Communication layer between nodes
URDFNo (optional but common)Robot structure blueprint
rosbagNoRecords topic data to disk
Launch fileNoAuto-starts multiple nodes

For the SO-101: Why URDF Matters for Sim-to-Real

Sim-to-real transfer means you train a VLA in simulation and deploy it on the physical arm. If you own a real SO-101 and want to do this, 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

Suppose 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]. Then your trained policy will try to move past the physical limit. That misalignment is where sim-to-real fails.

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. When you understand where each one starts and stops, you will save hours of confusion as you build your robotics stack.

More recent articles