πŸ›°οΈ FLYplan - v1 - Automated Operational Intent Strategy

From docked-GCS task planning to live OI lifecycle management β€” DJI FlightHub 2 first, ported to any manufacturer
v2.0 β€” Revised per team review TECH-002 / FSL β€” RTM Platform
Prepared for Lindsay Mohr, AIRmarket Β· August 17, 2026 Β· Grounded against live FlightHub2 / FSS API schemas

🎯 What changed in this revision

Contents

  1. Governing principles
  2. What the live API data confirms
  3. End-to-end pipeline (DJI FlightHub 2)
  4. FSS reconciliation and FSL flight binding
  5. MQTT / OpenAPI / DLB call inventory
  6. FlightHub 2 GUI: annotations and pilot alerts
  7. Conformance-driven OI modification
  8. Notification model
  9. Generalized adapter framework
  10. Phased roadmap
  11. Open questions

1. Governing principles

Three principles carry the whole design, and each one exists specifically to stop us from rebuilding something that already exists elsewhere in the stack.

Principle 1 β€” One authoritative OI, many mirrors RTTP is the single source of truth for the OI: its geometry, its lifecycle state, its timing. FlightHub 2, DJI Pilot 2, the FLYsafe RTM map, and Grafana are all subscribers that mirror that state for their own audience. Nothing outside RTTP originates or silently edits an OI.
Principle 2 β€” Conformance monitoring already exists; don't duplicate it FLYrtm's OpenUTM deployment already tracks the aircraft and determines conformance against the active OI. RTTP's job is to create, submit, activate, and deactivate the OI β€” and to react when OpenUTM determines the aircraft is non-conforming. No second containment-checking service gets built for this.
Principle 3 β€” FSS is the system of record for flight planning; FSL fills the gap Before RTTP creates anything, it checks whether FLYsafe.software (FSS) already has a planned flight for that aircraft and time window via the DLB Flight API. If yes, FSL's objects bind to that existing FSS flight. If no, FSL creates its own flight-binding record β€” clearly marked as FSL-originated β€” and that's the extent of the near-term build. Pushing a matching record back into FSS and uploading FSL telemetry to it is real, but later, work.

FlightHub 2

FLYsafe.software (FSS)

RTTP / FLYrtm β€” Authoritative

reconcile: existing flight?

no match found

mirror geometry + state

conformance state

non-conforming to modify OI

if distribution enabled

OI Service
geometry Β· lifecycle Β· timing

OpenUTM
(existing) β€” conformance determination

FSL Flight Binding Record
(created when FSS has no match)

DLB Flight API
planned missions / flights

Map annotations
(OI polygon mirror)

Notifications

DJI Pilot 2

Fig. 1 β€” Authority model: RTTP owns the OI and consumes FSS reconciliation + OpenUTM conformance as inputs; FlightHub 2 and Pilot 2 are presentation mirrors only.

2. What the live API data confirms

Rather than designing purely from DJI's public docs or the external chat the team shared, I pulled live schema from our actual FlightHub2 and FSS connections. That changed a few assumptions and confirmed others. The findings below are quoted directly from those live calls, cross-checked against the DJI-FLIGHT-HUB-RESEARCH.md already in this project.

πŸ“‹
FlightHub2 Task
DJI
Confirmed live: rich scheduling fields, but geometry is a reference, not inline data.
  • begin_at / end_at / run_at β€” real scheduling fields
  • wayline_uuid β€” reference only, empty for ad-hoc flights
  • current_waypoint_index present but unverified as live-updating
  • No lat/lon appears on the task record itself
πŸ—ΊοΈ
Wayline
DJI
Metadata-only in the list/detail API β€” real geometry is a downloaded file.
  • List/detail: template type, drone model, one start point only
  • Full waypoints/altitude/speed/actions live in a KMZ (WPML) file
  • Retrieved via a signed download URL, not inline JSON
πŸ›¬
Dock / drone telemetry
DJI
Best available takeoff/landing signal.
  • device_state.drone_in_dock 0/1 β€” hardware-level fact
  • Position, heading, mode_code alongside it
  • More reliable than task-status transitions (cloud-sync lag)
πŸ“
Map elements
DJI
The annotation mechanism is real and reachable today.
  • GeoJSON Point / Polygon grouped into named folders
  • properties.color, a notify-style flag observed
  • Confirmed create / update / delete flow via our own tooling
