On the Mavic Pro in the simulator a waypoint mission failed with "Execution of this process has timed out". The bridge now resends a timed-out upload with retryUploadMission (up to 3 times) and only reports the upload done once the operator is READY_TO_EXECUTE, and the error now says whether the upload or the start failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
49 lines
2.2 KiB
Dart
49 lines
2.2 KiB
Dart
import 'dart:math' as math;
|
||
|
||
import 'package:flutter/material.dart';
|
||
|
||
import '../../../../fly/hud_geometry.dart';
|
||
import '../../../../fly/modes/waypoint_mission.dart';
|
||
import '../../../../fly/safety_gate.dart';
|
||
import '../../dialogs/slide_to_confirm.dart';
|
||
|
||
/// Starts a waypoint mission the GO 4 way (plan P7): the pre-start check —
|
||
/// the [SafetyGate]'s mission checks against the aircraft's limits, the RTH
|
||
/// altitude, the route summary — then slide to start. The gate re-checks,
|
||
/// uploads (the run panel shows the progress) and starts.
|
||
Future<void> startWaypointFlow(
|
||
BuildContext context, {
|
||
required SafetyGate gate,
|
||
required WaypointMissionSpec spec,
|
||
required void Function(String label, Object error) onError,
|
||
}) async {
|
||
final MissionLimits limits = await gate.missionLimits();
|
||
if (!context.mounted) return;
|
||
final List<GateCheck> checks = gate.checkWaypointStart(spec, limits);
|
||
final double top = spec.points.fold(0.0, (double h, WaypointSpec p) => math.max(h, p.altitude));
|
||
final int rth = (gate.model.aircraft.goHomeHeight ?? 60).round().clamp(SafetyGate.minRthHeight, SafetyGate.maxRthHeight);
|
||
final String length = spec.length >= 1000 ? '${(spec.length / 1000).toStringAsFixed(2)} km' : '${spec.length.round()} m';
|
||
|
||
final SlideResult? r = await showSlideToConfirm(
|
||
context,
|
||
SlideConfirmSpec(
|
||
icon: 'route',
|
||
title: 'Start "${spec.name}"',
|
||
description: '${spec.points.length} waypoints · $length · about ${formatDuration(spec.estimatedSeconds)}'
|
||
'${spec.repeatTimes > 1 ? ' · ${spec.repeatTimes}×' : ''}. '
|
||
'Highest waypoint ${top.round()} m. When finished: ${spec.finishAction.label.toLowerCase()}. '
|
||
'Pause or Stop at any time, or press the remote\'s pause button.',
|
||
sliderLabel: 'Slide to start',
|
||
checks: checks,
|
||
number: SlideNumber(label: 'RTH altitude', initial: rth, min: SafetyGate.minRthHeight, max: SafetyGate.maxRthHeight),
|
||
),
|
||
);
|
||
if (r == null) return;
|
||
bool uploaded = false;
|
||
try {
|
||
await gate.startWaypointMission(spec, limits: limits, rthHeight: r.number, onUploaded: () => uploaded = true);
|
||
} catch (e) {
|
||
onError(uploaded ? 'Waypoint start' : 'Waypoint upload', e);
|
||
}
|
||
}
|