QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
RemoteControlCalibrationController.cc
Go to the documentation of this file.
2#include "Fact.h"
3#include "ParameterManager.h"
4#include "QGCApplication.h"
6#include "Vehicle.h"
7
8#include <QtCore/QSettings>
9#include <algorithm>
10
11QGC_LOGGING_CATEGORY(RemoteControlCalibrationControllerLog, "RemoteControl.RemoteControlCalibrationController")
12QGC_LOGGING_CATEGORY(RemoteControlCalibrationControllerVerboseLog, "RemoteControl.RemoteControlCalibrationController:verbose")
13
14static constexpr const char *msgBeginThrottleDown = QT_TR_NOOP(
15 "* Lower the Throttle stick all the way down as shown in diagram\n"
16 "* Please ensure all motor power is disconnected AND all props are removed from the vehicle.\n"
17 "* Click Next to continue"
18);
19static constexpr const char *msgBeginThrottleCenter = QT_TR_NOOP(
20 "* Center all sticks as shown in diagram.\n"
21 "* Please ensure all motor power is disconnected from the vehicle.\n"
22 "* Click Next to continue"
23);
24static constexpr const char *msgThrottleUp = QT_TR_NOOP("Move the Throttle stick all the way up and hold it there...");
25static constexpr const char *msgThrottleDown = QT_TR_NOOP("Move the Throttle stick all the way down and leave it there...");
26static constexpr const char *msgYawLeft = QT_TR_NOOP("Move the Yaw stick all the way to the left and hold it there...");
27static constexpr const char *msgYawRight = QT_TR_NOOP("Move the Yaw stick all the way to the right and hold it there...");
28static constexpr const char *msgRollLeft = QT_TR_NOOP("Move the Roll stick all the way to the left and hold it there...");
29static constexpr const char *msgRollRight = QT_TR_NOOP("Move the Roll stick all the way to the right and hold it there...");
30static constexpr const char *msgPitchDown = QT_TR_NOOP("Move the Pitch stick all the way down and hold it there...");
31static constexpr const char *msgPitchUp = QT_TR_NOOP("Move the Pitch stick all the way up and hold it there...");
32static constexpr const char *msgPitchCenter = QT_TR_NOOP("Allow the Pitch stick to move back to center...");
33static constexpr const char *msgExtensionHigh = QT_TR_NOOP("Move the %1 Extension stick to its high value position and hold it there...");
34static constexpr const char *msgExtensionLow = QT_TR_NOOP("Move the %1 Extension stick to its low value position and hold it there...");
35static constexpr const char *msgSwitchMinMaxRC = QT_TR_NOOP("Move all the transmitter switches and/or dials back and forth to their extreme positions.");
36static constexpr const char *msgComplete = QT_TR_NOOP("All settings have been captured. Click Next to write the new parameters to your board.");
37
39 : FactPanelController(parent)
40 , _stateMachine{
41 // stickFunction, stepFunction, channelInputFn, nextButtonFn
42 { stickFunctionMax, StateMachineStepStickNeutral, &RemoteControlCalibrationController::_inputCenterWaitBegin, &RemoteControlCalibrationController::_saveAllTrims },
43 { stickFunctionThrottle, StateMachineStepThrottleUp, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
44 { stickFunctionThrottle, StateMachineStepThrottleDown, &RemoteControlCalibrationController::_inputStickMin, nullptr },
45 { stickFunctionYaw, StateMachineStepYawRight, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
46 { stickFunctionYaw, StateMachineStepYawLeft, &RemoteControlCalibrationController::_inputStickMin, nullptr },
47 { stickFunctionRoll, StateMachineStepRollRight, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
48 { stickFunctionRoll, StateMachineStepRollLeft, &RemoteControlCalibrationController::_inputStickMin, nullptr },
49 { stickFunctionPitch, StateMachineStepPitchUp, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
50 { stickFunctionPitch, StateMachineStepPitchDown, &RemoteControlCalibrationController::_inputStickMin, nullptr },
51 { stickFunctionPitchExtension, StateMachineStepExtensionHighVert, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
52 { stickFunctionPitchExtension, StateMachineStepExtensionLowVert, &RemoteControlCalibrationController::_inputStickMin, nullptr },
53 { stickFunctionRollExtension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
54 { stickFunctionRollExtension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
55 { stickFunctionAux1Extension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
56 { stickFunctionAux1Extension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
57 { stickFunctionAux2Extension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
58 { stickFunctionAux2Extension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
59 { stickFunctionAux3Extension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
60 { stickFunctionAux3Extension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
61 { stickFunctionAux4Extension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
62 { stickFunctionAux4Extension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
63 { stickFunctionAux5Extension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
64 { stickFunctionAux5Extension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
65 { stickFunctionAux6Extension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
66 { stickFunctionAux6Extension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
67
68 { stickFunctionMax, StateMachineStepSwitchMinMax, &RemoteControlCalibrationController::_inputSwitchMinMax, &RemoteControlCalibrationController::_advanceState },
69 { stickFunctionMax, StateMachineStepComplete, nullptr, &RemoteControlCalibrationController::_saveCalibrationValues },
70 }
71{
72 _resetInternalCalibrationValues();
73 _loadCalibrationUISettings();
74
75 _stickDisplayPositions = { _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical,
76 _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical };
77
78 if (_vehicle->rover()) {
79 _centeredThrottle = true;
80 }
81
82 _stepFunctionToMsgStringMap = {
83 { StateMachineStepStickNeutral, msgBeginThrottleCenter }, // Adjusted based on throttle centered or not
84 { StateMachineStepThrottleUp, msgThrottleUp },
85 { StateMachineStepThrottleDown, msgThrottleDown },
86 { StateMachineStepYawRight, msgYawRight },
87 { StateMachineStepYawLeft, msgYawLeft },
88 { StateMachineStepRollRight, msgRollRight },
89 { StateMachineStepRollLeft, msgRollLeft },
90 { StateMachineStepPitchUp, msgPitchUp },
91 { StateMachineStepPitchDown, msgPitchDown },
92 { StateMachineStepExtensionHighHorz, msgExtensionHigh },
93 { StateMachineStepExtensionLowHorz, msgExtensionLow },
94 { StateMachineStepExtensionHighVert, msgExtensionHigh },
95 { StateMachineStepExtensionLowVert, msgExtensionLow },
96 { StateMachineStepPitchCenter, msgPitchCenter },
97 { StateMachineStepSwitchMinMax, msgSwitchMinMaxRC },
98 { StateMachineStepComplete, msgComplete },
99 };
100
101 // Map for throttle centered neutral position
102 _bothStickDisplayPositionThrottleCenteredMap = {
103 { StateMachineStepStickNeutral, {
104 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
105 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
106 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
107 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
108 }},
109 { StateMachineStepThrottleUp, {
110 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
111 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
112 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
113 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
114 }},
115 { StateMachineStepThrottleDown, {
116 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
117 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
118 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
119 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
120 }},
121 { StateMachineStepYawRight, {
122 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
123 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
124 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
125 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
126 }},
127 { StateMachineStepYawLeft, {
128 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
129 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
130 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
131 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
132 }},
133 { StateMachineStepRollRight, {
134 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
135 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
136 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
137 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
138 }},
139 { StateMachineStepRollLeft, {
140 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
141 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
142 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
143 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
144 }},
145 { StateMachineStepPitchUp, {
146 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
147 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
148 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
149 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
150 }},
151 { StateMachineStepPitchDown, {
152 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
153 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
154 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
155 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
156 }},
157 { StateMachineStepPitchCenter, {
158 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
159 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
160 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
161 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
162 }},
163 { StateMachineStepExtensionHighHorz, {
164 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
165 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
166 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
167 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
168 }},
169 { StateMachineStepExtensionHighVert, {
170 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
171 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
172 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
173 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
174 }},
175 { StateMachineStepExtensionLowHorz, {
176 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
177 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
178 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
179 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
180 }},
181 { StateMachineStepExtensionLowVert, {
182 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
183 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
184 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
185 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
186 }},
187 { StateMachineStepSwitchMinMax, {
188 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
189 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
190 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
191 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
192 }},
193 { StateMachineStepComplete, {
194 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
195 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
196 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
197 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
198 }},
199 };
200
201 // Map for throttle down neutral position
202 _bothStickDisplayPositionThrottleDownMap = {
203 { StateMachineStepStickNeutral, {
204 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
205 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
206 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
207 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
208 }},
209 { StateMachineStepThrottleUp, {
210 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
211 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
212 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
213 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
214 }},
215 { StateMachineStepThrottleDown, {
216 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
217 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
218 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
219 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
220 }},
221 { StateMachineStepYawRight, {
222 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
223 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
224 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
225 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
226 }},
227 { StateMachineStepYawLeft, {
228 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
229 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
230 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
231 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
232 }},
233 { StateMachineStepRollRight, {
234 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
235 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
236 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
237 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
238 }},
239 { StateMachineStepRollLeft, {
240 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
241 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
242 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
243 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
244 }},
245 { StateMachineStepPitchUp, {
246 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
247 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
248 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
249 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
250 }},
251 { StateMachineStepPitchDown, {
252 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
253 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
254 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
255 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
256 }},
257 { StateMachineStepPitchCenter, {
258 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
259 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
260 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
261 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
262 }},
263 { StateMachineStepExtensionHighHorz, {
264 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
265 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
266 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
267 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
268 }},
269 { StateMachineStepExtensionHighVert, {
270 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
271 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
272 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
273 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
274 }},
275 { StateMachineStepExtensionLowHorz, {
276 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
277 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
278 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
279 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
280 }},
281 { StateMachineStepExtensionLowVert, {
282 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
283 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
284 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
285 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
286 }},
287 { StateMachineStepSwitchMinMax, {
288 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
289 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
290 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
291 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
292 }},
293 { StateMachineStepComplete, {
294 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
295 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
296 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
297 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
298 }},
299 };
300}
301
302RemoteControlCalibrationController::~RemoteControlCalibrationController()
303{
304 _saveCalibrationUISettings();
305
306 // qCDebug(RemoteControlCalibrationControllerLog) << Q_FUNC_INFO << this;
307}
308
309void RemoteControlCalibrationController::start()
310{
311 _stopCalibration();
312 _readStoredCalibrationValues();
313}
314
315const RemoteControlCalibrationController::StateMachineEntry &RemoteControlCalibrationController::_getStateMachineEntry(int step) const
316{
317 if (step < 0 || step >= _stateMachine.size()) {
318 qCWarning(RemoteControlCalibrationControllerLog) << "Bad step value" << step;
319 step = 0;
320 }
321
322 return _stateMachine[step];
323}
324
325void RemoteControlCalibrationController::_advanceState()
326{
327 _currentStep++;
328 if (_currentStep >= _stateMachine.size()) {
329 _stopCalibration();
330 return;
331 }
332
333 _setupCurrentState();
334}
335
336void RemoteControlCalibrationController::_setupCurrentState()
337{
338 auto state = _getStateMachineEntry(_currentStep);
339
340 // If the stick function for this step is not enabled, skip to next step
341 if (state.stickFunction != stickFunctionMax && !_stickFunctionEnabled(state.stickFunction)) {
342 qCDebug(RemoteControlCalibrationControllerLog) << "Skipping step" << _currentStep << "for disabled stick function" << _stickFunctionToString(state.stickFunction);
343 _advanceState();
344 return;
345 }
346
347 // StateMachineStepSwitchMinMax is only used for RC transmitters
348 if (_joystickMode && state.stepFunction == StateMachineStepSwitchMinMax) {
349 _advanceState();
350 return;
351 }
352
353 _stepFunctionToMsgStringMap[StateMachineStepStickNeutral] = _centeredThrottle ? msgBeginThrottleCenter : msgBeginThrottleDown;
354
355 BothSticksDisplayPositions defaultPositions = { _stickDisplayPositionCentered, _stickDisplayPositionCentered };
356 BothSticksDisplayPositions bothStickPositions = _centeredThrottle
357 ? _bothStickDisplayPositionThrottleCenteredMap.value(state.stepFunction).value(_transmitterMode, defaultPositions)
358 : _bothStickDisplayPositionThrottleDownMap.value(state.stepFunction).value(_transmitterMode, defaultPositions);
359
360 QString msg = _stepFunctionToMsgStringMap.value(state.stepFunction, QString());
361 if (state.stepFunction == StateMachineStepExtensionHighHorz || state.stepFunction == StateMachineStepExtensionHighVert ||
362 state.stepFunction == StateMachineStepExtensionLowHorz || state.stepFunction == StateMachineStepExtensionLowVert) {
363 static const QMap <StickFunction, QString> extensionNameMap = {
364 { stickFunctionPitchExtension, QT_TR_NOOP("Pitch") },
365 { stickFunctionRollExtension, QT_TR_NOOP("Roll") },
366 { stickFunctionAux1Extension, QT_TR_NOOP("Aux 1") },
367 { stickFunctionAux2Extension, QT_TR_NOOP("Aux 2") },
368 { stickFunctionAux3Extension, QT_TR_NOOP("Aux 3") },
369 { stickFunctionAux4Extension, QT_TR_NOOP("Aux 4") },
370 { stickFunctionAux5Extension, QT_TR_NOOP("Aux 5") },
371 { stickFunctionAux6Extension, QT_TR_NOOP("Aux 6") },
372 };
373 msg = msg.arg(extensionNameMap.value(state.stickFunction, QT_TR_NOOP("Unknown")));
374 }
375
376 _setSingleStickDisplay(state.stepFunction == StateMachineStepExtensionHighHorz || state.stepFunction == StateMachineStepExtensionHighVert ||
377 state.stepFunction == StateMachineStepExtensionLowHorz || state.stepFunction == StateMachineStepExtensionLowVert);
378
379 _statusText->setProperty("text", msg);
380 _stickDisplayPositions = { bothStickPositions.leftStick.horizontal, bothStickPositions.leftStick.vertical,
381 bothStickPositions.rightStick.horizontal, bothStickPositions.rightStick.vertical };
383
384 _stickDetectChannel = _chanMax;
385 _stickDetectSettleStarted = false;
386
387 _saveCurrentRawValues();
388
389 _nextButton->setEnabled(state.nextButtonFn != nullptr);
390}
391
393{
394 auto channelCount = channelValues.size();
395 if (channelCount > _chanMax) {
396 qCWarning(RemoteControlCalibrationControllerLog) << "Too many channels:" << channelCount << ", max is" << _chanMax;
397 channelCount = _chanMax;
398 }
399
400 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "channelValues" << channelValues;
401
402 for (int channel=0; channel<channelCount; channel++) {
403 const int channelValue = channelValues[channel];
404 const ChannelInfo &channelInfo = _rgChannelInfo[channel];
405 const int adjustedValue = _adjustChannelRawValue(channelInfo, channelValue);
406
407 _channelRawValue[channel] = channelValue;
408 emit rawChannelValueChanged(channel, channelValue);
409
410 // Signal attitude rc values to Qml if mapped
411 if (channelInfo.stickFunction != stickFunctionMax) {
412 switch (channelInfo.stickFunction) {
413 case stickFunctionRoll:
414 emit adjustedRollChannelValueChanged(adjustedValue);
415 break;
416 case stickFunctionPitch:
417 emit adjustedPitchChannelValueChanged(adjustedValue);
418 break;
419 case stickFunctionYaw:
420 emit adjustedYawChannelValueChanged(adjustedValue);
421 break;
422 case stickFunctionThrottle:
423 emit adjustedThrottleChannelValueChanged(adjustedValue);
424 break;
425 case stickFunctionRollExtension:
427 break;
428 case stickFunctionPitchExtension:
430 break;
431 case stickFunctionAux1Extension:
433 break;
434 case stickFunctionAux2Extension:
436 break;
437 case stickFunctionAux3Extension:
439 break;
440 case stickFunctionAux4Extension:
442 break;
443 case stickFunctionAux5Extension:
445 break;
446 case stickFunctionAux6Extension:
448 break;
449 default:
450 break;
451 }
452 }
453
454 if (_currentStep == -1) {
455 if (_chanCount != channelCount) {
456 _chanCount = channelCount;
458 }
459 } else {
460 auto state = _getStateMachineEntry(_currentStep);
461 if (state.channelInputFn) {
462 (this->*state.channelInputFn)(state.stickFunction, channel, channelValue);
463 }
464 }
465 }
466}
467
468void RemoteControlCalibrationController::nextButtonClicked()
469{
470 if (_currentStep == -1) {
471 // Need to have enough channels
472 if (_chanCount < _chanMinimum) {
473 qgcApp()->showAppMessage(QStringLiteral("Detected %1 channels. To operate vehicle, you need at least %2 channels.").arg(_chanCount).arg(_chanMinimum));
474 return;
475 }
476 _startCalibration();
477 } else {
478 auto state = _getStateMachineEntry(_currentStep);
479 if (state.nextButtonFn) {
480 (this->*state.nextButtonFn)();
481 }
482 }
483}
484
485void RemoteControlCalibrationController::cancelButtonClicked()
486{
487 _stopCalibration();
488}
489
490void RemoteControlCalibrationController::_saveAllTrims()
491{
492 // We save all trims as the first step. At this point no channels are mapped but it should still
493 // allow us to get good trims for the roll/pitch/yaw/throttle even though we don't know which
494 // channels they are yet. AS we continue through the process the other channels will get their
495 // trims reset to correct values.
496
497 for (int i=0; i<_chanCount; i++) {
498 qCDebug(RemoteControlCalibrationControllerLog) << "_saveAllTrims channel:trim" << i << _channelRawValue[i];
499 _rgChannelInfo[i].channelTrim = _channelRawValue[i];
500 }
501 _advanceState();
502}
503
504void RemoteControlCalibrationController::_inputCenterWaitBegin(StickFunction /*stickFunction*/, int channel, int value)
505{
506 if (_joystickMode) {
507 // Track deadband adjustments in joystick mode
508 int newDeadband = abs(value) * 1.1; // add 10% on top for fudge factor
509 if (newDeadband > _rgChannelInfo[channel].deadband) {
510 _rgChannelInfo[channel].deadband = qMin(newDeadband, _calValidMaxValue );
511 qCDebug(RemoteControlCalibrationControllerLog) << "Channel:" << channel << "Deadband:" << _rgChannelInfo[channel].deadband;
512 StickFunction stickFunction = _rgChannelInfo[channel].stickFunction;
513 if (stickFunction != stickFunctionMax) {
514 _emitDeadbandChanged(stickFunction);
515 }
516 }
517 }
518
519 _nextButton->setEnabled(true);
520}
521
522bool RemoteControlCalibrationController::_stickSettleComplete(int value)
523{
524 // We are waiting for the stick to settle out to a max position
525
526 if (abs(_stickDetectValue - value) > _calSettleDelta) {
527 // Stick is moving too much to consider stopped
528
529 qCDebug(RemoteControlCalibrationControllerLog) << "Still moving, _stickDetectValue:value" << _stickDetectValue << value;
530
531 _stickDetectValue = value;
532 _stickDetectSettleStarted = false;
533 } else {
534 // Stick is still positioned within the specified small range
535
536 if (_stickDetectSettleStarted) {
537 // We have already started waiting
538
539 if (_stickDetectSettleElapsed.elapsed() > _stickDetectSettleMSecs) {
540 // Stick has stayed positioned in one place long enough, detection is complete.
541 return true;
542 }
543 } else {
544 // Start waiting for the stick to stay settled for _stickDetectSettleWaitMSecs msecs
545
546 qCDebug(RemoteControlCalibrationControllerLog) << "Starting settle timer, _stickDetectValue:value" << _stickDetectValue << value;
547
548 _stickDetectSettleStarted = true;
549 _stickDetectSettleElapsed.start();
550 }
551 }
552
553 return false;
554}
555
556void RemoteControlCalibrationController::_inputStickDetect(StickFunction stickFunction, int channel, int value)
557{
558 // If this channel is already used in a mapping we can't use it again
559 if (_rgChannelInfo[channel].stickFunction != stickFunctionMax) {
560 return;
561 }
562
563 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "_inputStickDetect function:channel:value" << _stickFunctionToString(stickFunction) << channel << value;
564
565 if (_stickDetectChannel == _chanMax) {
566 // We have not detected enough movement on a channel yet
567 // Note: We intentionally require movement here (not just being at extreme) because
568 // this function is called for ALL channels, and some (like triggers) may rest at
569 // extreme positions. Requiring movement ensures we detect the correct channel.
570
571 if (abs(_channelValueSave[channel] - value) > _calMoveDelta) {
572 // Stick has moved far enough to consider it as being selected for the function
573
574 qCDebug(RemoteControlCalibrationControllerLog) << "Starting settle wait - function:channel" << _stickFunctionToString(stickFunction) << channel;
575
576 // Setup up to detect stick being pegged to min or max value
577 _stickDetectChannel = channel;
578 _stickDetectValue = value;
579 }
580 } else if (channel == _stickDetectChannel) {
581 if (_stickSettleComplete(value)) {
582 ChannelInfo *const info = &_rgChannelInfo[channel];
583
584 // Map the channel to the function
585 _rgFunctionChannelMapping[stickFunction] = channel;
586 info->stickFunction = stickFunction;
587
588 // A non-reversed channel should show a higher value than center.
589 info->channelReversed = value < _channelValueSave[channel];
590 if (info->channelReversed) {
591 _rgChannelInfo[channel].channelMin = value;
592 } else {
593 _rgChannelInfo[channel].channelMax = value;
594 }
595
596 qCDebug(RemoteControlCalibrationControllerLog) << "Stick detected - function:channel:reversed:" << _stickFunctionToString(stickFunction) << channel << info->channelReversed;
597
599
600 _advanceState();
601 }
602 }
603}
604
605void RemoteControlCalibrationController::_inputStickMin(StickFunction stickFunction, int channel, int value)
606{
607 // We only care about the channel mapped to the function we are working on
608 if (_rgFunctionChannelMapping[stickFunction] != channel) {
609 return;
610 }
611
612 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "_inputStickMin function:channel:value" << _stickFunctionToString(stickFunction) << channel << value;
613
614 if (_stickDetectChannel == _chanMax) {
615 if (_rgChannelInfo[channel].channelReversed) {
616 if (value > _calCenterPoint + _calMoveDelta) {
617 qCDebug(RemoteControlCalibrationControllerLog) << "Movement detected, starting settle wait";
618 _stickDetectChannel = channel;
619 _stickDetectValue = value;
620 }
621 } else {
622 if (value < _calCenterPoint - _calMoveDelta) {
623 qCDebug(RemoteControlCalibrationControllerLog) << "Movement detected, starting settle wait";
624 _stickDetectChannel = channel;
625 _stickDetectValue = value;
626 }
627 }
628 } else {
629 // We are waiting for the selected channel to settle out
630 if (_stickSettleComplete(value)) {
631 auto& channelInfo = _rgChannelInfo[channel];
632
633 // Stick detection is complete. Stick should be at extreme position.
634 if (channelInfo.channelReversed) {
635 channelInfo.channelMax = value;
636 } else {
637 channelInfo.channelMin = value;
638 }
639
640 // Check if this is throttle and set trim accordingly
641 if (!_joystickMode && stickFunction == stickFunctionThrottle) {
642 channelInfo.channelTrim = value;
643 }
644
645 qCDebug(RemoteControlCalibrationControllerLog) << "Settle complete - function:channel:min:max:trim" << _stickFunctionToString(stickFunction) << channel << channelInfo.channelMin << channelInfo.channelMax << channelInfo.channelTrim;
646
647 _advanceState();
648 }
649 }
650}
651
652void RemoteControlCalibrationController::_inputCenterWait(StickFunction stickFunction, int channel, int value)
653{
654 // We only care about the channel mapped to the function we are working on
655 if (_rgFunctionChannelMapping[stickFunction] != channel) {
656 return;
657 }
658
659 qCDebug(RemoteControlCalibrationControllerLog) << "_inputCenterWait function:channel:value" << _stickFunctionToString(stickFunction) << channel << value;
660 if (_stickDetectChannel == _chanMax) {
661 // Sticks have not yet moved close enough to center
662
663 if (abs(_calCenterPoint - value) < _calRoughCenterDelta) {
664 // Stick has moved close enough to center that we can start waiting for it to settle
665 qCDebug(RemoteControlCalibrationControllerLog) << "_inputCenterWait Center detected. Waiting for settle.";
666 _stickDetectChannel = channel;
667 _stickDetectValue = value;
668 }
669 } else {
670 if (_stickSettleComplete(value)) {
671 _advanceState();
672 }
673 }
674}
675
676void RemoteControlCalibrationController::_inputSwitchMinMax(StickFunction /*stickFunction*/, int channel, int value)
677{
678 // If the channel is mapped we already have min/max
679 if (_rgChannelInfo[channel].stickFunction != stickFunctionMax) {
680 return;
681 }
682
683 if (abs(_calCenterPoint - value) > _calMoveDelta) {
684 // Stick has moved far enough from center to consider for min/max
685 if (value < _calCenterPoint) {
686 const int minValue = qMin(_rgChannelInfo[channel].channelMin, value);
687
688 qCDebug(RemoteControlCalibrationControllerLog) << "setting min channel:min" << channel << minValue;
689
690 _rgChannelInfo[channel].channelMin = minValue;
691 } else {
692 int maxValue = qMax(_rgChannelInfo[channel].channelMax, value);
693
694 qCDebug(RemoteControlCalibrationControllerLog) << "setting max channel:max" << channel << maxValue;
695
696 _rgChannelInfo[channel].channelMax = maxValue;
697 }
698 }
699}
700
702{
703 // Set all raw channels to not reversed and center point values
704 for (int i = 0; i < _chanMax; i++) {
705 ChannelInfo *const info = &_rgChannelInfo[i];
706 info->stickFunction = stickFunctionMax;
707 info->channelReversed = false;
711 info->deadband = 0;
712 }
713
714 // Initialize attitude function mapping to function channel not set
715 for (size_t i = 0; i < stickFunctionMax; i++) {
717 }
718
720}
721
723{
724 for (int chan = 0; chan<_chanMax; chan++) {
725 auto& channelInfo = _rgChannelInfo[chan];
726
727 if (chan < _chanCount) {
728 // Validate Min/Max values. Although the channel appears as available we still may
729 // not have good min/max/trim values for it. Set to defaults if needed.
730 if (channelInfo.channelMin > _calValidMinValue || channelInfo.channelMax < _calValidMaxValue) {
731 qCDebug(RemoteControlCalibrationControllerLog) << "resetting channel invalid min/max - chan:channelMin:calValidMinValue:channelMax:calValidMaxValue"
732 << chan << channelInfo.channelMin << _calValidMinValue << channelInfo.channelMax << _calValidMaxValue;
733 channelInfo.channelMin = _calDefaultMinValue;
734 channelInfo.channelMax = _calDefaultMaxValue;
735 channelInfo.channelTrim = channelInfo.channelMin + ((channelInfo.channelMax - channelInfo.channelMin) / 2);
736 } else {
737 switch (channelInfo.stickFunction) {
738 case stickFunctionThrottle:
739 case stickFunctionYaw:
740 case stickFunctionRoll:
741 case stickFunctionPitch:
742 // Make sure trim is within min/max
743 channelInfo.channelTrim = std::clamp(channelInfo.channelTrim, channelInfo.channelMin, channelInfo.channelMax);
744 break;
745 default:
746 // Non-attitude control channels have calculated trim
747 channelInfo.channelTrim = channelInfo.channelMin + ((channelInfo.channelMax - channelInfo.channelMin) / 2);
748 break;
749 }
750
751 }
752 } else {
753 // Unavailable channels are set to defaults
754 qCDebug(RemoteControlCalibrationControllerLog) << "resetting unavailable channel" << chan;
755 channelInfo.channelMin = _calDefaultMinValue;
756 channelInfo.channelMax = _calDefaultMaxValue;
757 channelInfo.channelTrim = channelInfo.channelMin + ((channelInfo.channelMax - channelInfo.channelMin) / 2);
758 channelInfo.channelReversed = false;
759 channelInfo.deadband = 0;
760 channelInfo.stickFunction = stickFunctionMax;
761
762 }
763 }
764}
765
766void RemoteControlCalibrationController::_startCalibration()
767{
768 if (_chanCount < _chanMinimum) {
769 qCWarning(RemoteControlCalibrationControllerLog) << "Call to RemoteControlCalibrationController::_startCalibration with _chanCount < _chanMinimum";
770 return;
771 }
772
774
775 if (!_calibrating) {
776 _calibrating = true;
777 emit calibratingChanged(true);
778 }
779
780 _nextButton->setProperty("text", tr("Next"));
781 _cancelButton->setEnabled(true);
782
783 _currentStep = 0;
784 _setupCurrentState();
785}
786
787void RemoteControlCalibrationController::_setSingleStickDisplay(bool singleStickDisplay)
788{
789 if (_singleStickDisplay != singleStickDisplay) {
790 _singleStickDisplay = singleStickDisplay;
791 emit singleStickDisplayChanged(singleStickDisplay);
792 }
793}
794
795void RemoteControlCalibrationController::_stopCalibration()
796{
797 _currentStep = -1;
798
799 if (_vehicle) {
800 _readStoredCalibrationValues();
801 }
802
803 if (_calibrating) {
804 _calibrating = false;
805 emit calibratingChanged(false);
806 }
807
808 if (_statusText) {
809 _statusText->setProperty("text", "");
810 }
811 if (_nextButton) {
812 _nextButton->setProperty("text", tr("Calibrate"));
813 }
814 if (_nextButton) {
815 _nextButton->setEnabled(true);
816 }
817 if (_cancelButton) {
818 _cancelButton->setEnabled(false);
819 }
820
821 _stickDisplayPositions = { _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical,
822 _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical };
824}
825
826void RemoteControlCalibrationController::_saveCurrentRawValues()
827{
828 for (int i = 0; i < _chanMax; i++) {
829 _channelValueSave[i] = _channelRawValue[i];
830 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "_saveCurrentRawValues channel:value" << i << _channelValueSave[i];
831 }
832}
833
835int RemoteControlCalibrationController::_adjustChannelRawValue(const ChannelInfo& info, int rawValue) const
836{
837 if (!info.channelReversed) {
838 return rawValue;
839 }
840
841 const int invertedValue = info.channelMin + info.channelMax - rawValue;
842 return std::clamp(invertedValue, info.channelMin, info.channelMax);
843}
844
845void RemoteControlCalibrationController::_loadCalibrationUISettings()
846{
847 QSettings settings;
848
849 settings.beginGroup(_settingsGroup);
850 _transmitterMode = settings.value(_settingsKeyTransmitterMode, 2).toInt();
851 settings.endGroup();
852
853 if (_transmitterMode < 1 || _transmitterMode > 4) {
854 _transmitterMode = 2;
855 }
856}
857
858void RemoteControlCalibrationController::_saveCalibrationUISettings()
859{
860 QSettings settings;
861
862 settings.beginGroup(_settingsGroup);
863 settings.setValue(_settingsKeyTransmitterMode, _transmitterMode);
864 settings.endGroup();
865}
866
867int RemoteControlCalibrationController::adjustedRollChannelValue()
868{
869 int channel = _rgFunctionChannelMapping[stickFunctionRoll];
870 if (channel != _chanMax) {
871 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
872 } else {
873 return _calCenterPoint;
874 }
875}
876
877int RemoteControlCalibrationController::adjustedPitchChannelValue()
878{
879 int channel = _rgFunctionChannelMapping[stickFunctionPitch];
880 if (channel != _chanMax) {
881 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
882 } else {
883 return _calCenterPoint;
884 }
885}
886
887int RemoteControlCalibrationController::adjustedYawChannelValue()
888{
889 int channel = _rgFunctionChannelMapping[stickFunctionYaw];
890 if (channel != _chanMax) {
891 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
892 } else {
893 return _calCenterPoint;
894 }
895}
896
897int RemoteControlCalibrationController::adjustedThrottleChannelValue()
898{
899 int channel = _rgFunctionChannelMapping[stickFunctionThrottle];
900 if (channel != _chanMax) {
901 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
902 } else {
903 return _calCenterPoint;
904 }
905}
906
907int RemoteControlCalibrationController::adjustedRollExtensionChannelValue()
908{
909 int channel = _rgFunctionChannelMapping[stickFunctionRollExtension];
910 if (channel != _chanMax) {
911 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
912 } else {
913 return _calCenterPoint;
914 }
915}
916
917int RemoteControlCalibrationController::adjustedPitchExtensionChannelValue()
918{
919 int channel = _rgFunctionChannelMapping[stickFunctionPitchExtension];
920 if (channel != _chanMax) {
921 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
922 } else {
923 return _calCenterPoint;
924 }
925}
926
927int RemoteControlCalibrationController::adjustedAux1ExtensionChannelValue()
928{
929 int channel = _rgFunctionChannelMapping[stickFunctionAux1Extension];
930 if (channel != _chanMax) {
931 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
932 } else {
933 return _calCenterPoint;
934 }
935}
936
937int RemoteControlCalibrationController::adjustedAux2ExtensionChannelValue()
938{
939 int channel = _rgFunctionChannelMapping[stickFunctionAux2Extension];
940 if (channel != _chanMax) {
941 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
942 } else {
943 return _calCenterPoint;
944 }
945}
946
947int RemoteControlCalibrationController::adjustedAux3ExtensionChannelValue()
948{
949 int channel = _rgFunctionChannelMapping[stickFunctionAux3Extension];
950 if (channel != _chanMax) {
951 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
952 } else {
953 return _calCenterPoint;
954 }
955}
956
957int RemoteControlCalibrationController::adjustedAux4ExtensionChannelValue()
958{
959 int channel = _rgFunctionChannelMapping[stickFunctionAux4Extension];
960 if (channel != _chanMax) {
961 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
962 } else {
963 return _calCenterPoint;
964 }
965}
966
967int RemoteControlCalibrationController::adjustedAux5ExtensionChannelValue()
968{
969 int channel = _rgFunctionChannelMapping[stickFunctionAux5Extension];
970 if (channel != _chanMax) {
971 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
972 } else {
973 return _calCenterPoint;
974 }
975}
976
977int RemoteControlCalibrationController::adjustedAux6ExtensionChannelValue()
978{
979 int channel = _rgFunctionChannelMapping[stickFunctionAux6Extension];
980 if (channel != _chanMax) {
981 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
982 } else {
983 return _calCenterPoint;
984 }
985}
986
987bool RemoteControlCalibrationController::rollChannelMapped()
988{
989 return (_rgFunctionChannelMapping[stickFunctionRoll] != _chanMax);
990}
991
992bool RemoteControlCalibrationController::pitchChannelMapped()
993{
994 return (_rgFunctionChannelMapping[stickFunctionPitch] != _chanMax);
995}
996
997bool RemoteControlCalibrationController::rollExtensionChannelMapped()
998{
999 return (_rgFunctionChannelMapping[stickFunctionRollExtension] != _chanMax);
1000}
1001
1002bool RemoteControlCalibrationController::pitchExtensionChannelMapped()
1003{
1004 return (_rgFunctionChannelMapping[stickFunctionPitchExtension] != _chanMax);
1005}
1006
1007bool RemoteControlCalibrationController::aux1ExtensionChannelMapped()
1008{
1009 return (_rgFunctionChannelMapping[stickFunctionAux1Extension] != _chanMax);
1010}
1011
1012bool RemoteControlCalibrationController::aux2ExtensionChannelMapped()
1013{
1014 return (_rgFunctionChannelMapping[stickFunctionAux2Extension] != _chanMax);
1015}
1016
1017bool RemoteControlCalibrationController::aux3ExtensionChannelMapped()
1018{
1019 return (_rgFunctionChannelMapping[stickFunctionAux3Extension] != _chanMax);
1020}
1021
1022bool RemoteControlCalibrationController::aux4ExtensionChannelMapped()
1023{
1024 return (_rgFunctionChannelMapping[stickFunctionAux4Extension] != _chanMax);
1025}
1026
1027bool RemoteControlCalibrationController::aux5ExtensionChannelMapped()
1028{
1029 return (_rgFunctionChannelMapping[stickFunctionAux5Extension] != _chanMax);
1030}
1031
1032bool RemoteControlCalibrationController::aux6ExtensionChannelMapped()
1033{
1034 return (_rgFunctionChannelMapping[stickFunctionAux6Extension] != _chanMax);
1035}
1036
1037bool RemoteControlCalibrationController::yawChannelMapped()
1038{
1039 return (_rgFunctionChannelMapping[stickFunctionYaw] != _chanMax);
1040}
1041
1042bool RemoteControlCalibrationController::throttleChannelMapped()
1043{
1044 return (_rgFunctionChannelMapping[stickFunctionThrottle] != _chanMax);
1045}
1046
1047bool RemoteControlCalibrationController::pitchExtensionEnabled()
1048{
1049 return _stickFunctionEnabled(stickFunctionPitchExtension);
1050}
1051
1052bool RemoteControlCalibrationController::rollExtensionEnabled()
1053{
1054 return _stickFunctionEnabled(stickFunctionRollExtension);
1055}
1056
1057bool RemoteControlCalibrationController::aux1ExtensionEnabled()
1058{
1059 return _stickFunctionEnabled(stickFunctionAux1Extension);
1060}
1061
1062bool RemoteControlCalibrationController::aux2ExtensionEnabled()
1063{
1064 return _stickFunctionEnabled(stickFunctionAux2Extension);
1065}
1066
1067bool RemoteControlCalibrationController::aux3ExtensionEnabled()
1068{
1069 return _stickFunctionEnabled(stickFunctionAux3Extension);
1070}
1071
1072bool RemoteControlCalibrationController::aux4ExtensionEnabled()
1073{
1074 return _stickFunctionEnabled(stickFunctionAux4Extension);
1075}
1076
1077bool RemoteControlCalibrationController::aux5ExtensionEnabled()
1078{
1079 return _stickFunctionEnabled(stickFunctionAux5Extension);
1080}
1081
1082bool RemoteControlCalibrationController::aux6ExtensionEnabled()
1083{
1084 return _stickFunctionEnabled(stickFunctionAux6Extension);
1085}
1086
1087bool RemoteControlCalibrationController::anyExtensionEnabled()
1088{
1089 return pitchExtensionEnabled() || rollExtensionEnabled() ||
1090 aux1ExtensionEnabled() || aux2ExtensionEnabled() ||
1091 aux3ExtensionEnabled() || aux4ExtensionEnabled() ||
1092 aux5ExtensionEnabled() || aux6ExtensionEnabled();
1093}
1094
1095bool RemoteControlCalibrationController::rollChannelReversed()
1096{
1097 if (_rgFunctionChannelMapping[stickFunctionRoll] != _chanMax) {
1098 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionRoll]].channelReversed;
1099 } else {
1100 return false;
1101 }
1102}
1103
1104bool RemoteControlCalibrationController::pitchChannelReversed()
1105{
1106 if (_rgFunctionChannelMapping[stickFunctionPitch] != _chanMax) {
1107 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionPitch]].channelReversed;
1108 } else {
1109 return false;
1110 }
1111}
1112
1113bool RemoteControlCalibrationController::rollExtensionChannelReversed()
1114{
1115 if (_rgFunctionChannelMapping[stickFunctionRollExtension] != _chanMax) {
1116 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionRollExtension]].channelReversed;
1117 } else {
1118 return false;
1119 }
1120}
1121
1122bool RemoteControlCalibrationController::pitchExtensionChannelReversed()
1123{
1124 if (_rgFunctionChannelMapping[stickFunctionPitchExtension] != _chanMax) {
1125 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionPitchExtension]].channelReversed;
1126 } else {
1127 return false;
1128 }
1129}
1130
1131bool RemoteControlCalibrationController::aux1ExtensionChannelReversed()
1132{
1133 if (_rgFunctionChannelMapping[stickFunctionAux1Extension] != _chanMax) {
1134 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionAux1Extension]].channelReversed;
1135 } else {
1136 return false;
1137 }
1138}
1139
1140bool RemoteControlCalibrationController::aux2ExtensionChannelReversed()
1141{
1142 if (_rgFunctionChannelMapping[stickFunctionAux2Extension] != _chanMax) {
1143 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionAux2Extension]].channelReversed;
1144 } else {
1145 return false;
1146 }
1147}
1148
1149bool RemoteControlCalibrationController::aux3ExtensionChannelReversed()
1150{
1151 if (_rgFunctionChannelMapping[stickFunctionAux3Extension] != _chanMax) {
1152 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionAux3Extension]].channelReversed;
1153 } else {
1154 return false;
1155 }
1156}
1157
1158bool RemoteControlCalibrationController::aux4ExtensionChannelReversed()
1159{
1160 if (_rgFunctionChannelMapping[stickFunctionAux4Extension] != _chanMax) {
1161 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionAux4Extension]].channelReversed;
1162 } else {
1163 return false;
1164 }
1165}
1166
1167bool RemoteControlCalibrationController::aux5ExtensionChannelReversed()
1168{
1169 if (_rgFunctionChannelMapping[stickFunctionAux5Extension] != _chanMax) {
1170 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionAux5Extension]].channelReversed;
1171 } else {
1172 return false;
1173 }
1174}
1175
1176bool RemoteControlCalibrationController::aux6ExtensionChannelReversed()
1177{
1178 if (_rgFunctionChannelMapping[stickFunctionAux6Extension] != _chanMax) {
1179 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionAux6Extension]].channelReversed;
1180 } else {
1181 return false;
1182 }
1183}
1184
1185bool RemoteControlCalibrationController::yawChannelReversed()
1186{
1187 if (_rgFunctionChannelMapping[stickFunctionYaw] != _chanMax) {
1189 } else {
1190 return false;
1191 }
1192}
1193
1194bool RemoteControlCalibrationController::throttleChannelReversed()
1195{
1196 if (_rgFunctionChannelMapping[stickFunctionThrottle] != _chanMax) {
1197 return _rgChannelInfo[_rgFunctionChannelMapping[stickFunctionThrottle]].channelReversed;
1198 } else {
1199 return false;
1200 }
1201}
1202
1203void RemoteControlCalibrationController::setTransmitterMode(int mode)
1204{
1205 if (mode < 1 || mode > 4) {
1206 qCWarning(RemoteControlCalibrationControllerLog) << "Invalid transmitter mode set:" << mode;
1207 mode = 2;
1208 }
1209 if (_transmitterMode != mode) {
1210 _transmitterMode = mode;
1212 }
1213}
1214
1216{
1217 emit rollChannelMappedChanged(rollChannelMapped());
1218 emit pitchChannelMappedChanged(pitchChannelMapped());
1219 emit rollExtensionChannelMappedChanged(rollExtensionChannelMapped());
1220 emit pitchExtensionChannelMappedChanged(pitchExtensionChannelMapped());
1221 emit aux1ExtensionChannelMappedChanged(aux1ExtensionChannelMapped());
1222 emit aux2ExtensionChannelMappedChanged(aux2ExtensionChannelMapped());
1223 emit aux3ExtensionChannelMappedChanged(aux3ExtensionChannelMapped());
1224 emit aux4ExtensionChannelMappedChanged(aux4ExtensionChannelMapped());
1225 emit aux5ExtensionChannelMappedChanged(aux5ExtensionChannelMapped());
1226 emit aux6ExtensionChannelMappedChanged(aux6ExtensionChannelMapped());
1227 emit yawChannelMappedChanged(yawChannelMapped());
1228 emit throttleChannelMappedChanged(throttleChannelMapped());
1229
1230 emit rollChannelReversedChanged(rollChannelReversed());
1231 emit pitchChannelReversedChanged(pitchChannelReversed());
1232 emit rollExtensionChannelReversedChanged(rollExtensionChannelReversed());
1233 emit pitchExtensionChannelReversedChanged(pitchExtensionChannelReversed());
1234 emit aux1ExtensionChannelReversedChanged(aux1ExtensionChannelReversed());
1235 emit aux2ExtensionChannelReversedChanged(aux2ExtensionChannelReversed());
1236 emit aux3ExtensionChannelReversedChanged(aux3ExtensionChannelReversed());
1237 emit aux4ExtensionChannelReversedChanged(aux4ExtensionChannelReversed());
1238 emit aux5ExtensionChannelReversedChanged(aux5ExtensionChannelReversed());
1239 emit aux6ExtensionChannelReversedChanged(aux6ExtensionChannelReversed());
1240 emit yawChannelReversedChanged(yawChannelReversed());
1241 emit throttleChannelReversedChanged(throttleChannelReversed());
1242
1243 _emitDeadbandChanged(stickFunctionRoll);
1244 _emitDeadbandChanged(stickFunctionPitch);
1245 _emitDeadbandChanged(stickFunctionRollExtension);
1246 _emitDeadbandChanged(stickFunctionPitchExtension);
1247 _emitDeadbandChanged(stickFunctionAux1Extension);
1248 _emitDeadbandChanged(stickFunctionAux2Extension);
1249 _emitDeadbandChanged(stickFunctionAux3Extension);
1250 _emitDeadbandChanged(stickFunctionAux4Extension);
1251 _emitDeadbandChanged(stickFunctionAux5Extension);
1252 _emitDeadbandChanged(stickFunctionAux6Extension);
1253 _emitDeadbandChanged(stickFunctionYaw);
1254 _emitDeadbandChanged(stickFunctionThrottle);
1255}
1256
1257int RemoteControlCalibrationController::rollDeadband()
1258{
1259 return _deadbandForFunction(stickFunctionRoll);
1260}
1261
1262int RemoteControlCalibrationController::pitchDeadband()
1263{
1264 return _deadbandForFunction(stickFunctionPitch);
1265}
1266
1267int RemoteControlCalibrationController::rollExtensionDeadband()
1268{
1269 return _deadbandForFunction(stickFunctionRollExtension);
1270}
1271
1272int RemoteControlCalibrationController::pitchExtensionDeadband()
1273{
1274 return _deadbandForFunction(stickFunctionPitchExtension);
1275}
1276
1277int RemoteControlCalibrationController::aux1ExtensionDeadband()
1278{
1279 return _deadbandForFunction(stickFunctionAux1Extension);
1280}
1281
1282int RemoteControlCalibrationController::aux2ExtensionDeadband()
1283{
1284 return _deadbandForFunction(stickFunctionAux2Extension);
1285}
1286
1287int RemoteControlCalibrationController::aux3ExtensionDeadband()
1288{
1289 return _deadbandForFunction(stickFunctionAux3Extension);
1290}
1291
1292int RemoteControlCalibrationController::aux4ExtensionDeadband()
1293{
1294 return _deadbandForFunction(stickFunctionAux4Extension);
1295}
1296
1297int RemoteControlCalibrationController::aux5ExtensionDeadband()
1298{
1299 return _deadbandForFunction(stickFunctionAux5Extension);
1300}
1301
1302int RemoteControlCalibrationController::aux6ExtensionDeadband()
1303{
1304 return _deadbandForFunction(stickFunctionAux6Extension);
1305}
1306
1307int RemoteControlCalibrationController::yawDeadband()
1308{
1309 return _deadbandForFunction(stickFunctionYaw);
1310}
1311
1312int RemoteControlCalibrationController::throttleDeadband()
1313{
1314 return _deadbandForFunction(stickFunctionThrottle);
1315}
1316
1317void RemoteControlCalibrationController::copyTrims()
1318{
1320}
1321
1323{
1324 switch (stickFunction) {
1325 case stickFunctionRoll:
1326 return tr("Roll");
1327 case stickFunctionPitch:
1328 return tr("Pitch");
1329 case stickFunctionYaw:
1330 return tr("Yaw");
1331 case stickFunctionThrottle:
1332 return tr("Throttle");
1333 case stickFunctionAux1Extension:
1334 return tr("Aux1 Extension");
1335 case stickFunctionAux2Extension:
1336 return tr("Aux2 Extension");
1337 case stickFunctionAux3Extension:
1338 return tr("Aux3 Extension");
1339 case stickFunctionAux4Extension:
1340 return tr("Aux4 Extension");
1341 case stickFunctionAux5Extension:
1342 return tr("Aux5 Extension");
1343 case stickFunctionAux6Extension:
1344 return tr("Aux6 Extension");
1345 case stickFunctionPitchExtension:
1346 return tr("Pitch Extension");
1347 case stickFunctionRollExtension:
1348 return tr("Roll Extension");
1349 default:
1350 return tr("Unknown");
1351 }
1352}
1353
1354void RemoteControlCalibrationController::setCenteredThrottle(bool centered)
1355{
1356 if (_centeredThrottle != centered) {
1357 _centeredThrottle = centered;
1358 emit centeredThrottleChanged(centered);
1359 }
1360}
1361
1362void RemoteControlCalibrationController::setJoystickMode(bool joystickMode)
1363{
1364 if (_joystickMode == joystickMode) {
1365 return;
1366 }
1367
1368 _joystickMode = joystickMode;
1369 setCenteredThrottle(joystickMode);
1370 emit joystickModeChanged(_joystickMode);
1371}
1372
1373int RemoteControlCalibrationController::_deadbandForFunction(StickFunction stickFunction) const
1374{
1375 if (stickFunction < 0 || stickFunction >= stickFunctionMax) {
1376 return 0;
1377 }
1378
1379 int channel = _rgFunctionChannelMapping[stickFunction];
1380 if (channel != _chanMax) {
1381 return _rgChannelInfo[channel].deadband;
1382 }
1383
1384 return 0;
1385}
1386
1387void RemoteControlCalibrationController::_emitDeadbandChanged(StickFunction stickFunction)
1388{
1389 const int deadband = _deadbandForFunction(stickFunction);
1390 switch (stickFunction) {
1391 case stickFunctionRoll:
1392 emit rollDeadbandChanged(deadband);
1393 break;
1394 case stickFunctionPitch:
1395 emit pitchDeadbandChanged(deadband);
1396 break;
1397 case stickFunctionYaw:
1398 emit yawDeadbandChanged(deadband);
1399 break;
1400 case stickFunctionThrottle:
1401 emit throttleDeadbandChanged(deadband);
1402 break;
1403 default:
1404 break;
1405 }
1406}
1407
1408void RemoteControlCalibrationController::_saveCalibrationValues()
1409{
1410 _saveStoredCalibrationValues();
1411 emit calibrationCompleted();
1412 _advanceState();
1413}
1414
1416{
1417 // By default only calibrate attitude control functions
1418 switch (stickFunction) {
1419 case stickFunctionRoll:
1420 case stickFunctionPitch:
1421 case stickFunctionYaw:
1422 case stickFunctionThrottle:
1423 return true;
1424 default:
1425 return false;
1426 }
1427}
#define qgcApp()
#define QGC_LOGGING_CATEGORY(name, categoryStr)
static constexpr const char * msgPitchDown
static constexpr const char * msgSwitchMinMaxRC
static constexpr const char * msgPitchUp
static constexpr const char * msgRollLeft
static constexpr const char * msgComplete
static constexpr const char * msgBeginThrottleCenter
static constexpr const char * msgThrottleUp
static constexpr const char * msgYawLeft
static constexpr const char * msgPitchCenter
static constexpr const char * msgExtensionHigh
static constexpr const char * msgRollRight
static constexpr const char * msgExtensionLow
static constexpr const char * msgThrottleDown
static constexpr const char * msgBeginThrottleDown
static constexpr const char * msgYawRight
Used for handling missing Facts from C++ code.
Abstract base class for calibrating RC and Joystick controller.
void pitchDeadbandChanged(int deadband)
QString _stickFunctionToString(StickFunction stickFunction)
void pitchChannelReversedChanged(bool reversed)
void adjustedAux1ExtensionChannelValueChanged(int rcValue)
int _calValidMinValue
Largest valid minimum channel range value.
void joystickModeChanged(bool joystickMode)
void rawChannelValuesChanged(QVector< int > channelValues)
void rollExtensionChannelReversedChanged(bool reversed)
void channelCountChanged(int channelCount)
void yawDeadbandChanged(int deadband)
void throttleDeadbandChanged(int deadband)
static constexpr int _chanMinimum
Minimum numner of channels required to run.
void pitchExtensionChannelReversedChanged(bool reversed)
int _calMoveDelta
Amount of delta past center which is considered stick movement.
void aux6ExtensionChannelMappedChanged(bool mapped)
void aux3ExtensionChannelMappedChanged(bool mapped)
void singleStickDisplayChanged(bool singleStickDisplay)
void aux4ExtensionChannelReversedChanged(bool reversed)
void adjustedThrottleChannelValueChanged(int rcValue)
void aux4ExtensionChannelMappedChanged(bool mapped)
void _resetInternalCalibrationValues()
Resets internal calibration values to their initial state in preparation for a new calibration sequen...
void aux3ExtensionChannelReversedChanged(bool reversed)
static constexpr int _chanMax
A set of information associated with a radio channel.
int _calRoughCenterDelta
Delta around center point which is considered to be roughly centered.
void rollChannelMappedChanged(bool mapped)
int _stickDetectSettleMSecs
Time in ms stick must be stable before detection completes.
void adjustedAux5ExtensionChannelValueChanged(int rcValue)
void adjustedAux2ExtensionChannelValueChanged(int rcValue)
void yawChannelReversedChanged(bool reversed)
void rollExtensionChannelMappedChanged(bool mapped)
void adjustedAux4ExtensionChannelValueChanged(int rcValue)
void aux6ExtensionChannelReversedChanged(bool reversed)
void adjustedRollChannelValueChanged(int rcValue)
void rollDeadbandChanged(int deadband)
void aux5ExtensionChannelReversedChanged(bool reversed)
void adjustedYawChannelValueChanged(int rcValue)
virtual bool _stickFunctionEnabled(StickFunction stickFunction)
Returns true if the stick function is enabled.
void aux1ExtensionChannelReversedChanged(bool reversed)
void adjustedAux3ExtensionChannelValueChanged(int rcValue)
void adjustedPitchChannelValueChanged(int rcValue)
int _calValidMaxValue
Smallest valid maximum channel range value.
int _calDefaultMinValue
Default value for Min if not set.
void pitchChannelMappedChanged(bool mapped)
int _calSettleDelta
Amount of delta which is considered no stick movement.
void aux5ExtensionChannelMappedChanged(bool mapped)
ChannelInfo _rgChannelInfo[_chanMax]
Information associated with each rc channel.
void calibratingChanged(bool calibrating)
void rawChannelValueChanged(int channel, int value)
void adjustedRollExtensionChannelValueChanged(int rcValue)
void throttleChannelMappedChanged(bool mapped)
int _rgFunctionChannelMapping[stickFunctionMax]
Maps from StickFunction to channel index. _chanMax indicates channel not set for this function.
int _chanCount
Number of actual rc channels available.
void rollChannelReversedChanged(bool reversed)
int _calDefaultMaxValue
Default value for Max if not set.
void centeredThrottleChanged(bool centeredThrottle)
void aux1ExtensionChannelMappedChanged(bool mapped)
void throttleChannelReversedChanged(bool reversed)
void pitchExtensionChannelMappedChanged(bool mapped)
void yawChannelMappedChanged(bool mapped)
void aux2ExtensionChannelMappedChanged(bool mapped)
void adjustedAux6ExtensionChannelValueChanged(int rcValue)
void aux2ExtensionChannelReversedChanged(bool reversed)
void adjustedPitchExtensionChannelValueChanged(int rcValue)
void startCalibration(QGCMAVLink::CalibrationType calType)
Definition Vehicle.cc:3218
int channelTrim
Trim position (usually center for sticks)
enum StickFunction stickFunction
Function mapped to this channel, stickFunctionMax for none.