Skip to content
v0.2.0 · Draft GitHub ↗ Apply for review →
↳ Multi-robot · RFC-0286
Accepted · reference slice shipped

One sentence moves a robot. One program moves a fleet, in sync.

The next step past "one English sentence makes a robot move" is a single program commanding several heterogeneous robots at once: name each one, address it, combine and synchronize their work, and have the validator reject a cross-robot collision before any actuator engages. No single vendor SDK does this across vendors.

Read RFC-0286 → Run the demo Layer-3 spec →
The worked example

A courier-to-arm handoff.

A mobile base brings a tray to a shared dock; a stationary arm picks a widget and places it on a conveyor; the courier leaves only after the arm has cleared. Two heterogeneous robots, one job neither can do alone.

ONE FLEET MISSION FILE
✓ validate_fleet → accepted
# courier_handoff.fleet.yaml: a roster, then the program members: - { name: courier, manifest: husky_amr } # mobile base - { name: arm, manifest: kawasaki_rs } # stationary arm --- behavior: type: sequence steps: - { type: "on", member: courier, body: { move_to: { location: handoff_dock } } } - { type: barrier, members: [courier, arm] } # both arrive before the exchange - type: parallel branches: - { type: "on", member: arm, body: { pick_from: { source: handoff_dock, object: widget } } } - { type: "on", member: courier, body: { wait: { duration: "2s" } } } # hold - { type: barrier, members: [courier, arm] } # courier leaves only once the arm clears - { type: "on", member: courier, body: { move_to: { location: staging } } }

on: addresses one member; barrier: synchronizes them. Each member runs against its own manifest, so the arm's place_at is checked against the arm and the courier's move_to against the courier. The point is what gets rejected.

Why it's worth building

Three reasons, each a real removal of work or risk.

DELETES THE GLUE

One language, not N SDKs.

Choreographing a mobile base and an industrial arm today means two vendor SDKs plus hand-rolled timing. A roster and one program replace it: one validator, one synchronizer.

CATCHES WHAT NO SDK CAN

Cross-robot safety, before anything moves.

The validator rejects two robots sent into the same place at the same instant, statically. No single vendor SDK can catch this, because no single SDK sees both robots.

SWAP A ROBOT, KEEP THE PLAN

Substrate-fungible orchestration.

Replace a member's robot and the choreography is unchanged. Only the roster entry changes. 'Universal' made concrete across vendors.

The load-bearing value

Four cross-robot checks the validator runs before anything moves.

fleet.undeclared_member

An `on:` or `barrier:` names a robot the roster does not declare.

fleet.capability_unsupported_on_member

A command is scoped to a member whose manifest cannot do it.

fleet.concurrent_shared_workspace

Two robots are driven to the same location at once with no barrier.

fleet.barrier_missing_peer_link

A barrier synchronizes a member that declares no peer link.

The third (two robots into the same place at the same instant) is the collision class no single vendor SDK can catch, because no single SDK sees both robots. That is the moat URML's validator extends from one robot to a fleet.

Where it stands, honestly

The reference slice is shipped and tested. Some of it is named as future work.

SHIPPED & TESTED
  • The cross-robot validator (validate_fleet) and its four checks
  • The reference FleetRuntime: hermetic, no ROS, any OS
  • A conformance lane: one positive, four negatives
  • A runnable demo: python examples/fleet/run_demo.py
NAMED AS FUTURE WORK
  • Collision is by declared-location name today; geometric volume overlap is future.
  • A barrier is statically checked; an executed concurrency-hazard scenario is future.
  • Building-scale fleet traffic (lift queues, aisle reservation) composes with Open-RMF, not URML.
  • A dedicated multi-robot LLM-bridge prompt mode is a follow-on.
Read RFC-0286 → Demo walkthrough
For robot & parts makers

Claim your robot's fleet name.

The lightest way into the URML world, lighter than building an adapter. Publish a small, self-declared manifest and your robot's name becomes a handle any fleet program can address. No code. One YAML file you write and own.

How to claim → Or the full compliance path →
WHAT A CLAIM IS, AND ISN'T
  • A name a fleet program can address. Opt-in, de-listable any time.
  • Self-declared by you. We never list a product its maker hasn't published.
  • Not an endorsement, in either direction.
  • Not a certification or compatibility mark.
  • Not a partnership. A claim is a claim, nothing more.