Multi-agent UAV pathfinding with collision avoidance and simulated mesh networking
Agents plan paths on a shared grid, broadcast intentions over a lossy simulated network, and replan when conflicts arise. The whole thing is deterministic given a seed, so runs are reproducible.
src/
├── core/ # Pure logic, zero deps, header-only
│ ├── types.h Arena-allocated value types (AgentId, Vec2, Grid)
│ ├── world.h World state + reservation table (time-wheel, O(1) lookups)
│ ├── planner.h A* with space-time reservation (implicit grid, flat arrays)
│ ├── swarm.h Top-level orchestrator
│ ├── arena.h Bump allocator for per-tick scratch memory
│ └── result.h Result<T,E> error handling
├── sim/ # Simulation shell (side effects live here)
│ ├── sim.h/cpp Tick loop, agent lifecycle
│ ├── net_sim.h/cpp Lossy broadcast network (configurable drop/latency/jitter)
│ ├── map_gen.h/cpp Procedural + file-based map loading
│ └── mavlink.h MAVLink-style message definitions
└── viz/ # GUI (Raylib + Dear ImGui)
├── renderer.h/cpp Grid renderer, path overlays, agent sprites
└── debug_ui.h/cpp ImGui debug panels, metrics dashboard
Core is pure and testable. Sim and viz are the shell. Ports & adapters pattern — swap the network adapter for a real UDP socket and the core doesn't know the difference.
The hot paths are designed around cache-friendly flat arrays and O(1) lookups:
| What | How | Cost |
|---|---|---|
| Reservation checks | Time-wheel ring buffer, t & 511 indexing |
O(1) |
| Agent lookups | Dense uint32_t IDs, array index |
O(1) |
| Grid access | Flat uint8_t[], y * width + x |
O(1) |
| Concurrency | Immutable WorldSnapshot, lock-free planning |
No contention |
| A* search | Implicit grid, flat g-score arrays, inline neighbors | No heap allocs in hot path |
Max 256 agents, 512-step horizon. Deterministic across platforms.
git clone https://github.com/your-username/uav-swarm-coordinator.git
cd uav-swarm-coordinator
mkdir build && cd build
cmake -S .. -B . -DCMAKE_BUILD_TYPE=Release
cmake --build . -j$(nproc)Dependencies are fetched automatically via CMake FetchContent:
- Raylib 5.5 — rendering
- Dear ImGui 1.92 — debug UI
- rlImGui — Raylib/ImGui backend glue
- Catch2 v3 — tests
You need a C++23 compiler (GCC 13+, Clang 16+, or MSVC 2022+) and CMake 3.24+.
# GUI mode
./swarm
# Headless (no window, just metrics)
./swarm_headlessdocker compose upRuns the simulation, spits out metrics JSON + trace CSV + a matplotlib visualization to /tmp/.
ctest --output-on-failure
# or run directly
./swarm_testsCovers arena allocation, type invariants, world state transitions, pathfinding correctness, and full swarm integration.
Plain text. . is open, # is a wall. Comments with //.
// 10x7 demo map
..........
..#....#..
..#....#..
..........
....##....
....##....
..........
- Each agent runs A* over a space-time grid (x, y, t) using a shared reservation table
- Agents broadcast their planned paths over the simulated network
- Messages can be dropped, delayed, or jittered based on config
- When an agent detects a conflict (someone else reserved its next cell), it replans
- Repeat until all agents reach their goals or the step limit is hit
The reservation table uses a time-wheel (ring buffer) so old reservations age out automatically — no cleanup pass needed.
MIT