Skip to content

Robot Description Framework (RDF)

An RDF file describes a robot in terms of its capabilities — what it can do — rather than low-level hardware details. It is the source of truth the Defined Robotics toolchain uses to validate tasks before compilation and parameterise verb behaviour at runtime.

Think of it as a passport for your robot: the verb compiler reads it before producing any BT XML.


Minimal example

name: my_robot
version: "0.0.1"
description: "A simple differential drive robot"

modules:
  - name: drive_base
    type: motor_controller
    capabilities:
      - name: navigation
        type: differential_drive
        version: "1.0"
        parameters:
          wheel_separation: 0.287
          wheel_radius: 0.033
          max_linear_velocity: 0.22
          max_angular_velocity: 2.84

This declares a robot with one module (drive_base) that provides the differential_drive capability. That capability is what allows the go_to and explore verbs to be used in tasks.


Two-module example

The simulation robot used in the starter repo uses two modules:

name: test_robot
version: "0.0.1"

modules:
  - name: drive_base
    type: motor_controller
    capabilities:
      - name: differential_drive
        type: differential_drive
        parameters:
          wheel_separation: 0.160
          wheel_radius: 0.033
          max_linear_velocity: 0.22
          max_angular_velocity: 2.84

  - name: lidar_module
    type: sensor
    capabilities:
      - name: laser_scanner
        type: lidar_2d
        parameters:
          range_min: 0.120
          range_max: 3.500
          samples: 360
          update_rate: 5.0
          topic: /scan

How capabilities gate task compilation

When you run:

defined compile tasks/patrol.task.yaml --rdf robot.rdf.yaml

The compiler checks every verb in the task against the RDF before producing any output:

✓ go_to      requires: differential_drive, lidar_2d  → present
✓ report     requires: (none)                         → OK
✗ capture_image requires: rgb_camera                 → MISSING

REJECTED: verb 'capture_image' requires capabilities ['rgb_camera']
not available on robot 'my_robot'

No partial XML is produced. The robot either can run the full task or it cannot.


Known capability types

These are the types recognised by the built-in verbs:

Type Used by verbs Typical parameters
differential_drive go_to, explore wheel_separation, wheel_radius, max_linear_velocity, max_angular_velocity
lidar_2d go_to, explore (via Nav2/SLAM) range_min, range_max, samples, update_rate, topic
rgb_camera capture_image resolution, fps
depth_camera custom verbs resolution, fps
imu custom verbs
wheel_encoders ticks_per_revolution

Custom types are fully supported — any string is accepted. Declare them in your RDF and reference them in your verb definition's required_capabilities.


Field reference

Robot (top-level)

Field Type Required Default Description
name string yes Robot identifier
version string no "0.0.1" RDF version
description string no Human-readable description
modules list[Module] no [] Hardware modules
physical PhysicalDescription no Physical/kinematic description for URDF generation

Module

Field Type Required Description
name string yes Module identifier (e.g. drive_base)
type string yes Module type (e.g. motor_controller, sensor, camera)
capabilities list[Capability] no Capabilities this module provides
parameters dict no Module-level parameters

Capability

Field Type Required Default Description
name string yes Capability identifier
type string yes Capability type (see known types above)
version string no "1.0" Version string
parameters dict no {} Capability-specific parameters passed to verbs

Physical description (optional)

The physical section enables URDF generation for simulation. Task compilation does not require it.

physical:
  meshes_package: my_robot_description  # ROS package containing mesh files (optional)
  links:
    - name: base_link
      mass: 1.0
      visual:
        box:
          size: [0.2, 0.15, 0.05]
      collision:
        box:
          size: [0.2, 0.15, 0.05]
    - name: wheel_left_link
      mass: 0.1
      visual:
        cylinder:
          radius: 0.033
          length: 0.018
  joints:
    - name: wheel_left_joint
      type: continuous
      parent: base_link
      child: wheel_left_link
      origin:
        xyz: [0, 0.08, 0]
        rpy: [-1.5708, 0, 0]
      axis: [0, 0, 1]
Field Type Required Description
name string yes Link identifier
mass float no Mass in kg (default: 0)
inertia Inertia no Inertia tensor — ixx, iyy, izz
origin Origin no Pose relative to parent — xyz, rpy
visual Geometry no Visual geometry
collision Geometry no Collision geometry

Geometry is one of: box (size), cylinder (radius, length), sphere (radius), or mesh (filename).

Joint fields

Field Type Required Description
name string yes Joint identifier
type string yes fixed, continuous, revolute, or prismatic
parent string yes Parent link name
child string yes Child link name
origin Origin no Joint origin pose
axis list[float] no Rotation/translation axis [x, y, z]
limit dict no lower, upper, effort, velocity — for revolute/prismatic

Python API

from defined_rdf.parser import load
from defined_rdf.registry import CapabilityRegistry

robot = load("robot.rdf.yaml")
registry = CapabilityRegistry(robot)

# Check a single capability
registry.has("differential_drive")   # True
registry.has("rgb_camera")           # False

# Get capability details
cap = registry.get("differential_drive")
print(cap.parameters["wheel_separation"])  # 0.160

# Check a set of requirements (used internally by the verb compiler)
met, missing = registry.check_requirements(["differential_drive", "rgb_camera"])
print(met)      # False
print(missing)  # ["rgb_camera"]

# List all capability types on this robot
registry.list_types()  # ['differential_drive', 'lidar_2d']

JSON Schema generation

The package ships with a machine-readable JSON Schema at schema/robot.rdf.schema.json. To regenerate it from the Pydantic models:

python -c "from defined_rdf.models import Robot; import json; print(json.dumps(Robot.model_json_schema(), indent=2))" > schema/robot.rdf.schema.json