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 "AppMessages.h"
6#include "Vehicle.h"
7
8#include <QtCore/QCoreApplication>
9#include <QtCore/QSettings>
10#include <algorithm>
11
12QGC_LOGGING_CATEGORY(RemoteControlCalibrationControllerLog, "RemoteControl.RemoteControlCalibrationController")
13QGC_LOGGING_CATEGORY(RemoteControlCalibrationControllerVerboseLog, "RemoteControl.RemoteControlCalibrationController:verbose")
14
15static constexpr const char *msgBeginThrottleDown = QT_TRANSLATE_NOOP("RemoteControlCalibrationController",
16 "* Lower the Throttle stick all the way down as shown in diagram\n"
17 "* Please ensure all motor power is disconnected AND all props are removed from the vehicle.\n"
18 "* Click Next to continue"
19);
20static constexpr const char *msgBeginThrottleCenter = QT_TRANSLATE_NOOP("RemoteControlCalibrationController",
21 "* Center all sticks as shown in diagram.\n"
22 "* Make sure any additional axes are at a neutral position.\n"
23 "* Please ensure all motor power is disconnected from the vehicle.\n"
24 "* Click Next to continue"
25);
26static constexpr const char *msgThrottleUp = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Throttle stick all the way up and hold it there...");
27static constexpr const char *msgThrottleDown = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Throttle stick all the way down and leave it there...");
28static constexpr const char *msgYawLeft = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Yaw stick all the way to the left and hold it there...");
29static constexpr const char *msgYawRight = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Yaw stick all the way to the right and hold it there...");
30static constexpr const char *msgRollLeft = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Roll stick all the way to the left and hold it there...");
31static constexpr const char *msgRollRight = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Roll stick all the way to the right and hold it there...");
32static constexpr const char *msgPitchDown = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Pitch stick all the way down and hold it there...");
33static constexpr const char *msgPitchUp = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the Pitch stick all the way up and hold it there...");
34static constexpr const char *msgPitchCenter = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Allow the Pitch stick to move back to center...");
35static constexpr const char *msgExtensionHigh = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move the %1 Extension stick to its high value position and hold it there...");
36static constexpr const char *msgExtensionLow = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "* Move the %1 Extension stick to its low value position and hold it there...\n* Select 'One-Sided' for controls like gamepad triggers.");
37static constexpr const char *msgSwitchMinMaxRC = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Move all the transmitter switches and/or dials back and forth to their extreme positions.");
38static constexpr const char *msgComplete = QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "All settings have been captured. Click Next to write the new parameters to your board.");
39
41 : FactPanelController(parent)
42 , _stateMachine{
43 // stickFunction, stepFunction, channelInputFn, nextButtonFn
44 { stickFunctionMax, StateMachineStepStickNeutral, &RemoteControlCalibrationController::_inputCenterWaitBegin, &RemoteControlCalibrationController::_saveAllTrims },
45 { stickFunctionThrottle, StateMachineStepThrottleUp, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
46 { stickFunctionThrottle, StateMachineStepThrottleDown, &RemoteControlCalibrationController::_inputStickMin, nullptr },
47 { stickFunctionYaw, StateMachineStepYawRight, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
48 { stickFunctionYaw, StateMachineStepYawLeft, &RemoteControlCalibrationController::_inputStickMin, nullptr },
49 { stickFunctionRoll, StateMachineStepRollRight, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
50 { stickFunctionRoll, StateMachineStepRollLeft, &RemoteControlCalibrationController::_inputStickMin, nullptr },
51 { stickFunctionPitch, StateMachineStepPitchUp, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
52 { stickFunctionPitch, StateMachineStepPitchDown, &RemoteControlCalibrationController::_inputStickMin, nullptr },
53 { stickFunctionPitchExtension, StateMachineStepExtensionHighVert, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
54 { stickFunctionPitchExtension, StateMachineStepExtensionLowVert, &RemoteControlCalibrationController::_inputStickMin, nullptr },
55 { stickFunctionRollExtension, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
56 { stickFunctionRollExtension, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
57 { stickFunctionAdditionalAxis1, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
58 { stickFunctionAdditionalAxis1, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
59 { stickFunctionAdditionalAxis2, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
60 { stickFunctionAdditionalAxis2, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
61 { stickFunctionAdditionalAxis3, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
62 { stickFunctionAdditionalAxis3, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
63 { stickFunctionAdditionalAxis4, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
64 { stickFunctionAdditionalAxis4, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
65 { stickFunctionAdditionalAxis5, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
66 { stickFunctionAdditionalAxis5, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
67 { stickFunctionAdditionalAxis6, StateMachineStepExtensionHighHorz, &RemoteControlCalibrationController::_inputStickDetect, nullptr },
68 { stickFunctionAdditionalAxis6, StateMachineStepExtensionLowHorz, &RemoteControlCalibrationController::_inputStickMin, nullptr },
69
70 { stickFunctionMax, StateMachineStepSwitchMinMax, &RemoteControlCalibrationController::_inputSwitchMinMax, &RemoteControlCalibrationController::_advanceState },
71 { stickFunctionMax, StateMachineStepComplete, nullptr, &RemoteControlCalibrationController::_saveCalibrationValues },
72 }
73{
74 _resetInternalCalibrationValues();
75 _loadCalibrationUISettings();
76
77 _stickDisplayPositions = { _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical,
78 _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical };
79
80 if (_vehicle->rover()) {
81 _centeredThrottle = true;
82 }
83
84 _stepFunctionToMsgStringMap = {
85 { StateMachineStepStickNeutral, msgBeginThrottleCenter }, // Adjusted based on throttle centered or not
86 { StateMachineStepThrottleUp, msgThrottleUp },
87 { StateMachineStepThrottleDown, msgThrottleDown },
88 { StateMachineStepYawRight, msgYawRight },
89 { StateMachineStepYawLeft, msgYawLeft },
90 { StateMachineStepRollRight, msgRollRight },
91 { StateMachineStepRollLeft, msgRollLeft },
92 { StateMachineStepPitchUp, msgPitchUp },
93 { StateMachineStepPitchDown, msgPitchDown },
94 { StateMachineStepExtensionHighHorz, msgExtensionHigh },
95 { StateMachineStepExtensionLowHorz, msgExtensionLow },
96 { StateMachineStepExtensionHighVert, msgExtensionHigh },
97 { StateMachineStepExtensionLowVert, msgExtensionLow },
98 { StateMachineStepPitchCenter, msgPitchCenter },
99 { StateMachineStepSwitchMinMax, msgSwitchMinMaxRC },
100 { StateMachineStepComplete, msgComplete },
101 };
102
103 // Map for throttle centered neutral position
104 _bothStickDisplayPositionThrottleCenteredMap = {
105 { StateMachineStepStickNeutral, {
106 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
107 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
108 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
109 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
110 }},
111 { StateMachineStepThrottleUp, {
112 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
113 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
114 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
115 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
116 }},
117 { StateMachineStepThrottleDown, {
118 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
119 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
120 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
121 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
122 }},
123 { StateMachineStepYawRight, {
124 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
125 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
126 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
127 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
128 }},
129 { StateMachineStepYawLeft, {
130 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
131 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
132 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
133 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
134 }},
135 { StateMachineStepRollRight, {
136 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
137 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
138 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
139 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
140 }},
141 { StateMachineStepRollLeft, {
142 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
143 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
144 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
145 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
146 }},
147 { StateMachineStepPitchUp, {
148 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
149 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
150 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
151 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
152 }},
153 { StateMachineStepPitchDown, {
154 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
155 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
156 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
157 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
158 }},
159 { StateMachineStepPitchCenter, {
160 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
161 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
162 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
163 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
164 }},
165 { StateMachineStepExtensionHighHorz, {
166 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
167 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
168 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
169 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
170 }},
171 { StateMachineStepExtensionHighVert, {
172 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
173 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
174 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
175 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
176 }},
177 { StateMachineStepExtensionLowHorz, {
178 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
179 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
180 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
181 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
182 }},
183 { StateMachineStepExtensionLowVert, {
184 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
185 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
186 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
187 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
188 }},
189 { StateMachineStepSwitchMinMax, {
190 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
191 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
192 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
193 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
194 }},
195 { StateMachineStepComplete, {
196 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
197 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
198 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
199 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
200 }},
201 };
202
203 // Map for throttle down neutral position
204 _bothStickDisplayPositionThrottleDownMap = {
205 { StateMachineStepStickNeutral, {
206 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
207 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
208 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
209 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
210 }},
211 { StateMachineStepThrottleUp, {
212 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
213 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
214 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
215 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
216 }},
217 { StateMachineStepThrottleDown, {
218 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
219 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
220 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
221 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
222 }},
223 { StateMachineStepYawRight, {
224 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
225 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
226 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
227 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
228 }},
229 { StateMachineStepYawLeft, {
230 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
231 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
232 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
233 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
234 }},
235 { StateMachineStepRollRight, {
236 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
237 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXRightYCentered } },
238 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
239 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
240 }},
241 { StateMachineStepRollLeft, {
242 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
243 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXLeftYCentered } },
244 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
245 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
246 }},
247 { StateMachineStepPitchUp, {
248 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
249 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
250 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionCentered } },
251 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYUp } },
252 }},
253 { StateMachineStepPitchDown, {
254 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
255 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
256 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
257 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionXCenteredYDown } },
258 }},
259 { StateMachineStepPitchCenter, {
260 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
261 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
262 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
263 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
264 }},
265 { StateMachineStepExtensionHighHorz, {
266 { 1, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
267 { 2, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
268 { 3, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
269 { 4, { _stickDisplayPositionXRightYCentered, _stickDisplayPositionCentered } },
270 }},
271 { StateMachineStepExtensionHighVert, {
272 { 1, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
273 { 2, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
274 { 3, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
275 { 4, { _stickDisplayPositionXCenteredYUp, _stickDisplayPositionXCenteredYUp } },
276 }},
277 { StateMachineStepExtensionLowHorz, {
278 { 1, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
279 { 2, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
280 { 3, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
281 { 4, { _stickDisplayPositionXLeftYCentered, _stickDisplayPositionCentered } },
282 }},
283 { StateMachineStepExtensionLowVert, {
284 { 1, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
285 { 2, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
286 { 3, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
287 { 4, { _stickDisplayPositionXCenteredYDown, _stickDisplayPositionCentered } },
288 }},
289 { StateMachineStepSwitchMinMax, {
290 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
291 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
292 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
293 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
294 }},
295 { StateMachineStepComplete, {
296 { 1, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
297 { 2, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
298 { 3, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
299 { 4, { _stickDisplayPositionCentered, _stickDisplayPositionCentered } },
300 }},
301 };
302}
303
305{
306 _saveCalibrationUISettings();
307
308 // qCDebug(RemoteControlCalibrationControllerLog) << Q_FUNC_INFO << this;
309}
310
312{
313 _stopCalibration();
314 _readStoredCalibrationValues();
315}
316
317const RemoteControlCalibrationController::StateMachineEntry &RemoteControlCalibrationController::_getStateMachineEntry(int step) const
318{
319 if (step < 0 || step >= _stateMachine.size()) {
320 qCWarning(RemoteControlCalibrationControllerLog) << "Bad step value" << step;
321 step = 0;
322 }
323
324 return _stateMachine[step];
325}
326
327void RemoteControlCalibrationController::_advanceState()
328{
329 _currentStep++;
330 if (_currentStep >= _stateMachine.size()) {
331 _stopCalibration();
332 return;
333 }
334
335 _setupCurrentState();
336}
337
338void RemoteControlCalibrationController::_setupCurrentState()
339{
340 auto state = _getStateMachineEntry(_currentStep);
341
342 // If the stick function for this step is not enabled, skip to next step
343 if (state.stickFunction != stickFunctionMax && !_stickFunctionEnabled(state.stickFunction)) {
344 qCDebug(RemoteControlCalibrationControllerLog) << "Skipping step" << _currentStep << "for disabled stick function" << _stickFunctionToString(state.stickFunction);
345 _advanceState();
346 return;
347 }
348
349 // StateMachineStepSwitchMinMax is only used for RC transmitters
350 if (_joystickMode && state.stepFunction == StateMachineStepSwitchMinMax) {
351 _advanceState();
352 return;
353 }
354
355 _stepFunctionToMsgStringMap[StateMachineStepStickNeutral] = _centeredThrottle ? msgBeginThrottleCenter : msgBeginThrottleDown;
356
357 BothSticksDisplayPositions defaultPositions = { _stickDisplayPositionCentered, _stickDisplayPositionCentered };
358 BothSticksDisplayPositions bothStickPositions = _centeredThrottle
359 ? _bothStickDisplayPositionThrottleCenteredMap.value(state.stepFunction).value(_transmitterMode, defaultPositions)
360 : _bothStickDisplayPositionThrottleDownMap.value(state.stepFunction).value(_transmitterMode, defaultPositions);
361
362 QString msg = QCoreApplication::translate("RemoteControlCalibrationController", _stepFunctionToMsgStringMap.value(state.stepFunction, ""));
363 if (state.stepFunction == StateMachineStepExtensionHighHorz || state.stepFunction == StateMachineStepExtensionHighVert ||
364 state.stepFunction == StateMachineStepExtensionLowHorz || state.stepFunction == StateMachineStepExtensionLowVert) {
365 static const QMap <StickFunction, const char*> extensionNameMap = {
366 { stickFunctionPitchExtension, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Pitch") },
367 { stickFunctionRollExtension, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Roll") },
368 { stickFunctionAdditionalAxis1, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Aux 1") },
369 { stickFunctionAdditionalAxis2, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Aux 2") },
370 { stickFunctionAdditionalAxis3, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Aux 3") },
371 { stickFunctionAdditionalAxis4, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Aux 4") },
372 { stickFunctionAdditionalAxis5, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Aux 5") },
373 { stickFunctionAdditionalAxis6, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Aux 6") },
374 };
375 const char* extName = extensionNameMap.value(state.stickFunction, QT_TRANSLATE_NOOP("RemoteControlCalibrationController", "Unknown"));
376 msg = msg.arg(QCoreApplication::translate("RemoteControlCalibrationController", extName));
377 }
378
379 _setSingleStickDisplay(state.stepFunction == StateMachineStepExtensionHighHorz || state.stepFunction == StateMachineStepExtensionHighVert ||
380 state.stepFunction == StateMachineStepExtensionLowHorz || state.stepFunction == StateMachineStepExtensionLowVert);
381
382 _statusText->setProperty("text", msg);
383 _stickDisplayPositions = { bothStickPositions.leftStick.horizontal, bothStickPositions.leftStick.vertical,
384 bothStickPositions.rightStick.horizontal, bothStickPositions.rightStick.vertical };
386
387 _stickDetectChannel = _chanMax;
388 _stickDetectSettleStarted = false;
389
390 _saveCurrentRawValues();
391
392 _nextButton->setEnabled(state.nextButtonFn != nullptr);
394}
395
396void RemoteControlCalibrationController::_processChannelValues(QVector<int> channelValues)
397{
398 auto channelCount = channelValues.size();
399 if (channelCount > _chanMax) {
400 qCWarning(RemoteControlCalibrationControllerLog) << "Too many channels:" << channelCount << ", max is" << _chanMax;
402 }
403
404 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "channelValues" << channelValues;
405
406 for (int channel=0; channel<channelCount; channel++) {
407 const int channelValue = channelValues[channel];
408 const ChannelInfo &channelInfo = _rgChannelInfo[channel];
409 const int adjustedValue = _adjustChannelRawValue(channelInfo, channelValue);
410
411 _channelRawValue[channel] = channelValue;
412 emit rawChannelValueChanged(channel, channelValue);
413
414 // Signal attitude rc values to Qml if mapped
415 if (channelInfo.stickFunction != stickFunctionMax) {
416 switch (channelInfo.stickFunction) {
418 emit adjustedRollChannelValueChanged(adjustedValue);
419 break;
421 emit adjustedPitchChannelValueChanged(adjustedValue);
422 break;
423 case stickFunctionYaw:
424 emit adjustedYawChannelValueChanged(adjustedValue);
425 break;
427 emit adjustedThrottleChannelValueChanged(adjustedValue);
428 break;
431 break;
434 break;
437 break;
440 break;
443 break;
446 break;
449 break;
452 break;
453 default:
454 break;
455 }
456 }
457
458 if (_currentStep == -1) {
459 if (_chanCount != channelCount) {
462 }
463 } else {
464 auto state = _getStateMachineEntry(_currentStep);
465 if (state.channelInputFn) {
466 (this->*state.channelInputFn)(state.stickFunction, channel, channelValue);
467 }
468 }
469 }
470}
471
473{
474 if (_currentStep == -1) {
475 // Need to have enough channels
476 if (_chanCount < _chanMinimum) {
477 QGC::showAppMessage(QStringLiteral("Detected %1 channels. To operate vehicle, you need at least %2 channels.").arg(_chanCount).arg(_chanMinimum));
478 return;
479 }
480 _startCalibration();
481 } else {
482 auto state = _getStateMachineEntry(_currentStep);
483 if (state.nextButtonFn) {
484 (this->*state.nextButtonFn)();
485 }
486 }
487}
488
490{
491 if (!oneSidedButtonVisible()) {
492 return;
493 }
494
495 _applyOneSidedCalibration();
496}
497
499{
500 _stopCalibration();
501}
502
503void RemoteControlCalibrationController::_saveAllTrims()
504{
505 // We save all trims as the first step. At this point no channels are mapped but it should still
506 // allow us to get good trims for the roll/pitch/yaw/throttle even though we don't know which
507 // channels they are yet. AS we continue through the process the other channels will get their
508 // trims reset to correct values.
509
510 for (int i=0; i<_chanCount; i++) {
511 qCDebug(RemoteControlCalibrationControllerLog) << "_saveAllTrims channel:trim" << i << _channelRawValue[i];
512 _rgChannelInfo[i].channelTrim = _channelRawValue[i];
513 }
514 _advanceState();
515}
516
517void RemoteControlCalibrationController::_inputCenterWaitBegin(StickFunction /*stickFunction*/, int channel, int value)
518{
519 if (_joystickMode) {
520 // Track deadband adjustments in joystick mode
521 int newDeadband = abs(value) * 1.1; // add 10% on top for fudge factor
522 if (newDeadband > _rgChannelInfo[channel].deadband) {
523 _rgChannelInfo[channel].deadband = qMin(newDeadband, _calValidMaxValue );
524 qCDebug(RemoteControlCalibrationControllerLog) << "Channel:" << channel << "Deadband:" << _rgChannelInfo[channel].deadband;
525 StickFunction stickFunction = _rgChannelInfo[channel].stickFunction;
526 if (stickFunction != stickFunctionMax) {
527 _emitDeadbandChanged(stickFunction);
528 }
529 }
530 }
531
532 _nextButton->setEnabled(true);
533}
534
535bool RemoteControlCalibrationController::_stickSettleComplete(int value)
536{
537 // We are waiting for the stick to settle out to a max position
538
539 if (abs(_stickDetectValue - value) > _calSettleDelta) {
540 // Stick is moving too much to consider stopped
541 _stickDetectValue = value;
542 _stickDetectSettleStarted = false;
543 qCDebug(RemoteControlCalibrationControllerLog) << "Still moving - _stickDetectValue" << value;
544 } else {
545 // Stick is still positioned within the specified small range
546
547 if (_stickDetectSettleStarted) {
548 // We have already started waiting
549
550 if (_stickDetectSettleElapsed.elapsed() > _stickDetectSettleMSecs) {
551 // Stick has stayed positioned in one place long enough, detection is complete.
552 return true;
553 }
554 } else {
555 // Start waiting for the stick to stay settled for _stickDetectSettleWaitMSecs msecs
556
557 qCDebug(RemoteControlCalibrationControllerLog) << "Starting settle timer - _stickDetectValue:value" << _stickDetectValue << value;
558
559 _stickDetectSettleStarted = true;
560 _stickDetectSettleElapsed.start();
561 }
562 }
563
564 return false;
565}
566
567void RemoteControlCalibrationController::_inputStickDetect(StickFunction stickFunction, int channel, int value)
568{
569 // If this channel is already used in a mapping we can't use it again
570 if (_rgChannelInfo[channel].stickFunction != stickFunctionMax) {
571 return;
572 }
573
574 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "_inputStickDetect function:channel:value" << _stickFunctionToString(stickFunction) << channel << value;
575
576 if (_stickDetectChannel == _chanMax) {
577 // We have not detected enough movement on a channel yet
578 // Note: We intentionally require movement here (not just being at extreme) because
579 // this function is called for ALL channels, and some (like triggers) may rest at
580 // extreme positions. Requiring movement ensures we detect the correct channel.
581
582 if (abs(_channelValueSave[channel] - value) > _calMoveDelta) {
583 // Stick has moved far enough to consider it as being selected for the function
584
585 qCDebug(RemoteControlCalibrationControllerLog) << "Starting settle wait - function:channel" << _stickFunctionToString(stickFunction) << channel;
586
587 // Setup up to detect stick being pegged to min or max value
588 _stickDetectChannel = channel;
589 _stickDetectValue = value;
590 }
591 } else if (channel == _stickDetectChannel) {
592 if (_stickSettleComplete(value)) {
593 ChannelInfo *const info = &_rgChannelInfo[channel];
594
595 // Map the channel to the function
596 _rgFunctionChannelMapping[stickFunction] = channel;
597 info->stickFunction = stickFunction;
598
599 // A non-reversed channel should show a higher value than center.
600 info->channelReversed = value < _channelValueSave[channel];
601 if (info->channelReversed) {
602 _rgChannelInfo[channel].channelMin = value;
603 } else {
604 _rgChannelInfo[channel].channelMax = value;
605 }
606
607 qCDebug(RemoteControlCalibrationControllerLog) <<
608 QStringLiteral("Stick detected - function:channel:reversed:trim:%1").arg(info->channelReversed ? "min" : "max") <<
609 _stickFunctionToString(stickFunction) << channel << info->channelReversed << info->channelTrim <<
610 (info->channelReversed ? info->channelMin : info->channelMax);
611
613
614 _advanceState();
615 }
616 }
617}
618
619void RemoteControlCalibrationController::_inputStickMin(StickFunction stickFunction, int channel, int value)
620{
621 // We only care about the channel mapped to the function we are working on
622 if (_rgFunctionChannelMapping[stickFunction] != channel) {
623 return;
624 }
625
626 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "_inputStickMin function:channel:value" << _stickFunctionToString(stickFunction) << channel << value;
627
628 if (_stickDetectChannel == _chanMax) {
629 if (_rgChannelInfo[channel].channelReversed) {
630 if (value > _calCenterPoint + _calMoveDelta) {
631 qCDebug(RemoteControlCalibrationControllerLog) << "Movement detected, starting settle wait";
632 _stickDetectChannel = channel;
633 _stickDetectValue = value;
634 }
635 } else {
636 if (value < _calCenterPoint - _calMoveDelta) {
637 qCDebug(RemoteControlCalibrationControllerLog) << "Movement detected, starting settle wait";
638 _stickDetectChannel = channel;
639 _stickDetectValue = value;
640 }
641 }
642 } else {
643 // We are waiting for the selected channel to settle out
644 if (_stickSettleComplete(value)) {
645 auto& channelInfo = _rgChannelInfo[channel];
646
647 // Stick detection is complete. Stick should be at extreme position.
648 if (channelInfo.channelReversed) {
649 channelInfo.channelMax = value;
650 } else {
651 channelInfo.channelMin = value;
652 }
653
654 // Check if this is throttle and set trim accordingly
655 if (!_joystickMode && stickFunction == stickFunctionThrottle) {
656 channelInfo.channelTrim = value;
657 }
658
659 qCDebug(RemoteControlCalibrationControllerLog) << "Settle complete - function:channel:min:max:trim" << _stickFunctionToString(stickFunction) << channel << channelInfo.channelMin << channelInfo.channelMax << channelInfo.channelTrim;
660
661 _advanceState();
662 }
663 }
664}
665
666void RemoteControlCalibrationController::_inputCenterWait(StickFunction stickFunction, int channel, int value)
667{
668 // We only care about the channel mapped to the function we are working on
669 if (_rgFunctionChannelMapping[stickFunction] != channel) {
670 return;
671 }
672
673 qCDebug(RemoteControlCalibrationControllerLog) << "_inputCenterWait function:channel:value" << _stickFunctionToString(stickFunction) << channel << value;
674 if (_stickDetectChannel == _chanMax) {
675 // Sticks have not yet moved close enough to center
676
677 if (abs(_calCenterPoint - value) < _calRoughCenterDelta) {
678 // Stick has moved close enough to center that we can start waiting for it to settle
679 qCDebug(RemoteControlCalibrationControllerLog) << "_inputCenterWait Center detected. Waiting for settle.";
680 _stickDetectChannel = channel;
681 _stickDetectValue = value;
682 }
683 } else {
684 if (_stickSettleComplete(value)) {
685 _advanceState();
686 }
687 }
688}
689
690void RemoteControlCalibrationController::_applyOneSidedCalibration()
691{
692 if (!_isOneSidedCalibrationStep(_currentStep)) {
693 return;
694 }
695
696 const StateMachineEntry &state = _getStateMachineEntry(_currentStep);
697 const int channel = _rgFunctionChannelMapping[state.stickFunction];
698 if (channel < 0 || channel >= _chanMax) {
699 return;
700 }
701
702 ChannelInfo &channelInfo = _rgChannelInfo[channel];
703 const int trimValue = channelInfo.channelTrim;
704 if (channelInfo.channelReversed) {
705 channelInfo.channelMax = trimValue;
706 } else {
707 channelInfo.channelMin = trimValue;
708 }
709
710 qCDebug(RemoteControlCalibrationControllerLog)
711 << "Applying one-sided calibration - function:channel:reversed:trim:min:max"
712 << _stickFunctionToString(state.stickFunction)
713 << channel
714 << channelInfo.channelReversed
715 << channelInfo.channelTrim
716 << channelInfo.channelMin
717 << channelInfo.channelMax;
718
719 _advanceState();
720}
721
722void RemoteControlCalibrationController::_inputSwitchMinMax(StickFunction /*stickFunction*/, int channel, int value)
723{
724 // If the channel is mapped we already have min/max
725 if (_rgChannelInfo[channel].stickFunction != stickFunctionMax) {
726 return;
727 }
728
729 if (abs(_calCenterPoint - value) > _calMoveDelta) {
730 // Stick has moved far enough from center to consider for min/max
731 if (value < _calCenterPoint) {
732 const int minValue = qMin(_rgChannelInfo[channel].channelMin, value);
733
734 qCDebug(RemoteControlCalibrationControllerLog) << "setting min channel:min" << channel << minValue;
735
736 _rgChannelInfo[channel].channelMin = minValue;
737 } else {
738 int maxValue = qMax(_rgChannelInfo[channel].channelMax, value);
739
740 qCDebug(RemoteControlCalibrationControllerLog) << "setting max channel:max" << channel << maxValue;
741
742 _rgChannelInfo[channel].channelMax = maxValue;
743 }
744 }
745}
746
748{
749 // Set all raw channels to not reversed and center point values
750 for (int i = 0; i < _chanMax; i++) {
751 ChannelInfo *const info = &_rgChannelInfo[i];
753 info->channelReversed = false;
757 info->deadband = 0;
758 }
759
760 // Initialize attitude function mapping to function channel not set
761 for (size_t i = 0; i < stickFunctionMax; i++) {
763 }
764
766}
767
769{
770 for (int chan = 0; chan<_chanMax; chan++) {
771 auto& channelInfo = _rgChannelInfo[chan];
772
773 if (chan < _chanCount) {
774 const bool extensionFunction = channelInfo.stickFunction == stickFunctionPitchExtension ||
775 channelInfo.stickFunction == stickFunctionRollExtension ||
776 channelInfo.stickFunction == stickFunctionAdditionalAxis1 ||
777 channelInfo.stickFunction == stickFunctionAdditionalAxis2 ||
778 channelInfo.stickFunction == stickFunctionAdditionalAxis3 ||
779 channelInfo.stickFunction == stickFunctionAdditionalAxis4 ||
780 channelInfo.stickFunction == stickFunctionAdditionalAxis5 ||
781 channelInfo.stickFunction == stickFunctionAdditionalAxis6;
782 const bool positiveOnlyExtension = extensionFunction &&
783 (channelInfo.channelTrim == channelInfo.channelMin) &&
784 (channelInfo.channelMax >= _calValidMaxValue);
785 const bool negativeOnlyExtension = extensionFunction &&
786 (channelInfo.channelTrim == channelInfo.channelMax) &&
787 (channelInfo.channelMin <= _calValidMinValue);
788 const bool oneSidedExtension = positiveOnlyExtension || negativeOnlyExtension;
789
790 // Validate Min/Max values. Although the channel appears as available we still may
791 // not have good min/max/trim values for it. Set to defaults if needed.
792 if (!oneSidedExtension && (channelInfo.channelMin > _calValidMinValue || channelInfo.channelMax < _calValidMaxValue)) {
793 qCDebug(RemoteControlCalibrationControllerLog) << "resetting channel invalid min/max - chan:channelMin:calValidMinValue:channelMax:calValidMaxValue"
794 << chan << channelInfo.channelMin << _calValidMinValue << channelInfo.channelMax << _calValidMaxValue;
795 channelInfo.channelMin = _calDefaultMinValue;
796 channelInfo.channelMax = _calDefaultMaxValue;
797 channelInfo.channelTrim = channelInfo.channelMin + ((channelInfo.channelMax - channelInfo.channelMin) / 2);
798 } else {
799 if (oneSidedExtension) {
800 continue;
801 }
802
803 switch (channelInfo.stickFunction) {
805 case stickFunctionYaw:
808 // Make sure trim is within min/max
809 channelInfo.channelTrim = std::clamp(channelInfo.channelTrim, channelInfo.channelMin, channelInfo.channelMax);
810 break;
811 default:
812 // Non-attitude control channels have calculated trim
813 channelInfo.channelTrim = channelInfo.channelMin + ((channelInfo.channelMax - channelInfo.channelMin) / 2);
814 break;
815 }
816
817 }
818 } else {
819 // Unavailable channels are set to defaults
820 qCDebug(RemoteControlCalibrationControllerLog) << "resetting unavailable channel" << chan;
821 channelInfo.channelMin = _calDefaultMinValue;
822 channelInfo.channelMax = _calDefaultMaxValue;
823 channelInfo.channelTrim = channelInfo.channelMin + ((channelInfo.channelMax - channelInfo.channelMin) / 2);
824 channelInfo.channelReversed = false;
825 channelInfo.deadband = 0;
826 channelInfo.stickFunction = stickFunctionMax;
827
828 }
829 }
830}
831
832void RemoteControlCalibrationController::_startCalibration()
833{
834 if (_chanCount < _chanMinimum) {
835 qCWarning(RemoteControlCalibrationControllerLog) << "Call to RemoteControlCalibrationController::_startCalibration with _chanCount < _chanMinimum";
836 return;
837 }
838
840
841 if (!_calibrating) {
842 _calibrating = true;
843 emit calibratingChanged(true);
844 }
845
846 _nextButton->setProperty("text", tr("Next"));
847 _cancelButton->setEnabled(true);
848
849 _currentStep = 0;
850 _setupCurrentState();
851}
852
853void RemoteControlCalibrationController::_setSingleStickDisplay(bool singleStickDisplay)
854{
855 if (_singleStickDisplay != singleStickDisplay) {
856 _singleStickDisplay = singleStickDisplay;
858 }
859}
860
861void RemoteControlCalibrationController::_stopCalibration()
862{
863 _currentStep = -1;
864
865 if (_vehicle) {
866 _readStoredCalibrationValues();
867 }
868
869 if (_calibrating) {
870 _calibrating = false;
871 emit calibratingChanged(false);
872 }
873
874 if (_statusText) {
875 _statusText->setProperty("text", "");
876 }
877 if (_nextButton) {
878 _nextButton->setProperty("text", tr("Calibrate"));
879 }
880 if (_nextButton) {
881 _nextButton->setEnabled(true);
882 }
883 if (_cancelButton) {
884 _cancelButton->setEnabled(false);
885 }
886
887 _stickDisplayPositions = { _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical,
888 _stickDisplayPositionCentered.horizontal, _stickDisplayPositionCentered.vertical };
891}
892
894{
895 return _calibrating && _isOneSidedCalibrationStep(_currentStep);
896}
897
898bool RemoteControlCalibrationController::_isOneSidedCalibrationStep(int step) const
899{
900 if (step < 0 || step >= _stateMachine.size()) {
901 return false;
902 }
903
904 const StateMachineEntry &entry = _stateMachine[step];
905 const bool isLowStep = entry.stepFunction == StateMachineStepExtensionLowHorz || entry.stepFunction == StateMachineStepExtensionLowVert;
906 const bool isAdditionalAxis = entry.stickFunction >= stickFunctionAdditionalAxis1 && entry.stickFunction < stickFunctionMax;
907 return isLowStep && isAdditionalAxis;
908}
909
910void RemoteControlCalibrationController::_saveCurrentRawValues()
911{
912 for (int i = 0; i < _chanMax; i++) {
913 _channelValueSave[i] = _channelRawValue[i];
914 qCDebug(RemoteControlCalibrationControllerVerboseLog) << "_saveCurrentRawValues channel:value" << i << _channelValueSave[i];
915 }
916}
917
919int RemoteControlCalibrationController::_adjustChannelRawValue(const ChannelInfo& info, int rawValue) const
920{
921 if (!info.channelReversed) {
922 return rawValue;
923 }
924
925 const int invertedValue = info.channelMin + info.channelMax - rawValue;
926 return std::clamp(invertedValue, info.channelMin, info.channelMax);
927}
928
929void RemoteControlCalibrationController::_loadCalibrationUISettings()
930{
931 QSettings settings;
932
933 settings.beginGroup(_settingsGroup);
934 _transmitterMode = settings.value(_settingsKeyTransmitterMode, 2).toInt();
935 settings.endGroup();
936
937 if (_transmitterMode < 1 || _transmitterMode > 4) {
938 _transmitterMode = 2;
939 }
940}
941
942void RemoteControlCalibrationController::_saveCalibrationUISettings()
943{
944 QSettings settings;
945
946 settings.beginGroup(_settingsGroup);
947 settings.setValue(_settingsKeyTransmitterMode, _transmitterMode);
948 settings.endGroup();
949}
950
952{
954 if (channel != _chanMax) {
955 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
956 } else {
957 return _calCenterPoint;
958 }
959}
960
962{
964 if (channel != _chanMax) {
965 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
966 } else {
967 return _calCenterPoint;
968 }
969}
970
972{
974 if (channel != _chanMax) {
975 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
976 } else {
977 return _calCenterPoint;
978 }
979}
980
982{
984 if (channel != _chanMax) {
985 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
986 } else {
987 return _calCenterPoint;
988 }
989}
990
992{
994 if (channel != _chanMax) {
995 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
996 } else {
997 return _calCenterPoint;
998 }
999}
1000
1002{
1004 if (channel != _chanMax) {
1005 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1006 } else {
1007 return _calCenterPoint;
1008 }
1009}
1010
1012{
1014 if (channel != _chanMax) {
1015 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1016 } else {
1017 return _calCenterPoint;
1018 }
1019}
1020
1022{
1024 if (channel != _chanMax) {
1025 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1026 } else {
1027 return _calCenterPoint;
1028 }
1029}
1030
1032{
1034 if (channel != _chanMax) {
1035 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1036 } else {
1037 return _calCenterPoint;
1038 }
1039}
1040
1042{
1044 if (channel != _chanMax) {
1045 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1046 } else {
1047 return _calCenterPoint;
1048 }
1049}
1050
1052{
1054 if (channel != _chanMax) {
1055 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1056 } else {
1057 return _calCenterPoint;
1058 }
1059}
1060
1062{
1064 if (channel != _chanMax) {
1065 return _adjustChannelRawValue(_rgChannelInfo[channel], _channelRawValue[channel]);
1066 } else {
1067 return _calCenterPoint;
1068 }
1069}
1070
1075
1080
1085
1090
1095
1100
1105
1110
1115
1120
1125
1130
1135
1140
1145
1150
1155
1160
1165
1170
1179
1188
1197
1206
1215
1224
1233
1242
1251
1260
1269
1278
1280{
1281 if (mode < 1 || mode > 4) {
1282 qCWarning(RemoteControlCalibrationControllerLog) << "Invalid transmitter mode set:" << mode;
1283 mode = 2;
1284 }
1285 if (_transmitterMode != mode) {
1286 _transmitterMode = mode;
1288 }
1289}
1290
1292{
1305
1318
1319 _emitDeadbandChanged(stickFunctionRoll);
1320 _emitDeadbandChanged(stickFunctionPitch);
1321 _emitDeadbandChanged(stickFunctionRollExtension);
1322 _emitDeadbandChanged(stickFunctionPitchExtension);
1323 _emitDeadbandChanged(stickFunctionAdditionalAxis1);
1324 _emitDeadbandChanged(stickFunctionAdditionalAxis2);
1325 _emitDeadbandChanged(stickFunctionAdditionalAxis3);
1326 _emitDeadbandChanged(stickFunctionAdditionalAxis4);
1327 _emitDeadbandChanged(stickFunctionAdditionalAxis5);
1328 _emitDeadbandChanged(stickFunctionAdditionalAxis6);
1329 _emitDeadbandChanged(stickFunctionYaw);
1330 _emitDeadbandChanged(stickFunctionThrottle);
1331}
1332
1334{
1335 return _deadbandForFunction(stickFunctionRoll);
1336}
1337
1339{
1340 return _deadbandForFunction(stickFunctionPitch);
1341}
1342
1347
1352
1357
1362
1367
1372
1377
1382
1384{
1385 return _deadbandForFunction(stickFunctionYaw);
1386}
1387
1389{
1390 return _deadbandForFunction(stickFunctionThrottle);
1391}
1392
1397
1399{
1400 switch (stickFunction) {
1401 case stickFunctionRoll:
1402 return tr("Roll");
1403 case stickFunctionPitch:
1404 return tr("Pitch");
1405 case stickFunctionYaw:
1406 return tr("Yaw");
1408 return tr("Throttle");
1410 return tr("Additional Axis 1");
1412 return tr("Additional Axis 2");
1414 return tr("Additional Axis 3");
1416 return tr("Additional Axis 4");
1418 return tr("Additional Axis 5");
1420 return tr("Additional Axis 6");
1422 return tr("Pitch Extension");
1424 return tr("Roll Extension");
1425 default:
1426 return tr("Unknown");
1427 }
1428}
1429
1431{
1432 if (_centeredThrottle != centered) {
1433 _centeredThrottle = centered;
1434 emit centeredThrottleChanged(centered);
1435 }
1436}
1437
1439{
1440 if (_joystickMode == joystickMode) {
1441 return;
1442 }
1443
1444 _joystickMode = joystickMode;
1446 emit joystickModeChanged(_joystickMode);
1447}
1448
1449int RemoteControlCalibrationController::_deadbandForFunction(StickFunction stickFunction) const
1450{
1451 if (stickFunction < 0 || stickFunction >= stickFunctionMax) {
1452 return 0;
1453 }
1454
1455 int channel = _rgFunctionChannelMapping[stickFunction];
1456 if (channel != _chanMax) {
1457 return _rgChannelInfo[channel].deadband;
1458 }
1459
1460 return 0;
1461}
1462
1463void RemoteControlCalibrationController::_emitDeadbandChanged(StickFunction stickFunction)
1464{
1465 const int deadband = _deadbandForFunction(stickFunction);
1466 switch (stickFunction) {
1467 case stickFunctionRoll: emit rollDeadbandChanged(deadband); break;
1468 case stickFunctionPitch: emit pitchDeadbandChanged(deadband); break;
1469 case stickFunctionYaw: emit yawDeadbandChanged(deadband); break;
1470 case stickFunctionThrottle: emit throttleDeadbandChanged(deadband); break;
1471 case stickFunctionRollExtension: emit rollExtensionDeadbandChanged(deadband); break;
1479 default:
1480 break;
1481 }
1482}
1483
1484void RemoteControlCalibrationController::_saveCalibrationValues()
1485{
1486 _saveStoredCalibrationValues();
1487 emit calibrationCompleted();
1488 _advanceState();
1489}
1490
1492{
1493 // By default only calibrate attitude control functions
1494 switch (stickFunction) {
1495 case stickFunctionRoll:
1496 case stickFunctionPitch:
1497 case stickFunctionYaw:
1499 return true;
1500 default:
1501 return false;
1502 }
1503}
#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)
void additionalAxis2DeadbandChanged(int deadband)
QString _stickFunctionToString(StickFunction stickFunction)
void pitchChannelReversedChanged(bool reversed)
int _calValidMinValue
Largest valid minimum channel range value.
void joystickModeChanged(bool joystickMode)
void pitchExtensionDeadbandChanged(int deadband)
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)
void additionalAxis4ChannelMappedChanged(bool mapped)
StickFunction
These identify the various controls functions. They are also used as indices into the _rgFunctioInfo ...
int _calMoveDelta
Amount of delta past center which is considered stick movement.
void singleStickDisplayChanged(bool singleStickDisplay)
void oneSidedButtonVisibleChanged(bool visible)
void additionalAxis1ChannelMappedChanged(bool mapped)
void adjustedThrottleChannelValueChanged(int rcValue)
void adjustedAdditionalAxis4ChannelValueChanged(int rcValue)
void additionalAxis5ChannelReversedChanged(bool reversed)
void _resetInternalCalibrationValues()
Resets internal calibration values to their initial state in preparation for a new calibration sequen...
void additionalAxis3DeadbandChanged(int deadband)
void additionalAxis5ChannelMappedChanged(bool mapped)
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)
void additionalAxis6ChannelMappedChanged(bool mapped)
int _stickDetectSettleMSecs
Time in ms stick must be stable before detection completes.
void additionalAxis2ChannelMappedChanged(bool mapped)
void additionalAxis6DeadbandChanged(int deadband)
void rollExtensionDeadbandChanged(int deadband)
void additionalAxis2ChannelReversedChanged(bool reversed)
void yawChannelReversedChanged(bool reversed)
void rollExtensionChannelMappedChanged(bool mapped)
void adjustedAdditionalAxis6ChannelValueChanged(int rcValue)
void adjustedRollChannelValueChanged(int rcValue)
void rollDeadbandChanged(int deadband)
void adjustedYawChannelValueChanged(int rcValue)
virtual bool _stickFunctionEnabled(StickFunction stickFunction)
Returns true if the stick function is enabled.
void adjustedAdditionalAxis2ChannelValueChanged(int rcValue)
void additionalAxis4ChannelReversedChanged(bool reversed)
void additionalAxis4DeadbandChanged(int deadband)
void additionalAxis6ChannelReversedChanged(bool reversed)
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)
void additionalAxis3ChannelReversedChanged(bool reversed)
int _calSettleDelta
Amount of delta which is considered no stick movement.
void additionalAxis5DeadbandChanged(int deadband)
ChannelInfo _rgChannelInfo[_chanMax]
Information associated with each rc channel.
void additionalAxis1DeadbandChanged(int deadband)
void adjustedAdditionalAxis5ChannelValueChanged(int rcValue)
void additionalAxis1ChannelReversedChanged(bool reversed)
void calibratingChanged(bool calibrating)
void adjustedAdditionalAxis3ChannelValueChanged(int rcValue)
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 throttleChannelReversedChanged(bool reversed)
void pitchExtensionChannelMappedChanged(bool mapped)
void yawChannelMappedChanged(bool mapped)
void additionalAxis3ChannelMappedChanged(bool mapped)
void adjustedPitchExtensionChannelValueChanged(int rcValue)
void adjustedAdditionalAxis1ChannelValueChanged(int rcValue)
void startCalibration(QGCMAVLink::CalibrationType calType)
Definition Vehicle.cc:2325
void showAppMessage(const QString &message, const QString &title)
Modal application message. Queued if the UI isn't ready yet.
Definition AppMessages.cc:9
int channelTrim
Trim position (usually center for sticks)
enum StickFunction stickFunction
Function mapped to this channel, stickFunctionMax for none.