live mission details in footer implemented
This commit is contained in:
@@ -1,11 +1,31 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import '../../domain/waypoint/flat_waypoint_list.dart';
|
||||
import '../flight_controller_link.dart';
|
||||
|
||||
/// Synthetische Telemetrie fuer UI-Entwicklung/Tests ohne Hardware oder SITL
|
||||
/// (Architektur-Doku 3.1).
|
||||
///
|
||||
/// Verankert am ersten Wegpunkt der uebergebenen Mission (Doku: "solange die
|
||||
/// Drohne nicht verbunden ist, Mock-Daten fuer die neue Live-Details-
|
||||
/// Ansicht nutzbar machen") statt an einem fest verdrahteten Ort (frueher
|
||||
/// Berlin) - dadurch liegt die simulierte Position tatsaechlich auf der
|
||||
/// gerade bearbeiteten Route, und activeWaypointIndex ist von Anfang an
|
||||
/// gesetzt (0, "erster Wegpunkt aktiv"), auch ohne den noch nicht
|
||||
/// umgesetzten Missions-Upload-Flow. Fehlt eine Mission (keine Wegpunkte),
|
||||
/// bleibt der alte Berlin-Fallback bestehen, damit die Klasse auch ganz
|
||||
/// ohne Mission nutzbar ist.
|
||||
class MockFlightControllerLink implements FlightControllerLink {
|
||||
MockFlightControllerLink({List<Waypoint> initialWaypoints = const []})
|
||||
: _anchorLat = initialWaypoints.isEmpty ? 52.5 : initialWaypoints.first.lat,
|
||||
_anchorLon = initialWaypoints.isEmpty ? 13.4 : initialWaypoints.first.lon,
|
||||
_activeWaypointIndex = initialWaypoints.isEmpty ? null : 0;
|
||||
|
||||
final double _anchorLat;
|
||||
final double _anchorLon;
|
||||
final _random = math.Random();
|
||||
|
||||
bool _armed = false;
|
||||
int? _activeWaypointIndex;
|
||||
StreamController<TelemetryFrame>? _telemetryController;
|
||||
@@ -13,6 +33,16 @@ class MockFlightControllerLink implements FlightControllerLink {
|
||||
double _heading = 0;
|
||||
double _batteryPercent = 100;
|
||||
|
||||
/// Aktuelle Drift vom Ankerpunkt in Metern (Nord/Ost) - Zufalls-Trudeln
|
||||
/// innerhalb eines 10-m-Radius statt eines fest stehenden Punkts, damit
|
||||
/// auch die Distanz/ETA-Anzeige der neuen Details-Pille sichtbar auf
|
||||
/// Werteaenderungen reagiert (Doku 9: UI-Entwicklung ohne Hardware).
|
||||
double _driftNorthM = 0;
|
||||
double _driftEastM = 0;
|
||||
static const _driftRadiusM = 10.0;
|
||||
static const _driftStepM = 1.5;
|
||||
static const _metersPerDegreeLat = 111320.0;
|
||||
|
||||
@override
|
||||
FcCapabilities get capabilities => const FcCapabilities(
|
||||
supportsMultiMission: true,
|
||||
@@ -37,9 +67,27 @@ class MockFlightControllerLink implements FlightControllerLink {
|
||||
// Langsam sinkender Akkustand, damit die Anzeige auch ohne Hardware
|
||||
// sichtbar auf Werteaenderungen reagiert (Doku 9).
|
||||
_batteryPercent = (_batteryPercent - 0.1).clamp(0, 100);
|
||||
|
||||
// Zufallsschritt, danach auf den 10-m-Radius um den Ankerpunkt
|
||||
// zurueckgeklemmt statt frei wegzulaufen.
|
||||
_driftNorthM += (_random.nextDouble() - 0.5) * 2 * _driftStepM;
|
||||
_driftEastM += (_random.nextDouble() - 0.5) * 2 * _driftStepM;
|
||||
final driftMagnitude = math.sqrt(
|
||||
_driftNorthM * _driftNorthM + _driftEastM * _driftEastM,
|
||||
);
|
||||
if (driftMagnitude > _driftRadiusM) {
|
||||
final scale = _driftRadiusM / driftMagnitude;
|
||||
_driftNorthM *= scale;
|
||||
_driftEastM *= scale;
|
||||
}
|
||||
final metersPerDegreeLon =
|
||||
_metersPerDegreeLat * math.cos(_anchorLat * math.pi / 180);
|
||||
final lat = _anchorLat + _driftNorthM / _metersPerDegreeLat;
|
||||
final lon = _anchorLon + _driftEastM / metersPerDegreeLon;
|
||||
|
||||
_telemetryController?.add(TelemetryFrame(
|
||||
lat: 52.5,
|
||||
lon: 13.4,
|
||||
lat: lat,
|
||||
lon: lon,
|
||||
hasFix: true,
|
||||
numSat: 12,
|
||||
altitudeM: 120,
|
||||
|
||||
Reference in New Issue
Block a user