101 lines
3.7 KiB
Dart
101 lines
3.7 KiB
Dart
import 'package:latlong2/latlong.dart';
|
|
|
|
import '../waypoint/flat_waypoint_list.dart';
|
|
|
|
const _distance = Distance(roundResult: false);
|
|
|
|
/// Gesamtdistanz/-dauer einer Mission (HTML-Demonstrator: computeStats()).
|
|
class MissionStats {
|
|
const MissionStats({required this.distanceM, required this.durationSec});
|
|
|
|
final double distanceM;
|
|
final double durationSec;
|
|
}
|
|
|
|
/// Geteilt zwischen Plan- und Fly-Modus sowie der Warnungsberechnung (Doku
|
|
/// 3.9/3.10), die dieselben Werte fuer Zeit-/Reichweiten-Warnungen braucht.
|
|
MissionStats computeMissionStats(List<Waypoint> waypoints) {
|
|
var totalDist = 0.0;
|
|
var totalDur = 0.0;
|
|
for (var i = 0; i < waypoints.length - 1; i++) {
|
|
final a = LatLng(waypoints[i].lat, waypoints[i].lon);
|
|
final b = LatLng(waypoints[i + 1].lat, waypoints[i + 1].lon);
|
|
final d = _distance(a, b);
|
|
totalDist += d;
|
|
totalDur += d / waypoints[i + 1].speedMs;
|
|
}
|
|
return MissionStats(distanceM: totalDist, durationSec: totalDur);
|
|
}
|
|
|
|
/// Live-Missionsstatus im Fly-Modus fuer die Details-Pille (Doku: "aktiver
|
|
/// Wegpunkt (z.B. 3/23), Distanz und Zeit zum naechsten Wegpunkt" statt der
|
|
/// statischen Plan-Werte). MSP liefert das nicht direkt - `MSP_COMP_GPS`
|
|
/// gibt nur Distanz/Richtung zum HOME-Punkt (`GPS_distanceToHome`/
|
|
/// `GPS_directionToHome`, iNAV `fc_msp.c`), und obwohl iNAV intern fuer sein
|
|
/// eigenes OSD bereits eine Distanz zum aktiven Wegpunkt berechnet
|
|
/// (`posControl.wpDistance`/`posControl.activeWaypointIndex`/
|
|
/// `posControl.geoWaypointCount` in `navigation.c`/`osd.c`, Format dort
|
|
/// exakt "TO WP %u/%u (%s)"), ist das ueber keine MSP-Nachricht abrufbar -
|
|
/// deshalb hier aus der aktuellen Position + den ohnehin bekannten
|
|
/// Wegpunktkoordinaten selbst berechnet.
|
|
class FlyMissionStatus {
|
|
const FlyMissionStatus({
|
|
required this.activeWaypointNumber,
|
|
required this.waypointCount,
|
|
this.distanceToActiveWaypointM,
|
|
this.etaToActiveWaypointSec,
|
|
});
|
|
|
|
/// 1-basiert fuer die Anzeige ("3/23"), waehrend der uebergebene
|
|
/// activeWaypointIndex-Parameter (TelemetryFrame.activeWaypointIndex)
|
|
/// intern 0-basiert ist.
|
|
final int activeWaypointNumber;
|
|
final int waypointCount;
|
|
|
|
/// Null, solange keine gueltige Position bekannt ist (kein GPS-Fix).
|
|
final double? distanceToActiveWaypointM;
|
|
|
|
/// Null, solange keine Distanz oder keine hinreichende Geschwindigkeit
|
|
/// bekannt ist (Division durch (nahe) Null wuerde sonst eine bedeutungs-
|
|
/// lose Restzeit vortaeuschen).
|
|
final double? etaToActiveWaypointSec;
|
|
}
|
|
|
|
/// Vergleiche Klassendoku [FlyMissionStatus]. Liefert null, solange keine
|
|
/// Mission aktiv ist oder [activeWaypointIndex] (0-basiert) ausserhalb der
|
|
/// Wegpunktliste liegt (z.B. kurz nach Missionsende).
|
|
FlyMissionStatus? computeFlyMissionStatus({
|
|
required List<Waypoint> waypoints,
|
|
required int? activeWaypointIndex,
|
|
double? currentLat,
|
|
double? currentLon,
|
|
double? currentSpeedMs,
|
|
}) {
|
|
if (activeWaypointIndex == null ||
|
|
activeWaypointIndex < 0 ||
|
|
activeWaypointIndex >= waypoints.length) {
|
|
return null;
|
|
}
|
|
final target = waypoints[activeWaypointIndex];
|
|
|
|
double? distance;
|
|
if (currentLat != null && currentLon != null) {
|
|
distance = _distance(LatLng(currentLat, currentLon), LatLng(target.lat, target.lon));
|
|
}
|
|
|
|
double? eta;
|
|
// Unter 0.5 m/s waere eine aus der Distanz hochgerechnete Restzeit nur
|
|
// Sekunden bis Minuten vor einer erfundenen "fast unendlich" Anzeige -
|
|
// dann lieber "-" zeigen (siehe UI) statt eines irrefuehrenden Werts.
|
|
if (distance != null && currentSpeedMs != null && currentSpeedMs > 0.5) {
|
|
eta = distance / currentSpeedMs;
|
|
}
|
|
|
|
return FlyMissionStatus(
|
|
activeWaypointNumber: activeWaypointIndex + 1,
|
|
waypointCount: waypoints.length,
|
|
distanceToActiveWaypointM: distance,
|
|
etaToActiveWaypointSec: eta,
|
|
);
|
|
}
|