diff --git a/src/input/JoystickInput.cc b/src/input/JoystickInput.cc index bdfb9b24c195a0dd45913b83de7ad405d02ae919..ef7932b4a43a84295ddda72c98b374a032fa0c71 100644 --- a/src/input/JoystickInput.cc +++ b/src/input/JoystickInput.cc @@ -45,9 +45,6 @@ JoystickInput::JoystickInput() : calibrationNegative[i] = sdlJoystickMin; } - // Listen for when the active UAS changes so we can change who we're sending data to. - connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*))); - // Start this thread. This allows the Joystick Settings window to work correctly even w/o any UASes connected. start(); } @@ -191,7 +188,15 @@ void JoystickInput::run() { // First emit the uncalibrated values for each axis based on their ID. // This is generally not used for controlling a vehicle, but a UI representation, so it being slightly off is fine. - float axisValue = (SDL_JoystickGetAxis(joystick, i) - calibrationNegative[i]) / (calibrationPositive[i] - calibrationNegative[i]); + float axisValue = SDL_JoystickGetAxis(joystick, i); + if (joystickAxesInverted[i]) + { + axisValue = (axisValue - calibrationNegative[i]) / (calibrationPositive[i] - calibrationNegative[i]); + } + else + { + axisValue = (axisValue - calibrationPositive[i]) / (calibrationNegative[i] - calibrationPositive[i]); + } axisValue = 1.0f - axisValue; axisValue = axisValue * 2.0f - 1.0f; @@ -270,11 +275,14 @@ void JoystickInput::setActiveJoystick(int id) // Update cached joystick values joystickAxes.clear(); + joystickAxesInverted.clear(); for (int i = 0; i < joystickNumAxes; i++) { int axisValue = SDL_JoystickGetAxis(joystick, i); joystickAxes.append(axisValue); emit axisValueChanged(i, axisValue); + + joystickAxesInverted.append(false); } joystickButtons = 0; for (int i = 0; i < joystickNumButtons; i++) @@ -294,11 +302,57 @@ void JoystickInput::setActiveJoystick(int id) } } -float JoystickInput::getCurrentValueForAxis(int axisID) +void JoystickInput::setAxisMapping(int axis, JOYSTICK_INPUT_MAPPING newMapping) +{ + switch (newMapping) + { + case JOYSTICK_INPUT_MAPPING_ROLL: + rollAxis = axis; + break; + case JOYSTICK_INPUT_MAPPING_PITCH: + pitchAxis = axis; + break; + case JOYSTICK_INPUT_MAPPING_YAW: + yawAxis = axis; + break; + case JOYSTICK_INPUT_MAPPING_THROTTLE: + throttleAxis = axis; + break; + case JOYSTICK_INPUT_MAPPING_NONE: + default: + if (rollAxis == axis) + { + rollAxis = -1; + } + if (pitchAxis == axis) + { + pitchAxis = -1; + } + if (yawAxis == axis) + { + yawAxis = -1; + } + if (throttleAxis == axis) + { + throttleAxis = -1; + } + break; + } +} + +void JoystickInput::setAxisInversion(int axis, bool inverted) +{ + if (axis < joystickAxesInverted.size()) + { + joystickAxesInverted[axis] = inverted; + } +} + +float JoystickInput::getCurrentValueForAxis(int axis) { - if (axisID < joystickAxes.size()) + if (axis < joystickAxes.size()) { - return joystickAxes[axisID]; + return joystickAxes[axis]; } return 0.0f; } diff --git a/src/input/JoystickInput.h b/src/input/JoystickInput.h index 4d048b5e4c94195c33fcad6e82664d4c2dab63a6..f3390650504e035eedbad5d43a05cae76dba6cf1 100644 --- a/src/input/JoystickInput.h +++ b/src/input/JoystickInput.h @@ -130,7 +130,7 @@ public: return QString(SDL_JoystickName(id)); } - float getCurrentValueForAxis(int axisID); + float getCurrentValueForAxis(int axis); const double sdlJoystickMin; const double sdlJoystickMax; @@ -157,6 +157,7 @@ protected: int joystickNumButtons; QList joystickAxes; ///< The values of every axes during the last sample + QList joystickAxesInverted; ///< Whether each axis should be used inverted from what was reported quint16 joystickButtons; ///< The state of every button. Bitfield supporting 16 buttons with 1s indicating that the button is down. int xHat, yHat; ///< The horizontal/vertical hat directions. Values are -1, 0, 1, with (-1,-1) indicating bottom-left. @@ -214,29 +215,23 @@ signals: void hatDirectionChanged(int x, int y); public slots: + /** @brief Specify the UAS that this input should forward joystickChanged signals and buttonPresses to. */ void setActiveUAS(UASInterface* uas); /** @brief Switch to a new joystick by ID number. Both buttons and axes are updated with the proper signals emitted. */ void setActiveJoystick(int id); - - void setMappingRollAxis(int axis) - { - rollAxis = axis; - } - - void setMappingPitchAxis(int axis) - { - pitchAxis = axis; - } - - void setMappingYawAxis(int axis) - { - yawAxis = axis; - } - - void setMappingThrottleAxis(int axis) - { - throttleAxis = axis; - } + /** + * @brief Change the control mapping for a given joystick axis. + * @param axisID The axis to modify (0-indexed) + * @param newMapping The mapping to use. + * @see JOYSTICK_INPUT_MAPPING + */ + void setAxisMapping(int axis, JOYSTICK_INPUT_MAPPING newMapping); + /** + * @brief Specify if an axis should be inverted. + * @param axis The ID of the axis. + * @param inverted True indicates inverted from normal. Varies by controller. + */ + void setAxisInversion(int axis, bool inverted); }; #endif // _JOYSTICKINPUT_H_ diff --git a/src/ui/JoystickAxis.cc b/src/ui/JoystickAxis.cc index ec730e92ca51df3a452adb1edc2184b8b5cd9c4a..a17d63dbbf1fdd6ce2eaee728c6f2af1c637fa34 100644 --- a/src/ui/JoystickAxis.cc +++ b/src/ui/JoystickAxis.cc @@ -11,6 +11,7 @@ JoystickAxis::JoystickAxis(int id, QWidget *parent) : ui->setupUi(this); ui->label->setText(QString::number(id)); connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(mappingComboBoxChanged(int))); + connect(ui->checkBox, SIGNAL(clicked(bool)), this, SLOT(inversionCheckBoxChanged(bool))); } JoystickAxis::~JoystickAxis() @@ -27,3 +28,8 @@ void JoystickAxis::mappingComboBoxChanged(int newMapping) { emit mappingChanged(id, (JoystickInput::JOYSTICK_INPUT_MAPPING)newMapping); } + +void JoystickAxis::inversionCheckBoxChanged(bool inverted) +{ + emit inversionChanged(id, inverted); +} diff --git a/src/ui/JoystickAxis.h b/src/ui/JoystickAxis.h index 25aaa4598912189c8e19439904978f9c3a14b8b4..cfb7dea54ec4ffc80fefdae0c32eea98e2142a2c 100644 --- a/src/ui/JoystickAxis.h +++ b/src/ui/JoystickAxis.h @@ -19,6 +19,8 @@ public: signals: /** @brief Signal a change in this axis' yaw/pitch/roll mapping */ void mappingChanged(int id, JoystickInput::JOYSTICK_INPUT_MAPPING newMapping); + /** @brief Signal a change in this axis' inversion status */ + void inversionChanged(int id, bool); public slots: /** @brief Update the displayed value of the included progressbar. @@ -33,6 +35,8 @@ private: private slots: /** @brief Handle changes to the mapping dropdown bar. */ void mappingComboBoxChanged(int newMapping); + /** @brief Handle changes to the inversion checkbox. */ + void inversionCheckBoxChanged(bool inverted); }; #endif // JOYSTICKAXIS_H diff --git a/src/ui/JoystickAxis.ui b/src/ui/JoystickAxis.ui index 0d1fe959efbada999634b9fa5df53d8d51c57a5a..c3cb816572d4dc99e720f6c48f0a80186ee67c4d 100644 --- a/src/ui/JoystickAxis.ui +++ b/src/ui/JoystickAxis.ui @@ -6,12 +6,12 @@ 0 0 - 40 + 80 200 - + 0 0 @@ -120,6 +120,19 @@ + + + + + 0 + 0 + + + + Inverted + + + diff --git a/src/ui/JoystickWidget.cc b/src/ui/JoystickWidget.cc index 6bd29ad5cc47e301d3762677c5c053f43644549f..0ecb484b9e2b2584fe4bf2a9a7092e0a99c42b03 100644 --- a/src/ui/JoystickWidget.cc +++ b/src/ui/JoystickWidget.cc @@ -132,7 +132,8 @@ void JoystickWidget::updateUIForJoystick(int id) { JoystickAxis* axis = new JoystickAxis(i, m_ui->axesBox); axis->setValue(joystick->getCurrentValueForAxis(i)); - connect(axis, SIGNAL(mappingChanged(int,JoystickInput::JOYSTICK_INPUT_MAPPING)), this, SLOT(setMappingAxis(int,JoystickInput::JOYSTICK_INPUT_MAPPING))); + connect(axis, SIGNAL(mappingChanged(int,JoystickInput::JOYSTICK_INPUT_MAPPING)), this->joystick, SLOT(setAxisMapping(int,JoystickInput::JOYSTICK_INPUT_MAPPING))); + connect(axis, SIGNAL(inversionChanged(int,bool)), this->joystick, SLOT(setAxisInversion(int,bool))); // And make sure we insert BEFORE the vertical spacer. m_ui->axesLayout->insertWidget(i, axis); axes.append(axis); @@ -152,28 +153,6 @@ void JoystickWidget::setHat(int x, int y) m_ui->statusLabel->setText(tr("Hat position: x: %1, y: %2").arg(x).arg(y)); } -void JoystickWidget::setMappingAxis(int axisID, JoystickInput::JOYSTICK_INPUT_MAPPING newMapping) -{ - switch (newMapping) - { - case JoystickInput::JOYSTICK_INPUT_MAPPING_ROLL: - joystick->setMappingRollAxis(axisID); - break; - case JoystickInput::JOYSTICK_INPUT_MAPPING_PITCH: - joystick->setMappingPitchAxis(axisID); - break; - case JoystickInput::JOYSTICK_INPUT_MAPPING_YAW: - joystick->setMappingYawAxis(axisID); - break; - case JoystickInput::JOYSTICK_INPUT_MAPPING_THROTTLE: - joystick->setMappingThrottleAxis(axisID); - break; - case JoystickInput::JOYSTICK_INPUT_MAPPING_NONE: - default: - break; - } -} - void JoystickWidget::joystickButtonPressed(int key) { QString colorStyle = QString("QLabel { background-color: %1;}").arg(buttonLabelColor.name()); diff --git a/src/ui/JoystickWidget.h b/src/ui/JoystickWidget.h index de57a0a8409150f385dcca790bc7bf22a74f529d..624ec87f2434fc9218ffbe2e1e30c45c9d700cd2 100644 --- a/src/ui/JoystickWidget.h +++ b/src/ui/JoystickWidget.h @@ -55,8 +55,6 @@ public: public slots: /** @brief Update the UI for a new joystick based on SDL ID. */ void updateUIForJoystick(int id); - /** @brief Change the stored mapping for a given axis. */ - void setMappingAxis(int axisID, JoystickInput::JOYSTICK_INPUT_MAPPING newMapping); /** * @brief Update a given axis with a new value * @param axis The index of the axis to update.