✈️
FSS flight record
FSS / DLB
This is FLYsafe.software's flight-planning/compliance schema β€” matched against the DLB Flight API surface.
  • guid, drone_guid, flight_date_utc, mission_guid
  • approval_status, operation_type (VLOS/BVLOS), personnel[]
  • data_plan_area with SkylineBoundary, ContVolume, buffer geometry
  • automateFlight boolean already exists β€” the schema anticipates automated flights
πŸ”—
The gap this strategy closes
FSL
No populated join key currently exists between a FlightHub Task and an FSS flight.
  • mission_guid observed empty on live FSS records
  • No FlightHub task_uuid/wayline_uuid anywhere on the FSS side
  • Section 4 below defines exactly how this gets resolved going forward

3. End-to-end pipeline (DJI FlightHub 2, primary implementation)

This is the automated sequence the team described, updated to insert the FSS reconciliation step and to remove the standalone containment-monitoring logic in favor of consuming OpenUTM's existing conformance output.

FLYrtm / OpenUTMMQTT (dock/drone)RTTP OI ServiceGeometry EngineFSS (DLB Flight API)RTTP Task WatcherFlightHub 2FLYrtm / OpenUTMMQTT (dock/drone)RTTP OI ServiceGeometry EngineFSS (DLB Flight API)RTTP Task WatcherFlightHub 2origin=fsl_auto, fss_synced=falsealt[existing FSS flight found][no match]alt[non-conforming]Task planned (status=0, wayline_uuid set)poll list_flight_tasks (30 to 60s)query flights for drone_guid + time windowflight_guid / mission_guidbind to existing FSS flight_guidcreate FSL-native flight-binding recordget_wayline_download_url(wayline_uuid)signed KMZ URLdownload + parse WPML into waypoint listgenerate OV + CV from waypointsOV / CV geometrystate = OI_PENDING then OI_SUBMITTEDcreate/update map annotation (mirror)drone_in_dock 1 to 0 + altitude climbstate = OI_ACTIVEconformance state (existing service)execute configured OI action (alert / amend)update annotation + notificationdrone_in_dock 0 to 1state = OI_CLOSEDarchive annotation
Fig. 2 β€” Full sequence from task detection through OI close, including the FSS reconciliation branch and the OpenUTM conformance hand-off (no new monitoring loop).
1
Detect a new or updated scheduled Task
FlightHub 2's MQTT services topics are command/ack traffic to a device, not a task-lifecycle event stream β€” so discovery is poll-driven unless DJI's Cloud API supports webhook registration for our tenant (worth asking DJI directly; would replace polling). list_flight_tasks(status=0) on a 30–60s cadence, diffed against RTTP's known task registry by uuid. A task with status=0 and a populated wayline_uuid is the trigger. Tasks with no wayline_uuid (ad-hoc "FlyToTask") fall outside automatic OI generation and should raise a WARNING notification instead of being silently skipped.
2
Reconcile against FSS before creating anything (new)
Query FLYsafe.software via the DLB Flight API for a flight already planned on this aircraft within this time window β€” matching drone_guid (via the drone-serial↔GUID mapping already available in the FSS drone roster) against the task's begin_at/end_at. If a match exists, every FSL object created downstream binds to that FSS flight_guid/mission_guid β€” this becomes the canonical correlation key described in Section 4. If no match exists, FSL creates its own flight-binding record now, and that record is the near-term deliverable; it is not pushed back to FSS in this phase.
3
Consume the waypoints
get_wayline(wayline_uuid) for metadata, get_wayline_download_url(wayline_uuid) for a signed KMZ, then unzip and parse the WPML XML: per-waypoint <Point> coordinates, wpml:executeHeight, wpml:waylineCoordinateSysParam (altitude reference β€” relative-to-takeoff vs. AGL vs. EGM96, this needs to resolve correctly or the OV is wrong), and per-segment speed. This should be its own small, well-tested library given DJI's WPML schema drift across firmware/Pilot releases β€” it should reject missions with an unresolvable altitude reference rather than guessing.
4
Generate the Operational Volume and Contingency Volume
OV = buffer the 3D route by a horizontal margin (GNSS error + wind-drift allowance, sized per-project using the wind thresholds already configured in FlightHub 2's project_weather_blocking) and a vertical band around the route's min/max altitude. CV = a further buffer sized from realistic failure trajectories β€” lost-link flyaway distance (max speed Γ— reaction time) plus an unpowered-descent radius from max altitude β€” reusing the containment model that already exists for CAR 922.08 elsewhere in the architecture rather than inventing a parallel one.
5
Create the OI and submit it on schedule
RTTP creates the OI record immediately on task detection (OI_PENDING) β€” geometry and validation happen well ahead of flight β€” tagged with the FSS flight_guid or FSL flight-binding id from step 2 as its correlation key. "Submits as soon as scheduled" means the formal submission (OI_SUBMITTED) fires on a configurable lead time before scheduled_start, not necessarily at creation β€” a per-project config value, same pattern as the existing weather-blocking thresholds.
6
Activate on takeoff β€” not on the scheduled clock
scheduled_start is a plan, not a fact. The OI_ACCEPTED β†’ OI_ACTIVE trigger is the dock's drone_in_dock 1β†’0 transition, cross-checked against OSD altitude climbing above dock elevation β€” a hardware-level signal, more dependable than a task-status field that can lag the physical event.
7
Hand tracking to FLYrtm / OpenUTM β€” don't rebuild it
Once active, RTTP does not run its own containment loop. FLYrtm's existing OpenUTM deployment evaluates the telemetry already flowing through the standard 3-topic MQTT pipeline against the active OI and emits a conformance determination. RTTP subscribes to that determination and treats non-conformance as the trigger for OI action (Section 7).
8
Deactivate on landing / task close
Symmetric to activation: drone_in_dock 0β†’1 plus altitude returning to dock elevation, or a terminal flight_task_status from the task poll β€” transition OI_ACTIVE β†’ OI_CLOSED, reconcile the FlightHub annotation to a closed/archived state, and unsubscribe from conformance events for that OI.

OI lifecycle state machine

StateTriggerFlightHub mirror
OI_PENDINGTask detected + FSS reconciliation completeAnnotation created, grey, "Pending"
OI_SUBMITTEDLead-time window reached before scheduled startLabel updated, "Submitted"
OI_ACCEPTED / OI_REJECTEDSubmission responseBlue "Approved" or prominent red rejection warning
OI_ACTIVEdrone_in_dock 1β†’0 + altitude climbGreen, "Active"
OI_WARNING / OI_AMENDEDOpenUTM non-conformance determinationAmber/updated geometry + notification
OI_CLOSEDdrone_in_dock 0β†’1 or terminal task statusArchived / muted "Completed"

4. FSS reconciliation and FSL flight binding

This is the concrete answer to what was previously an open question in this project's earlier draft (how do we join a FlightHub Task to a FLYsafe flight, given mission_guid is empty in the live data). It's now a designed pipeline step rather than an assumption.

Yes, match found

No match

Task detected in FlightHub2
(status=0, wayline_uuid set)

Query FSS via DLB Flight API:
flight for this drone_guid
overlapping this time window?

Bind FSL objects to
existing FSS flight_guid / mission_guid

FSL creates its own
flight-binding record

origin = fsl_auto
fss_synced = false

Continue pipeline:
OV/CV generation then OI create/submit

FUTURE (not in scope now):
push matching flight record to FSS
+ upload FSL telemetry

Fig. 3 β€” FSS reconciliation decision tree. The dashed box is explicitly future work, not part of this build.

Near-term scope

The development focus right now is getting the left-hand branch of Fig. 3 right: querying FSS reliably (drone-serial↔GUID mapping has to be correct, and the time-window tolerance has to be tuned so it doesn't false-match two flights of the same drone close together), and building a clean, well-defined FSL-native flight-binding record when no FSS match exists. That record should carry everything downstream processing needs β€” the FlightHub task_uuid/wayline_uuid, dock/drone serials, the OI id, and explicit provenance fields (origin: "fsl_auto", fss_synced: false) so nothing downstream has to guess where the record came from.

Future scope β€” explicitly deferred

Eventually, FSL-originated flights should be pushed back into FSS: creating a matching flight record via the DLB Flight API's write endpoints, and uploading the telemetry RTTP already captured so FSS's own record isn't empty. Worth noting the FSS flight schema already has an automateFlight boolean β€” the vendor's own data model anticipated exactly this kind of automated-flight scenario, which is a good sign this sync is a supported pattern rather than something FSS would need to be reworked for. This is called out here specifically so it isn't quietly built early by accident β€” the team's direction is clear that this is a later phase (Section 10, Phase 5).

5. MQTT / OpenAPI / DLB call inventory

The concrete calls the DJI adapter and the FSS reconciliation step need, organized by pipeline phase. Endpoint shapes match DJI's published Cloud API structure and our own tool-confirmed schema; the exact base path should be confirmed live per tenant (ours currently resolves to es-flight-api-us.djigate.com).

πŸ”Ž
Discovery (REST, poll)
DJI
GET /workspaces/{ws}/flight-tasks?status=0
GET /workspaces/{ws}/flight-tasks/{task_id}
GET /workspaces/{ws}/waylines/{wayline_id}
GET /workspaces/{ws}/waylines/{wayline_id}/url
πŸ“‘
Telemetry (MQTT, subscribe)
DJI
thing/product/{dock_sn}/osd
thing/product/{dock_sn}/state
thing/product/{dock_sn}/events
sys/product/{dock_sn}/status
πŸ—ΊοΈ
Map mirror (REST, write)
DJI
POST .../element-groups/{group_id}/elements
PUT .../elements/{element_id}
DELETE .../elements/{element_id}
✈️
FSS reconciliation (DLB Flight API)
FSS
GET /flights?drone_guid=..&date_from=..&date_to=..
GET /drones/{drone_guid}
Write-side endpoints (create flight, upload telemetry) exist on the DLB API but are not called in this phase β€” reserved for the future sync work in Section 4.
πŸ“Ά
Conformance (existing, internal)
FLYrtm
Not a new call β€” RTTP subscribes to whatever internal event/topic OpenUTM already publishes for conformance state. The exact contract needs confirming with the OpenUTM deployment owner (Section 11).
⚠️
Unverified β€” confirm before relying on
Verify
FlightHub notification-push alongside a map element, and Pilot 2 folder distribution, are described in DJI's public docs (and the external chat) but not yet confirmed against our tenant's OpenAPI tier.

6. FlightHub 2 GUI: annotations and pilot alerts

The annotation mechanism the team asked about is real and reachable today through our own tooling β€” list_element_groups/list_elements confirm FlightHub 2 organizes map content into named groups holding GeoJSON Point/Polygon features with a color property and what appears to be a per-element notify flag.

Recommended structure: one dedicated element group per FlightHub 2 project β€” "FLYsafe Operational Intents" β€” holding one Polygon per active/recent OI, named with the OI id and current state (e.g. OI-927155 Β· ACTIVE), colored by state (grey/pending β†’ blue/accepted β†’ green/active β†’ amber/warning β†’ red/critical β†’ muted grey/closed). Every OI state transition in Section 3's state machine fires a corresponding annotation update, not just the initial creation. Keep the OV and CV visually distinct in weight β€” OV solid and saturated ("where I'm expected to be"), CV thin/dashed and optionally toggled off by default per-project β€” so the map doesn't get overloaded.

Needs verification before building on it Whether our FlightHub 2 tenant actually supports (a) a text notification surfacing as a real alert/toast alongside a map element, and (b) distributing an annotation folder to DJI Pilot 2 so the OI polygon shows in the pilot's in-flight app. Both are described in DJI's Cloud API / FlightHub Sync documentation, and the notify field we observed on live elements is circumstantial support β€” but this should be a direct test (create one annotation with notify set, confirm a FlightHub user actually sees something) before it's load-bearing in the plan. The native HMS/Payload-SDK path for RC vibration/buzzer alerts is architecturally different again β€” it needs onboard PSDK hardware, not just Cloud API calls β€” and should be scoped as its own future workstream, not bundled into this phase.

7. Conformance-driven OI modification

This section replaces what would otherwise have been a new "containment tracking service" with a much smaller design: RTTP as a consumer of conformance state that already exists, not a producer of it.

A
Conformance determination (existing β€” FLYrtm / OpenUTM)
OpenUTM already evaluates real-time position against the active OI volume and determines a conformance state. RTTP does not reimplement this. The one open item is confirming the exact interface β€” event bus topic, REST callback, or query API β€” that RTTP should subscribe to for that determination (Section 11).
B
RTTP action on non-conformance
When OpenUTM reports non-conforming, RTTP's OI Service is what's configured to act: raise the appropriate notification severity (Section 8) and, depending on phase, either alert-only or compute and submit an amended OI. This is the "the system will be configured to take OI action for modifying" behavior the team described β€” it's a reaction to an existing signal, not new detection logic.
C
Predictive advisories (phase 2+)
Whether OpenUTM already exposes a predictive/advisory conformance state (e.g. "approaching boundary" ahead of an actual breach) or only a binary conforming/non-conforming result is an open question worth resolving early β€” if predictive advisories already exist there, RTTP should consume them rather than computing its own time-to-breach estimate from heading/speed/climb rate.
D
Automatic OI amendment (phase 3)
When non-conformance is correlated with a flight-mode change to manual or gohome/RTL (from DJI OSD telemetry), RTTP computes an amended OV/CV β€” e.g. extended toward the RTL home point, or widened to cover the manual-control deviation β€” and resubmits it through the same pipeline as a new OI, updating the FlightHub mirror and any downstream authority notification. This is the highest-value, highest-risk phase and needs an explicit decision on what "auto-approved amendment" is allowed to mean regulatorily before it ships with no human in the loop.

8. Notification model

One shared notification object across all of RTTP β€” sourced from OpenUTM's conformance events, task/OI lifecycle transitions, and FSS reconciliation outcomes alike β€” keeps severity handling from being reimplemented per source.

ClassExamplesPilot interruption
INFOOI created/accepted, FSS match found, mission syncedNone
ADVISORYOI ending soon, no FSS match (FSL-native record created)Passive / map only
WARNINGOpenUTM reports non-conforming, amended OI pendingFlightHub notification
CRITICALSustained non-conformance, OI rejected with imminent operation, flight without a valid OIFlightHub notification + escalation
{
  "event": "OI_NON_CONFORMANT",
  "severity": "WARNING",
  "oi_id": "OI-927155",
  "source": "flyrtm_openutm",
  "platform": "dji_flighthub2",
  "dock_sn": "8UUXN6700A0AJF",
  "message": "OpenUTM reports aircraft non-conforming to active OI.",
  "location": { "lat": 53.7377, "lon": -113.0317, "alt_m": 621.4 }
}

9. Generalized adapter framework

To satisfy the eventual port to Auterion, ArduPilot, and PX4, everything above should sit behind a small adapter interface β€” with one important clarification this revision adds: conformance monitoring is not part of any per-platform adapter. OpenUTM operates on telemetry that's already normalized through the existing 3-topic MQTT architecture regardless of source platform, so it sits above the adapter layer entirely.

Platform-agnostic (RTTP core)

Per-platform GCSAdapter

DJI FlightHub2
REST poll + MQTT
KMZ/WPML parsing
dock drone_in_dock signal

Auterion
Suite REST/gRPC
possible native MAVLink
mission items - verify

ArduPilot / PX4
native MAVLink mission protocol
already flowing via existing
Aircraft Agent / GCS Plugin

Normalized WaypointList +
Telemetry stream

Geometry Engine (OV/CV)

OI Service (lifecycle state machine)

FLYrtm / OpenUTM
conformance (existing, reused)

Map mirror + Notification adapters
(optional per platform)

Fig. 4 β€” Adapter framework. OI lifecycle, geometry generation, and conformance consumption are all platform-agnostic; only mission-fetch and takeoff/landing-signal logic differ per manufacturer.

A worthwhile planning note: DJI β€” the platform being built first β€” is also the hardest one, since it has no native waypoint-index or mission-progress telemetry. ArduPilot and PX4 already flow through the existing Aircraft Agent / GCS Plugin into the standard MAVLink topic and natively expose MISSION_CURRENT/mode transitions, so their adapters are comparatively simple ports, not new integrations. Auterion sits in between and needs its own short research pass (mirroring the DJI research already done in this project) before implementation, since its cloud API surface and auth model haven't been verified against a live tenant.

10. Phased roadmap

0
Validation
Confirm the OpenUTM conformance event contract; confirm the DLB Flight API's query capability for drone+time-window matching and its rate limits; confirm whether current_waypoint_index is genuinely live; confirm FlightHub notification-push and Pilot 2 distribution for our tenant.
1
DJI one-way mirror (MVP)
Task detection β†’ FSS reconciliation β†’ wayline/KMZ parsing β†’ OV/CV generation β†’ OI created in RTTP β†’ FlightHub annotation kept in sync. Manual state transitions for now; validates the geometry engine and the FSS-matching logic against real missions.
2
Full automatic lifecycle
Scheduled submission timing, MQTT-driven takeoff/landing detection, subscription to OpenUTM's conformance output, and the full notification model β€” end to end, no manual step from task-planned to OI-closed.
3
Predictive and dynamic
Predictive advisories (if not already provided by OpenUTM), then automatic OI amendment on manual-mode/RTL-driven non-conformance, plus a scoping decision on native HMS/PSDK alerting as a separate hardware-gated workstream.
4
Multi-platform port
ArduPilot/PX4 adapter (low incremental effort β€” reuses existing MAVLink infrastructure), then Auterion pending its own research pass.
5
FSS bidirectional sync (future, not scoped now)
Push FSL-originated flight-binding records into FSS as real flight records via the DLB Flight API, and upload the telemetry RTTP captured, so FSS's own record isn't left empty for automated dock flights.

11. Open questions