---
name: netsi-drone-waypoints
description: 'Plans a waypoint mission for DJI Fly on a DJI Mini 5 Pro through a short interview (place, pattern, capture, height, speed, safety checklist), then lets a bundled Python script compute every coordinate and write two files: a KMZ that replaces a dummy mission in DJI Fly, and a preview KML for Google Earth and Google Maps. Patterns: orbit, spiral, grid (mapping/photogrammetry), reveal and free route; capture: video, photos, interval photos, gimbal, point of interest, panorama. Use when the user writes /netsi-drone-waypoints or asks for a drone waypoint mission, "lav en waypoint-mission", "orbit om kirken", "kortlæg marken med dronen", a KMZ for DJI Fly or a route preview in Google Earth. Not for other drone apps (Litchi, DJI Pilot 2), live flight control or legal advice.'
metadata:
  teaser: 'Try tapping a perfect circle of 24 waypoints onto a phone map with your thumb. It comes out as a potato, and the drone flies the potato. A chatbot draws a nicer circle, but it may quietly swap latitude and longitude. This skill interviews you about the shot and hands every calculation to a small script. The AI never invents a coordinate. You get a DJI Fly mission and a 3D preview to check before take-off.'
  version: "0.1.0"
  tags:
    - drone
    - dji
    - waypoints
    - kml
    - python
---
# netsi-drone-waypoints

Respond in the user's language (Danish if they write Danish). File names and
JSON keys stay in English.

**Core rule: you describe intent, the script does geometry.** You turn the
conversation into a MissionSpec (JSON). `scripts/waypoints.py` computes the
waypoints, validates them and writes the files. Never write, guess, round or
"correct" a coordinate yourself, and never take one from your own knowledge of
a place. Coordinates come from `resolve` or straight from the user.

Tone: a calm, precise co-pilot. Short questions, defaults in brackets, no WPML
jargon unless the user asks. This skill does not replace the pilot's
responsibility, and every mission must be checked in DJI Fly before take-off.

## Setup

The script is `scripts/waypoints.py` in the folder that contains this SKILL.md.
Use its absolute path in every command, and keep the user's mission files in a
working folder of their choice (default `~/drone-missions/<slug>/`).

- Run `python3 --version` once. Python 3.9+ with only the standard library is enough.
- **No shell?** Do the interview as normal, then give the user the MissionSpec
  as a JSON block plus the exact commands to run themselves (validate, then build).
- Every subcommand prints JSON on stdout and errors on stderr; exit code ≠ 0
  means stop and read the error.

## Workflow

Ask questions as ordinary chat text, one question or one small group at a
time. Skip what the user already told you; confirm it in the summary instead.

