A simulation framework for testing collision detection and decision-making algorithms in Autonomous Mobile Robot (AMR) fleets. The system includes a mock fleet simulator, collision monitor, and real-time web visualization.
docker compose up -dThis starts four services:
- RabbitMQ (AMQP broker): Fleet telemetry bus
- mock-fleet: Simulated robots publishing telemetry
- collision-monitor: Decision engine (pause/resume commands)
- fleet-visualizer: Web dashboard
Open your browser to http://localhost:8080
The dashboard displays:
- Real-time robot positions and paths
- Current pause/resume state
- Battery levels, deadlines, and load status
- Collision predictions and decision traces
All services read config/settings.yaml (bind-mounted at startup). Edit this file to change:
- Fleet size (
fleet.generation.number_of_robots) - Robot paths (
fleet.generation.path_length_steps) - Collision detection parameters (
collision.footprint) - Decision algorithm and tuning (
decision.algorithm,decision.params) - Visualizer settings (
visualizer.*)
After editing config/settings.yaml, reload the mock fleet to regenerate robots:
curl -X POST http://localhost:8081/api/fleet/reloadThe visualizer and collision monitor will immediately pick up the new fleet. RabbitMQ stays running, so the simulation is uninterrupted.
# Check new fleet metadata
curl http://localhost:8081/api/fleet
# Check robots in the visualizer
curl http://localhost:8080/api/robotsStart only RabbitMQ + visualizer (empty canvas):
docker compose up -d rabbitmq fleet-visualizerStart just the simulator + monitor (no web UI):
docker compose up -d rabbitmq collision-monitor mock-fleetThe collision monitor plans with a receding horizon: every decision cycle it replans a
Move/Pause matrix over decision.params.time_window_ticks from fresh telemetry, dispatches
only tick 1, and keeps the rest of the matrix as next cycle's warm start.
Three optimizers are available via decision.algorithm in config/settings.yaml:
GreedyPriorityOptimizer— one grant per conflict component, chosen by descending priority weight. No lookahead search; the fast, explainable baseline.SimulatedAnnealingOptimizer(default) — per-component simulated annealing over the Move/Pause matrix with a lexicographic cost (collisions > permanent blocks > deadlock > weighted progress) enforced through penalty magnitudes.LateAcceptanceHillClimbingOptimizer— same framing as SA but with LAHC's history-based acceptance (no temperature schedule) and exact tuple-lexicographic cost comparison.
Switch algorithms without editing code:
# Edit config (decision.algorithm)
vi config/settings.yaml
# Restart the monitor to pick up the new algorithm
docker compose up -d --force-recreate collision-monitorWatch the per-cycle decision trace:
docker compose logs -f collision-monitor | grep DECISION-CYCLE
# Shows algo=..., paused=[...], resumed=[...], cost and per-component statsuv run --with pyyaml,aio-pika,pytest --python 3.11 -m pytest tests/ -q
# or, with dependencies installed: python -m pytest tests/ -qdocker compose down- mock-fleet: Generates a seeded fleet of robots with randomized paths, battery levels, and deadlines. Publishes telemetry every 1 second to RabbitMQ.
- collision-monitor: Consumes telemetry, predicts collisions, runs the configured decision optimizer (Greedy, Simulated Annealing, or Late Acceptance Hill Climbing), and publishes Pause/Resume commands.
- fleet-visualizer: Serves the web dashboard and WebSocket bridge for real-time updates from RabbitMQ.
All services restart automatically on exit, so configuration changes are easy to test.
GET /health— Service health checkGET /api/robots— Current robot state (JSON)GET /api/config— Visualizer configuration (JSON)WS /telemetry— WebSocket for real-time telemetry
GET /health— Service health checkGET /api/fleet— Fleet metadata and generation configPOST /api/fleet/reload— Reload config and regenerate fleet
See config/settings.yaml for full details on:
- amqp: RabbitMQ broker URL and exchange/queue names
- decision: Algorithm selection (
algorithm), cycle interval, and tuning parameters (params, passed verbatim to the optimizer constructor). - collision: Prediction horizon, footprint size, safety margins, priority weights
- fleet: Robot count, paths, battery, deadlines, telemetry rate
- visualizer: Canvas bounds, rendering settings, WebSocket heartbeat