Plan a UAV sensor-collection mission
Measure per-leg coverage and battery use, reject an overlong route, replan around an exclusion and validate a handoff.

Blueprint Bina: I want you to inspect the failed case and the record that explains the next decision.
Predict the reading, then compare it with the measurement.
Python 3 in your browser (JupyterLite)
Python · no installOpen the notebook in your browser and run each Python cell; no install or account is needed.
Three ways to run: use JupyterLite here with no install; run main.py locally from the downloadable lab folder; or open the same notebook in Google Colab.
Steps
Step 1
- Do
- In the JupyterLite notebook, run the Step 1 cell to define a survey envelope and record contract.
- You will see
- Input: execute notebook step 1 with the record’s unchanged fixture, seed, and parameters. Observed: Fictional field=80x80 m; altitude fixed=20 m; speed=5 m/s Observed: Battery=36.0 Wh; reserve=6.0 Wh; travel=0.08 Wh/m Observed: Hover=0.3 Wh/s; dwell=2 s; manoeuvre allowance=0.2 Wh/leg
- Why it matters
- Expected: STEP 1 mission envelope frozen from this deterministic notebook step. Interpretation: The legacy lab requires an envelope before route generation. Declared energy, dwell and reserve assumptions make this classroom simulation reproducible. Action: Run python main.py and inspect step 1: define a survey envelope and record contract. Boundary: this local fixture is not a live device, network, or site measurement.

Step 1 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 2
- Do
- In the JupyterLite notebook, run the Step 2 cell to inspect route v1 before execution.
- You will see
- Input: execute notebook step 2 with the record’s unchanged fixture, seed, and parameters. Observed: Inspect route v1 before execution Observed: 1 ( 10, 20) A 22.36 2 2.59 12.5% Observed: 2 ( 30, 20) B 20.00 2 2.40 25.0%
- Why it matters
- Expected: STEP 2 v1 manifest ready from this deterministic notebook step. Interpretation: A route manifest must show geometry, collection actions and their costs. Cumulative coverage here counts sensor records, not area swept by a camera. Action: Run python main.py and inspect step 2: inspect route v1 before execution. Boundary: this local fixture is not a live device, network, or site measurement.

Step 2 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 3
- Do
- In the JupyterLite notebook, run the Step 3 cell to reject an overlong v0 and keep the reason.
- You will see
- Input: execute notebook step 3 with the record’s unchanged fixture, seed, and parameters. Observed: Reject an overlong v0 and keep the reason Observed: v0 two surveys 52.11 30.00 REJECT Observed: v1 one survey 26.06 30.00 ACCEPT
- Why it matters
- Expected: STEP 3 energy gate rejects v0 from this deterministic notebook step. Interpretation: Reserve is a gate, not a battery label. Keeping the rejected double-survey candidate explains why optional scope was removed. Action: Run python main.py and inspect step 3: reject an overlong v0 and keep the reason. Boundary: this local fixture is not a live device, network, or site measurement.

Step 3 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 4
- Do
- In the JupyterLite notebook, run the Step 4 cell to execute v1 and inspect the battery ledger.
- You will see
- Input: execute notebook step 4 with the record’s unchanged fixture, seed, and parameters. Observed: Execute v1 and inspect the battery ledger Observed: 1 33.41 1.99 25.42 Observed: 2 31.01 3.08 21.93
- Why it matters
- Expected: STEP 4 normal route reserve PASS from this deterministic notebook step. Interpretation: Checking return feasibility before each leg prevents accepting a mission only because its final energy total looks plausible. The ledger exposes the remaining margin. Action: Run python main.py and inspect step 4: execute v1 and inspect the battery ledger. Boundary: this local fixture is not a live device, network, or site measurement.

Step 4 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 5
- Do
- In the JupyterLite notebook, run the Step 5 cell to inject a no-fly rectangle and replan v2.
- You will see
- Input: execute notebook step 5 with the record’s unchanged fixture, seed, and parameters. Observed: Inject a no-fly rectangle and replan v2 Observed: Exclusion x=35..55, y=10..30 Observed: Direct B->D intersects exclusion=True: REJECT direct leg
- Why it matters
- Expected: STEP 5 no-fly detour computed from this deterministic notebook step. Interpretation: Avoidance changes both path length and collection scope. The geometric segment test rejects the blocked path and records the excluded sensor explicitly. Action: Run python main.py and inspect step 5: inject a no-fly rectangle and replan v2. Boundary: this local fixture is not a live device, network, or site measurement.

