Point the fly-mode rubber band at home during Return-to-Home

iNAV freezes activeWaypointIndex at whatever mission waypoint was
active when RTH engaged instead of updating it to reflect the new
target - navigation.c derives NAV_Status.activeWpIndex unconditionally
from posControl.activeWaypointIndex, and none of the RTH state-entry
handlers touch that field. Drawing the guidance line to that stale
index would point at a waypoint the aircraft may have already passed.

Extracted the target selection into computeRubberBandTarget() (mission
stats.dart) so the RTH special-case and the abort-back-to-waypoint-mode
fallback are unit-tested rather than only living inline in the widget
build method - since it re-evaluates navMode on every frame, aborting
RTH switches the line back to the mission waypoint with no extra
transition logic needed.
This commit is contained in:
Constantin Leue
2026-08-09 21:31:00 +02:00
parent fdefa3e257
commit afc380cabc
3 changed files with 131 additions and 14 deletions
+38
View File
@@ -98,3 +98,41 @@ FlyMissionStatus? computeFlyMissionStatus({
etaToActiveWaypointSec: eta,
);
}
/// `MW_GPS_MODE_RTH` (siehe MspNavMode._modeNames in msp_telemetry_codec.dart).
const navModeReturnToHome = 2;
/// Ziel des Gummiband-Pfeils von der Drohne zum aktuellen Flugziel im
/// Fly-Modus (Doku: MissionMap.rubberBandLine) - normalerweise der aktive
/// Missionswegpunkt, waehrend Return-to-Home ([navModeReturnToHome])
/// stattdessen [homePoint].
///
/// iNAV friert `activeWaypointIndex` beim RTH-Eintritt auf dem zuletzt
/// aktiven Missionswegpunkt ein, statt ihn auf den Homepoint zu setzen
/// (`navigation.c`: `NAV_Status.activeWpIndex` wird unbedingt aus
/// `posControl.activeWaypointIndex` abgeleitet, keiner der
/// `navOnEnteringState_NAV_STATE_RTH_*`-Handler fasst diesen Wert an) - ein
/// Gummiband zu diesem (ggf. laengst passierten) Wegpunkt waere im RTH-Fall
/// irrefuehrend. Da [navMode] bei jedem neuen Telemetrie-Frame neu geprueft
/// wird, schaltet ein Abbruch von RTH zurueck in den Wegpunktmodus das
/// Ergebnis von selbst wieder auf den Missionswegpunkt zurueck.
///
/// Liefert null, wenn kein sinnvolles Ziel bekannt ist (RTH ohne bereits
/// abgefragten Homepoint, oder [activeWaypointIndex] ausserhalb der Liste).
LatLng? computeRubberBandTarget({
required int navMode,
required int? activeWaypointIndex,
required List<Waypoint> waypoints,
LatLng? homePoint,
}) {
if (navMode == navModeReturnToHome) {
return homePoint;
}
if (activeWaypointIndex == null ||
activeWaypointIndex < 0 ||
activeWaypointIndex >= waypoints.length) {
return null;
}
final target = waypoints[activeWaypointIndex];
return LatLng(target.lat, target.lon);
}