Preflight energy, geofence, and contingency checker for beyond-visual-line-of-sight (BVLOS) drone operations
Two YAML files — a mission and a vehicle profile — answer the questions no
spreadsheet handles: does this aircraft keep its reserve given tomorrow's wind
over this terrain, does the route clip restricted airspace, and can it still
fly home from every waypoint? The answer is deterministic, reproducible, and
fail-closed: missing evidence can never produce a GO.
$ bvlos-sim estimate alpine_mission.yaml quadplane_v1.yaml --format checklist
## Pre-Flight Checklist: alpine_demo_001
✓ Energy feasibility PASS reserve 591.06 Wh above threshold (816.06 Wh at landing, 225.00 Wh threshold)
◌ Geofence clearance N/A not evaluated
✓ Landing-zone coverage PASS reachable zone found at all 166 checked state(s)
◌ Resource availability N/A not evaluated
◌ Link availability N/A not evaluated
◌ Obstacle clearance N/A not evaluated
✓ Weather limits PASS worst wind 3.55 m/s at leg 3 (rtl)
✓ RTH reserve PASS reserve intact for RTH from all 4 leg(s)
◌ Ground risk class N/A not evaluated
Warnings 2 ENERGY_MODEL_UNCALIBRATED, HOVER_POWER_USED_AS_DESCENT_POWER
Status: NO-GO
Blocked by: missing evidence (geofence, resource, link, obstacle, ground_risk); blocking warnings (ENERGY_MODEL_UNCALIBRATED, HOVER_POWER_USED_AS_DESCENT_POWER) — the checklist is fail-closed
$ bvlos-sim estimate alpine_infeasible.yaml small_battery.yaml --format summary
INFEASIBLE reserve −95.0 % flight 7m 58s RTH infeasible warnings 2 [RESERVE_BELOW_THRESHOLD]
A GO is reachable, and the repository ships the mission that earns one — every
evidence category supplied, coefficients calibrated from a flight log, no
warning waived:
$ bvlos-sim estimate examples/missions/pipeline_demo_001_go.yaml \
examples/vehicles/quadplane_v1_complete.yaml \
--calibration examples/calibration/quadplane_v1_calibration.json \
--calibration-traces examples/flight_logs/pipeline_demo_001_trace.json \
--format checklist
...
✓ Obstacle clearance PASS 0 violations across 3 leg(s) and 1 obstacle(s)
✓ Weather limits PASS worst wind 2.72 m/s at leg 1 (wp1)
✓ RTH feasibility PASS selected external resource covers RTH peak power
Ground risk class INFO mission iGRC 3
Departure time INFO 2026-07-21T12:00:00Z
Warnings 1 ENERGY_MODEL_PARTIALLY_CALIBRATED
Acknowledged warnings 1 ENERGY_MODEL_PARTIALLY_CALIBRATED
Status: GO
git clone https://github.com/Monotox/bvlos-sim && cd bvlos-sim
uv sync
# pre-fetched Alpine demo: real SRTM terrain, Open-Meteo wind, OSM landing zones — no network
uv run bvlos-sim estimate \
examples/real_world/alpine_mission.yaml \
examples/real_world/quadplane_v1.yaml \
--format checklistExpect Status: NO-GO and exit 10 — the demo deliberately omits
geofence/resource/link/obstacle/ground-risk evidence, and the checklist is
fail-closed.
Add --engineering-only for the pure-physics verdict. It changes the exit
code to 0, not the checklist: the operational verdict is never
renderer-dependent, so --format checklist still prints Status: NO-GO. To
read the engineering answer, ask the summary renderer for it:
$ bvlos-sim estimate examples/real_world/alpine_mission.yaml \
examples/real_world/quadplane_v1.yaml --format summary --engineering-only
FEASIBLE reserve 262.7 % flight 7m 58s warnings 2
The getting-started tutorial walks through both,
then through the complete-evidence mission that earns a GO.
Fetch real terrain, wind, and landing zones for your own area:
uv sync --extra scripts
uv run python bvlos_sim/scripts/fetch_all.py <lat> <lon> --output-dir assets/
# prints the assets: block to paste into your mission YAMLAsk what battery the mission actually needs. The vehicle must declare
energy.battery_specific_energy_wh_per_kg and
energy.battery_excluded_operating_mass_kg so a candidate pack's mass feeds
back into the power model — without both, the command exits 11:
uv run bvlos-sim size-battery \
examples/real_world/alpine_infeasible.yaml \
examples/real_world/quadplane_small_battery_sizing.yaml --margin 20
# Minimum feasible capacity: 153.9 Wh (with 20 % safety margin: 184.3 Wh)Test contingencies — inject a lost link at a waypoint and assert the divert still lands with reserve:
uv run bvlos-sim scenario examples/scenarios/pipeline_demo_001_scenario.yamlCheck the model against a real flight, then calibrate it:
uv run bvlos-sim ingest-log flight.bin --trace-id f1 -o trace.json \
--mission mission.yaml --vehicle vehicle.yaml
uv run bvlos-sim validate mission.yaml vehicle.yaml trace.json
uv run bvlos-sim calibrate vehicle.yaml trace.json --format json -o cal.json
uv run bvlos-sim estimate mission.yaml vehicle.yaml \
--calibration cal.json --calibration-traces trace.jsonEighteen commands cover estimation, batch runs, Monte Carlo diagnostics, SORA 2.5 pre-assessment, QGroundControl import/export, and ArduPilot SITL evidence — the CLI reference documents every one, with exit codes. Outputs are versioned JSON envelopes plus Markdown, one-line summary, checklist, GeoJSON, and KML renderings that open in QGroundControl, QGIS, and Google Earth.
- Energy — per-phase power with a wind triangle solved per leg, so an outbound headwind isn't averaged away by the tailwind home; reserve at landing plus a return-to-home reserve gate at every leg.
- Environment — per-leg SRTM terrain, spatiotemporal wind grids, geometric geofence intersection with altitude bounds and time windows, landing-zone reachability with Dubins divert paths, obstacle clearance.
- Contingency — scenario events (lost link, wind change, landing zone loss) with RTL/land/loiter/divert policy outcomes and CI-ready assertions.
- Risk — SORA 2.5 iGRC/ARC/SAIL pre-assessment, strictly evidence-gated.
- Uncertainty — seeded Monte Carlo and stochastic-propagation diagnostics with conditional p5/p50/p95 envelopes.
bvlos-sim is a deterministic, offline feasibility model — an early,
auditable gate before regulator-facing tooling and flight testing. It has
no regulatory standing, ships placeholder vehicle profiles you must calibrate
against your own logs, and is MIT-licensed with no warranty. Estimation makes
no network calls: every input is a static file you fetched and committed, so a
GO is only as current as those files. The bvlos-fetch-* helpers above are
the authoring-time step that produces them, and they stamp each asset with its
source, licence, and fetch timestamp. The reasoning is in
Design.
- Getting started — zero to first verdict in five minutes.
- CLI reference — every command, format, and exit code.
- Missions and vehicles — authoring all input YAML, field by field.
- SITL — the ArduPilot container and evidence workflow.
- Design — fail-closed philosophy, scope, architecture, contracts.
- Roadmap — status and known gaps; ticket backlog for the work log.
- Contributing — setup, tests, style, and contract rules.
MIT — for this project's own code, docs, and synthetic data.
Two bundled example assets are derived from third-party databases with their
own terms that MIT cannot override: examples/real_world/assets/landing_zones.geojson
(OpenStreetMap, ODbL 1.0) and examples/real_world/assets/wind_grid.yaml
(Open-Meteo, CC BY 4.0).
Read NOTICE before fetching your own. openAIP airspace is CC
BY-NC 4.0; openAIP says its data must remain free but may be bundled with a
paid/commercial application that does not exclusively sell the data.
Open-Meteo's free API tier is non-commercial only. The applicable attribution
and source-specific obligations travel with anything you fetch through the
bvlos-fetch-* commands.