16#include <QtCore/QCoreApplication>
18#include <QtCore/QSettings>
19#include <QtCore/QThread>
26static constexpr const char* kButtonActionArrayGroup =
"JoystickButtonActionSettingsArray";
27static constexpr const char* kButtonActionNameKey =
"actionName";
28static constexpr const char* kButtonRepeatKey =
"repeat";
29static constexpr const char* kAxisSettingsArrayGroup =
"JoystickAxisSettingsArray";
30static constexpr const char* kAxisFunctionKey =
"function";
31static constexpr const char* kAxisMinKey =
"min";
32static constexpr const char* kAxisMaxKey =
"max";
33static constexpr const char* kAxisCenterKey =
"center";
34static constexpr const char* kAxisDeadbandKey =
"deadband";
35static constexpr const char* kAxisReversedKey =
"reversed";
41 : actionName(actionName_)
44 qCDebug(JoystickLog) <<
this;
47AvailableButtonAction::AvailableButtonAction(
const QString &actionName_,
bool canRepeat_, QObject *parent)
49 , _actionName(actionName_)
52 qCDebug(JoystickLog) <<
this;
57Joystick::Joystick(
const QString &name,
int axisCount,
int buttonCount,
int hatCount, QObject *parent)
60 , _axisCount(axisCount)
61 , _buttonCount(buttonCount)
63 , _hatButtonCount(4 * hatCount)
64 , _totalButtonCount(_buttonCount + _hatButtonCount)
65 , _rgCalibration(_axisCount)
66 , _buttonEventStates(_totalButtonCount)
67 , _assignedButtonActions(_totalButtonCount, nullptr)
71 , _joystickSettings(name, _axisCount, _totalButtonCount)
75 <<
"axisCount:" << axisCount
76 <<
"buttonCount:" << buttonCount
77 <<
"hatCount:" << hatCount
80 if (QCoreApplication *
const app = QCoreApplication::instance()) {
81 QThread *
const guiThread = app->thread();
82 if (_joystickSettings.thread() != guiThread) {
83 _joystickSettings.moveToThread(guiThread);
86 const auto ensureFactThread = [guiThread](
Fact *fact) {
87 if (fact && fact->thread() != guiThread) {
88 fact->moveToThread(guiThread);
92 ensureFactThread(_joystickSettings.calibrated());
93 ensureFactThread(_joystickSettings.circleCorrection());
94 ensureFactThread(_joystickSettings.useDeadband());
95 ensureFactThread(_joystickSettings.negativeThrust());
96 ensureFactThread(_joystickSettings.throttleSmoothing());
97 ensureFactThread(_joystickSettings.axisFrequencyHz());
98 ensureFactThread(_joystickSettings.buttonFrequencyHz());
99 ensureFactThread(_joystickSettings.throttleModeCenterZero());
100 ensureFactThread(_joystickSettings.transmitterMode());
101 ensureFactThread(_joystickSettings.exponentialPct());
102 ensureFactThread(_joystickSettings.enableManualControlAux1());
103 ensureFactThread(_joystickSettings.enableManualControlAux2());
104 ensureFactThread(_joystickSettings.enableManualControlAux3());
105 ensureFactThread(_joystickSettings.enableManualControlAux4());
106 ensureFactThread(_joystickSettings.enableManualControlAux5());
107 ensureFactThread(_joystickSettings.enableManualControlAux6());
111 connect(_joystickSettings.enableManualControlPitchExtension(), &
Fact::rawValueChanged,
this, [
this]() {
112 _joystickSettings.calibrated()->setRawValue(false);
114 connect(_joystickSettings.enableManualControlRollExtension(), &
Fact::rawValueChanged,
this, [
this]() {
115 _joystickSettings.calibrated()->setRawValue(false);
118 _joystickSettings.calibrated()->setRawValue(false);
121 _joystickSettings.calibrated()->setRawValue(false);
124 _joystickSettings.calibrated()->setRawValue(false);
127 _joystickSettings.calibrated()->setRawValue(false);
130 _joystickSettings.calibrated()->setRawValue(false);
133 _joystickSettings.calibrated()->setRawValue(false);
136 _resetFunctionToAxisMap();
137 _resetAxisCalibrationData();
138 _resetButtonActionData();
139 _resetButtonEventStates();
141 _buildAvailableButtonsActionList(MultiVehicleManager::instance()->activeVehicle());
143 _loadFromSettingsIntoCalibrationData();
150 if (QThread::currentThread() ==
this) {
151 qCWarning(JoystickLog) <<
"Skipping wait() on joystick thread";
157 _resetButtonActionData();
161void Joystick::_resetFunctionToAxisMap()
163 _axisFunctionToJoystickAxisMap.clear();
165 _axisFunctionToJoystickAxisMap[
static_cast<AxisFunction_t>(i)] = kJoystickAxisNotAssigned;
169void Joystick::_resetAxisCalibrationData()
171 _resetFunctionToAxisMap();
172 for (
int axis = 0; axis <
_axisCount; axis++) {
173 auto& calibration = _rgCalibration[axis];
178void Joystick::_resetButtonActionData()
180 for (
int i = 0; i < _assignedButtonActions.count(); i++) {
181 delete _assignedButtonActions[i];
182 _assignedButtonActions[i] =
nullptr;
186void Joystick::_resetButtonEventStates()
188 for (
int i = 0; i < _buttonEventStates.count(); i++) {
193void Joystick::_loadButtonSettings()
195 const QString actionNameKey = QString::fromLatin1(kButtonActionNameKey);
196 const QString repeatKey = QString::fromLatin1(kButtonRepeatKey);
198 QSettings buttonSettings;
199 buttonSettings.beginGroup(_joystickSettings.
settingsGroup());
201 if (buttonSettings.childGroups().contains(QString::fromLatin1(kButtonActionArrayGroup))) {
202 buttonSettings.beginGroup(QString::fromLatin1(kButtonActionArrayGroup));
204 qCDebug(JoystickLog) <<
"Button Actions:";
206 bool foundButton =
false;
207 for (
int buttonIndex = 0; buttonIndex < _totalButtonCount; buttonIndex++) {
208 if (!buttonSettings.childGroups().contains(QString::number(buttonIndex))) {
212 buttonSettings.beginGroup(QString::number(buttonIndex));
213 const QString actionName = buttonSettings.value(actionNameKey).toString();
214 const bool repeat = buttonSettings.value(repeatKey,
false).toBool();
215 buttonSettings.endGroup();
217 if (actionName.isEmpty()) {
218 qCWarning(JoystickLog)
220 <<
"button:" << buttonIndex
221 <<
"has empty action name, clearing action from data";
222 buttonSettings.remove(QString::number(buttonIndex));
225 if (_findAvailableButtonActionIndex(actionName) == -1) {
226 qCWarning(JoystickLog)
228 <<
"button:" << buttonIndex
229 <<
"has unknown action name:" << actionName
230 <<
", clearing action from data";
231 buttonSettings.remove(QString::number(buttonIndex));
234 if (actionName == _buttonActionNone) {
235 buttonSettings.remove(QString::number(buttonIndex));
240 _assignedButtonActions[buttonIndex] = buttonAction;
241 _assignedButtonActions[buttonIndex]->buttonElapsedTimer.start();
246 <<
"button:" << buttonIndex
247 <<
"actionName:" << actionName
248 <<
"repeat:" << repeat;
251 buttonSettings.endGroup();
254 buttonSettings.remove(QString::fromLatin1(kButtonActionArrayGroup));
259void Joystick::_foundInvalidAxisSettingsCleanup()
261 _clearAxisSettings();
262 _resetAxisCalibrationData();
263 _joystickSettings.
calibrated()->setRawValue(
false);
266void Joystick::_loadAxisSettings(
bool joystickCalibrated,
int transmitterMode)
268 QSettings axisSettings;
273 if (!joystickCalibrated) {
274 _clearAxisSettings();
275 _resetAxisCalibrationData();
279 const QString functionKey = QString::fromLatin1(kAxisFunctionKey);
280 const QString minKey = QString::fromLatin1(kAxisMinKey);
281 const QString maxKey = QString::fromLatin1(kAxisMaxKey);
282 const QString centerKey = QString::fromLatin1(kAxisCenterKey);
283 const QString deadbandKey = QString::fromLatin1(kAxisDeadbandKey);
284 const QString reversedKey = QString::fromLatin1(kAxisReversedKey);
286 qCDebug(JoystickLog) <<
"Axis Settings:";
288 axisSettings.beginGroup(QString::fromLatin1(kAxisSettingsArrayGroup));
289 for (
int axis = 0; axis <
_axisCount; axis++) {
290 if (!axisSettings.childGroups().contains(QString::number(axis))) {
294 <<
"no settings found, skipping";
298 axisSettings.beginGroup(QString::number(axis));
300 auto& axisCalibration = _rgCalibration[axis];
302 const int axisFunction = axisSettings.value(functionKey,
maxAxisFunction).toInt();
304 qCWarning(JoystickLog) <<
"Invalid function" << axisFunction <<
"for axis" << axis;
305 axisSettings.endGroup();
308 _setJoystickAxisForAxisFunction(
static_cast<AxisFunction_t>(axisFunction), axis);
310 axisCalibration.center = axisSettings.value(centerKey, axisCalibration.center).toInt();
311 axisCalibration.min = axisSettings.value(minKey, axisCalibration.min).toInt();
312 axisCalibration.max = axisSettings.value(maxKey, axisCalibration.max).toInt();
313 axisCalibration.deadband = axisSettings.value(deadbandKey, axisCalibration.deadband).toInt();
314 axisCalibration.reversed = axisSettings.value(reversedKey, axisCalibration.reversed).toBool();
319 <<
"min:" << axisCalibration.min
320 <<
"max:" << axisCalibration.max
321 <<
"center:" << axisCalibration.center
322 <<
"reversed:" << axisCalibration.reversed
323 <<
"deadband:" << axisCalibration.deadband
326 axisSettings.endGroup();
328 axisSettings.endGroup();
331 bool rollFunctionNotAssigned = _axisFunctionToJoystickAxisMap[
rollFunction] == kJoystickAxisNotAssigned;
332 if (rollFunctionNotAssigned) {
333 qCWarning(JoystickLog) <<
"Roll axis function not assigned";
335 bool pitchFunctionNotAssigned = _axisFunctionToJoystickAxisMap[
pitchFunction] == kJoystickAxisNotAssigned;
336 if (pitchFunctionNotAssigned) {
337 qCWarning(JoystickLog) <<
"Pitch axis function not assigned";
339 bool yawFunctionNotAssigned = _axisFunctionToJoystickAxisMap[
yawFunction] == kJoystickAxisNotAssigned;
340 if (yawFunctionNotAssigned) {
341 qCWarning(JoystickLog) <<
"Yaw axis function not assigned";
343 bool throttleFunctionNotAssigned = _axisFunctionToJoystickAxisMap[
throttleFunction] == kJoystickAxisNotAssigned;
344 if (throttleFunctionNotAssigned) {
345 qCWarning(JoystickLog) <<
"Throttle axis function not assigned";
347 bool pitchExtensionFunctionRequiredButNotAssigned =
false;
349 pitchExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
pitchExtensionFunction) == kJoystickAxisNotAssigned;
350 if (pitchExtensionFunctionRequiredButNotAssigned) {
351 qCWarning(JoystickLog) <<
"Internal Error: Missing pitch extension axis function mapping!";
354 bool rollExtensionFunctionRequiredButNotAssigned =
false;
356 rollExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
rollExtensionFunction) == kJoystickAxisNotAssigned;
357 if (rollExtensionFunctionRequiredButNotAssigned) {
358 qCWarning(JoystickLog) <<
"Internal Error: Missing roll extension axis function mapping!";
361 bool aux1ExtensionFunctionRequiredButNotAssigned =
false;
363 aux1ExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
aux1ExtensionFunction) == kJoystickAxisNotAssigned;
364 if (aux1ExtensionFunctionRequiredButNotAssigned) {
365 qCWarning(JoystickLog) <<
"Internal Error: Missing aux1 extension axis function mapping!";
368 bool aux2ExtensionFunctionRequiredButNotAssigned =
false;
370 aux2ExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
aux2ExtensionFunction) == kJoystickAxisNotAssigned;
371 if (aux2ExtensionFunctionRequiredButNotAssigned) {
372 qCWarning(JoystickLog) <<
"Internal Error: Missing aux2 extension axis function mapping!";
375 bool aux3ExtensionFunctionRequiredButNotAssigned =
false;
377 aux3ExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
aux3ExtensionFunction) == kJoystickAxisNotAssigned;
378 if (aux3ExtensionFunctionRequiredButNotAssigned) {
379 qCWarning(JoystickLog) <<
"Internal Error: Missing aux3 extension axis function mapping!";
382 bool aux4ExtensionFunctionRequiredButNotAssigned =
false;
384 aux4ExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
aux4ExtensionFunction) == kJoystickAxisNotAssigned;
385 if (aux4ExtensionFunctionRequiredButNotAssigned) {
386 qCWarning(JoystickLog) <<
"Internal Error: Missing aux4 extension axis function mapping!";
389 bool aux5ExtensionFunctionRequiredButNotAssigned =
false;
391 aux5ExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
aux5ExtensionFunction) == kJoystickAxisNotAssigned;
392 if (aux5ExtensionFunctionRequiredButNotAssigned) {
393 qCWarning(JoystickLog) <<
"Internal Error: Missing aux5 extension axis function mapping!";
396 bool aux6ExtensionFunctionRequiredButNotAssigned =
false;
398 aux6ExtensionFunctionRequiredButNotAssigned = _getJoystickAxisForAxisFunction(
aux6ExtensionFunction) == kJoystickAxisNotAssigned;
399 if (aux6ExtensionFunctionRequiredButNotAssigned) {
400 qCWarning(JoystickLog) <<
"Internal Error: Missing aux6 extension axis function mapping!";
403 if (rollFunctionNotAssigned || pitchFunctionNotAssigned || yawFunctionNotAssigned || throttleFunctionNotAssigned ||
404 pitchExtensionFunctionRequiredButNotAssigned || rollExtensionFunctionRequiredButNotAssigned ||
405 aux1ExtensionFunctionRequiredButNotAssigned || aux2ExtensionFunctionRequiredButNotAssigned || aux3ExtensionFunctionRequiredButNotAssigned ||
406 aux4ExtensionFunctionRequiredButNotAssigned || aux5ExtensionFunctionRequiredButNotAssigned || aux6ExtensionFunctionRequiredButNotAssigned) {
407 qCWarning(JoystickLog) <<
"Missing control axis function(s), resetting all axis settings, marking joystick as uncalibrated and disabled";
408 _resetAxisCalibrationData();
409 _clearAxisSettings();
410 _joystickSettings.
calibrated()->setRawValue(
false);
411 _joystickManager->setActiveJoystickEnabledForActiveVehicle(
false);
417 _remapFunctionsInFunctionMapToNewTransmittedMode(2, transmitterMode);
420void Joystick::_loadFromSettingsIntoCalibrationData()
422 _resetAxisCalibrationData();
423 _resetButtonActionData();
427 bool calibrated = _joystickSettings.
calibrated()->rawValue().toBool();
428 int transmitterMode = _joystickSettings.
transmitterMode()->rawValue().toInt();
430 qCDebug(JoystickLog) <<
name();
431 qCDebug(JoystickLog) <<
" calibrated:" << _joystickSettings.
calibrated()->rawValue().toBool();
432 qCDebug(JoystickLog) <<
" throttleSmoothing:" << _joystickSettings.
throttleSmoothing()->rawValue().toBool();
433 qCDebug(JoystickLog) <<
" axisFrequencyHz:" << _joystickSettings.
axisFrequencyHz()->rawValue().toDouble();
434 qCDebug(JoystickLog) <<
" buttonFrequencyHz:" << _joystickSettings.
buttonFrequencyHz()->rawValue().toDouble();
435 qCDebug(JoystickLog) <<
" throttleModeCenterZero:" << _joystickSettings.
throttleModeCenterZero()->rawValue().toBool();
436 qCDebug(JoystickLog) <<
" negativeThrust:" << _joystickSettings.
negativeThrust()->rawValue().toBool();
437 qCDebug(JoystickLog) <<
" circleCorrection:" << _joystickSettings.
circleCorrection()->rawValue().toBool();
438 qCDebug(JoystickLog) <<
" exponentialPct:" << _joystickSettings.
exponentialPct()->rawValue().toDouble();
439 qCDebug(JoystickLog) <<
" useDeadband:" << _joystickSettings.
useDeadband()->rawValue().toBool();
440 qCDebug(JoystickLog) <<
" transmitterMode:" << transmitterMode;
443 qCDebug(JoystickLog) <<
" enableManualControlAux1:" << _joystickSettings.
enableManualControlAux1()->rawValue().toBool();
444 qCDebug(JoystickLog) <<
" enableManualControlAux2:" << _joystickSettings.
enableManualControlAux2()->rawValue().toBool();
445 qCDebug(JoystickLog) <<
" enableManualControlAux3:" << _joystickSettings.
enableManualControlAux3()->rawValue().toBool();
446 qCDebug(JoystickLog) <<
" enableManualControlAux4:" << _joystickSettings.
enableManualControlAux4()->rawValue().toBool();
447 qCDebug(JoystickLog) <<
" enableManualControlAux5:" << _joystickSettings.
enableManualControlAux5()->rawValue().toBool();
448 qCDebug(JoystickLog) <<
" enableManualControlAux6:" << _joystickSettings.
enableManualControlAux6()->rawValue().toBool();
450 _loadAxisSettings(calibrated, transmitterMode);
451 _loadButtonSettings();
454void Joystick::_saveAxisSettings(
int transmitterMode)
456 qCDebug(JoystickLog) <<
name();
460 _remapFunctionsInFunctionMapToNewTransmittedMode(transmitterMode, 2);
462 QSettings axisSettings;
464 axisSettings.beginGroup(QString::fromLatin1(kAxisSettingsArrayGroup));
466 const QString functionKey = QString::fromLatin1(kAxisFunctionKey);
467 const QString minKey = QString::fromLatin1(kAxisMinKey);
468 const QString maxKey = QString::fromLatin1(kAxisMaxKey);
469 const QString centerKey = QString::fromLatin1(kAxisCenterKey);
470 const QString deadbandKey = QString::fromLatin1(kAxisDeadbandKey);
471 const QString reversedKey = QString::fromLatin1(kAxisReversedKey);
473 for (
int axis = 0; axis <
_axisCount; axis++) {
474 AxisCalibration_t *
const calibration = &_rgCalibration[axis];
475 axisSettings.beginGroup(QString::number(axis));
477 axisSettings.setValue(centerKey, calibration->center);
478 axisSettings.setValue(minKey, calibration->min);
479 axisSettings.setValue(maxKey, calibration->max);
480 axisSettings.setValue(deadbandKey, calibration->deadband);
481 axisSettings.setValue(reversedKey, calibration->reversed);
483 axisSettings.setValue(functionKey,
static_cast<int>(function));
488 <<
"min:" << calibration->min
489 <<
"max:" << calibration->max
490 <<
"center:" << calibration->center
491 <<
"reversed:" << calibration->reversed
492 <<
"deadband:" << calibration->deadband
495 axisSettings.endGroup();
498 axisSettings.endGroup();
499 axisSettings.endGroup();
502 _remapFunctionsInFunctionMapToNewTransmittedMode(2, transmitterMode);
505void Joystick::_saveButtonSettings()
507 qCDebug(JoystickLog) <<
name();
509 const QString actionNameKey = QString::fromLatin1(kButtonActionNameKey);
510 const QString repeatKey = QString::fromLatin1(kButtonRepeatKey);
512 QSettings buttonSettings;
513 buttonSettings.beginGroup(_joystickSettings.
settingsGroup());
514 buttonSettings.beginGroup(QString::fromLatin1(kButtonActionArrayGroup));
516 bool anyButtonsSaved =
false;
517 for (
int buttonIndex = 0; buttonIndex < _totalButtonCount; buttonIndex++) {
521 buttonSettings.beginGroup(QString::number(buttonIndex));
522 buttonSettings.setValue(actionNameKey, buttonAction->
actionName);
523 buttonSettings.setValue(repeatKey, buttonAction->
repeat);
524 buttonSettings.endGroup();
526 anyButtonsSaved =
true;
530 <<
"button:" << buttonIndex
532 <<
"repeat:" << buttonAction->
repeat;
535 buttonSettings.remove(QString::number(buttonIndex));
539 buttonSettings.endGroup();
540 buttonSettings.endGroup();
542 if (!anyButtonsSaved) {
543 qCDebug(JoystickLog) <<
" No button actions to save, cleared button action settings.";
544 _clearButtonSettings();
548void Joystick::_clearAxisSettings()
550 QSettings axisSettings;
552 axisSettings.remove(QString::fromLatin1(kAxisSettingsArrayGroup));
553 axisSettings.endGroup();
556void Joystick::_clearButtonSettings()
558 QSettings buttonSettings;
559 buttonSettings.beginGroup(_joystickSettings.
settingsGroup());
560 buttonSettings.remove(QString::fromLatin1(kButtonActionArrayGroup));
561 buttonSettings.endGroup();
564void Joystick::_saveFromCalibrationDataIntoSettings()
566 bool calibrated = _joystickSettings.
calibrated()->rawValue().toBool();
567 int transmitterMode = _joystickSettings.
transmitterMode()->rawValue().toInt();
569 qCDebug(JoystickLog) <<
name();
570 qCDebug(JoystickLog) <<
" calibrated:" << calibrated;
571 qCDebug(JoystickLog) <<
" throttleSmoothing:" << _joystickSettings.
throttleSmoothing()->rawValue().toBool();
572 qCDebug(JoystickLog) <<
" axisFrequencyHz:" << _joystickSettings.
axisFrequencyHz()->rawValue().toDouble();
573 qCDebug(JoystickLog) <<
" buttonFrequencyHz:" << _joystickSettings.
buttonFrequencyHz()->rawValue().toDouble();
574 qCDebug(JoystickLog) <<
" throttleModeCenterZero:" << _joystickSettings.
throttleModeCenterZero()->rawValue().toBool();
575 qCDebug(JoystickLog) <<
" negativeThrust:" << _joystickSettings.
negativeThrust()->rawValue().toBool();
576 qCDebug(JoystickLog) <<
" circleCorrection:" << _joystickSettings.
circleCorrection()->rawValue().toBool();
577 qCDebug(JoystickLog) <<
" exponentialPct:" << _joystickSettings.
exponentialPct()->rawValue().toDouble();
578 qCDebug(JoystickLog) <<
" useDeadband:" << _joystickSettings.
useDeadband()->rawValue().toBool();
579 qCDebug(JoystickLog) <<
" enableManualControlAux1:" << _joystickSettings.
enableManualControlAux1()->rawValue().toBool();
580 qCDebug(JoystickLog) <<
" enableManualControlAux2:" << _joystickSettings.
enableManualControlAux2()->rawValue().toBool();
581 qCDebug(JoystickLog) <<
" enableManualControlAux3:" << _joystickSettings.
enableManualControlAux3()->rawValue().toBool();
582 qCDebug(JoystickLog) <<
" enableManualControlAux4:" << _joystickSettings.
enableManualControlAux4()->rawValue().toBool();
583 qCDebug(JoystickLog) <<
" enableManualControlAux5:" << _joystickSettings.
enableManualControlAux5()->rawValue().toBool();
584 qCDebug(JoystickLog) <<
" enableManualControlAux6:" << _joystickSettings.
enableManualControlAux6()->rawValue().toBool();
585 qCDebug(JoystickLog) <<
" transmitterMode:" << transmitterMode;
587 _clearAxisSettings();
589 _saveAxisSettings(transmitterMode);
592 _clearButtonSettings();
593 _saveButtonSettings();
596void Joystick::_remapFunctionsInFunctionMapToNewTransmittedMode(
int fromMode,
int toMode)
598 static constexpr const int modeCount = 4;
599 static constexpr const int attitudeControlCount = 4;
600 static constexpr const AxisFunction_t mapping[modeCount][attitudeControlCount] = {
608 AxisFunctionMap_t tempMap = _axisFunctionToJoystickAxisMap;
610 for (
int i=0; i<attitudeControlCount; i++) {
611 auto fromAxisFunction = mapping[fromMode - 1][i];
612 auto toAxisFunction = mapping[toMode - 1][i];
614 tempMap[toAxisFunction] = _axisFunctionToJoystickAxisMap[fromAxisFunction];
619 _axisFunctionToJoystickAxisMap[axisFunction] = tempMap[axisFunction];
625 bool openFailed =
false;
626 bool updateFailed =
false;
629 qCWarning(JoystickLog) <<
"Failed to open joystick:" <<
_name;
634 _axisElapsedTimer.start();
636 for (
int buttonIndex = 0; buttonIndex < _totalButtonCount; buttonIndex++) {
637 if (_assignedButtonActions[buttonIndex]) {
638 _assignedButtonActions[buttonIndex]->buttonElapsedTimer.start();
642 while (!_exitThread) {
644 qCWarning(JoystickLog) <<
"Joystick disconnected or update failed:" <<
_name;
655 const double axisFrequencyHz = _joystickSettings.
axisFrequencyHz()->rawValue().toDouble();
656 const double buttonFrequencyHz = _joystickSettings.
buttonFrequencyHz()->rawValue().toDouble();
658 const int sleep = qMin(
static_cast<int>(1000.0 / axisFrequencyHz),
static_cast<int>(1000.0 / buttonFrequencyHz)) / 2;
659 QThread::msleep(sleep);
665 if ((openFailed || updateFailed) && !_exitThread) {
666 qCDebug(JoystickLog) <<
"Triggering joystick rescan after failure";
667 QMetaObject::invokeMethod(JoystickManager::instance(),
"_checkForAddedOrRemovedJoysticks", Qt::QueuedConnection);
671void Joystick::_updateButtonEventState(
int buttonIndex,
const bool buttonPressed, ButtonEvent_t &buttonEventState)
675 qCDebug(JoystickLog) <<
"Button" << buttonIndex <<
"down transition";
678 qCDebug(JoystickLog) <<
"Button" << buttonIndex <<
"repeat";
683 qCDebug(JoystickLog) <<
"Button" << buttonIndex <<
"up transition";
686 qCDebug(JoystickLog) <<
"Button" << buttonIndex <<
"none";
692void Joystick::_updateButtonEventStates(QVector<ButtonEvent_t> &buttonEventStates)
694 if (buttonEventStates.size() < _totalButtonCount) {
695 qCWarning(JoystickLog) <<
"Internal Error: buttonEventStates size incorrect!";
700 for (
int buttonIndex = 0; buttonIndex <
_buttonCount; buttonIndex++) {
701 const bool buttonIsPressed = _getButton(buttonIndex);
702 _updateButtonEventState(buttonIndex, buttonIsPressed, buttonEventStates[buttonIndex]);
706 const int numHatButtons = 4;
708 for (
int hatIndex = 0; hatIndex <
_hatCount; hatIndex++) {
709 for (
int hatButtonIndex = 0; hatButtonIndex < numHatButtons; hatButtonIndex++) {
710 const bool buttonIsPressed = _getHat(hatIndex, hatButtonIndex);
711 const int currentIndex = nextIndex;
712 _updateButtonEventState(currentIndex, buttonIsPressed, buttonEventStates[currentIndex]);
718void Joystick::_handleButtons()
720 if (_currentPollingType == NotPolling) {
721 qCWarning(JoystickLog) <<
"Internal Error: Joystick not polling!";
725 _updateButtonEventStates(_buttonEventStates);
727 if (_currentPollingType == PollingForConfiguration) {
728 for (
int buttonIndex = 0; buttonIndex < _totalButtonCount; buttonIndex++) {
730 qCDebug(JoystickLog) <<
"Button pressed - button" << buttonIndex;
733 qCDebug(JoystickLog) <<
"Button released - button" << buttonIndex;
737 }
else if (_currentPollingType == PollingForVehicle) {
738 Vehicle *
const vehicle = _pollingVehicle;
740 qCWarning(JoystickLog) <<
"Internal Error: No vehicle for joystick!";
743 if (!_joystickManager->activeJoystickEnabledForActiveVehicle()) {
744 qCWarning(JoystickLog) <<
"Internal Error: Joystick not enabled for vehicle!";
747 if (!_joystickSettings.
calibrated()->rawValue().toBool()) {
752 const int buttonDelay =
static_cast<int>(1000.0 / _joystickSettings.
buttonFrequencyHz()->rawValue().toDouble());
753 for (
int buttonIndex = 0; buttonIndex < _totalButtonCount; buttonIndex++) {
754 if (!_assignedButtonActions[buttonIndex]) {
757 auto assignedAction = _assignedButtonActions[buttonIndex];
759 const QString buttonAction = assignedAction->
actionName;
760 if (buttonAction.isEmpty() || (buttonAction == _buttonActionNone)) {
764 auto buttonEventState = _buttonEventStates[buttonIndex];
766 if (assignedAction->repeat) {
767 if (assignedAction->buttonElapsedTimer.elapsed() > buttonDelay) {
768 assignedAction->buttonElapsedTimer.start();
769 qCDebug(JoystickLog) <<
"Repeat - button:action" << buttonIndex << buttonAction;
775 QList<int> multiActionButtons = { buttonIndex };
776 for (
int multiIndex = 0; multiIndex < _totalButtonCount; multiIndex++) {
777 if (_assignedButtonActions[multiIndex] && (_assignedButtonActions[multiIndex]->actionName == buttonAction)) {
781 multiActionButtons.append(multiIndex);
790 if (multiActionButtons.size() > 1) {
791 qCDebug(JoystickLog) <<
"Multi-button action - buttons:action" << multiActionButtons << buttonAction;
793 qCDebug(JoystickLog) <<
"Action triggered - button:Action" << buttonIndex << buttonAction;
800 qCDebug(JoystickLog) <<
"Button up - button:action" << buttonIndex << buttonAction;
808float Joystick::_adjustRange(
int value,
const AxisCalibration_t &calibration,
bool withDeadbands)
810 float valueNormalized;
814 if (value > calibration.center) {
816 valueNormalized = value - calibration.center;
817 axisLength = calibration.max - calibration.center;
820 valueNormalized = calibration.center - value;
821 axisLength = calibration.center - calibration.min;
826 if (valueNormalized > calibration.deadband) {
827 axisPercent = (valueNormalized - calibration.deadband) / (axisLength - calibration.deadband);
828 }
else if (valueNormalized<-calibration.deadband) {
829 axisPercent = (valueNormalized + calibration.deadband) / (axisLength - calibration.deadband);
834 axisPercent = valueNormalized / axisLength;
837 float correctedValue = axisBasis * axisPercent;
838 if (calibration.reversed) {
839 correctedValue *= -1.0f;
842 return std::max(-1.0f, std::min(correctedValue, 1.0f));
845void Joystick::_handleAxis()
847 const int axisDelay =
static_cast<int>(1000.0 / _joystickSettings.
axisFrequencyHz()->rawValue().toDouble());
848 if (_axisElapsedTimer.elapsed() <= axisDelay) {
852 _axisElapsedTimer.start();
854 if (_currentPollingType == NotPolling) {
855 qCWarning(JoystickLog) <<
"Internal Error: Joystick not polling!";
859 if (_currentPollingType == PollingForConfiguration) {
863 for (
int axisIndex = 0; axisIndex <
_axisCount; axisIndex++) {
864 channelValues[axisIndex] = _getAxisValue(axisIndex);
867 }
else if (_currentPollingType == PollingForVehicle) {
868 Vehicle *
const vehicle = _pollingVehicle;
870 qCWarning(JoystickLog) <<
"Internal Error: No vehicle for joystick!";
873 if (!_joystickManager->activeJoystickEnabledForActiveVehicle()) {
874 qCWarning(JoystickLog) <<
"Internal Error: Joystick not enabled for vehicle!";
877 if (!_joystickSettings.
calibrated()->rawValue().toBool()) {
881 bool useDeadband = _joystickSettings.
useDeadband()->rawValue().toBool();
883 bool negativeThrust = _joystickSettings.
negativeThrust()->rawValue().toBool();
884 bool circleCorrection = _joystickSettings.
circleCorrection()->rawValue().toBool();
885 bool throttleSmoothing = _joystickSettings.
throttleSmoothing()->rawValue().toBool();
886 double exponentialPercent = _joystickSettings.
exponentialPct()->rawValue().toDouble();
888 if (_getJoystickAxisForAxisFunction(
rollFunction) == kJoystickAxisNotAssigned ||
889 _getJoystickAxisForAxisFunction(
pitchFunction) == kJoystickAxisNotAssigned ||
890 _getJoystickAxisForAxisFunction(
yawFunction) == kJoystickAxisNotAssigned ||
891 _getJoystickAxisForAxisFunction(
throttleFunction) == kJoystickAxisNotAssigned) {
892 qCWarning(JoystickLog) <<
"Internal Error: Missing attitude control axis function mapping!";
895 int axisIndex = _getJoystickAxisForAxisFunction(
rollFunction);
896 float roll = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
898 float pitch = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
899 axisIndex = _getJoystickAxisForAxisFunction(
yawFunction);
900 float yaw = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex],useDeadband);
902 float throttle = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], throttleModeCenterZero ? useDeadband : false);
904 float pitchExtension = qQNaN();
907 qCWarning(JoystickLog) <<
"Internal Error: Missing pitch extension axis function mapping!";
911 pitchExtension = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
913 float rollExtension = qQNaN();
916 qCWarning(JoystickLog) <<
"Internal Error: Missing roll extension axis function mapping!";
920 rollExtension = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
922 float aux1 = qQNaN();
925 qCWarning(JoystickLog) <<
"Internal Error: Missing aux1 extension axis function mapping!";
929 aux1 = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
931 float aux2 = qQNaN();
934 qCWarning(JoystickLog) <<
"Internal Error: Missing aux2 extension axis function mapping!";
938 aux2 = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
940 float aux3 = qQNaN();
943 qCWarning(JoystickLog) <<
"Internal Error: Missing aux3 extension axis function mapping!";
947 aux3 = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
949 float aux4 = qQNaN();
952 qCWarning(JoystickLog) <<
"Internal Error: Missing aux4 extension axis function mapping!";
956 aux4 = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
958 float aux5 = qQNaN();
961 qCWarning(JoystickLog) <<
"Internal Error: Missing aux5 extension axis function mapping!";
965 aux5 = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
967 float aux6 = qQNaN();
970 qCWarning(JoystickLog) <<
"Internal Error: Missing aux6 extension axis function mapping!";
974 aux6 = _adjustRange(_getAxisValue(axisIndex), _rgCalibration[axisIndex], useDeadband);
977 if (throttleSmoothing) {
978 static float throttleSmoothingValue = 0.f;
979 throttleSmoothingValue += (throttle * (40 / 1000.f));
980 throttleSmoothingValue = std::max(
static_cast<float>(-1.f), std::min(throttleSmoothingValue,
static_cast<float>(1.f)));
981 throttle = throttleSmoothingValue;
984 if (circleCorrection) {
985 const float roll_limited = std::max(
static_cast<float>(-M_PI_4), std::min(roll,
static_cast<float>(M_PI_4)));
986 const float pitch_limited = std::max(
static_cast<float>(-M_PI_4), std::min(pitch,
static_cast<float>(M_PI_4)));
987 const float yaw_limited = std::max(
static_cast<float>(-M_PI_4), std::min(yaw,
static_cast<float>(M_PI_4)));
988 const float throttle_limited = std::max(
static_cast<float>(-M_PI_4), std::min(throttle,
static_cast<float>(M_PI_4)));
991 roll = std::max(-1.0f, std::min(tanf(asinf(roll_limited)), 1.0f));
992 pitch = std::max(-1.0f, std::min(tanf(asinf(pitch_limited)), 1.0f));
993 yaw = std::max(-1.0f, std::min(tanf(asinf(yaw_limited)), 1.0f));
994 throttle = std::max(-1.0f, std::min(tanf(asinf(throttle_limited)), 1.0f));
997 if ( exponentialPercent > 0.0 ) {
998 const float exponential = -
static_cast<float>(exponentialPercent / 100.0);
999 roll = -exponential * powf(roll, 3) + ((1 + exponential) * roll);
1000 pitch = -exponential * powf(pitch,3) + ((1 + exponential) * pitch);
1001 yaw = -exponential * powf(yaw, 3) + ((1 + exponential) * yaw);
1005 if (throttleModeCenterZero && vehicle->
supports()->throttleModeCenterZero()) {
1007 throttle = std::max(0.0f, throttle);
1010 throttle = (throttle + 1.0f) / 2.0f;
1013 qCDebug(JoystickVerboseLog)
1016 <<
"pitch:" << -pitch
1018 <<
"throttle:" << throttle
1019 <<
"pitchExtension:" << pitchExtension
1020 <<
"rollExtension:" << rollExtension
1030 quint64 buttonPressedBits = 0;
1031 for (
int buttonIndex = 0; buttonIndex < _totalButtonCount; buttonIndex++) {
1032 const quint64 buttonBit =
static_cast<quint64
>(1LL << buttonIndex);
1034 buttonPressedBits |= buttonBit;
1040 const uint16_t lowButtons =
static_cast<uint16_t
>(buttonPressedBits & 0xFFFF);
1041 const uint16_t highButtons =
static_cast<uint16_t
>((buttonPressedBits >> 16) & 0xFFFF);
1044 vehicle->
sendJoystickDataThreadSafe(roll, pitch, yaw, throttle, lowButtons, highButtons, pitchExtension, rollExtension, aux1, aux2, aux3, aux4, aux5, aux6);
1048void Joystick::_startPollingForActiveVehicle()
1050 Vehicle *activeVehicle = MultiVehicleManager::instance()->activeVehicle();
1051 if (!activeVehicle) {
1052 qCWarning(JoystickLog) <<
"Internal Error: No active vehicle to poll for";
1055 _startPollingForVehicle(*activeVehicle);
1058void Joystick::_startPollingForVehicle(
Vehicle &vehicle)
1060 if (_currentPollingType == PollingForVehicle) {
1061 qCWarning(JoystickLog) <<
"Internal Error: Joystick already polling for vehicle!";
1064 if (_previousPollingType != NotPolling) {
1065 qCWarning(JoystickLog) <<
"Internal Error: Joystick previous polling type not None:" << _pollingTypeToString(_previousPollingType);
1068 if (_currentPollingType == NotPolling && isRunning()) {
1069 qCWarning(JoystickLog) <<
"Internal Error: Joystick polling should not be running!";
1073 _currentPollingType = PollingForVehicle;
1074 _pollingVehicle = &vehicle;
1076 _buildAvailableButtonsActionList(_pollingVehicle);
1098 qDebug(JoystickLog) <<
"Started joystick polling for vehicle" << _pollingVehicle->
id();
1103void Joystick::_startPollingForConfiguration()
1105 if (_currentPollingType == PollingForConfiguration) {
1106 qCWarning(JoystickLog) <<
"Internal Error: Joystick already polling for configuration!";
1109 if (_previousPollingType != NotPolling) {
1110 qCWarning(JoystickLog) <<
"Internal Error: Joystick previous polling type not None:" << _pollingTypeToString(_previousPollingType);
1114 qCDebug(JoystickLog) <<
"Started joystick polling for configuration. Saved previous polling type:" << _pollingTypeToString(_currentPollingType);
1116 _previousPollingType = _currentPollingType;
1117 _currentPollingType = PollingForConfiguration;
1124void Joystick::_stopPollingForConfiguration()
1126 if (_currentPollingType != PollingForConfiguration) {
1127 qCWarning(JoystickLog) <<
"Internal Error: Joystick not polling for configuration!";
1131 qCWarning(JoystickLog) <<
"Internal Error: Joystick polling not running!";
1135 qCDebug(JoystickLog) <<
"Stopped joystick polling for configuration. Restored previous polling type:" << _pollingTypeToString(_previousPollingType);
1137 _currentPollingType = _previousPollingType;
1138 _previousPollingType = NotPolling;
1140 if (_currentPollingType == NotPolling) {
1145void Joystick::_stopAllPolling()
1147 if (_pollingVehicle) {
1148 (void) disconnect(
this,
nullptr, _pollingVehicle,
nullptr);
1151 (void) disconnect(
this,
nullptr, gimbal,
nullptr);
1153 _pollingVehicle =
nullptr;
1156 qCDebug(JoystickLog) <<
"Stopped all joystick polling";
1158 _currentPollingType = NotPolling;
1159 _previousPollingType = NotPolling;
1166QString Joystick::_pollingTypeToString(PollingType pollingType)
const
1168 switch (pollingType) {
1170 return QStringLiteral(
"NotPolling");
1171 case PollingForConfiguration:
1172 return QStringLiteral(
"PollingForConfiguration");
1173 case PollingForVehicle:
1174 return QStringLiteral(
"PollingForVehicle");
1179 return QStringLiteral(
"UnknownPollingType");
1184 if (!_validAxis(axis)) {
1188 _rgCalibration[axis] = calibration;
1193 if (!_validAxis(axis)) {
1197 return _rgCalibration[axis];
1200void Joystick::_setJoystickAxisForAxisFunction(AxisFunction_t axisFunction,
int joystickAxis)
1203 qCWarning(JoystickLog) <<
"Internal Error: maxAxisFunction passed to _setJoystickAxisForAxisFunction";
1206 if (joystickAxis == kJoystickAxisNotAssigned) {
1207 qCWarning(JoystickLog) <<
"Internal Error: kJoystickAxisNotAssigned passed to _setJoystickAxisForAxisFunction";
1211 if (!_validAxis(joystickAxis)) {
1215 _axisFunctionToJoystickAxisMap[axisFunction] = joystickAxis;
1218int Joystick::_getJoystickAxisForAxisFunction(AxisFunction_t axisFunction)
const
1221 qCWarning(JoystickLog) <<
"Internal Error: maxAxisFunction passed to _getJoystickAxisForAxisFunction";
1222 return kJoystickAxisNotAssigned;
1225 return _axisFunctionToJoystickAxisMap.value(axisFunction, kJoystickAxisNotAssigned);
1230 switch (axisFunction) {
1232 return RemoteControlCalibrationController::stickFunctionRoll;
1234 return RemoteControlCalibrationController::stickFunctionPitch;
1236 return RemoteControlCalibrationController::stickFunctionYaw;
1238 return RemoteControlCalibrationController::stickFunctionThrottle;
1240 return RemoteControlCalibrationController::stickFunctionAux1Extension;
1242 return RemoteControlCalibrationController::stickFunctionAux2Extension;
1244 return RemoteControlCalibrationController::stickFunctionAux3Extension;
1246 return RemoteControlCalibrationController::stickFunctionAux4Extension;
1248 return RemoteControlCalibrationController::stickFunctionAux5Extension;
1250 return RemoteControlCalibrationController::stickFunctionAux6Extension;
1252 return RemoteControlCalibrationController::stickFunctionPitchExtension;
1254 return RemoteControlCalibrationController::stickFunctionRollExtension;
1256 return RemoteControlCalibrationController::stickFunctionMax;
1263 switch (stickFunction) {
1264 case RemoteControlCalibrationController::stickFunctionRoll:
1266 case RemoteControlCalibrationController::stickFunctionPitch:
1268 case RemoteControlCalibrationController::stickFunctionYaw:
1270 case RemoteControlCalibrationController::stickFunctionThrottle:
1272 case RemoteControlCalibrationController::stickFunctionAux1Extension:
1274 case RemoteControlCalibrationController::stickFunctionAux2Extension:
1276 case RemoteControlCalibrationController::stickFunctionAux3Extension:
1278 case RemoteControlCalibrationController::stickFunctionAux4Extension:
1280 case RemoteControlCalibrationController::stickFunctionAux5Extension:
1282 case RemoteControlCalibrationController::stickFunctionAux6Extension:
1284 case RemoteControlCalibrationController::stickFunctionPitchExtension:
1286 case RemoteControlCalibrationController::stickFunctionRollExtension:
1288 case RemoteControlCalibrationController::stickFunctionMax:
1306 if (!_validButton(button) || !_assignedButtonActions[button]) {
1310 _assignedButtonActions[button]->repeat = repeat;
1311 _assignedButtonActions[button]->buttonElapsedTimer.start();
1315 settings.beginGroup(QString::fromLatin1(kButtonActionArrayGroup));
1316 settings.beginGroup(QString::number(button));
1317 const QString repeatKey = QString::fromLatin1(kButtonRepeatKey);
1318 settings.setValue(repeatKey, repeat);
1326 if (!_validButton(button) || !_assignedButtonActions[button]) {
1330 return _assignedButtonActions[button]->repeat;
1335 if (!_validButton(button)) {
1339 qCDebug(JoystickLog) <<
"button:actionName" << button << actionName;
1343 settings.beginGroup(QString::fromLatin1(kButtonActionArrayGroup));
1344 settings.beginGroup(QString::number(button));
1345 const QString actionNameKey = QString::fromLatin1(kButtonActionNameKey);
1346 const QString repeatKey = QString::fromLatin1(kButtonRepeatKey);
1348 if (actionName.isEmpty() || actionName == _buttonActionNone) {
1349 if (_assignedButtonActions[button]) {
1350 delete _assignedButtonActions[button];
1351 _assignedButtonActions[button] =
nullptr;
1353 settings.setValue(actionNameKey, _buttonActionNone);
1354 settings.setValue(repeatKey,
false);
1356 if (!_assignedButtonActions[button]) {
1359 _assignedButtonActions[button]->actionName = actionName;
1361 const int idx = _findAvailableButtonActionIndex(actionName);
1363 const AvailableButtonAction *
const buttonAction = qobject_cast<const AvailableButtonAction*>(_availableButtonActions->
get(idx));
1364 if (!buttonAction->canRepeat()) {
1365 _assignedButtonActions[button]->repeat =
false;
1370 settings.setValue(actionNameKey, _assignedButtonActions[button]->actionName);
1371 settings.setValue(repeatKey, _assignedButtonActions[button]->repeat);
1383 if (_validButton(button)) {
1384 if (_assignedButtonActions[button]) {
1385 return _assignedButtonActions[button]->actionName;
1389 return QString(_buttonActionNone);
1396 list.reserve(_totalButtonCount);
1398 for (
int button = 0; button < _totalButtonCount; button++) {
1399 if (_assignedButtonActions[button]) {
1400 list << _assignedButtonActions[button]->actionName;
1402 list << _buttonActionNone;
1409void Joystick::_executeButtonAction(
const QString &action,
const ButtonEvent_t buttonEvent)
1411 Vehicle *
const vehicle = _pollingVehicle;
1413 qCWarning(JoystickLog) <<
"Internal Error: No vehicle for joystick!";
1416 if (!_joystickManager->activeJoystickEnabledForActiveVehicle()) {
1417 qCWarning(JoystickLog) <<
"Internal Error: Joystick not enabled for vehicle!";
1420 if (action == _buttonActionNone) {
1425 const QString action;
1426 const ButtonEvent_t event;
1427 std::function<void()> func;
1429 auto actionInfo = std::to_array<ActionInfo>({
1481 auto it = std::find_if(actionInfo.begin(), actionInfo.end(), [&action, &buttonEvent](
const ActionInfo &info) {
1482 return (info.action == action) && (info.event == buttonEvent);
1484 if (it != actionInfo.end()) {
1492 for (
int i = 0; i<_mavlinkActionManager->actions()->count(); i++) {
1494 if (action == mavlinkAction->label()) {
1495 mavlinkAction->sendTo(vehicle);
1502bool Joystick::_validAxis(
int axis)
const
1508 qCWarning(JoystickLog) <<
"Invalid axis index" << axis;
1512bool Joystick::_validButton(
int button)
const
1514 if ((button >= 0) && (button < _totalButtonCount)) {
1518 qCWarning(JoystickLog) <<
"Invalid button index" << button;
1522int Joystick::_findAvailableButtonActionIndex(
const QString &action)
1524 for (
int i = 0; i < _availableButtonActions->
count(); i++) {
1525 const AvailableButtonAction *
const buttonAction = qobject_cast<const AvailableButtonAction*>(_availableButtonActions->
get(i));
1526 if (buttonAction->action() == action) {
1534void Joystick::_buildAvailableButtonsActionList(
Vehicle *vehicle)
1536 if (_availableButtonActions->
count()) {
1539 _availableActionTitles.clear();
1547 for (
const QString &mode : list) {
1579#ifndef QGC_NO_ARDUPILOT_DIALECT
1584 const auto customActions = QGCCorePlugin::instance()->joystickActions();
1585 for (
const auto &action : customActions) {
1589 for (
int i = 0; i < _mavlinkActionManager->actions()->count(); i++) {
1594 for (
int i = 0; i < _availableButtonActions->
count(); i++) {
1595 const AvailableButtonAction *
const buttonAction = qobject_cast<const AvailableButtonAction*>(_availableButtonActions->
get(i));
1596 _availableActionTitles << buttonAction->action();
1606 return QStringLiteral(
"Roll");
1608 return QStringLiteral(
"Pitch");
1610 return QStringLiteral(
"Yaw");
1612 return QStringLiteral(
"Throttle");
1614 return QStringLiteral(
"Aux 1 Extension");
1616 return QStringLiteral(
"Aux 2 Extension");
1618 return QStringLiteral(
"Aux 3 Extension");
1620 return QStringLiteral(
"Aux 4 Extension");
1622 return QStringLiteral(
"Aux 5 Extension");
1624 return QStringLiteral(
"Aux 6 Extension");
1626 return QStringLiteral(
"Pitch Extension");
1628 return QStringLiteral(
"Roll Extension");
1630 return QStringLiteral(
"Unassigned");
1637 _startPollingForConfiguration();
1642 _stopPollingForConfiguration();
1647 if (!_validAxis(joystickAxis)) {
1653 if (_axisFunctionToJoystickAxisMap.value(axisFunction, kJoystickAxisNotAssigned) == joystickAxis) {
1654 return axisFunction;
1665 if (QThread::currentThread() ==
this) {
1666 qCWarning(JoystickLog) <<
"Skipping wait() on joystick thread";
1675 if (_linkedGroupId != groupId) {
1676 _linkedGroupId = groupId;
1680 settings.beginGroup(QStringLiteral(
"Joystick"));
1682 if (groupId.isEmpty()) {
1683 settings.remove(QStringLiteral(
"LinkedGroupId"));
1685 settings.setValue(QStringLiteral(
"LinkedGroupId"), groupId);
1696 if (_linkedGroupRole != role) {
1697 _linkedGroupRole = role;
1701 settings.beginGroup(QStringLiteral(
"Joystick"));
1703 if (role.isEmpty()) {
1704 settings.remove(QStringLiteral(
"LinkedGroupRole"));
1706 settings.setValue(QStringLiteral(
"LinkedGroupRole"), role);
#define QGC_LOGGING_CATEGORY(name, categoryStr)
A Fact is used to hold a single value within the system.
void rawValueChanged(const QVariant &value)
void gimbalYawLock(bool yawLock)
void gimbalYawStart(int direction)
void gimbalPitchStart(int direction)
Fact *negativeThrust READ negativeThrust CONSTANT Fact * negativeThrust()
Fact *axisFrequencyHz READ axisFrequencyHz CONSTANT Fact * axisFrequencyHz()
Fact *throttleModeCenterZero READ throttleModeCenterZero CONSTANT Fact * throttleModeCenterZero()
Fact *enableManualControlAux2 READ enableManualControlAux2 CONSTANT Fact * enableManualControlAux2()
Fact *circleCorrection READ circleCorrection CONSTANT Fact * circleCorrection()
Fact *throttleSmoothing READ throttleSmoothing CONSTANT Fact * throttleSmoothing()
Fact *transmitterMode READ transmitterMode CONSTANT Fact * transmitterMode()
Fact *enableManualControlAux6 READ enableManualControlAux6 CONSTANT Fact * enableManualControlAux6()
Fact *calibrated READ calibrated CONSTANT Fact * calibrated()
Fact *buttonFrequencyHz READ buttonFrequencyHz CONSTANT Fact * buttonFrequencyHz()
Fact *enableManualControlRollExtension READ enableManualControlRollExtension CONSTANT Fact * enableManualControlRollExtension()
Fact *enableManualControlPitchExtension READ enableManualControlPitchExtension CONSTANT Fact * enableManualControlPitchExtension()
Fact *exponentialPct READ exponentialPct CONSTANT Fact * exponentialPct()
Fact *enableManualControlAux3 READ enableManualControlAux3 CONSTANT Fact * enableManualControlAux3()
Fact *enableManualControlAux4 READ enableManualControlAux4 CONSTANT Fact * enableManualControlAux4()
Fact *enableManualControlAux5 READ enableManualControlAux5 CONSTANT Fact * enableManualControlAux5()
Fact *useDeadband READ useDeadband CONSTANT Fact * useDeadband()
Fact *enableManualControlAux1 READ enableManualControlAux1 CONSTANT Fact * enableManualControlAux1()
void setLinkedGroupId(const QString &groupId)
void stopConfiguration()
Tells the joystick that the configuration UI is being closed so it can do any special processing requ...
void rawButtonPressedChanged(int index, bool pressed)
Signalled during PollingForConfiguration.
void gimbalYawLock(bool lock)
RemoteControlCalibrationController::StickFunction mapAxisFunctionToRCCStickFunction(AxisFunction_t axisFunction) const
void setLinkedGroupRole(const QString &role)
void setFlightMode(const QString &flightMode)
void motorInterlock(bool enable)
static QString axisFunctionToString(AxisFunction_t function)
void setFunctionForChannel(RemoteControlCalibrationController::StickFunction stickFunction, int channel)
void axisValues(float roll, float pitch, float yaw, float throttle)
void buttonActionsChanged()
@ ButtonEventDownTransition
@ ButtonEventUpTransition
void assignableActionsChanged()
void unknownAction(const QString &action)
int getChannelForFunction(RemoteControlCalibrationController::StickFunction stickFunction) const
QString getButtonAction(int button) const
void stepZoom(int direction)
QStringList buttonActions() const
AxisFunction_t mapRCCStickFunctionToAxisFunction(RemoteControlCalibrationController::StickFunction stickFunction) const
void startConfiguration()
Tells the joystick that the configuration UI is being displayed so it can do any special processing r...
QString name READ name int axisCount
Joystick::AxisCalibration_t getAxisCalibration(int axis) const
void setAxisCalibration(int axis, const AxisCalibration_t &calibration)
void gripperAction(QGCMAVLink::GripperActions gripperAction)
void startContinuousZoom(int direction)
JoystickSettings * settings()
bool getButtonRepeat(int button)
void setButtonAction(int button, const QString &action)
void stepCamera(int direction)
void setVtolInFwdFlight(bool set)
void stepStream(int direction)
void landingGearRetract()
void gimbalPitchStart(int direction)
void linkedGroupChanged()
void rawChannelValuesChanged(QVector< int > channelValues)
Signalled during PollingForConfiguration.
void gimbalYawStart(int direction)
void setButtonRepeat(int button, bool repeat)
void append(QObject *object)
Caller maintains responsibility for object ownership and deletion.
int count() const override final
void clearAndDeleteContents() override final
Clears the list and calls deleteLater on each entry.
QString settingsGroup() const
Provides access to all app settings.
bool negativeThrust() const
void motorInterlock(bool enable)
Command vehicle to Enable/Disable Motor Interlock.
void sendGripperAction(QGCMAVLink::GripperActions gripperOption)
void emergencyStop()
Command vehicle to kill all motors no matter what state.
void setFlightMode(const QString &flightMode)
void landingGearDeploy()
Command vichecle to deploy landing gear.
void flightModesChanged()
GimbalController * gimbalController()
void setVtolInFwdFlight(bool vtolInFwdFlight)
void sendJoystickDataThreadSafe(float roll, float pitch, float yaw, float thrust, quint16 buttons, quint16 buttons2, float pitchExtension, float rollExtension, float aux1, float aux2, float aux3, float aux4, float aux5, float aux6)
void landingGearRetract()
Command vichecle to retract landing gear.
VehicleSupports * supports()
QStringList flightModes()
void setArmedShowError(bool armed)