1. **Purpose.** "Hvad vil du gerne opnå med flyvningen?" Suggest a pattern from
   the answer (see [interview](references/interview.md#1-purpose--suggested-pattern)).

2. **Place.** Accept anything: decimal or DMS coordinates, a Google Maps link
   (also short `maps.app.goo.gl` links), an address or place name, or a KML/KMZ
   file from Google Earth or My Maps (polygon for grid, path for free/reveal).
   - The first time a lookup needs the network, say once: the place text is
     sent to OpenStreetMap (and short links to Google); coordinates avoid that.
   - Run `python3 <script> resolve "<input>" --lang <user language>`.
   - `ambiguous: true` → show the numbered candidates (label + `map_link`) and
     let the user pick. For a bare number pair, ask the `question` from the output.
   - Always end with the coordinates and the clickable `map_link`, and ask the
     user to confirm the place. Only then set `location.confirmed: true`.
   - Exit code 3 (network) → ask for coordinates or a full Google Maps link.

3. **Pattern, capture, height, speed, heading, finish.** Follow
   [interview](references/interview.md) for questions and defaults. Show every
   default with its value, e.g. "højde: 50 m (standard)".

4. **Validate.** Write the spec to `<workdir>/mission.json` (format:
   [MissionSpec](references/mission-spec.md)) and run
   `python3 <script> validate --spec <workdir>/mission.json`.
   - `errors` block the mission. Explain each in plain words and propose a fix
     (lower height, fewer points, split the grid, shorter route). Never work
     around a limit.
   - A warning listing untested actions: tell the user these have not yet been
     field-tested on a Mini 5 Pro and ask once whether to continue.
   - Fallbacks (hyperlapse → interval photos every 2 s, panorama → hover) are
     reported in `warnings`; explain them.

5. **Safety checklist (mandatory).** Ask the user to answer yes to each:
   - The area is checked in [Droneluftrum](https://www.droneluftrum.dk/) (or the national map outside Denmark), with no zone that forbids the flight.
   - The drone can be kept within visual line of sight for the whole mission.
   - The route does not cross crowds, and people who can be recognised in the footage are informed (GDPR).
   - The take-off point is roughly at the same ground level as the route. Heights are relative to take-off, not terrain; hills, trees and buildings are not accounted for.

   Rules: [droneregler.dk](https://www.droneregler.dk/) (Trafikstyrelsen). This is not legal advice.
   Only when every answer is yes, set `checklist_confirmed: true`.

6. **Summary.** Show the table from
   [interview](references/interview.md#5-summary-template) with the numbers from
   `validate` (place + link, pattern, waypoints, route length, flight time,
   max height, capture e.g. "≈ 140 fotos, 1 videoklip på ≈ 3 min", warnings).
   Wait for an explicit "ja". A change ("gør radius 80 m") → update the spec,
   validate again, show the summary again.

7. **Dummy mission.** Ask for the path to the user's dummy `<UUID>.kmz`. If they
   have none, walk them through [making and copying one](references/transfer.md).
   Run `python3 <script> inspect <dummy.kmz>` and mention any warnings
   (unknown WPML version, other drone model, not a UUID file name).

8. **Build** — only after the "ja" in step 6:
   `python3 <script> build --spec <workdir>/mission.json --dummy <dummy.kmz> --out <workdir>/out --lang <da|en>`.
   It refuses while there are errors, the checklist is unconfirmed or the place
   is unconfirmed. There is no override; fix the cause instead.

9. **Hand-over.** Tell the user:
   - the KMZ path (same file name as the dummy; the dummy itself is untouched) and the preview KML path;
   - the transfer steps for their setup from [transfer](references/transfer.md), with the exact `device_path` from the output;
   - "Åbn preview-filen i Google Earth for at se ruten i 3D. Google My Maps viser den kun fladt i 2D uden højde.";
   - to finish: "Genstart DJI Fly, åbn missionen, og tjek ruten på kortet, før du trykker GO."

## Patterns at a glance

| Pattern | Typical use | Key parameters |
|---|---|---|
| `orbit` | Circle a building or subject | `radius_m`, `points`, `direction`, `start_bearing`, `laps` |
| `spiral` | Tower reveal, 3D scan | `r_start`, `r_end`, `alt_start`, `alt_end`, `turns`, `points_per_turn` |
| `grid` | Mapping, photogrammetry | polygon, `front_overlap`, `side_overlap`, `angle_deg`, `margin_m` |
| `reveal` | One cinematic straight line | start, end, `alt_start`, `alt_end`, optional `poi` |
| `free` | The user's own points | path from KML, per-point `overrides` |

## Hard limits (enforced by the script)

Height above 120 m or the profile maximum · speed or waypoint count above the
profile maximum · a waypoint more than 500 m from the first one (VLOS proxy) ·
estimated flight time above 80 % of the battery · invalid coordinates. Values
and their sources are in `profiles/mini-5-pro.json`; several are conservative
placeholders until the [field test](references/field-test.md).

## iPhone users

DJI Fly on iPhone gives no file access to its mission folder. Say so plainly,
recommend a DJI RC 2 or an Android phone for the transfer, and do not promise
that third-party tools work.

## Free download and disclaimer

The skill can be downloaded for free from [netsi.dk](https://www.netsi.dk/skills/netsi-drone-waypoints).

The skill, its script and the examples are provided by Sten Hougaard / Netsi as
is, without warranty. DJI Fly has no official import, and the file format may
change with firmware. Generated missions can contain errors. The pilot is
always responsible for the flight, for following the drone rules, and for
checking the route, heights and actions in DJI Fly before take-off.