Step 5 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 6
- Do
- In the JupyterLite notebook, run the Step 6 cell to execute the detour and hover-to-collect schedule.
- You will see
- Input: execute notebook step 6 with the record’s unchanged fixture, seed, and parameters. Observed: A 6.47 2 collected Observed: B 12.47 2 collected Observed: D 25.28 2 collected
- Why it matters
- Expected: STEP 6 stress flight logged; coverage incomplete from this deterministic notebook step. Interpretation: A detour can be safe while failing the data goal. Hover receipts show which seven sites were collected and why the eighth needs a later re-flight. Action: Run python main.py and inspect step 6: execute the detour and hover-to-collect schedule. Boundary: this local fixture is not a live device, network, or site measurement.

Step 6 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 7
- Do
- In the JupyterLite notebook, run the Step 7 cell to stress the coupled energy and fallback gates.
- You will see
- Input: execute notebook step 7 with the record’s unchanged fixture, seed, and parameters. Observed: 36 10/10 7/8 9.22 COMPLETE Observed: 30 7/10 5/8 13.09 HOLD before unsafe leg Observed: 24 5/10 3/8 13.49 HOLD before unsafe leg
- Why it matters
- Expected: STEP 7 energy sensitivity measured from this deterministic notebook step. Interpretation: Lower battery and higher travel cost can invalidate the same geometry. A stopped simulation is a failed gate, not a completed mission; the remaining return budget is shown. Action: Run python main.py and inspect step 7: stress the coupled energy and fallback gates. Boundary: this local fixture is not a live device, network, or site measurement.

Step 7 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 8
- Do
- In the JupyterLite notebook, run the Step 8 cell to transfer skipped work only after the handoff gates.
- You will see
- Input: execute notebook step 8 with the record’s unchanged fixture, seed, and parameters. Observed: age=10 battery=24 exclusion=False -> HOLD stale telemetry; owner unchanged Observed: age= 1 battery= 8 exclusion=False -> HOLD return reserve; owner unchanged Observed: age= 1 battery=24 exclusion=True -> HOLD exclusion active; owner unchanged
- Why it matters
- Expected: STEP 8 handoff gates and ownership recorded from this deterministic notebook step. Interpretation: Ownership changes only after freshness, reserve and exclusion checks. The accepted handoff queues future work and does not claim a collection that never happened. Action: Run python main.py and inspect step 8: transfer skipped work only after the handoff gates. Boundary: this local fixture is not a live device, network, or site measurement.

Step 8 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab) Step 9
- Do
- In the JupyterLite notebook, run the Step 9 cell to reconcile manifest, executed legs and collection records.
- You will see
- Input: execute notebook step 9 with the record’s unchanged fixture, seed, and parameters. Observed: normal: planned=9 flown=9 collected=8 coverage=100.0% Observed: stress: planned=10 flown=10 collected=7 coverage=87.5% Observed: Manifest/trace agreement: PASS; reserve/return margins: PASS
- Why it matters
- Expected: STEP 9 validation PASS; re-fly remains explicit from this deterministic notebook step. Interpretation: The legacy acceptance rule compares planned and executed records. The model passes its checks while the mission decision remains revise because coverage is incomplete. Action: Run python main.py and inspect step 9: reconcile manifest, executed legs and collection records. Boundary: this local fixture is not a live device, network, or site measurement.

Step 9 · Python 3 in your browser (JupyterLite); numbered callout added to a real capture. Enlarge screenshot (new tab)
Chapter checks
These questions refer to the chapter’s examples. Use the return links to review their answers.
A UAV must inspect a long fence line after high winds, needing repeated boundary records and short close-ups at damage, not a full field map. Which mission pattern is the best starting point?
Return to the chapter’s knowledge checkA UAV must inspect a long fence line after high winds. The team needs repeated boundary records and short close-up checks at damaged sections, not a full map of the surrounding field. Which mission pattern is the best starting point?
Return to the chapter’s knowledge check
Return to Practice: UAV Missions and Avoidance · Browse Labs