Files
PilotVault/Fly App/test/fly/profile_fixtures.dart
T
tajniak81andClaude Opus 5.5 60c2fd7f64 Give the Fly App GO 4-style gimbal controls
Plan P5: a value bubble on the pitch slider while dragging, press-and-drag
on the video as a speed joystick (re-sent at 10 Hz, zero on release), and a
gimbal settings sheet: mode, 30° extension, yaw follow, recenter / face down /
yaw recenter, roll fine-tune, auto calibration and advanced speed/smoothness
rows gated by the gimbal's capability ranges.

GimbalBridge reports mode, trim, calibration and stop/overload state in the
gimbal telemetry group, and getter-only settings in a new gimbalSettings slow
group. The reported-plus-pending overlay moves out of CameraState into a
SettingsOverlay mixin shared by camera and gimbal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:22:42 +02:00

142 lines
5.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// Synthetic `productProfile` events, shaped exactly as `ProductProfileBridge.kt`
/// emits them, for the three reference products of plan P0.
library;
Map<String, dynamic> _camera({
String name = 'FC1102',
bool aperture = false,
bool ssd = false,
bool zoom = false,
bool hybridZoom = false,
List<String> apertures = const <String>[],
}) =>
<String, dynamic>{
'index': 0,
'displayName': name,
'isThermal': false,
'ssdSupported': ssd,
'opticalZoomSupported': zoom,
'hybridZoomSupported': hybridZoom,
'digitalZoomSupported': false,
'adjustableApertureSupported': aperture,
'adjustableFocalPointSupported': aperture,
'meteringSupported': true,
'playbackSupported': true,
'mediaDownloadSupported': true,
'modes': <String>['SHOOT_PHOTO', 'RECORD_VIDEO'],
'exposureModes': <String>['PROGRAM', 'MANUAL'],
'isos': <String>['AUTO', '100', '200', '400', '800', '1600'],
'shutterSpeeds': <String>['1/8000', '1/1000', '1/100', '1/30'],
'apertures': apertures,
'exposureCompensations': <String>['-3.0', '0.0', '+3.0'],
'videoResolutions': <String>[
'RESOLUTION_3840x2160@FRAME_RATE_29_DOT_970_FPS',
'RESOLUTION_1920x1080@FRAME_RATE_59_DOT_940_FPS',
],
'photoModes': <String>['SINGLE', 'HDR', 'BURST', 'AEB', 'INTERVAL'],
'whiteBalancePresets': <String>['AUTO', 'SUNNY', 'CLOUDY', 'CUSTOM'],
'videoStandards': <String>['NTSC', 'PAL'],
'colors': <String>['NONE', 'D_LOG'],
};
Map<String, dynamic> _gimbal({bool yaw = false, double pitchMax = 0, bool tuning = false}) => <String, dynamic>{
'index': 0,
'capabilitiesKnown': true,
'pitch': <String, dynamic>{'min': -90.0, 'max': pitchMax},
'yaw': yaw ? <String, dynamic>{'min': -320.0, 'max': 320.0} : null,
'roll': null,
'pitchAdjustable': true,
'yawAdjustable': yaw,
'rollAdjustable': false,
'pitchRangeExtensionSupported': pitchMax > 0,
'controller': tuning
? <String, dynamic>{
'pitchMaxSpeed': <String, dynamic>{'min': 1.0, 'max': 100.0},
'pitchSmoothing': <String, dynamic>{'min': 0.0, 'max': 30.0},
'yawMaxSpeed': <String, dynamic>{'min': 1.0, 'max': 100.0},
}
: <String, dynamic>{},
};
Map<String, dynamic> _fc({bool assistant = true, bool sticks = true}) => <String, dynamic>{
'flightAssistantSupported': assistant,
'virtualStickAvailable': sticks,
'rtkSupported': false,
'compassCount': 1,
'imuCount': 1,
'simulatorAvailable': true,
};
/// Spark over Wi-Fi with no RC: no remote controller component, link reported
/// as Wi-Fi, one smart battery.
final Map<String, dynamic> sparkWifi = <String, dynamic>{
'type': 'productProfile',
'connected': true,
'model': 'Spark',
'modelDisplayName': 'Spark',
'productKind': 'aircraft',
'cameras': <dynamic>[_camera(name: 'FC1102')],
'gimbals': <dynamic>[_gimbal()],
'link': 'wifi',
'flightController': _fc(),
'remoteController': null,
'batteries': <dynamic>[
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 3},
],
};
/// Phantom 4 on Lightbridge, gimbal pitch extendable to +30°.
final Map<String, dynamic> phantom4 = <String, dynamic>{
'type': 'productProfile',
'connected': true,
'model': 'PHANTOM_4',
'modelDisplayName': 'Phantom 4',
'productKind': 'aircraft',
'cameras': <dynamic>[_camera(name: 'FC330')],
'gimbals': <dynamic>[_gimbal(pitchMax: 30)],
'link': 'lightbridge',
'flightController': _fc(),
'remoteController': <String, dynamic>{'masterSlaveSupported': false},
'batteries': <dynamic>[
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 4},
],
};
/// Inspire 2 with a Zenmuse X5S: dual batteries, SSD, adjustable aperture,
/// 3-axis gimbal with yaw, master/slave RC.
final Map<String, dynamic> inspire2X5s = <String, dynamic>{
'type': 'productProfile',
'connected': true,
'model': 'INSPIRE_2',
'modelDisplayName': 'Inspire 2',
'productKind': 'aircraft',
'cameras': <dynamic>[
_camera(name: 'Zenmuse X5S', aperture: true, ssd: true, apertures: <String>['f/1.7', 'f/2.8', 'f/5.6', 'f/16']),
],
'gimbals': <dynamic>[_gimbal(yaw: true, pitchMax: 30, tuning: true)],
'link': 'lightbridge',
'flightController': _fc(),
'remoteController': <String, dynamic>{'masterSlaveSupported': true},
'batteries': <dynamic>[
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 6},
<String, dynamic>{'index': 1, 'isSmart': true, 'cells': 6},
],
};
/// Mavic 2 Zoom: hybrid zoom (optical 24–48 mm, then digital), fixed aperture.
final Map<String, dynamic> mavic2Zoom = <String, dynamic>{
'type': 'productProfile',
'connected': true,
'model': 'MAVIC_2_ZOOM',
'modelDisplayName': 'Mavic 2 Zoom',
'productKind': 'aircraft',
'cameras': <dynamic>[_camera(name: 'FC2204', zoom: true, hybridZoom: true)],
'gimbals': <dynamic>[_gimbal()],
'link': 'ocusync',
'flightController': _fc(),
'remoteController': <String, dynamic>{'masterSlaveSupported': false},
'batteries': <dynamic>[
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 4},
],
};