Getting started¶
By the end you'll have run a real preflight check on a bundled Alpine mission, read its go/no-go verdict, and produced a one-line summary you could wire into CI. Takes about five minutes; everything runs offline.
Before you begin¶
- Python 3.12+
- uv
git clone https://github.com/Monotox/bvlos-sim
cd bvlos-sim
uv sync
uv run bvlos-sim --help # verify the CLI answers
1. Run the preflight checklist¶
The repository ships a pre-fetched mission over the Lucerne/Zug Alps — real SRTM terrain, a real Open-Meteo wind grid, real OpenStreetMap landing zones — so no network is needed:
uv run bvlos-sim estimate \
examples/real_world/alpine_mission.yaml \
examples/real_world/quadplane_v1.yaml \
--format checklist
You should see every evaluated check pass, and still:
## 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
...
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
The exit code is 10. This is deliberate: the checklist is fail-closed —
evidence that was never evaluated (◌ N/A) can never contribute to a GO.
The demo mission omits geofence, resource, link, obstacle, and ground-risk
inputs, so it cannot pass an operational preflight, and the Blocked by:
line names exactly what's missing.
Both warnings apply that same principle to the numbers themselves.
ENERGY_MODEL_UNCALIBRATED says this vehicle profile ships placeholder power
values, so every energy figure above is arithmetic on invented coefficients.
HOVER_POWER_USED_AS_DESCENT_POWER says the profile declares no
energy.descent_power_w, so the powered descent of this hover-capable aircraft
is billed at hover_power_w — conservative, because a VTOL descends on its lift
rotors, but unmeasured. Step 4 shows the profile that has been calibrated
against a flight log.
2. Get the engineering verdict¶
When you only want the physics — is the route flyable with this battery in this wind — opt out of the operational gate:
uv run bvlos-sim estimate \
examples/real_world/alpine_mission.yaml \
examples/real_world/quadplane_v1.yaml \
--format summary --engineering-only
Exit code 0. reserve 262.7 % means the predicted energy at landing is
262.7% above the reserve threshold (25% of battery for this mission) — it is
a margin over the reserve, not battery state of charge.
The flag matters for the first word as well as the exit code. Drop
--engineering-only and the same run prints INFEASIBLE and exits 10, with
the identical reserve 262.7 %: the summary's status token follows the
readiness gate, and this mission is missing evidence. INFEASIBLE there is a
statement about the preflight, not about the physics — which is why the
engineering verdict needs its own flag.
3. See a failure¶
The same route with a battery that cannot make it:
uv run bvlos-sim estimate \
examples/real_world/alpine_infeasible.yaml \
examples/real_world/quadplane_small_battery.yaml \
--format summary
Exit code 10 again — but the bracketed failure code is what tells you this
one is physical. Step 2's INFEASIBLE carried no code because nothing was
computationally wrong with it; here the reserve genuinely lands 95.0 % under
its threshold, and --engineering-only prints the same line and the same
exit code. size-battery tells you the smallest battery that fixes it — but it
needs two fields quadplane_small_battery.yaml does not carry, so use the
sibling profile that does:
uv run bvlos-sim size-battery \
examples/real_world/alpine_infeasible.yaml \
examples/real_world/quadplane_small_battery_sizing.yaml
## Battery Sizing: alpine_infeasible_001
Mission energy required: 86.8 Wh
Reserve threshold (25 %): 38.5 Wh (of battery capacity)
Minimum feasible capacity: 153.9 Wh
Maximum feasible capacity: 900.0 Wh
Search resolution: 1.0 Wh
...
Recommendation: target 169.3 Wh (10 % margin); do not exceed the verified 900.0 Wh upper bound.
Status: SIZED
The elided lines are the 10/20/30 % margin table; --margin N narrows it to
one. Exit code 0 — SIZED is a successful answer, not a verdict on the
mission.
The sizing profile is identical to quadplane_small_battery.yaml plus
energy.battery_specific_energy_wh_per_kg and
energy.battery_excluded_operating_mass_kg. The command needs both to feed a
candidate pack's mass back into the power model; without them it exits 11
with Battery sizing requires capacity-mass feedback inputs. See
Missions and vehicles.
4. See a GO¶
Everything so far was blocked. This is what clearing the gate looks like:
uv run 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
## Pre-Flight Checklist: pipeline_demo_001_go
✓ Energy feasibility PASS reserve 650.08 Wh above threshold (875.08 Wh at landing, 225.00 Wh threshold)
✓ Geofence clearance PASS 0 conflicts across 1 zone(s)
✓ Landing-zone coverage PASS reachable zone found at all 14 checked state(s)
✓ Resource availability PASS system 'fiber-power-primary' sufficient
✓ Link availability PASS link 'mesh-primary' available
✓ 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
Exit code 0. Three things earn it, and dropping any one of them puts the
verdict back to NO-GO:
- Every evidence category is supplied. Open
examples/missions/pipeline_demo_001_go.yamland you'll find geofence, landing-zone, obstacle, terrain, population, and wind assets, pluslink_systems,airspace, andsorablocks. The vehicle suppliesresource_systemsandcharacteristic_dimension_m. - The coefficients are reproducibly calibrated.
--calibration-tracessupplies the exact normalized trace document; the command recomputes its dataset digest, reruns the deterministic fitter, and applies the profile only when every fitted parameter matches. That runtime proof clearsENERGY_MODEL_UNCALIBRATED. Only fitted energy coefficients clear it —cruise_power_w,hover_power_w,climb_power_w,descent_power_w, taken from observedbattery_current_a×battery_voltage_v. This artifact fits two of the four (climb_power_wandcruise_power_w; the demo flight never hovers or descends with battery telemetry, and the other two are declined in the artifact'snotes).cruise_power_wis the minimum required energy fit; a profile that fits cruise speed and climb rate alone leaves the warning in place, because the warning is about the power numbers. - No warning is waived. The mission has no
accepted_warning_codesat all. AGOthat needs a waiver is worth less than one that doesn't.
Drop either calibration flag and run it again: same route, same assets, back to NO-GO (or invalid input when a profile is present without its traces).
5. Check inputs without running anything¶
uv run bvlos-sim estimate \
examples/real_world/alpine_mission.yaml \
examples/real_world/quadplane_v1.yaml \
--validate-only
--validate-only schema-checks the mission, vehicle, and every referenced
asset file, then exits — 0 when everything loads, 11 with a pointed error
when it doesn't. Point the mission at a terrain file that isn't there and you
get terrain: assets/does_not_exist.yaml: FAILED (Unable to read terrain
file.) and exit 11. Use it in CI before long runs, and while authoring your
own files.
What you built¶
You ran the full preflight pipeline: a fail-closed operational checklist, an
engineering feasibility verdict, an infeasible counter-example, a complete-evidence
GO, and input validation — all deterministic, all reproducible.
Next:
- Author your own mission and vehicle — Missions and vehicles.
- Fetch real terrain/wind/landing-zone data for your own area —
examples/real_world/README.md. - Every command, flag, and exit code — CLI reference.
- Why the tool refuses to guess — Design.