https://github.com/thanos/ex_drone
BEAM-native drone control for Elixir and Erlang. Fly, monitor, simulate, and coordinate programmable drones using supervised processes, telemetry, missions, and swarm APIs.
https://github.com/thanos/ex_drone
autonomous beam crazyflie distributed-systems drone drones elixir erlang mavlink mission-planning otp px4 robotics simulation swarm-robotics telemetry tello uas uav
Last synced: about 14 hours ago
JSON representation
BEAM-native drone control for Elixir and Erlang. Fly, monitor, simulate, and coordinate programmable drones using supervised processes, telemetry, missions, and swarm APIs.
- Host: GitHub
- URL: https://github.com/thanos/ex_drone
- Owner: thanos
- License: mit
- Created: 2026-06-09T20:04:49.000Z (13 days ago)
- Default Branch: main
- Last Pushed: 2026-06-12T21:46:33.000Z (10 days ago)
- Last Synced: 2026-06-19T23:22:45.358Z (3 days ago)
- Topics: autonomous, beam, crazyflie, distributed-systems, drone, drones, elixir, erlang, mavlink, mission-planning, otp, px4, robotics, simulation, swarm-robotics, telemetry, tello, uas, uav
- Language: Elixir
- Homepage:
- Size: 146 KB
- Stars: 8
- Watchers: 0
- Forks: 1
- Open Issues: 11
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ex_drone
[](https://hex.pm/packages/ex_drone)
[](https://hexdocs.pm/ex_drone)
[](LICENSE)
[](https://github.com/thanos/ex_drone/actions/workflows/ci.yml) [](https://coveralls.io/github/thanos/ex_drone?branch=main)
BEAM-native drone control for Elixir and Erlang. Fly, monitor, and simulate programmable drones using supervised processes, telemetry, and missions.
## Safety Warning
**Drones are physical devices that can cause injury or property damage.**
- Do not fly near faces or people
- Use prop guards at all times
- Test in the simulator before connecting to real hardware
- Use open indoor spaces or outdoor areas with clear lines of sight
- Have an emergency stop ready at all times
- Understand and follow local laws and regulations
## Installation
Add `ex_drone` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:ex_drone, "~> 0.1.0"}
]
end
```
## Quick Start
```elixir
# Connect to the simulator (no hardware needed)
{:ok, drone} = Drone.connect(:sim, name: :my_drone)
# Enter SDK mode
Drone.connect_sdk(drone)
# Fly
Drone.takeoff(drone)
Drone.move(drone, :up, 40)
Drone.move(drone, :forward, 100)
Drone.rotate(drone, :cw, 90)
Drone.land(drone)
# Disconnect
Drone.disconnect(drone)
```
## Safety Policies
All commands pass through a safety pipeline before reaching the drone:
```elixir
# Indoor flight with tight limits
{:ok, drone} = Drone.connect(:sim, name: :classroom, safety: [indoor: true])
# Custom safety limits
{:ok, drone} = Drone.connect(:sim, name: :safe,
safety: [
max_altitude_cm: 200,
max_distance_cm: 500,
prop_guards: true
]
)
# Dry-run mode (validates commands without sending)
{:ok, drone} = Drone.connect(:sim, name: :test, safety: [dry_run: true])
```
See `Drone.Safety.Policy` for all safety options.
## Tello Connection
```elixir
{:ok, drone} = Drone.connect(:tello, name: :tello_1)
Drone.connect_sdk(drone)
Drone.takeoff(drone)
Drone.land(drone)
Drone.disconnect(drone)
```
## Mission Scripts
```elixir
mission =
Drone.Mission.new()
|> Drone.Mission.sdk_mode()
|> Drone.Mission.takeoff()
|> Drone.Mission.move(:up, 40)
|> Drone.Mission.rotate(:cw, 90)
|> Drone.Mission.land()
{:ok, results} = Drone.Mission.run(mission, :my_drone)
```
## Architecture
- **Drone.Vehicle** -- One GenServer per drone, supervised
- **Drone.Adapter** -- Behaviour for drone communication (Sim, Tello, future adapters)
- **Drone.Geometry** -- Shared position math (move, rotate, flip deltas)
- **Drone.Safety** -- Pure validation module, no side effects
- **Drone.Telemetry** -- `:telemetry` events for observability
- **Drone.Mission** -- Command sequence DSL
## Roadmap
### v0.1.0 — Tello + Simulator Foundation (current)
Public API, supervised processes, safety pipeline, simulator, Tello adapter, missions, telemetry.
- [x] `Drone` public API (`connect/2`, `disconnect/1`, `takeoff/1`, `move/3`, `rotate/3`, etc.)
- [x] `Drone.Vehicle` — one GenServer per drone, supervised
- [x] `Drone.Adapter` behaviour — pluggable adapters
- [x] `Drone.Adapters.Sim` — in-process simulator with position tracking, battery drain, failure injection
- [x] `Drone.Adapters.Tello` — DJI Tello UDP adapter (command encoding, response parsing, state management)
- [x] `Drone.Command` — struct constructors for 14 command types
- [x] `Drone.Safety` — 8-stage validation pipeline (args, mode, allowlist, flying, altitude, distance, battery, geofence)
- [x] `Drone.Safety.Policy` — default, indoor, unrestricted presets
- [x] `Drone.Safety.Geofence` — circle and polygon geofencing
- [x] `Drone.Geometry` — shared position math (heading-aware movement, rotation, flips)
- [x] `Drone.Telemetry` — `:telemetry` events (command start/stop, safety reject, connect, disconnect)
- [x] `Drone.Mission` — command sequence DSL with error-early semantics
- [x] `Drone.Error` — error type helpers (`safety/1`, `adapter/1`, `invalid_command/1`)
- [x] Command argument validation per Tello SDK ranges
- [x] Emergency stop bypassing all safety checks
- [x] Dry-run mode for validating missions without flying
- [x] Flight time simulation (`query(:time)` returns cumulative motor-on seconds)
- [x] CI/CD — lint, test matrix (1.17-1.20 / OTP 26-29), coverage (90.2%), sobelow, dialyzer, docs, Hex.pm publish
- [x] 253 tests, 90.2% coverage, credo --strict clean, --warnings-as-errors clean
### v0.2.0 — Adapters & Resilience
New hardware adapters, command retry, async missions, and reconnect.
- [ ] `Drone.Adapters.Crazyflie` — Crazyflie BLE/USB adapter
- [ ] `Drone.Adapters.MAVLink` — MAVLink-compatible drones via serial/UDP
- [ ] Adapter registry — `Drone.Adapter.register/2` for third-party adapters
- [ ] Common adapter test suite — shared `Drone.Adapter.Acceptance` tests
- [ ] Command retry with configurable backoff (`safe_to_retry?/1` already in `Drone.Command`)
- [ ] `Mission.run_async/2` — fire-and-forget mission execution with progress events
- [ ] Reconnect on adapter failure — Vehicle auto-reconnects after network errors
- [ ] `Drone.Adapters.Tello` — state recovery on reconnect (re-query SDK mode, battery, position)
- [ ] Configurable command timeout per-vehicle (default 10s)
### v0.3.0 — Multi-Drone Coordination
Swarm primitives for coordinating multiple drones.
- [ ] `Drone.Swarm` — supervised group of drones with shared mission context
- [ ] Formation flying — grid, line, circle — via relative position commands
- [ ] `Drone.Mission.concurrent/2` — run missions on multiple drones in parallel
- [ ] Collision avoidance in simulator — safety policy rejects commands that would collide
- [ ] Coordinated takeoff/land — swarm-level commands that dispatch to individual drones
### v0.4.0 — Video & Sensors
Video stream handling and real-time sensor data from Tello EDU.
- [ ] `Drone.Adapters.Tello.Stream` — receive H.264 video stream via UDP
- [ ] `Drone.Adapters.Tello.State` — subscribe to real-time telemetry (100ms interval)
- [ ] `Drone.Telemetry.stream/1` — stream telemetry events as Elixir Stream
- [ ] Video frame extraction — decode keyframes to JPEG for snapshot API
- [ ] `Drone.query(:wifi_signal)` — WiFi signal quality from state stream
### v0.5.0 — Persistence & Analytics
Flight logging, replay, and observability.
- [ ] Ecto-backed persistence — mission logs, flight history, anomaly tracking
- [ ] Mission replay — replay a recorded mission against a simulator for regression testing
- [ ] `:telemetry` analytics dashboard — LiveDashboard plugin with real-time charts
- [ ] Flight log query API — filter by drone, date, safety rejections, battery level
### v1.0.0 — Stable API
API freeze, production hardening, and deployment guides.
- [ ] API stability guarantee — no breaking changes within 1.x
- [ ] Fly.io deployment guide — run command relay in the cloud
- [ ] Nerves integration guide — run on Raspberry Pi with Tello
- [ ] Comprehensive property-based testing (`StreamData`)
- [ ] Performance benchmarks and soak tests
## License
MIT