Systems & Robotics

DishPatch

An open-source restaurant service-robot platform spanning POS ordering, live dispatch and monitoring, and a Nav2-driven ROS 2 robot fleet on AWS.

DishPatch is an open-source service-robot platform for restaurants. It is three systems: the POS takes orders, the control system turns them into deliveries and shows them to an operator, and a simulated ROS 2 fleet drives them to the table. They meet at only two points: a DynamoDB table and a rosbridge WebSocket.

All three are live: the POS, the control dashboard, and the robot visualiser.

DishPatch system architecture
DishPatch architecture across the POS, the control system, the robot fleet, and the robot visualiser.

Why it exists

Commercial service-robot platforms are mature, but they are expensive, closed, and hard to customise. DishPatch covers the same workflow as an open developer platform, where the ordering app, dispatch, cloud infrastructure, and robots are all visible and replaceable.

An order, end to end

  1. The POS writes the order to DynamoDB with the status Preparing. It sends no message or event.
  2. Once a second, the control backend scans for Preparing orders and takes the oldest.
  3. It picks a robot that is idle and parked at the counter, because the counter is where the meal is, and publishes a goal pose for the order's table through rosbridge.
  4. Nav2 plans the path and drives, replanning about once a second. Each robot reports its position, speed, and battery ten times a second.
  5. Nav2 decides when the robot has arrived. A drive ends when Nav2 holds no live goal and the robot is within 0.6 m of the table. After five seconds at the table, the order is marked Completed and the robot heads back to the counter.
  6. The dashboard shows all of it over STOMP: the fleet ten times a second, and the order list every four seconds.

An operator can also cancel a Preparing order from the dashboard, and the robot is taken off the delivery on the next tick.

The database is the queue

There is no message queue between the POS and the control backend. Pending orders are just the rows marked Preparing, sorted by order date on every tick for first-in, first-out dispatch. That gives one source of truth, and nothing is lost when the backend restarts: an order it was delivering is still Preparing, so it gets dispatched again. The POS also never needs to know the control system exists. The cost is up to a second of latency, plus a full table scan on every tick.

DishPatch POS frontend
The POS frontend handles tables, the cart, and order placement.

Control system

DishPatch control dashboard
The operator dashboard: live robots on the floor plan, the fleet table, and the order list.

The dashboard is a React app of resizable widgets: a Leaflet map with robot markers and trails coloured by status, the fleet table, and the order list with each order's age and a cancel button. Selecting a robot highlights it and its order across every widget. All of it runs on a single STOMP connection over SockJS.

The Spring Boot backend runs dispatch as a small state machine (TO_TABLE → AT_TABLE → RETURNING) on a one-second tick that never blocks. If Nav2 loses or aborts a goal, dispatch re-sends it, and after a few failed attempts it puts the order back in the queue and sends the robot home. A robot only counts as free when it is parked at the counter, so any robot the backend didn't place itself, after a boot or a restart, is driven to the counter first.

Robotics layer

DishPatch virtual robot fleet
The virtual fleet runs ROS 2, Nav2, and rosbridge in Docker on EC2.

The deployed fleet is simulated: robots run Nav2 against a real 60 m × 39 m floor plan in Docker containers rather than on hardware. The interface is the one a physical robot would use, a goal pose in and telemetry out, so real hardware can replace the simulation without changing anything above it.

Each robot runs under its own namespace. A fake driver turns cmd_vel into odometry, and a status node publishes /{ns}/status at 10 Hz. Nav2's bt_navigator subscribes to /{ns}/goal_pose directly. An earlier relay node did the same job, which turned every goal into two, with the second aborting the first, so it was removed. One shared Nav2 container serves the whole fleet. To keep that container fast enough, the Nav2 map is downsampled to 5 cm per pixel, which brings it down from 16.8 million cells to 935 thousand.

The backend finds robots on its own by reading rosbridge's topic list, and a robot can also join the EC2 fleet from a laptop or WSL over the rosbridge WebSocket.

DishPatch robot visualiser in Foxglove Studio
Foxglove Studio at robot.dish-patch.com, connected straight to rosbridge: the map, costmaps, and each robot's pose and path.

The floor plan comes from a single source. map-source/ generates the dashboard's map, the backend's drop points (T1–T18, R1–R7), and Nav2's map, so all three stay in sync.

Testing and deployment

The control backend has 163 unit, integration, and API tests. They run in about seven seconds, on every pull request and again before every deploy. Instead of reporting line coverage, the suite is measured with PIT mutation testing, at a 62.7% mutation score and 80.3% test strength. The test-quality report covers the method, and the gaps it found.

Six pieces deploy independently, each from its own GitHub Actions workflow. The three frontends are on S3 + CloudFront, the POS backend is a Lambda container behind API Gateway, and the control backend and fleet run on two EC2 instances. The AWS workflows authenticate through IAM OIDC, with no stored keys.

My part

DishPatch is a team project at ANU. There are six of us, working in a repo Herman Tang started. The parts I built:

  • The dispatch pipeline in the control backend: the state machine, goal recovery, and the counter rule.
  • The map pipeline: map-source/, its staging script, the drop points, and the Nav2 map.
  • Fleet fixes: removing the duplicate goal relay, 10 Hz status, the smaller Nav2 map, and the fleet's deploy workflow.
  • The dashboard's widget layout, cross-widget selection, and robot trails.
  • The control backend test suite and its test-quality report.
  • Most of the current docs: the architecture overview, the API reference, and the component READMEs.