Files
dmc/DMC_Architektur_und_Design.md
T

299 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Drone Mission Control (DMC) — Architektur- und Design-Dokumentation
> Zusammenfassung aller bisher in diesem Projekt getroffenen Architektur- und Design-Entscheidungen: vom HTML/JS-Demonstrator ("Drone Mission Command.html") bis zur geplanten Flutter-Zielarchitektur.
---
## 1. Projektüberblick
**Ziel:** Mobile App zur Missionsplanung und Flugsteuerung für einen Fixed-Wing-Drohnen-Aufbau (Heewing T1 Ranger, iNAV-Firmware), mit Fokus auf Wegpunkt-Missionen, Live-Fly-Modus und Point-and-Fly (PnF)-Einzelziel-Anflug.
**Zwei Entwicklungsstränge:**
1. **HTML/JS-Demonstrator** (`Drone Mission Command.html`, vormals `taf_mission_planner_osm_v13.html`) — iteratives Rapid-Prototyping zur Validierung von Workflow und Feature-Umfang, lauffähig im Browser.
2. **Flutter-Zielarchitektur** — die für die produktive App geplante Struktur, die den Demonstrator ablösen soll.
**Sprachregelung:** Konversation und Dokumentation auf Deutsch, Code und UI-Texte auf Englisch.
---
## 2. Systemarchitektur (Flutter-Zielarchitektur)
Fünf-Schichten-Architektur, gemeinsam festgelegt:
```
┌─────────────────────────────────────────────┐
│ UI Layer (Screens: Plan / Fly / Settings / │
│ Library) │
├─────────────────────────────────────────────┤
│ App-Mode State Machine │
│ (Plan → Connect → Upload → Fly) │
├─────────────────────────────────────────────┤
│ Mission Domain Layer │
│ (Strategy Pattern: TrackMission, │
│ SurveyAreaMission*, SearchAreaMission*) │
├─────────────────────────────────────────────┤
│ Mission-Sync Service │ Telemetry Service │
├─────────────────────────────────────────────┤
│ Transport / Protokoll-Layer │
│ (FlightControllerLink-Abstraktion) │
└─────────────────────────────────────────────┘
```
\* geplant, noch nicht implementiert
### 2.1 Kernprinzip: Protokoll-Abstraktion
Ein einheitliches Interface `FlightControllerLink` kapselt die Kommunikation mit dem Flightcontroller, unabhängig davon, ob iNAV (via MSP) oder ArduPilot (via MAVLink) angesprochen wird. Die Mission-Domain-Schicht kennt nur eine protokollneutrale `FlatWaypointList`; die Divergenz zu MSP bzw. MAVLink findet ausschließlich im letzten Schritt (Encoder) statt.
### 2.2 App-Mode State Machine
Explizite Zustandsfolge: **Plan → Connect → Upload → Fly**, inkl. definiertem "Ready-to-Fly"-Gate:
> Mission hochgeladen **und** verifiziert **und** Drohne noch disarmed.
Grund: iNAV (und MAVLink bei iNAV) akzeptiert `MSP_SET_WP`-Uploads grundsätzlich nur im **unarmed**-Zustand. Der Handover-Prozess (Connect → Verify → Upload → Ready-to-Fly) muss dieses Gate technisch erzwingen, nicht nur als UI-Konvention behandeln.
---
## 3. Komponenten
### 3.1 `FlightControllerLink` (Interface)
Zentrale Abstraktion für alle FC-Interaktionen.
**Methoden/Properties:**
- `connect()`, `disconnect()`
- `capabilities` → `FcCapabilities`-Struct (Feature-Flags: `supportsMultiMission`, `supportsInFlightUpload`, `maxWaypoints`, …)
- `uploadMission(FlatWaypointList)`
- `setFlightMode(mode)` — abstrakte Modus-Konstanten: `MISSION_RUN`, `GUIDED_POINT`, `RETURN_HOME`, `HOLD`
- `arm()`
- `subscribeTelemetry()`
- `readActiveWaypointIndex()`
**Implementierungen:**
- `MspFlightControllerLink` — für iNAV, eigenständiger MSP-Adapter (kein fertiges Dart-Paket verfügbar, komplett selbst implementiert)
- `MavlinkFlightControllerLink` — für ArduPilot (perspektivisch, nicht MVP)
- `MockFlightControllerLink` — synthetische Telemetrie für Tests ohne Hardware/SITL
### 3.2 Mission Domain Layer
Strategy-Pattern für erweiterbare Missionstypen:
- `TrackMission` — aktuell implementiert (Wegpunkt-Strecke)
- `SurveyAreaMission` — geplant (Flächenabflug)
- `SearchAreaMission` — geplant (Suchmuster)
Gemeinsame Datenstruktur: `FlatWaypointList` (protokollunabhängig), am Ende protokollspezifisch codiert durch:
- `MspWaypointEncoder` (iNAV)
- `MavlinkMissionEncoder` (ArduPilot)
### 3.3 Mission-Sync Service
Orchestriert den Ablauf Connect → Verify → Upload → Ready-to-Fly. Erzwingt das Ready-to-Fly-Gate.
### 3.4 Telemetry Service
Abonniert Live-Telemetrie vom FC, liefert normalisierte `TelemetryFrame`-Objekte an die UI. Läuft in einem eigenen **Isolate**, um Kartenrendering nicht zu blockieren.
### 3.5 Drohnen-Profil (Settings)
Enthält u. a.:
- **FC-Typ** — bewusst als explizites Setting im Drohnen-Profil verankert, **nicht** aus dem Transportkanal abgeleitet (siehe Abschnitt 4.3)
- Flugleistungsdaten: min/max Speed, min. Kurvenradius, max. Steig-/Sinkrate, max. Reichweite, max. Flugdauer, Cruise Speed
- Standardprofil: **T1 Ranger** (Heewing)
- Liste mehrerer Profile, aufrufbar über Tap, Teil des Vollbild-Menüs (gemeinsam mit Missionsübersicht, per Tabs umschaltbar)
### 3.6 Waypoint-Liste (UI-Komponente)
- Spalten: **Execute** (Dropdown: —/Loiter/Landing) und **Action**
- Swipe-adjustierbare Wertechips für Alt/Speed/Catch-Radius (vertikal ±10, horizontal ±1, 14px/Step, Achsen-Lock bei 8px)
- Zeilen-Edit-Modus bewusst **entkoppelt** vom Karten-Edit-Modus (siehe Abschnitt 4.4)
- Zeile antippen → Karte zentriert auf diesen Wegpunkt, Liste schließt sich
- Liste zeigt englische Spaltenüberschriften, ausreichend Randabstand zu den Drehrädern
- Automatisches Beenden des Zeilen-Edit-Modus beim Schließen der Liste (Sicherung gegen inkonsistenten Zustand)
### 3.7 Flugpfad-Darstellung
- Kein einfacher Spline durch alle Punkte, sondern physikalisch fundierte Geometrie: **Geradenstücke + tangentiale Kreisbögen (Fillets)** pro Kursänderung, abgeleitet aus Geschwindigkeit + max. Schräglage (25°)
- Machbarkeitsprüfung kombiniert Tangentenlänge der Kurve mit dem Fangradius (60 m): überschreitet die Tangentenlänge den Fangradius, wird der Turn rot markiert
- Höhenprofil-Anzeige in der unteren Leiste
### 3.8 Wind-System
- `buildCombinedWindLevels()` — vereint Druckflächendaten und feste Nabenhöhen (10/80/120/180 m AGL, in ASL umgerechnet) als Stützpunkte für Interpolation
- `windUrlsFor()` — baut zwei getrennte, fokussierte Open-Meteo-Requests
- Alle drei Konsumenten (Header, Waypoints, Validierungspanel) nutzen denselben Mechanismus
- Böen (`wind_gusts_10m`) nur im Validierungspanel, nicht in der Wegpunktanzeige
### 3.9 Terrain-System
- Distanzbasierte Sampling-Strategie: alle 30 m (`TERRAIN_SAMPLE_SPACING`), min. 10 / max. 2000 Samples (`TERRAIN_MAX_SAMPLES`)
- Einzelpunkt-Höhenabfrage (`fetchElevationAt`) für Point-and-Fly-Kollisionsprüfung
- Datenquelle: AWS Terrarium Tiles
### 3.10 Point-and-Fly (PnF) Modus
- Zentrales Fadenkreuz (amber) auf dem Bildschirm
- Setzt transienten Einzel-Wegpunkt (Loiter-Aktion) mit aktuellen Radwerten für Alt/Speed
- Terrain-Kollisionsprüfung: mind. 60 m Bodenabstand, referenziert gegen Home-Wegpunkt-Höhe
- Zielpunkt übernimmt beim Setzen die zu diesem Zeitpunkt gültigen Radwerte dauerhaft (ändert sich nicht rückwirkend)
- Zielpunkt verschwindet beim Moduswechsel oder Verlassen des Fly-Modus
- Zentrale Sichtbarkeitslogik über ein gemeinsames Prädikat (Räder, Fadenkreuz, Readouts konsistent)
### 3.11 Fly-Modus allgemein
- `setFlightMode()` zentralisiert
- Eintritt in Fly-Modus setzt immer auf Standardmodus **Waypoint** zurück
- Verlassen des Fly-Modus klappt Dropdown automatisch ein
- Readouts: drei Zeilen (Titel, SET in Blau, LIVE in Grün)
### 3.12 Branding/Logo
- M-/D-/C-Monogramm-Konstruktion (Drone Mission Command)
- Finale Lösung: vertikal gespiegeltes "C" mit kurzem vertikalem Schließstrich statt verjüngtem "D" — mathematisch als Sonderfall derselben Tangentenkonstruktion bestätigt (Stammlänge 75,2 Einheiten, 92,4 % bilaterale Symmetrie)
---
## 4. Getroffene Design-Entscheidungen inkl. Begründung
| # | Entscheidung | Begründung |
|---|---|---|
| 4.1 | **MVP-Scope: nur Android, nur iNAV via MSP, nur WiFi/TCP** | Reduziert Komplexität für ersten Release; MAVLink, USB-Seriell und iOS werden bewusst zurückgestellt |
| 4.2 | **MSP für iNAV, MAVLink für ArduPilot**, beide hinter `FlightControllerLink` | Jedes Protokoll spricht die native Sprache seines FC; einheitliche Domain-Schicht bleibt protokollunabhängig |
| 4.3 | **FC-Typ als explizites Setting im Drohnen-Profil**, nicht aus Transport abgeleitet | Zukunftssicher: falls iNAV später testweise über MAVLink läuft, bleibt Zuordnung eindeutig steuerbar |
| 4.4 | **Zeilen-Edit-Modus der Wegpunktliste von Karten-Edit-Modus entkoppelt** | Nutzer-Feedback: gekoppeltes Verhalten war unerwartet/unerwünscht — Bearbeiten in der Liste soll nicht automatisch den Karten-Modus verändern |
| 4.5 | **"Ready-to-Fly"-Gate = Upload + Verifiziert + Disarmed** | iNAV/MAVLink erlauben grundsätzlich keinen Missions-Upload im armed-Zustand; das Gate muss dies technisch erzwingen |
| 4.6 | **Physikalisch fundierter Flugpfad (Geraden + Kreisbögen) statt Spline** | Ehrlichere Darstellung dessen, was ein realer Autopilot (ArduPlane/iNAV) tatsächlich fliegt; verhindert falsches Sicherheitsgefühl bei engen Kurven |
| 4.7 | **Tangentenkonstruktion statt frei gezogener Linien beim Logo** | Vermeidet sichtbaren Knick zwischen Gerade und Bogen; mathematisch konsistent mit der ursprünglichen D-Form |
| 4.8 | **Gespiegeltes C statt verjüngtem D als Logo-Grundform** | Wirkt symmetrischer, ist aber dieselbe Konstruktion nur gespiegelt und geschlossen |
| 4.9 | **Böen nur im Validierungspanel, nicht in der Wegpunktanzeige** | 10-m-Böendaten sind auf Flughöhe nicht aussagekräftig |
| 4.10 | **Zwei getrennte Open-Meteo-Requests statt einem kombinierten** | Ein kombinierter 35-Variablen-Request verursachte Modellauswahl-Fehler; auch ein einzelner Request für die Validierung schlug fehl — zwei fokussierte Requests bestätigt als robustes Muster |
| 4.11 | **`typeof x === 'number'`-Guards überall im Wind-Code** | Open-Meteo liefert bei fehlenden Werten `null`, nicht `undefined` — ungeschützter Code führte zu drei aufeinanderfolgenden Rendering-Fehlern |
| 4.12 | **Distanzbasiertes statt festes Terrain-Sampling (30 m Spacing)** | Gleichmäßigere Auflösung unabhängig von der Missionslänge, mit sinnvollen Ober-/Untergrenzen (10–2000 Samples) |
| 4.13 | **Fester Dateiname "Drone Mission Command.html"** | Bewusst beibehalten, um `localStorage`-Daten über Updates hinweg zu erhalten |
| 4.14 | **Klettersteigungsprüfung nutzt geradlinige statt Bogen-Distanz** | Bewusste Vereinfachung; als vernachlässigbar bewertet, aber offen dokumentiert (siehe Abschnitt 6) |
| 4.15 | **Drift statt Hive für Missions-Persistenz (Flutter-Ziel)** | Indexierte Abfragen nötig (Suche nach Name, Ort, Datum); zudem kompatibel mit künftigem local-first Server-Sync-Muster (Dirty-Flags, Server-IDs) |
| 4.16 | **Bloc/Riverpod-Kombination für State-Management (Flutter-Ziel)** | Bloc passt zur expliziten App-Mode-State-Machine (erzwungene Event→State-Struktur, Debug-Tooling); Riverpod ist ergonomischer für viele kleine reaktive Zustände wie Telemetriewerte |
| 4.17 | **`flutter_map` statt `google_maps_flutter` (Flutter-Ziel)** | Freies OSM-Tile-Modell entspricht dem Leaflet-Demonstrator; anderes Lizenz-/API-Modell bei Google Maps unerwünscht; ermöglicht direkte Portierung der Tangenten-Bogen-Geometrie |
| 4.18 | **`flutter_map_tile_caching` (FMTC) für Offline-Kacheln (Flutter-Ziel)** | Automatisches Caching pro Mission, gekeyt über die Bounding-Box der Mission |
| 4.19 | **Eigener MSP-Encoder/Decoder in Dart (Flutter-Ziel)** | Kein fertiges Dart-Paket verfügbar; Struktur bereits aus MSP-Recherche bekannt |
| 4.20 | **Foreground Service (Android) für Telemetrie im Hintergrund (Flutter-Ziel)** | Ohne Foreground Service + Wake Lock würde Android die Verbindung bei App-Wechsel/Display-Sperre kappen |
| 4.21 | **Protokoll-Parsing in eigenem Isolate (Flutter-Ziel)** | Verhindert UI-Ruckeln bei hoher Telemetrie-Rate; Isolates kommunizieren nur über Message-Passing, kein Shared Memory |
| 4.22 | **Mission-Domain-Layer + Protokoll-Adapter als eigenständiges reines Dart-Package (Flutter-Ziel)** | Isoliert unit-testbar ohne Emulator; wiederverwendbar für z. B. CLI-Tools oder Backend-Simulatoren |
| 4.23 | **`go_router` für Navigation (Flutter-Ziel)** | Typisierte Übergänge, passend zum expliziten Mode-Wechsel-Trigger der State-Machine |
| 4.24 | **SSID-Anzeige in den Settings aufgegeben, Verbindungspille zeigt nur generisches "Connected"** | Auf echter Hardware (Pixel-Gerät, Android 16) liefert `NetworkCapabilities.getTransportInfo()` konsequent ein redigiertes `WifiInfo` (SSID `<unknown ssid>`, BSSID maskiert) — bestätigt per natives `Log.d` in `MlrsNetworkPlugin.onAvailable()`/`onCapabilitiesChanged()`, gegengeprüft mit `adb shell dumpsys wifi` (Shell-Kontext kennt und ordnet die echte SSID korrekt der App zu, das App-API liefert sie aber nicht). Die im Code angenommene "Ausnahme für selbst angefragte `WifiNetworkSpecifier`-Netze ohne `ACCESS_FINE_LOCATION`" gilt offenbar nur für `WifiManager.getConnectionInfo()`, nicht für diesen `NetworkCapabilities`-Weg über `ConnectivityManager.NetworkCallback`. Statt `ACCESS_FINE_LOCATION` (inkl. Laufzeit-Prompt) nur für diese kosmetische Anzeige hinzuzufügen, hat der Nutzer sich bewusst dagegen entschieden — die zugrundeliegende SSID-Merk-Logik (`UdpTransport.connectedSsid`/`_rememberSsid`, `preferredSsid` für stilles Reconnect) bleibt bestehen, liefert im Regelfall aber `null`/keinen Effekt |
| 4.25 | **Homepoint-Abfrage (`MSP_WP`/0x76, WP#0) gezielt statt kontinuierlich, nur bei Connect/GPS-Fix/Armen** | `getWaypoint()` in `navigation.c` liefert für WP#0 den Homepoint (`GPS_home.lat/lon/alt`), aber (0,0,0) statt eines Fehlers, solange `STATE(GPS_FIX_HOME)` nicht gesetzt ist — als "kein Homepoint" behandelt (`parseMspHomePoint`). Der FC selbst friert den Homepoint nicht beim ersten GPS-Fix ein, sondern lässt ihn der Drohne folgen, solange sie disarmed ist und noch nie armed war (`updateHomePosition()`), und sperrt ihn erst beim ersten Armen (iNAV-Default `reset_home_type = FIRST_ARM`, `settings.yaml`) — kontinuierliches Polling wäre also die meiste Zeit sinnlos; `home_point_provider.dart` fragt stattdessen gezielt bei genau diesen drei Momenten neu ab |
---
## 5. Verworfene Alternativen
| Verworfene Option | Warum nicht gewählt |
|---|---|
| **Spline/Glättungskurve durch alle Wegpunkte** | Suggeriert unrealistische Kurvenradien; ersetzt durch Geraden+Kreisbögen-Modell (4.6) |
| **Freie Linienführung beim Logo (statt Tangentenkonstruktion)** | Hätte sichtbaren Knick zwischen Gerade und Bogen erzeugt |
| **Verjüngtes "D" als finale Logoform** | Wirkte weniger symmetrisch als gespiegeltes/geschlossenes "C" (Farbschwerpunkt-Analyse: −27,2 → −22,7 Einheiten Verbesserung) |
| **Kombinierter 35-Variablen-Wetter-Request** | Verursachte Modellauswahl-Fehler bei Open-Meteo |
| **Einzelner Request für das Wind-Validierungspanel** | Ebenfalls fehlgeschlagen; bestätigte die Notwendigkeit des Zwei-Request-Musters |
| **Gekoppelter Zeilen-/Karten-Edit-Modus** | Erste Implementierung koppelte beide Modi; nach Nutzer-Feedback explizit wieder entkoppelt |
| **Böen-Anzeige auch in der Wegpunktliste** | Als nicht aussagekräftig auf Flughöhe verworfen, in Validierungspanel belassen |
| **`dart_mavlink`-Community-Paket unkritisch übernehmen** | Nicht offiziell gelistet, wirkt wenig gepflegt — Alternative (eigener Generator aus MAVLink-XML) als Option offengehalten, aber noch nicht entschieden |
| **Feste Anzahl Terrain-Samples (z. B. 50)** | Ungleichmäßige Auflösung je nach Missionslänge; durch distanzbasiertes Sampling ersetzt |
| **USB-Seriell als Transportkanal (aktuell)** | Auf iOS ohne MFi-Zertifizierung praktisch nicht machbar; für aktuellen WiFi-Bridge-Plan nicht kritisch, aber als Plattformrisiko vermerkt, falls später gewünscht |
| **Auto-Erkennung des FC-Typs aus der Transportverbindung** | Weniger robust/eindeutig als explizites Profil-Setting (4.3) |
| **Hive für Missions-Persistenz (ursprünglich vorgeschlagen)** | Ausreichend für aktuellen Funktionsumfang, aber keine indexierten Abfragen — zugunsten von Drift verworfen, sobald Suche/Sync-Anforderungen klar wurden |
---
## 6. Offene Fragen / TODOs
- **Klettersteigungsprüfung gegen tatsächliche Bogenlänge statt Geradenverbindung berechnen** — aktuell bewusste Vereinfachung, könnte bei engen Kombinationen aus Höhenänderung und scharfer Kurve leicht zu optimistisch sein.
- **iNAV-10-Änderungen an Mission-/Wegpunktsystem** — zum Recherchezeitpunkt keine bestätigten grundlegenden Änderungen gegenüber v9 gefunden; Release-Termin (evtl. Ende 2026) und Feature-Freeze noch offen, vor App-Release erneut prüfen.
- **Experimenteller iNAV-Community-Branch für Wegpunkt-Upload im Flug (bei nicht aktivem NAV-WP-Modus)** — Status unklar, ob in einen stabilen Release gewandert; vor Release gegen aktuelle 9.x-Firmware verifizieren, nicht darauf verlassen.
- **`MSP2_INAV_WIND` (0x2231) für geschätzte Windstärke/-richtung im Drone Status** — vom iNAV-Windschätzer (`flight/wind_estimator.c`, GPS-basiert, kein Pitot nötig) berechnet, aber bis 9.1.0 nur ins OSD gerendert, nicht per MSP abrufbar. Command wurde erst kürzlich auf dem Branch `release/9.1` hinzugefügt (Commit "feat(msp): add MSP2_INAV_WIND (0x2231) to expose wind estimator", Bugfix in PR iNavFlight/inav#11762, gemerged 2026-08-03) — bislang in **keinem** getaggten Release (weder 9.1.0 noch `master`) enthalten, T1 Ranger müsste also erst auf eine Firmware ab diesem Commit geflasht werden. Response-Payload laut `fc_msp.c`: `u16 windSpeed` (cm/s, horizontal), `u16 windAngle` (Grad, 0–359, Earth-Frame), `u8 windFlags` (1 = Schätzung gültig). Vor Umsetzung erneut prüfen, ob der Command in einem stabilen Release gelandet ist.
- **`MSP2_INAV_GEOZONE`/`_SET_GEOZONE` + `_GEOZONE_VERTEX`/`_SET_GEOZONE_VERTEX`** (`0x2210`–`0x2213`) für Geofencing — bisher ungenutzt, aber vermutlich das interessanteste noch nicht angebundene MSP-Feature für DMC. Indexbasiert abgefragt (`mspFcGeozoneOutCommand`/`mspFcGeozoneVerteciesOutCommand` in `fc_msp.c`): pro Zone (Request-Byte = Zonenindex) `u8 type` (Inclusion/Exclusion), `u8 shape` (Kreis/Polygon), `u32 minAltitude`, `u32 maxAltitude`, `u8 isSealevelRef`, `u8 fenceAction` (`NONE`/`AVOID`/`POS_HOLD`/`RTH`, siehe `settings.yaml` Table `fence_action`), `u8 vertexCount`; Vertices einzeln per `(zoneId, vertexId)` nachladbar (`u32 lat`, `u32 lon`, bei Kreisform zusätzlich ein Radius-Vertex). Könnte analog zur bestehenden Flugpfad-Machbarkeitsprüfung (`domain/mission/mission_warnings.dart`) als Warnung genutzt werden, wenn eine geplante Route eine auf der Drohne konfigurierte No-Fly-Zone kreuzt.
- **`MSP2_INAV_SAFEHOME`/`_SET_SAFEHOME`** (`0x2038`/`0x2039`) für alternative RTH-Landepunkte — bisher ungenutzt. Indexbasiert (ein Request pro Slot, bis `MAX_SAFE_HOMES`): `u8 enabled`, `u32 lat`, `u32 lon`. Könnte eine "Backup-Landepunkte verwalten"-Ansicht ermöglichen, eigener UI-Scope (Liste/Editor), nicht MVP-kritisch.
- **`MSP2_INAV_BATTERY_CONFIG`** (`0x2005`, alternativ als Teilmenge von `MSPV2_INAV_MISC`/`0x2003`) für die auf dem FC hinterlegte Batteriekonfiguration — bisher ungenutzt. Liefert `u8 cells` sowie `u16 cellDetect`/`cellMin`/`cellMax`/`cellWarning` (je 0.01V/Zelle, `fc_msp.c` `case MSP2_INAV_BATTERY_CONFIG`, Felder verifiziert gegen `settings.yaml`: `vbat_cell_detect_voltage`/`vbat_max_cell_voltage`/`vbat_min_cell_voltage`/`vbat_warning_cell_voltage`). Könnte künftig `DroneProfile.batteryCellCount`/die Pro-Zelle-Schwellwerte mit der tatsächlichen FC-Konfiguration abgleichen oder daraus vorbefüllen, statt sie nur manuell im Profil-Editor zu pflegen.
- **`MSPV2_INAV_AIR_SPEED`** (`0x2009`) für echte Fahrt durch die Luft (Pitot) — liefert `u32 getAirspeedEstimate()`, ohne `USE_PITOT`-Sensor konstant `0`. Für den T1 Ranger aktuell nicht relevant (kein Pitot-Rohr vorgesehen); bei künftigem Pitot-Ausbau erneut prüfen.
- **`MSP2_INAV_TEMPERATURES`** (`0x201E`) für Temperatursensor-Werte — Array von bis zu `MAX_TEMP_SENSORS` `i16`-Werten (`-1000` = ungültig), braucht konfigurierte Temp-Sensoren (`USE_TEMPERATURE_SENSOR`). Im aktuellen T1-Ranger-Aufbau keine physischen Temp-Sensoren vorgesehen, daher niedrige Priorität.
- **Bit-Layout von `sensorStatus`/`armingFlags`/`boxModeFlags`** (Teil der bereits genutzten `MSP2_INAV_STATUS`, `0x2000`) — vollständig dokumentiert direkt im Code, siehe Doc-Kommentare zu `MspCommands.inavStatus` und `MspArmingFlags` in [msp_commands.dart](app/lib/transport/msp/msp_commands.dart), um Drift zwischen Architektur-Doku und Code zu vermeiden. Insbesondere `boxModeFlags` ist dort ausführlich erklärt: die Bit-Position ist NICHT fest, sondern muss einmalig über `MSP_BOXIDS` (ID 119) mit der jeweiligen Firmware-Konfiguration korreliert werden.
- **`dart_mavlink`-Paket vs. eigener Generator aus MAVLink-XML-Dialektdateien** — Entscheidung für die MAVLink-Anbindung (nicht MVP-kritisch, aber für spätere ArduPilot-Unterstützung relevant) noch offen.
- **XR1-Empfänger-Kompatibilität mit mLRS** — XR4 ist vom mLRS-Team offiziell validiert, XR1 nur wahrscheinlich kompatibel (über generisches Firmware-Target), nicht bestätigt.
- **iOS-Hintergrundverbindung** — Konzept (Background Modes / "voip"/"location"-Capability) benannt, aber nicht MVP-relevant (MVP ist Android-only) und nicht im Detail ausgearbeitet.
- **USB-Seriell als späterer Fallback-Transportkanal** — Plattformrisiko (iOS ohne MFi quasi unmöglich) früh klären, falls dies später doch gewünscht wird.
- **Melos-Monorepo vs. Einzelpaket-Struktur** — konkreter Ordner-/Package-Vorschlag für das Flutter-Projekt wurde als nächster Schritt vorgeschlagen, aber noch nicht ausgearbeitet.
- **`SurveyAreaMission` und `SearchAreaMission`** — als Missionstypen im Strategy-Pattern vorgesehen, aber inhaltlich noch nicht spezifiziert oder implementiert.
- **Winkelannahmen der Flugpfad-Machbarkeitsprüfung (25° Schräglage, 20° Steigwinkel)** — zur Diskussion gestellt, ob diese Werte angepasst werden sollen; keine endgültige Entscheidung dokumentiert.
- **Migration vom HTML-Demonstrator zur Flutter-App** — Reihenfolge/Umfang der Portierung (z. B. wann welches Feature 1:1 übernommen wird) ist nicht Schritt-für-Schritt festgelegt.
---
## 7. Umfangreiche Feature-Liste
### 7.1 Missionsplanung
- Wegpunkt-Missionen (Track-Missionen) auf OSM-Kartenbasis (Leaflet.js im Demonstrator)
- Wegpunkt hinzufügen/verschieben/löschen direkt auf der Karte
- Wegpunktliste mit swipe-adjustierbaren Werten für Höhe, Geschwindigkeit, Fangradius (Catch-Radius)
- Execute-Aktion pro Wegpunkt: —, Loiter, Landing
- Zeilen-Edit-Modus unabhängig vom Karten-Edit-Modus
- Tippen auf Listenzeile zentriert Karte auf diesen Wegpunkt
- Automatisches Schließen des Edit-Modus beim Schließen der Liste
- Höhenprofil-Anzeige der gesamten Wegpunktliste in der unteren Leiste
- Physikalisch realistische Flugpfad-Darstellung (Geraden + Kreisbögen statt Spline)
- Farbliche Markierung nicht machbarer Kurven (Tangentenlänge > Fangradius)
- Klettersteigungs-/Sinkraten-Prüfung pro Streckenabschnitt
- JUMP-Wegpunkt-Unterstützung für Patrouillen-/Loop-Missionen (iNAV Action-Code 6, mit Wiederholzähler inkl. Endlos-Option)
- Mehrfach-Missionsverwaltung (bis zu 9 Missionen im FC speicherbar, iNAV-seitig)
- Aktiven Wegpunkt live aus FC auslesen und in der Liste hervorheben (`MSP_NAV_STATUS`/`wp_number`)
- Adressensuche/Geocoding (Nominatim)
- Terrainprofil entlang der Mission (AWS Terrarium Tiles, distanzbasiertes Sampling)
### 7.2 Flugbetrieb (Fly-Modus)
- Umschaltbare Flugmodi: Waypoint, Point-and-Fly, weitere abstrahiert über `MISSION_RUN`/`GUIDED_POINT`/`RETURN_HOME`/`HOLD`
- Standard-Rückstellung auf Waypoint-Modus beim Eintritt in Fly-Modus
- Live-Telemetrie-Anzeige (SET- vs. LIVE-Werte für Höhe/Geschwindigkeit)
- Drehräder (Wheels) zur Live-Anpassung von Soll-Höhe/-Geschwindigkeit
- Point-and-Fly: zentrales Fadenkreuz, Einzelziel setzen ohne bestehende Mission zu verändern
- Terrain-Kollisionsprüfung bei PnF (Mindestabstand 60 m über Grund)
- Persistente Zielpunkt-Beschriftung mit zum Setzzeitpunkt gültigen Werten
- Wind-Anzeige nach Höhe interpoliert (10/80/120/180 m AGL + Druckflächendaten)
- Wind-Validierungspanel mit Böen-Anzeige
- Home-Button (zentriert an der oberen Bildschirmkante)
- Maximieren-Button mit Mindestabstand zu den Drehrädern
### 7.3 Drohnen-Profile
- Mehrere Drohnenprofile verwaltbar, Standardprofil T1 Ranger
- Profilliste als Tab im Vollbild-Menü (gemeinsam mit Missionsübersicht)
- Profildaten: min/max Speed, min. Kurvenradius, max. Steig-/Sinkrate, max. Reichweite, max. Flugdauer, Cruise Speed
- FC-Typ als explizites Profil-Setting (MSP/MAVLink)
### 7.4 Konnektivität (geplant/MVP)
- WiFi/TCP-Verbindung zum Flightcontroller (DroneBridge, mLRS-WiFi-Bridge)
- MSP-Protokoll nativ für iNAV
- MAVLink-Protokoll für ArduPilot (Post-MVP)
- Feature-Capability-Abfrage je FC (`FcCapabilities`: Multi-Mission, In-Flight-Upload, max. Wegpunkte)
- Ready-to-Fly-Gate mit Upload-/Verifikations-/Arm-Status
### 7.5 Persistenz & Datenhaltung
- Lokale Speicherung von Missionen, Profilen, Einstellungen
- Autosave/Mission-Drafts
- Suche nach Missionen nach Name, Ort, Datum (Flutter-Ziel, Drift)
- Vorbereitung für lokal-first Server-Sync (Dirty-Flags, Server-IDs)
### 7.6 Branding/Visuelles Design
- Eigenes Monogramm-Logo (M/D/C-Konstruktion, gespiegeltes C mit Schließstrich)
- Konsistentes Farbschema für SET/LIVE-Anzeigen (Blau/Grün)
- Einheitliche Chip-Optik für swipe-adjustierbare Werte und Execute-Dropdown
### 7.7 Nicht-funktionale Eigenschaften
- Android-Landscape-Ausrichtung (MVP)
- Offline-Kartenkachel-Caching pro Mission (Flutter-Ziel)
- Hintergrund-Telemetrie ohne Verbindungsabbruch bei App-Wechsel (Flutter-Ziel)
- Testbarkeit ohne physische Hardware via Mock-FC-Link
- Reine, UI-unabhängige Testbarkeit der Mission-Domain-Logik (separates Dart-Package, Flutter-Ziel)
---
## 8. Technologie-Stack im Überblick
| Bereich | Demonstrator (HTML/JS) | Flutter-Ziel |
|---|---|---|
| Karten | Leaflet.js + OSM-Tiles | `flutter_map` + `flutter_map_tile_caching` |
| Wind | Open-Meteo API | Open-Meteo API |
| Geocoding | Nominatim | Nominatim |
| Terrain | AWS Terrarium Tiles | AWS Terrarium Tiles |
| Persistenz | `localStorage` | Drift (SQLite) |
| State-Management | (imperativ, Vanilla JS) | Bloc + Riverpod (kombiniert) |
| MSP-Protokoll | eigene JS-Implementierung | eigene Dart-Implementierung |
| MAVLink | — (nicht MVP) | `dart_mavlink` (Risiko prüfen) oder eigener Generator |
| Hintergrundbetrieb | — | `flutter_foreground_task` (Android) |
| Navigation | — | `go_router` |
| Nebenläufigkeit | — | Dart Isolates für Protokoll-Parsing |
---
*Dieses Dokument fasst den Stand der bisherigen Projektkonversationen zusammen. Es wird empfohlen, es bei künftigen Architekturentscheidungen fortzuschreiben.*