Give the Fly App GO 4-style obstacle radar, on-screen sticks, AirSense and fly zones

Vision radar: graded obstacle sectors around the centre of the video,
the nearest distance per side, the obstacle overhead, and BLOCKED on a
side whose sensors cannot see once the motors run. On aircraft with 360°
sensing, sides without their own readings are filled from the
perception ring. The same sectors sit on the attitude ball's rim, turned
by the heading. Settings > Vision gains Display radar chart and the
braking / sensing distances per direction.

On-screen sticks: the rail's STICKS button hands the aircraft to two
stick pads after a slide-to-confirm. The 25 Hz stream runs natively and
sends zeros once Dart's last command is 300 ms old, so a stalled UI
leaves the aircraft hovering. The sticks close when the remote takes
over, on RTH or on landing. They are simulator-only on aircraft with a
remote unless Settings > General > Developer allows real flights; Spark
and Mavic Air on Wi-Fi may fly them for real. Which MSDK axis is forward
in velocity + body mode is coded from DJI's documentation and must be
checked in the simulator first.

AirSense: a banner for manned aircraft at warning level 2 and up, with
distance, direction and ICAO code; the planes on the map; the full list
in a sheet and Settings > Safety; and the aircraft's own avoidance
action with its countdown.

Fly zones: DJI GEO zones around the aircraft (or the phone) on the map
with their height limits, a banner for FlySafe notices and in/near-zone
states, take-off refused in restricted and locked authorization zones,
self-unlock of authorization zones, the aircraft's licences (enable,
sync from the DJI account, remove all; ground only), and the GEO
database version with an update button.

Tested with unit and widget tests and screenshot renders only; nothing
has run on an aircraft or the simulator yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
tajniak81andClaude Opus 5.5 committed 2026-10-20 21:14:12 +02:00
1 parent 93f4a580e9
commit e02bb0e5cd
34 files changed
+4376 -15

No files matched your search

@@ -100,6 +100,13 @@ abstract final class SettingsTabs {
static const String stickDiagram = 'stickDiagram';
static const String gimbalList = 'gimbalList';
static const String showRoute = 'showRoute';
static const String radarChart = 'radarChart';
static const String stickPads = 'stickPads';
static const String airSenseList = 'airSenseList';
static const String sensingDistances = 'sensingDistances';
static const String flyZoneList = 'flyZoneList';
static const String flyZoneLicences = 'flyZoneLicences';
static const String flyZoneDatabase = 'flyZoneDatabase';
static const String clearRoute = 'clearRoute';
static const String about = 'about';
static const String developer = 'developer';
@@ -195,11 +202,18 @@ abstract final class SettingsTabs {
const KeySwitchSpec(id: 'escBeep', label: 'ESC beeping', key: SettingsKeys.escBeep),
const GroupSpec('SENSORS'),
const CustomSpec(id: sensors, keys: <DjiKey>[SettingsKeys.imuCount, SettingsKeys.compassCount]),
GroupSpec('AIRSENSE', requires: HudFeatures.airSense),
CustomSpec(id: airSenseList, requires: HudFeatures.airSense),
GroupSpec('FLY ZONES', requires: HudFeatures.flyZones),
CustomSpec(id: flyZoneList, requires: HudFeatures.flyZones),
CustomSpec(id: flyZoneLicences, requires: HudFeatures.flyZones),
CustomSpec(id: flyZoneDatabase, requires: HudFeatures.flyZones),
];
// ── Vision ──────────────────────────────────────────────────────────────────
static final List<SettingSpec> _vision = <SettingSpec>[
GroupSpec('OBSTACLE AVOIDANCE', requires: HudFeatures.settingsObstacle),
CustomSpec(id: radarChart, requires: HudFeatures.visionRadar),
KeySwitchSpec(
id: 'collision',
label: 'Obstacle avoidance',
@@ -238,6 +252,7 @@ abstract final class SettingsTabs {
key: SettingsKeys.rthRemoteAvoidance,
requires: HudFeatures.settingsObstacle,
),
CustomSpec(id: sensingDistances, requires: HudFeatures.settingsObstacle),
const GroupSpec('POSITIONING & LANDING'),
const KeySwitchSpec(id: 'vps', label: 'Vision positioning', key: SettingsKeys.vps),
const KeySwitchSpec(
@@ -496,6 +511,8 @@ abstract final class SettingsTabs {
const GroupSpec('MAP'),
const CustomSpec(id: showRoute),
const CustomSpec(id: clearRoute),
GroupSpec('ON-SCREEN STICKS', requires: HudFeatures.virtualSticks),
CustomSpec(id: stickPads, requires: HudFeatures.virtualSticks),
const GroupSpec('ABOUT'),
const CustomSpec(id: about, keys: <DjiKey>[SettingsKeys.firmwarePackage, SettingsKeys.fcSerial]),
const GroupSpec('DEVELOPER'),