Knowing the protocol is one thing. Running a fleet with it is another. This final post closes the series with the architecture that turns VDA 5050 from a spec into a working, deadlock-free system.
The fleet manager: a broker, a clock, and a queue
The fleet manager is deliberately simple in shape. It's a single process that:
- Subscribes to every vehicle's
stateandconnectiontopics - Publishes
orderandinstantActionsto vehicles - Runs a single-threaded drain loop that does all the work
The threading model is the design. The MQTT network thread only enqueues messages; a 10 Hz loop drains the queue and does everything single-threaded. No locks, no races — every decision happens in one place, in a deterministic order.
Traffic control: the floor ledger
The fleet manager keeps a ledger of who holds which piece of floor. The core insight is a boundary statement:
Reservation is process deconfliction, never a collision claim. Nothing in the ledger stops a truck. The scanners and onboard guards do that. What the ledger buys is that the fleet never asks two vehicles onto the same floor.
Three rules make it work:
| Rule | Meaning |
|---|---|
| An edge is undirected | One corridor segment is one piece of floor, whichever way you drive it |
| A grant is a contiguous prefix | A vehicle holds a continuous run of floor, re-seated as it moves |
| Deadlock is broken by wait-die | The youngest task in a cycle yields, by task age |
The undirected edge is what catches the head-on case: two vehicles routed at each other meet in the ledger long before they meet in the aisle.
Deadlock: wait-die by task age
When two vehicles each wait on floor the other holds, the ledger detects the cycle and breaks it. The rule is wait-die: the youngest task in the cycle releases everything except the node its truck stands on, and yields.
The subtlety is why age, not some other metric. Restamping a task's age would create a livelock — the oldest task would become the youngest and yield to whoever it just gave way to. Age is stable, so the resolution is stable.
The factsheet: interoperability as a contract
Before the master plans anything, it reads each vehicle's factsheet — kinematics, speed limits, dimensions, supported actions. A forklift and a tugger declare different capabilities, and the master plans accordingly.
This is what makes the fleet genuinely vendor-agnostic. The master never hard-codes assumptions about a manufacturer. It reads the contract and adapts.
VDA 5050 vs MassRobotics: complementary, not competing
A common question is how VDA 5050 relates to the MassRobotics AMR Interoperability Standard. The answer is that they solve different problems:
| Dimension | VDA 5050 | MassRobotics |
|---|---|---|
| Architecture | Centralized master control | Decentralized status sharing |
| Control model | Active (orders, routes, deadlock) | Passive observation |
| Transport | MQTT | WebSockets |
| Task management | Core | Out of scope |
| Traffic management | Core | Out of scope |
VDA 5050 is the vertical control plane — master to robot. MassRobotics is the horizontal awareness plane — robots publishing standardized status any listening system can read. A mature fleet can use both: VDA 5050 for control, MassRobotics as a sidecar for cross-vendor awareness.
The integration roadmap
For an existing AMR fleet, the path to VDA 5050 is incremental:
- Pin the version — target a specific spec version and stick to it
- Implement the factsheet first — it's the capability contract everything else builds on
- Get the connection watchdog right — a fleet that can't detect a dead vehicle is unsafe
- Add the order lifecycle — base/horizon is the key to safe incremental movement
- Layer traffic control last — it's the highest-value, highest-complexity piece
The whole series has been building toward this: a fleet where heterogeneous robots, a central master, and a floor ledger work together through one open standard.
This series is part of a larger body of work on PLC-supervised AGV fleet control. The full project — including the safety architecture, the OPC UA bridge, and the fleet layer — is documented on the project page and in the source repository.