diff --git a/src/Joystick/Joystick.cc b/src/Joystick/Joystick.cc index f521d21095d91396808a635786b0e8aeb1cb73ec..294f85681808fadb29597ca3bbfe88f5568b0be6 100644 --- a/src/Joystick/Joystick.cc +++ b/src/Joystick/Joystick.cc @@ -175,10 +175,8 @@ void Joystick::_activeVehicleChanged(Vehicle* activeVehicle) void Joystick::_loadSettings() { - QSettings settings; - + QSettings settings; settings.beginGroup(_settingsGroup); - Vehicle* activeVehicle = _multiVehicleManager->activeVehicle(); if(_txModeSettingsKey && activeVehicle) @@ -191,25 +189,25 @@ void Joystick::_loadSettings() qCDebug(JoystickLog) << "_loadSettings " << _name; - _calibrated = settings.value(_calibratedSettingsKey, false).toBool(); - _exponential = settings.value(_exponentialSettingsKey, 0).toFloat(); - _accumulator = settings.value(_accumulatorSettingsKey, false).toBool(); - _deadband = settings.value(_deadbandSettingsKey, false).toBool(); + _calibrated = settings.value(_calibratedSettingsKey, false).toBool(); + _exponential = settings.value(_exponentialSettingsKey, 0).toFloat(); + _accumulator = settings.value(_accumulatorSettingsKey, false).toBool(); + _deadband = settings.value(_deadbandSettingsKey, false).toBool(); + _frequency = settings.value(_frequencySettingsKey, 25.0f).toFloat(); _circleCorrection = settings.value(_circleCorrectionSettingsKey, false).toBool(); - _frequency = settings.value(_frequencySettingsKey, 25.0f).toFloat(); - _throttleMode = (ThrottleMode_t)settings.value(_throttleModeSettingsKey, ThrottleModeDownZero).toInt(&convertOk); + _throttleMode = static_cast(settings.value(_throttleModeSettingsKey, ThrottleModeDownZero).toInt(&convertOk)); badSettings |= !convertOk; qCDebug(JoystickLog) << "_loadSettings calibrated:txmode:throttlemode:exponential:deadband:badsettings" << _calibrated << _transmitterMode << _throttleMode << _exponential << _deadband << badSettings; - QString minTpl ("Axis%1Min"); - QString maxTpl ("Axis%1Max"); - QString trimTpl ("Axis%1Trim"); - QString revTpl ("Axis%1Rev"); + QString minTpl ("Axis%1Min"); + QString maxTpl ("Axis%1Max"); + QString trimTpl ("Axis%1Trim"); + QString revTpl ("Axis%1Rev"); QString deadbndTpl ("Axis%1Deadbnd"); - for (int axis=0; axis<_axisCount; axis++) { + for (int axis = 0; axis < _axisCount; axis++) { Calibration_t* calibration = &_rgCalibration[axis]; calibration->center = settings.value(trimTpl.arg(axis), 0).toInt(&convertOk); @@ -226,7 +224,6 @@ void Joystick::_loadSettings() calibration->reversed = settings.value(revTpl.arg(axis), false).toBool(); - qCDebug(JoystickLog) << "_loadSettings axis:min:max:trim:reversed:deadband:badsettings" << axis << calibration->min << calibration->max << calibration->center << calibration->reversed << calibration->deadband << badSettings; } @@ -268,31 +265,29 @@ void Joystick::_saveSettings() settings.beginGroup(_name); - settings.setValue(_calibratedSettingsKey, _calibrated); - settings.setValue(_exponentialSettingsKey, _exponential); - settings.setValue(_accumulatorSettingsKey, _accumulator); - settings.setValue(_deadbandSettingsKey, _deadband); - settings.setValue(_circleCorrectionSettingsKey, _circleCorrection); - settings.setValue(_frequencySettingsKey, _frequency); + settings.setValue(_calibratedSettingsKey, _calibrated); + settings.setValue(_exponentialSettingsKey, _exponential); + settings.setValue(_accumulatorSettingsKey, _accumulator); + settings.setValue(_deadbandSettingsKey, _deadband); + settings.setValue(_frequencySettingsKey, _frequency); settings.setValue(_throttleModeSettingsKey, _throttleMode); + settings.setValue(_circleCorrectionSettingsKey, _circleCorrection); qCDebug(JoystickLog) << "_saveSettings calibrated:throttlemode:deadband:txmode" << _calibrated << _throttleMode << _deadband << _circleCorrection << _transmitterMode; - QString minTpl ("Axis%1Min"); - QString maxTpl ("Axis%1Max"); - QString trimTpl ("Axis%1Trim"); - QString revTpl ("Axis%1Rev"); + QString minTpl ("Axis%1Min"); + QString maxTpl ("Axis%1Max"); + QString trimTpl ("Axis%1Trim"); + QString revTpl ("Axis%1Rev"); QString deadbndTpl ("Axis%1Deadbnd"); - for (int axis=0; axis<_axisCount; axis++) { + for (int axis = 0; axis < _axisCount; axis++) { Calibration_t* calibration = &_rgCalibration[axis]; - settings.setValue(trimTpl.arg(axis), calibration->center); settings.setValue(minTpl.arg(axis), calibration->min); settings.setValue(maxTpl.arg(axis), calibration->max); settings.setValue(revTpl.arg(axis), calibration->reversed); settings.setValue(deadbndTpl.arg(axis), calibration->deadband); - qCDebug(JoystickLog) << "_saveSettings name:axis:min:max:trim:reversed:deadband" << _name << axis @@ -308,12 +303,12 @@ void Joystick::_saveSettings() int temp[maxFunction]; _remapAxes(_transmitterMode, 2, temp); - for (int function=0; function= 0) { + joystickCombo.currentIndex = index + } + } + } } + } + //-- Separator + Rectangle { + width: parent.width + height: 1 + border.color: qgcPal.text + border.width: 1 + } + //-- Main Row + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter + // Left side column + Column { + id: leftColumn + spacing: ScreenTools.defaultFontPixelHeight - ColorAnimation { - id: barAnimation - target: bar - property: "color" - from: "yellow" - to: __barColor - duration: 1500 - } + // Attitude Controls + Column { + width: parent.width + spacing: 5 + QGCLabel { text: qsTr("Attitude Controls") } - // Axis value debugger - /* - QGCLabel { - anchors.fill: parent - text: axisValue - } - */ + Item { + width: parent.width + height: defaultTextHeight * 2 - } - } // Component - axisMonitorDisplayComponent + QGCLabel { + id: rollLabel + width: _attitudeLabelWidth + text: activeVehicle.sub ? qsTr("Lateral") : qsTr("Roll") + } - // Main view Qml starts here + Loader { + id: rollLoader + anchors.left: rollLabel.right + anchors.right: parent.right + height: ScreenTools.defaultFontPixelHeight + width: 100 + sourceComponent: axisMonitorDisplayComponent + property bool mapped: controller.rollAxisMapped + property bool reversed: controller.rollAxisReversed + } - // Left side column - Column { - id: leftColumn - anchors.rightMargin: ScreenTools.defaultFontPixelWidth - anchors.left: parent.left - anchors.right: rightColumn.left - spacing: ScreenTools.defaultFontPixelHeight + Connections { + target: _activeJoystick + onManualControl: rollLoader.item.axisValue = roll*32768.0 + } + } - // Attitude Controls - Column { - width: parent.width - spacing: 5 + Item { + width: parent.width + height: defaultTextHeight * 2 - QGCLabel { text: qsTr("Attitude Controls") } + QGCLabel { + id: pitchLabel + width: _attitudeLabelWidth + text: activeVehicle.sub ? qsTr("Forward") : qsTr("Pitch") + } - Item { - width: parent.width - height: defaultTextHeight * 2 + Loader { + id: pitchLoader + anchors.left: pitchLabel.right + anchors.right: parent.right + height: ScreenTools.defaultFontPixelHeight + width: 100 + sourceComponent: axisMonitorDisplayComponent + property bool mapped: controller.pitchAxisMapped + property bool reversed: controller.pitchAxisReversed + } - QGCLabel { - id: rollLabel - width: _attitudeLabelWidth - text: activeVehicle.sub ? qsTr("Lateral") : qsTr("Roll") - } + Connections { + target: _activeJoystick + onManualControl: pitchLoader.item.axisValue = pitch*32768.0 + } + } - Loader { - id: rollLoader - anchors.left: rollLabel.right - anchors.right: parent.right - height: ScreenTools.defaultFontPixelHeight - width: 100 - sourceComponent: axisMonitorDisplayComponent - property bool mapped: controller.rollAxisMapped - property bool reversed: controller.rollAxisReversed - } + Item { + width: parent.width + height: defaultTextHeight * 2 - Connections { - target: _activeJoystick - onManualControl: rollLoader.item.axisValue = roll*32768.0 - } - } + QGCLabel { + id: yawLabel + width: _attitudeLabelWidth + text: qsTr("Yaw") + } - Item { - width: parent.width - height: defaultTextHeight * 2 + Loader { + id: yawLoader + anchors.left: yawLabel.right + anchors.right: parent.right + height: ScreenTools.defaultFontPixelHeight + width: 100 + sourceComponent: axisMonitorDisplayComponent + property bool mapped: controller.yawAxisMapped + property bool reversed: controller.yawAxisReversed + } - QGCLabel { - id: pitchLabel - width: _attitudeLabelWidth - text: activeVehicle.sub ? qsTr("Forward") : qsTr("Pitch") - } + Connections { + target: _activeJoystick + onManualControl: yawLoader.item.axisValue = yaw*32768.0 + } + } - Loader { - id: pitchLoader - anchors.left: pitchLabel.right - anchors.right: parent.right - height: ScreenTools.defaultFontPixelHeight - width: 100 - sourceComponent: axisMonitorDisplayComponent - property bool mapped: controller.pitchAxisMapped - property bool reversed: controller.pitchAxisReversed - } + Item { + width: parent.width + height: defaultTextHeight * 2 - Connections { - target: _activeJoystick - onManualControl: pitchLoader.item.axisValue = pitch*32768.0 - } - } + QGCLabel { + id: throttleLabel + width: _attitudeLabelWidth + text: qsTr("Throttle") + } - Item { - width: parent.width - height: defaultTextHeight * 2 + Loader { + id: throttleLoader + anchors.left: throttleLabel.right + anchors.right: parent.right + height: ScreenTools.defaultFontPixelHeight + width: 100 + sourceComponent: axisMonitorDisplayComponent + property bool mapped: controller.throttleAxisMapped + property bool reversed: controller.throttleAxisReversed + } - QGCLabel { - id: yawLabel - width: _attitudeLabelWidth - text: qsTr("Yaw") - } + Connections { + target: _activeJoystick + onManualControl: throttleLoader.item.axisValue = _activeJoystick.negativeThrust ? -throttle*32768.0 : (-2*throttle+1)*32768.0 + } + } - Loader { - id: yawLoader - anchors.left: yawLabel.right - anchors.right: parent.right - height: ScreenTools.defaultFontPixelHeight - width: 100 - sourceComponent: axisMonitorDisplayComponent - property bool mapped: controller.yawAxisMapped - property bool reversed: controller.yawAxisReversed - } + Item { + width: parent.width + height: controller.hasGimbal ? defaultTextHeight * 2 : 0 + visible: controller.hasGimbal - Connections { - target: _activeJoystick - onManualControl: yawLoader.item.axisValue = yaw*32768.0 - } - } + QGCLabel { + id: gimbalPitchLabel + width: _attitudeLabelWidth + text: qsTr("Gimbal Pitch") + } - Item { - width: parent.width - height: defaultTextHeight * 2 + Loader { + id: gimbalPitchLoader + anchors.left: gimbalPitchLabel.right + anchors.right: parent.right + height: ScreenTools.defaultFontPixelHeight + width: 100 + sourceComponent: axisMonitorDisplayComponent + property bool mapped: controller.gimbalPitchAxisMapped + property bool reversed: controller.gimbalPitchAxisReversed + } - QGCLabel { - id: throttleLabel - width: _attitudeLabelWidth - text: qsTr("Throttle") - } + Connections { + target: _activeJoystick + onManualControl: gimbalPitchLoader.item.axisValue = gimbalPitch * 32768.0 + } + } - Loader { - id: throttleLoader - anchors.left: throttleLabel.right - anchors.right: parent.right - height: ScreenTools.defaultFontPixelHeight - width: 100 - sourceComponent: axisMonitorDisplayComponent - property bool mapped: controller.throttleAxisMapped - property bool reversed: controller.throttleAxisReversed - } + Item { + width: parent.width + height: controller.hasGimbal ? defaultTextHeight * 2 : 0 + visible: controller.hasGimbal - Connections { - target: _activeJoystick - onManualControl: throttleLoader.item.axisValue = _activeJoystick.negativeThrust ? -throttle*32768.0 : (-2*throttle+1)*32768.0 - } - } + QGCLabel { + id: gimbalYawLabel + width: _attitudeLabelWidth + text: qsTr("Gimbal Yaw") + } - Item { - width: parent.width - height: defaultTextHeight * 2 + Loader { + id: gimbalYawLoader + anchors.left: gimbalYawLabel.right + anchors.right: parent.right + height: ScreenTools.defaultFontPixelHeight + width: 100 + sourceComponent: axisMonitorDisplayComponent + property bool mapped: controller.gimbalYawAxisMapped + property bool reversed: controller.gimbalYawAxisReversed + } - QGCLabel { - id: gimbalPitchLabel - width: _attitudeLabelWidth - text: qsTr("Gimbal Pitch") - } + Connections { + target: _activeJoystick + onManualControl: gimbalYawLoader.item.axisValue = gimbalYaw * 32768.0 + } + } - Loader { - id: gimbalPitchLoader - anchors.left: gimbalPitchLabel.right - anchors.right: parent.right - height: ScreenTools.defaultFontPixelHeight - width: 100 - sourceComponent: axisMonitorDisplayComponent - property bool mapped: controller.gimbalPitchAxisMapped - property bool reversed: controller.gimbalPitchAxisReversed - } + } // Column - Attitude Control labels - Connections { - target: _activeJoystick - onManualControl: gimbalPitchLoader.item.axisValue = gimbalPitch * 32768.0 + // Command Buttons + Row { + spacing: 10 + visible: _activeJoystick.requiresCalibration + anchors.horizontalCenter: parent.horizontalCenter + QGCButton { + id: skipButton + text: qsTr("Skip") + width: ScreenTools.defaultFontPixelWidth * 10 + onClicked: controller.skipButtonClicked() + } + QGCButton { + id: cancelButton + text: qsTr("Cancel") + width: ScreenTools.defaultFontPixelWidth * 10 + onClicked: controller.cancelButtonClicked() + } + QGCButton { + id: nextButton + primary: true + text: qsTr("Calibrate") + width: ScreenTools.defaultFontPixelWidth * 10 + onClicked: controller.nextButtonClicked() + } } - } - - Item { - width: parent.width - height: defaultTextHeight * 2 + // Status Text QGCLabel { - id: gimbalYawLabel - width: _attitudeLabelWidth - text: qsTr("Gimbal Yaw") + text: controller.statusText + width: parent.width + wrapMode: Text.WordWrap + visible: text !== "" } - Loader { - id: gimbalYawLoader - anchors.left: gimbalYawLabel.right - anchors.right: parent.right - height: ScreenTools.defaultFontPixelHeight - width: 100 - sourceComponent: axisMonitorDisplayComponent - property bool mapped: controller.gimbalYawAxisMapped - property bool reversed: controller.gimbalYawAxisReversed + //-- Separator + Rectangle { + width: parent.width + height: 1 + border.color: qgcPal.text + border.width: 1 } - Connections { - target: _activeJoystick - onManualControl: gimbalYawLoader.item.axisValue = gimbalYaw * 32768.0 - } - } + // Settings + Row { + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth - } // Column - Attitude Control labels + // Left column settings + Column { + width: parent.width * 0.5 + spacing: ScreenTools.defaultFontPixelHeight - // Command Buttons - Row { - spacing: 10 - visible: _activeJoystick.requiresCalibration - anchors.horizontalCenter: parent.horizontalCenter - QGCButton { - id: skipButton - text: qsTr("Skip") - onClicked: controller.skipButtonClicked() - } - QGCButton { - id: cancelButton - text: qsTr("Cancel") - onClicked: controller.cancelButtonClicked() - } - QGCButton { - id: nextButton - primary: true - text: qsTr("Calibrate") - onClicked: controller.nextButtonClicked() - } - } + QGCLabel { text: qsTr("Additional Joystick settings:") } - // Status Text - QGCLabel { - id: statusText - width: parent.width - wrapMode: Text.WordWrap - } + Column { + width: parent.width + spacing: ScreenTools.defaultFontPixelHeight - Rectangle { - width: parent.width - height: 1 - border.color: qgcPal.text - border.width: 1 - } + Column { + spacing: ScreenTools.defaultFontPixelHeight / 3 + visible: activeVehicle.supportsThrottleModeCenterZero - // Settings - Row { - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth + QGCRadioButton { + text: qsTr("Center stick is zero throttle") + checked: _activeJoystick ? _activeJoystick.throttleMode === 0 : false - // Left column settings - Column { - width: parent.width / 2 - spacing: ScreenTools.defaultFontPixelHeight + onClicked: _activeJoystick.throttleMode = 0 + } - QGCLabel { text: qsTr("Additional Joystick settings:") } + Row { + x: 20 + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: _activeJoystick ? _activeJoystick.throttleMode === 0 : false - Column { - width: parent.width - spacing: ScreenTools.defaultFontPixelHeight + QGCCheckBox { + id: accumulator + checked: _activeJoystick ? _activeJoystick.accumulator : false + text: qsTr("Spring loaded throttle smoothing") + onClicked: _activeJoystick.accumulator = checked + } + } - QGCCheckBox { - id: enabledCheckBox - enabled: _activeJoystick ? _activeJoystick.calibrated : false - text: _activeJoystick ? _activeJoystick.calibrated ? qsTr("Enable joystick input") : qsTr("Enable not allowed (Calibrate First)") : "" - onClicked: activeVehicle.joystickEnabled = checked - Component.onCompleted: checked = activeVehicle.joystickEnabled + QGCRadioButton { + text: qsTr("Full down stick is zero throttle") + checked: _activeJoystick ? _activeJoystick.throttleMode === 1 : false - Connections { - target: activeVehicle + onClicked: _activeJoystick.throttleMode = 1 + } - onJoystickEnabledChanged: { - enabledCheckBox.checked = activeVehicle.joystickEnabled + QGCCheckBox { + visible: activeVehicle.supportsNegativeThrust + id: negativeThrust + text: qsTr("Allow negative Thrust") + enabled: _activeJoystick.negativeThrust = activeVehicle.supportsNegativeThrust + checked: _activeJoystick ? _activeJoystick.negativeThrust : false + onClicked: _activeJoystick.negativeThrust = checked + } } - } - Connections { - target: joystickManager + Column { + spacing: ScreenTools.defaultFontPixelHeight - onActiveJoystickChanged: { - if(_activeJoystick) { - enabledCheckBox.checked = Qt.binding(function() { return _activeJoystick.calibrated && activeVehicle.joystickEnabled }) + QGCLabel { + id: expoSliderLabel + text: qsTr("Exponential:") } - } - } - } - - QGCLabel { - text: qsTr("Active joystick:") - } - QGCComboBox { - id: joystickCombo - width: parent.width * 0.9 - model: joystickManager.joystickNames - - onActivated: joystickManager.activeJoystickName = textAt(index) - - Component.onCompleted: { - var index = joystickCombo.find(joystickManager.activeJoystickName) - if (index === -1) { - console.warn(qsTr("Active joystick name not in combo"), joystickManager.activeJoystickName) - } else { - joystickCombo.currentIndex = index + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCSlider { + id: expoSlider + width: ScreenTools.defaultFontPixelWidth * 14 + minimumValue: 0 + maximumValue: 0.75 + Component.onCompleted: value = -_activeJoystick.exponential + onValueChanged: _activeJoystick.exponential = -value + } + QGCLabel { + id: expoSliderIndicator + text: expoSlider.value.toFixed(2) + } + } } - } - Connections { - target: joystickManager - onAvailableJoysticksChanged: { - var index = joystickCombo.find(joystickManager.activeJoystickName) - if (index >= 0) { - joystickCombo.currentIndex = index + QGCCheckBox { + id: advancedSettings + checked: activeVehicle.joystickMode !== 0 + text: qsTr("Advanced settings (careful!)") + + onClicked: { + if (!checked) { + activeVehicle.joystickMode = 0 + } } } - } - } - Column { - spacing: ScreenTools.defaultFontPixelHeight / 3 - visible: activeVehicle.supportsThrottleModeCenterZero + Row { + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: advancedSettings.checked - QGCRadioButton { - text: qsTr("Center stick is zero throttle") - checked: _activeJoystick ? _activeJoystick.throttleMode === 0 : false + QGCLabel { + id: joystickModeLabel + anchors.baseline: joystickModeCombo.baseline + text: qsTr("Joystick mode:") + } - onClicked: _activeJoystick.throttleMode = 0 - } + QGCComboBox { + id: joystickModeCombo + currentIndex: activeVehicle.joystickMode + width: ScreenTools.defaultFontPixelWidth * 20 + model: activeVehicle.joystickModes - Row { - x: 20 - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth - visible: _activeJoystick ? _activeJoystick.throttleMode === 0 : false + onActivated: activeVehicle.joystickMode = index + } + } - QGCCheckBox { - id: accumulator - checked: _activeJoystick ? _activeJoystick.accumulator : false - text: qsTr("Spring loaded throttle smoothing") + Row { + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: advancedSettings.checked + QGCLabel { + text: qsTr("Message frequency (Hz):") + anchors.verticalCenter: parent.verticalCenter + } + QGCTextField { + text: _activeJoystick.frequency + validator: DoubleValidator { bottom: 0.25; top: 100.0; } + inputMethodHints: Qt.ImhFormattedNumbersOnly + onEditingFinished: { + _activeJoystick.frequency = parseFloat(text) + } + } + } - onClicked: _activeJoystick.accumulator = checked + Row { + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: advancedSettings.checked + QGCCheckBox { + id: joystickCircleCorrection + checked: activeVehicle.joystickMode !== 0 + text: qsTr("Enable circle correction") + + Component.onCompleted: checked = _activeJoystick.circleCorrection + onClicked: { + _activeJoystick.circleCorrection = checked + } + } } - } - QGCRadioButton { - text: qsTr("Full down stick is zero throttle") - checked: _activeJoystick ? _activeJoystick.throttleMode === 1 : false + Row { + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: advancedSettings.checked - onClicked: _activeJoystick.throttleMode = 1 - } + QGCCheckBox { + id: deadband + checked: controller.deadbandToggle + text: qsTr("Deadbands") - QGCCheckBox { - visible: activeVehicle.supportsNegativeThrust - id: negativeThrust - text: qsTr("Allow negative Thrust") - enabled: _activeJoystick.negativeThrust = activeVehicle.supportsNegativeThrust - checked: _activeJoystick ? _activeJoystick.negativeThrust : false - onClicked: _activeJoystick.negativeThrust = checked + onClicked: controller.deadbandToggle = checked + } + } + Row{ + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: advancedSettings.checked + QGCLabel{ + width: parent.width * 0.85 + font.pointSize: ScreenTools.smallFontPointSize + wrapMode: Text.WordWrap + text: qsTr("Deadband can be set during the first ") + + qsTr("step of calibration by gently wiggling each axis. ") + + qsTr("Deadband can also be adjusted by clicking and ") + + qsTr("dragging vertically on the corresponding axis monitor.") + visible: controller.deadbandToggle + } + } } - } + } // Column - left column + // Right column settings Column { - spacing: ScreenTools.defaultFontPixelHeight + width: parent.width / 2 + spacing: ScreenTools.defaultFontPixelHeight - QGCLabel { - id: expoSliderLabel - text: qsTr("Exponential:") - } + Connections { + target: _activeJoystick - Row { - spacing: ScreenTools.defaultFontPixelWidth - QGCSlider { - id: expoSlider - width: ScreenTools.defaultFontPixelWidth * 14 - minimumValue: 0 - maximumValue: 0.75 - Component.onCompleted: value = -_activeJoystick.exponential - onValueChanged: _activeJoystick.exponential = -value - } - QGCLabel { - id: expoSliderIndicator - text: expoSlider.value.toFixed(2) + onRawButtonPressedChanged: { + if (buttonActionRepeater.itemAt(index)) { + buttonActionRepeater.itemAt(index).pressed = pressed + } + if (jsButtonActionRepeater.itemAt(index)) { + jsButtonActionRepeater.itemAt(index).pressed = pressed + } } } - } + //-- AP_JSButton Buttons (ArduSub) + QGCLabel { text: qsTr("Button actions:"); visible: activeVehicle.supportsJSButton; } + Column { + width: parent.width + visible: activeVehicle.supportsJSButton + spacing: ScreenTools.defaultFontPixelHeight / 3 + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + horizontalAlignment: Text.AlignHCenter + width: ScreenTools.defaultFontPixelHeight * 1.5 + text: qsTr("#") + } + QGCLabel { + width: ScreenTools.defaultFontPixelWidth * 15 + text: qsTr("Function: ") + } + QGCLabel { + width: ScreenTools.defaultFontPixelWidth * 15 + text: qsTr("Shift Function: ") + } + } // Row + Repeater { + id: jsButtonActionRepeater + model: _activeJoystick ? Math.min(_activeJoystick.totalButtonCount, _maxButtons) : 0 + + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: activeVehicle.supportsJSButton + + property bool pressed + + Rectangle { + anchors.verticalCenter: parent.verticalCenter + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: width + border.width: 1 + border.color: qgcPal.text + color: pressed ? qgcPal.buttonHighlight : qgcPal.button + + + QGCLabel { + anchors.fill: parent + color: pressed ? qgcPal.buttonHighlightText : qgcPal.buttonText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: modelData + } + } + + FactComboBox { + id: mainJSButtonActionCombo + width: ScreenTools.defaultFontPixelWidth * 15 + fact: controller.parameterExists(-1, "BTN"+index+"_FUNCTION") ? controller.getParameterFact(-1, "BTN" + index + "_FUNCTION") : null; + indexModel: false + } + + FactComboBox { + id: shiftJSButtonActionCombo + width: ScreenTools.defaultFontPixelWidth * 15 + fact: controller.parameterExists(-1, "BTN"+index+"_SFUNCTION") ? controller.getParameterFact(-1, "BTN" + index + "_SFUNCTION") : null; + indexModel: false + } + } // Row + } // Repeater + } // Column + } // Column - right setting column + } // Row - Settings + + } // Column - Left Main Column + // Right side column + Column { + width: Math.min(ScreenTools.defaultFontPixelWidth * 35, availableWidth * 0.4) + spacing: ScreenTools.defaultFontPixelHeight - QGCCheckBox { - id: advancedSettings - checked: activeVehicle.joystickMode !== 0 - text: qsTr("Advanced settings (careful!)") + Row { + spacing: ScreenTools.defaultFontPixelWidth + anchors.horizontalCenter: parent.horizontalCenter - onClicked: { - if (!checked) { - activeVehicle.joystickMode = 0 - } - } + QGCLabel { + text: "TX Mode:" + anchors.verticalCenter: parent.verticalCenter } - Row { - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth - visible: advancedSettings.checked - - QGCLabel { - id: joystickModeLabel - anchors.baseline: joystickModeCombo.baseline - text: qsTr("Joystick mode:") - } - - QGCComboBox { - id: joystickModeCombo - currentIndex: activeVehicle.joystickMode - width: ScreenTools.defaultFontPixelWidth * 20 - model: activeVehicle.joystickModes + QGCRadioButton { + text: "1" + checked: controller.transmitterMode == 1 + enabled: !controller.calibrating + onClicked: controller.transmitterMode = 1 + anchors.verticalCenter: parent.verticalCenter + } - onActivated: activeVehicle.joystickMode = index - } + QGCRadioButton { + text: "2" + checked: controller.transmitterMode == 2 + enabled: !controller.calibrating + onClicked: controller.transmitterMode = 2 + anchors.verticalCenter: parent.verticalCenter } - Row { - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth - visible: advancedSettings.checked - QGCLabel { - text: qsTr("Message frequency (Hz):") - anchors.verticalCenter: parent.verticalCenter - } - QGCTextField { - text: _activeJoystick.frequency - validator: DoubleValidator { bottom: 0.25; top: 100.0; } - inputMethodHints: Qt.ImhFormattedNumbersOnly - onEditingFinished: { - _activeJoystick.frequency = parseFloat(text) - } - } + QGCRadioButton { + text: "3" + checked: controller.transmitterMode == 3 + enabled: !controller.calibrating + onClicked: controller.transmitterMode = 3 + anchors.verticalCenter: parent.verticalCenter } - Row { - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth - visible: advancedSettings.checked - QGCCheckBox { - id: joystickCircleCorrection - checked: activeVehicle.joystickMode !== 0 - text: qsTr("Enable circle correction") + QGCRadioButton { + text: "4" + checked: controller.transmitterMode == 4 + enabled: !controller.calibrating + onClicked: controller.transmitterMode = 4 + anchors.verticalCenter: parent.verticalCenter + } + } - Component.onCompleted: checked = _activeJoystick.circleCorrection - onClicked: { - _activeJoystick.circleCorrection = checked - } + //------------------------------------------------------------- + //-- Joystick Icon + Rectangle { + width: Math.round(parent.width * 0.9) + height: Math.round(width * 0.5) + radius: ScreenTools.defaultFontPixelWidth * 2 + color: qgcPal.window + border.color: qgcPal.text + border.width: ScreenTools.defaultFontPixelWidth * 0.25 + anchors.horizontalCenter: parent.horizontalCenter + property bool hasStickPositions: controller.stickPositions.length === 4 + Connections { + target: controller + onStickPositionsChanged: { + console.log(controller.stickPositions[0] + ' ' + controller.stickPositions[1] + ' ' + controller.stickPositions[2] + ' ' + controller.stickPositions[3]) } } - Row { - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth - visible: advancedSettings.checked - - QGCCheckBox { - id: deadband - checked: controller.deadbandToggle - text: qsTr("Deadbands") - - onClicked: controller.deadbandToggle = checked - } + //--------------------------------------------------------- + //-- Left Stick + Rectangle { + width: parent.width * 0.25 + height: width + radius: width * 0.5 + color: qgcPal.window + border.color: qgcPal.text + border.width: ScreenTools.defaultFontPixelWidth * 0.125 + x: (parent.width * 0.25) - (width * 0.5) + y: (parent.height * 0.5) - (height * 0.5) } - Row{ - width: parent.width - spacing: ScreenTools.defaultFontPixelWidth - visible: advancedSettings.checked - QGCLabel{ - width: parent.width * 0.85 - font.pointSize: ScreenTools.smallFontPointSize - wrapMode: Text.WordWrap - text: qsTr("Deadband can be set during the first ") + - qsTr("step of calibration by gently wiggling each axis. ") + - qsTr("Deadband can also be adjusted by clicking and ") + - qsTr("dragging vertically on the corresponding axis monitor.") - visible: controller.deadbandToggle - } + Rectangle { + color: qgcPal.colorGreen + width: parent.width * 0.035 + height: width + radius: width * 0.5 + visible: parent.hasStickPositions + x: (parent.width * controller.stickPositions[0]) - (width * 0.5) + y: (parent.height * controller.stickPositions[1]) - (height * 0.5) + } + //--------------------------------------------------------- + //-- Right Stick + Rectangle { + width: parent.width * 0.25 + height: width + radius: width * 0.5 + color: qgcPal.window + border.color: qgcPal.text + border.width: ScreenTools.defaultFontPixelWidth * 0.125 + x: (parent.width * 0.75) - (width * 0.5) + y: (parent.height * 0.5) - (height * 0.5) + } + Rectangle { + color: qgcPal.colorGreen + width: parent.width * 0.035 + height: width + radius: width * 0.5 + visible: parent.hasStickPositions + x: (parent.width * controller.stickPositions[2]) - (width * 0.5) + y: (parent.height * controller.stickPositions[3]) - (height * 0.5) + } + //--------------------------------------------------------- + //-- Gimbal Pitch + Rectangle { + width: ScreenTools.defaultFontPixelWidth * 0.125 + height: parent.height * 0.2 + color: qgcPal.text + visible: controller.hasGimbal + x: (parent.width * 0.5) - (width * 0.5) + y: (parent.height * 0.5) - (height * 0.5) + } + Rectangle { + color: qgcPal.colorGreen + width: parent.width * 0.035 + height: width + radius: width * 0.5 + visible: controller.hasGimbal + x: (parent.width * controller.gimbalPositions[0]) - (width * 0.5) + y: (parent.height * controller.gimbalPositions[1]) - (height * 0.5) + } + //--------------------------------------------------------- + //-- Gimbal Yaw + Rectangle { + width: parent.width * 0.2 + height: ScreenTools.defaultFontPixelWidth * 0.125 + color: qgcPal.text + visible: controller.hasGimbal + x: (parent.width * 0.5) - (width * 0.5) + y: (parent.height * 0.3) - (height * 0.5) + } + Rectangle { + color: qgcPal.colorGreen + width: parent.width * 0.035 + height: width + radius: width * 0.5 + visible: controller.hasGimbal + x: (parent.width * controller.gimbalPositions[2]) - (width * 0.5) + y: (parent.height * controller.gimbalPositions[3]) - (height * 0.5) } } - } // Column - left column - // Right column settings - Column { - width: parent.width / 2 - spacing: ScreenTools.defaultFontPixelHeight + // Axis monitor + Column { + width: parent.width + spacing: 5 - Connections { - target: _activeJoystick + QGCLabel { + text: qsTr("Axis Monitor") + anchors.horizontalCenter: parent.horizontalCenter + } - onRawButtonPressedChanged: { - if (buttonActionRepeater.itemAt(index)) { - buttonActionRepeater.itemAt(index).pressed = pressed + Connections { + target: controller + + onAxisValueChanged: { + if (axisMonitorRepeater.itemAt(axis)) { + axisMonitorRepeater.itemAt(axis).loader.item.axisValue = value + } } - if (jsButtonActionRepeater.itemAt(index)) { - jsButtonActionRepeater.itemAt(index).pressed = pressed + + onAxisDeadbandChanged: { + if (axisMonitorRepeater.itemAt(axis)) { + axisMonitorRepeater.itemAt(axis).loader.item.deadbandValue = value + } } } - } - - QGCLabel { text: qsTr("Button actions:") } - - Column { - width: parent.width - spacing: ScreenTools.defaultFontPixelHeight / 3 Repeater { - id: buttonActionRepeater - model: _activeJoystick ? Math.min(_activeJoystick.totalButtonCount, _maxButtons) : 0 + id: axisMonitorRepeater + model: _activeJoystick ? _activeJoystick.axisCount : 0 + width: parent.width Row { - spacing: ScreenTools.defaultFontPixelWidth - visible: !activeVehicle.supportsJSButton - - property bool pressed + spacing: 5 + anchors.horizontalCenter: parent.horizontalCenter - QGCCheckBox { - anchors.verticalCenter: parent.verticalCenter - checked: _activeJoystick ? _activeJoystick.buttonActions[modelData] !== "" : false + // Need this to get to loader from Connections above + property Item loader: theLoader - onClicked: _activeJoystick.setButtonAction(modelData, checked ? buttonActionCombo.textAt(buttonActionCombo.currentIndex) : "") + QGCLabel { + id: axisLabel + text: modelData } - Rectangle { - anchors.verticalCenter: parent.verticalCenter - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: width - border.width: 1 - border.color: qgcPal.text - color: pressed ? qgcPal.buttonHighlight : qgcPal.button - - - QGCLabel { - anchors.fill: parent - color: pressed ? qgcPal.buttonHighlightText : qgcPal.buttonText - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: modelData + Loader { + id: theLoader + anchors.verticalCenter: axisLabel.verticalCenter + height: ScreenTools.defaultFontPixelHeight + width: 200 + sourceComponent: axisMonitorDisplayComponent + Component.onCompleted: item.narrowIndicator = true + + property bool mapped: true + readonly property bool reversed: false + + MouseArea { + id: deadbandMouseArea + anchors.fill: parent.item + enabled: controller.deadbandToggle + preventStealing: true + + property real startX + property real direction + + onPressed: { + startX = mouseX + direction = startX > width/2 ? 1 : -1 + parent.item.deadbandColor = "#3C6315" + } + onPositionChanged: { + var mouseToDeadband = 32768/(width/2) // Factor to have deadband follow the mouse movement + var newValue = parent.item.deadbandValue + direction*(mouseX - startX)*mouseToDeadband + if ((newValue > 0) && (newValue <32768)){parent.item.deadbandValue=newValue;} + startX = mouseX + } + onReleased: { + controller.setDeadbandValue(modelData,parent.item.deadbandValue) + parent.item.deadbandColor = "#8c161a" + } } } - QGCComboBox { - id: buttonActionCombo - width: ScreenTools.defaultFontPixelWidth * 20 - model: _activeJoystick ? _activeJoystick.actions : 0 - - onActivated: _activeJoystick.setButtonAction(modelData, textAt(index)) - Component.onCompleted: currentIndex = find(_activeJoystick.buttonActions[modelData]) - } } - } // Repeater + } + } // Column - Axis Monitor - Row { - spacing: ScreenTools.defaultFontPixelWidth - visible: activeVehicle.supportsJSButton + // Button monitor + Column { + width: parent.width + spacing: ScreenTools.defaultFontPixelHeight - QGCLabel { - horizontalAlignment: Text.AlignHCenter - width: ScreenTools.defaultFontPixelHeight * 1.5 - text: qsTr("#") - } + QGCLabel { + text: qsTr("Button Monitor") + anchors.horizontalCenter: parent.horizontalCenter + } - QGCLabel { - width: ScreenTools.defaultFontPixelWidth * 15 - text: qsTr("Function: ") - } + Connections { + target: _activeJoystick - QGCLabel { - width: ScreenTools.defaultFontPixelWidth * 15 - text: qsTr("Shift Function: ") + onRawButtonPressedChanged: { + if (buttonMonitorRepeater.itemAt(index)) { + buttonMonitorRepeater.itemAt(index).pressed = pressed + } } - } // Row - - Repeater { - id: jsButtonActionRepeater - model: _activeJoystick ? Math.min(_activeJoystick.totalButtonCount, _maxButtons) : 0 + } - Row { - spacing: ScreenTools.defaultFontPixelWidth - visible: activeVehicle.supportsJSButton + Flow { + width: parent.width * 0.9 + spacing: -1 + anchors.horizontalCenter: parent.horizontalCenter - property bool pressed + Repeater { + id: buttonMonitorRepeater + model: _activeJoystick ? _activeJoystick.totalButtonCount : 0 Rectangle { - anchors.verticalCenter: parent.verticalCenter - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: width - border.width: 1 - border.color: qgcPal.text - color: pressed ? qgcPal.buttonHighlight : qgcPal.button + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: width + border.width: 1 + border.color: qgcPal.text + color: pressed ? qgcPal.buttonHighlight : qgcPal.windowShade + property bool pressed QGCLabel { anchors.fill: parent @@ -726,222 +900,149 @@ SetupPage { text: modelData } } + } // Repeater + } // Row + } // Column - Axis Monitor + } // Column - Right Column + } // Main Row + //-- Separator + Rectangle { + width: parent.width + height: 1 + border.color: qgcPal.text + border.width: 1 + } + //-- Button Actions + QGCLabel { text: qsTr("Button actions:"); visible: !activeVehicle.supportsJSButton; } + Flow { + width: parent.width + spacing: ScreenTools.defaultFontPixelWidth + visible: !activeVehicle.supportsJSButton + Repeater { + id: buttonActionRepeater + model: _activeJoystick ? Math.min(_activeJoystick.totalButtonCount, _maxButtons) : [] + Row { + spacing: ScreenTools.defaultFontPixelWidth + visible: !activeVehicle.supportsJSButton + property bool pressed + QGCCheckBox { + anchors.verticalCenter: parent.verticalCenter + checked: _activeJoystick ? _activeJoystick.buttonActions[modelData] !== "" : false + onClicked: _activeJoystick.setButtonAction(modelData, checked ? buttonActionCombo.textAt(buttonActionCombo.currentIndex) : "") + } + Rectangle { + anchors.verticalCenter: parent.verticalCenter + width: ScreenTools.defaultFontPixelHeight * 1.5 + height: width + border.width: 1 + border.color: qgcPal.text + color: pressed ? qgcPal.buttonHighlight : qgcPal.button + QGCLabel { + anchors.fill: parent + color: pressed ? qgcPal.buttonHighlightText : qgcPal.buttonText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: modelData + } + } + QGCComboBox { + id: buttonActionCombo + width: ScreenTools.defaultFontPixelWidth * 20 + model: _activeJoystick ? _activeJoystick.actions : 0 - FactComboBox { - id: mainJSButtonActionCombo - width: ScreenTools.defaultFontPixelWidth * 15 - fact: controller.parameterExists(-1, "BTN"+index+"_FUNCTION") ? controller.getParameterFact(-1, "BTN" + index + "_FUNCTION") : null; - indexModel: false - } + onActivated: _activeJoystick.setButtonAction(modelData, textAt(index)) + Component.onCompleted: currentIndex = find(_activeJoystick.buttonActions[modelData]) + } + } + } + } + } + // Live axis monitor control component + Component { + id: axisMonitorDisplayComponent - FactComboBox { - id: shiftJSButtonActionCombo - width: ScreenTools.defaultFontPixelWidth * 15 - fact: controller.parameterExists(-1, "BTN"+index+"_SFUNCTION") ? controller.getParameterFact(-1, "BTN" + index + "_SFUNCTION") : null; - indexModel: false - } - } // Row - } // Repeater - } // Column - } // Column - right setting column - } // Row - Settings - } // Column - Left Main Column - - // Right side column - Column { - id: rightColumn - anchors.top: parent.top - anchors.right: parent.right - width: Math.min(joystickPage.ScreenTools.defaultFontPixelWidth * 35, availableWidth * 0.4) - spacing: ScreenTools.defaultFontPixelHeight + Item { + property int axisValue: 0 + property int deadbandValue: 0 + property bool narrowIndicator: false + property color deadbandColor: "#8c161a" - Row { - spacing: ScreenTools.defaultFontPixelWidth - anchors.horizontalCenter: parent.horizontalCenter + property color __barColor: qgcPal.windowShade - QGCLabel { - text: "TX Mode:" + // Bar + Rectangle { + id: bar anchors.verticalCenter: parent.verticalCenter + width: parent.width + height: parent.height / 2 + color: __barColor } - QGCRadioButton { - text: "1" - checked: controller.transmitterMode == 1 - enabled: !controller.calibrating - onClicked: controller.transmitterMode = 1 + // Deadband + Rectangle { + id: deadbandBar anchors.verticalCenter: parent.verticalCenter - } + x: _deadbandPosition + width: _deadbandWidth + height: parent.height / 2 + color: deadbandColor + visible: controller.deadbandToggle - QGCRadioButton { - text: "2" - checked: controller.transmitterMode == 2 - enabled: !controller.calibrating - onClicked: controller.transmitterMode = 2 - anchors.verticalCenter: parent.verticalCenter + property real _percentDeadband: ((2 * deadbandValue) / (32768.0 * 2)) + property real _deadbandWidth: parent.width * _percentDeadband + property real _deadbandPosition: (parent.width - _deadbandWidth) / 2 } - QGCRadioButton { - text: "3" - checked: controller.transmitterMode == 3 - enabled: !controller.calibrating - onClicked: controller.transmitterMode = 3 - anchors.verticalCenter: parent.verticalCenter + // Center point + Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + width: ScreenTools.defaultFontPixelWidth / 2 + height: parent.height + color: qgcPal.window } - QGCRadioButton { - text: "4" - checked: controller.transmitterMode == 4 - enabled: !controller.calibrating - onClicked: controller.transmitterMode = 4 + // Indicator + Rectangle { anchors.verticalCenter: parent.verticalCenter - } - } - - QGCColoredImage { - width: parent.width * 0.9 - height: width * 0.5 - sourceSize.height: height - fillMode: Image.PreserveAspectFit - smooth: true - source: "/res/calibration/joystick.svg" - anchors.horizontalCenter: parent.horizontalCenter - } - - // Axis monitor - Column { - width: parent.width - spacing: 5 + width: parent.narrowIndicator ? height/6 : height + height: parent.height * 0.75 + x: (reversed ? (parent.width - _indicatorPosition) : _indicatorPosition) - (width / 2) + radius: width / 2 + color: qgcPal.text + visible: mapped - QGCLabel { - text: qsTr("Axis Monitor") - anchors.horizontalCenter: parent.horizontalCenter + property real _percentAxisValue: ((axisValue + 32768.0) / (32768.0 * 2)) + property real _indicatorPosition: parent.width * _percentAxisValue } - Connections { - target: controller - - onAxisValueChanged: { - if (axisMonitorRepeater.itemAt(axis)) { - axisMonitorRepeater.itemAt(axis).loader.item.axisValue = value - } - } - - onAxisDeadbandChanged: { - if (axisMonitorRepeater.itemAt(axis)) { - axisMonitorRepeater.itemAt(axis).loader.item.deadbandValue = value - } - } + QGCLabel { + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: qsTr("Not Mapped") + visible: !mapped } - Repeater { - id: axisMonitorRepeater - model: _activeJoystick ? _activeJoystick.axisCount : 0 - width: parent.width - - Row { - spacing: 5 - anchors.horizontalCenter: parent.horizontalCenter - - // Need this to get to loader from Connections above - property Item loader: theLoader - - QGCLabel { - id: axisLabel - text: modelData - } - - Loader { - id: theLoader - anchors.verticalCenter: axisLabel.verticalCenter - height: ScreenTools.defaultFontPixelHeight - width: 200 - sourceComponent: axisMonitorDisplayComponent - Component.onCompleted: item.narrowIndicator = true - - property bool mapped: true - readonly property bool reversed: false - - MouseArea { - id: deadbandMouseArea - anchors.fill: parent.item - enabled: controller.deadbandToggle - preventStealing: true - - property real startX - property real direction - - onPressed: { - startX = mouseX - direction = startX > width/2 ? 1 : -1 - parent.item.deadbandColor = "#3C6315" - } - onPositionChanged: { - var mouseToDeadband = 32768/(width/2) // Factor to have deadband follow the mouse movement - var newValue = parent.item.deadbandValue + direction*(mouseX - startX)*mouseToDeadband - if ((newValue > 0) && (newValue <32768)){parent.item.deadbandValue=newValue;} - startX = mouseX - } - onReleased: { - controller.setDeadbandValue(modelData,parent.item.deadbandValue) - parent.item.deadbandColor = "#8c161a" - } - } - } - - } + ColorAnimation { + id: barAnimation + target: bar + property: "color" + from: "yellow" + to: __barColor + duration: 1500 } - } // Column - Axis Monitor - // Button monitor - Column { - width: parent.width - spacing: ScreenTools.defaultFontPixelHeight + // Axis value debugger + /* QGCLabel { - text: qsTr("Button Monitor") - anchors.horizontalCenter: parent.horizontalCenter - } - - Connections { - target: _activeJoystick - - onRawButtonPressedChanged: { - if (buttonMonitorRepeater.itemAt(index)) { - buttonMonitorRepeater.itemAt(index).pressed = pressed - } - } + anchors.fill: parent + text: axisValue } + */ - Flow { - width: parent.width * 0.9 - spacing: -1 - anchors.horizontalCenter: parent.horizontalCenter - - Repeater { - id: buttonMonitorRepeater - model: _activeJoystick ? _activeJoystick.totalButtonCount : 0 - - Rectangle { - width: ScreenTools.defaultFontPixelHeight * 1.5 - height: width - border.width: 1 - border.color: qgcPal.text - color: pressed ? qgcPal.buttonHighlight : qgcPal.windowShade - - property bool pressed - - QGCLabel { - anchors.fill: parent - color: pressed ? qgcPal.buttonHighlightText : qgcPal.buttonText - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - text: modelData - } - } - } // Repeater - } // Row - } // Column - Axis Monitor - } // Column - Right Column + } + } // Component - axisMonitorDisplayComponent } // Item } // Component - pageComponent } // SetupPage diff --git a/src/VehicleSetup/JoystickConfigController.cc b/src/VehicleSetup/JoystickConfigController.cc index 7745dddd4c90790b6a64200c264921cfad8b23c5..c97a9ca15e15bb1b2487e8ccd02eee44b675269b 100644 --- a/src/VehicleSetup/JoystickConfigController.cc +++ b/src/VehicleSetup/JoystickConfigController.cc @@ -43,13 +43,74 @@ const char* JoystickConfigController::_imageRollRight = "joystickRollRight.p const char* JoystickConfigController::_imagePitchUp = "joystickPitchUp.png"; const char* JoystickConfigController::_imagePitchDown = "joystickPitchDown.png"; +static const JoystickConfigController::stateStickPositions stSticksCentered { + 0.25, 0.5, 0.75, 0.5 +}; + +static const JoystickConfigController::stateStickPositions stLeftStickUp { + 0.25, 0.3084, 0.75, 0.5 +}; + +static const JoystickConfigController::stateStickPositions stLeftStickDown { + 0.25, 0.6916, 0.75, 0.5 +}; + +static const JoystickConfigController::stateStickPositions stLeftStickLeft { + 0.1542, 0.5, 0.75, 0.5 +}; + +static const JoystickConfigController::stateStickPositions stLeftStickRight { + 0.3458, 0.5, 0.75, 0.5 +}; + +static const JoystickConfigController::stateStickPositions stRightStickUp { + 0.25, 0.5, 0.75, 0.3084 +}; + +static const JoystickConfigController::stateStickPositions stRightStickDown { + 0.25, 0.5, 0.75, 0.6916 +}; + +static const JoystickConfigController::stateStickPositions stRightStickLeft { + 0.25, 0.5, 0.6542, 0.5 +}; + +static const JoystickConfigController::stateStickPositions stRightStickRight { + 0.25, 0.5, 0.8423, 0.5 +}; + +//-- Gimbal + +static const JoystickConfigController::stateStickPositions stGimbalCentered { + 0.5, 0.5, 0.5, 0.3 +}; + +static const JoystickConfigController::stateStickPositions stGimbalPitchDown { + 0.5, 0.6, 0.5, 0.3 +}; + +static const JoystickConfigController::stateStickPositions stGimbalPitchUp { + 0.5, 0.4, 0.5, 0.3 +}; + +static const JoystickConfigController::stateStickPositions stGimbalYawLeft { + 0.5, 0.5, 0.4, 0.3 +}; + +static const JoystickConfigController::stateStickPositions stGimbalYawRight { + 0.5, 0.5, 0.6, 0.3 +}; + JoystickConfigController::JoystickConfigController(void) : _joystickManager(qgcApp()->toolbox()->joystickManager()) { connect(_joystickManager, &JoystickManager::activeJoystickChanged, this, &JoystickConfigController::_activeJoystickChanged); _activeJoystickChanged(_joystickManager->activeJoystick()); + _setStickPositions(); _resetInternalCalibrationValues(); + _currentStickPositions << _sticksCentered.leftX << _sticksCentered.leftY << _sticksCentered.rightX << _sticksCentered.rightY; + _currentGimbalPositions << stGimbalCentered.leftX << stGimbalCentered.leftY << stGimbalCentered.rightX << stGimbalCentered.rightY; } void JoystickConfigController::start(void) @@ -91,29 +152,29 @@ const JoystickConfigController::stateMachineEntry* JoystickConfigController::_ge static const char* msgGimbalYawLeft = "Move the Gimbal Yaw control all the way to the left and hold it there..."; static const char* msgGimbalYawRight = "Move the Gimbal Yaw control all the way to the right and hold it there..."; static const char* msgComplete = "All settings have been captured. Click Next to enable the joystick."; - + static const stateMachineEntry rgStateMachine[] = { //Function - { Joystick::maxFunction, msgBegin, _imageCenter, &JoystickConfigController::_inputCenterWaitBegin, &JoystickConfigController::_saveAllTrims, nullptr, 0 }, - { Joystick::throttleFunction, msgThrottleUp, _imageThrottleUp, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 0 }, - { Joystick::throttleFunction, msgThrottleDown, _imageThrottleDown, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 0 }, - { Joystick::yawFunction, msgYawRight, _imageYawRight, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 1 }, - { Joystick::yawFunction, msgYawLeft, _imageYawLeft, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 1 }, - { Joystick::rollFunction, msgRollRight, _imageRollRight, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 2 }, - { Joystick::rollFunction, msgRollLeft, _imageRollLeft, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 2 }, - { Joystick::pitchFunction, msgPitchUp, _imagePitchUp, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 3 }, - { Joystick::pitchFunction, msgPitchDown, _imagePitchDown, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 3 }, - { Joystick::pitchFunction, msgPitchCenter, _imageCenter, &JoystickConfigController::_inputCenterWait, nullptr, nullptr, 3 }, - - { Joystick::gimbalPitchFunction, msgGimbalPitchUp, _imageThrottleUp, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 4 }, - { Joystick::gimbalPitchFunction, msgGimbalPitchDown, _imageThrottleDown, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 4 }, - { Joystick::gimbalYawFunction, msgGimbalYawRight, _imageYawRight, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 5 }, - { Joystick::gimbalYawFunction, msgGimbalYawLeft, _imageYawLeft, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 5 }, - - { Joystick::maxFunction, msgComplete, _imageCenter, nullptr, &JoystickConfigController::_writeCalibration, nullptr, -1 }, + { Joystick::maxFunction, msgBegin, _sticksCentered, stGimbalCentered, &JoystickConfigController::_inputCenterWaitBegin, &JoystickConfigController::_saveAllTrims, nullptr, 0 }, + { Joystick::throttleFunction, msgThrottleUp, _sticksThrottleUp, stGimbalCentered, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 0 }, + { Joystick::throttleFunction, msgThrottleDown, _sticksThrottleDown, stGimbalCentered, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 0 }, + { Joystick::yawFunction, msgYawRight, _sticksYawRight, stGimbalCentered, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 1 }, + { Joystick::yawFunction, msgYawLeft, _sticksYawLeft, stGimbalCentered, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 1 }, + { Joystick::rollFunction, msgRollRight, _sticksRollRight, stGimbalCentered, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 2 }, + { Joystick::rollFunction, msgRollLeft, _sticksRollLeft, stGimbalCentered, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 2 }, + { Joystick::pitchFunction, msgPitchUp, _sticksPitchUp, stGimbalCentered, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 3 }, + { Joystick::pitchFunction, msgPitchDown, _sticksPitchDown, stGimbalCentered, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 3 }, + { Joystick::pitchFunction, msgPitchCenter, _sticksCentered, stGimbalCentered, &JoystickConfigController::_inputCenterWait, nullptr, nullptr, 3 }, + + { Joystick::gimbalPitchFunction, msgGimbalPitchUp, _sticksCentered, stGimbalPitchUp, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 4 }, + { Joystick::gimbalPitchFunction, msgGimbalPitchDown, _sticksCentered, stGimbalPitchDown, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 4 }, + { Joystick::gimbalYawFunction, msgGimbalYawRight, _sticksCentered, stGimbalYawRight, &JoystickConfigController::_inputStickDetect, nullptr, nullptr, 5 }, + { Joystick::gimbalYawFunction, msgGimbalYawLeft, _sticksCentered, stGimbalYawLeft, &JoystickConfigController::_inputStickMin, nullptr, nullptr, 5 }, + + { Joystick::maxFunction, msgComplete, _sticksCentered, stGimbalCentered, nullptr, &JoystickConfigController::_writeCalibration, nullptr, -1 }, }; - Q_ASSERT(step >=0 && step < static_cast((sizeof(rgStateMachine) / sizeof(rgStateMachine[0])))); + Q_ASSERT(step >= 0 && step < static_cast((sizeof(rgStateMachine) / sizeof(rgStateMachine[0])))); return &rgStateMachine[step]; } @@ -132,13 +193,18 @@ void JoystickConfigController::_advanceState() void JoystickConfigController::_setupCurrentState() { const stateMachineEntry* state = _getStateMachineEntry(_currentStep); - _statusText->setProperty("text", state->instructions); - _setHelpImage(state->image); + _setStatusText(state->instructions); _stickDetectAxis = _axisNoAxis; _stickDetectSettleStarted = false; _calSaveCurrentValues(); _nextButton->setEnabled(state->nextFn != nullptr); _skipButton->setEnabled(state->skipFn != nullptr); + _currentStickPositions.clear(); + _currentStickPositions << state->stickPositions.leftX << state->stickPositions.leftY << state->stickPositions.rightX << state->stickPositions.rightY; + _currentGimbalPositions.clear(); + _currentGimbalPositions << state->gimbalPositions.leftX << state->gimbalPositions.leftY << state->gimbalPositions.rightX << state->gimbalPositions.rightY; + emit stickPositionsChanged(); + emit gimbalPositionsChanged(); } void JoystickConfigController::_axisValueChanged(int axis, int value) @@ -151,6 +217,7 @@ void JoystickConfigController::_axisValueChanged(int axis, int value) // Track the axis count by keeping track of how many axes we see if (axis + 1 > static_cast(_axisCount)) { _axisCount = axis + 1; + emit hasGimbalChanged(); } } if (_currentStep != -1) { @@ -404,7 +471,6 @@ void JoystickConfigController::_resetInternalCalibrationValues() info->axisMax = JoystickConfigController::_calCenterPoint; info->axisTrim = JoystickConfigController::_calCenterPoint; } - // Initialize attitude function mapping to function axis not set for (size_t i = 0; i < Joystick::maxFunction; i++) { _rgFunctionAxisMapping[i] = _axisNoAxis; @@ -456,40 +522,32 @@ void JoystickConfigController::_validateCalibration() { for (int chan = 0; chan < _axisCount; chan++) { struct AxisInfo* info = &_rgAxisInfo[chan]; - if (chan < _axisCount) { - // Validate Min/Max values. Although the axis appears as available we still may - // not have good min/max/trim values for it. Set to defaults if needed. - if (info->axisMin < _calValidMinValue || info->axisMax > _calValidMaxValue) { - qCDebug(JoystickConfigControllerLog) << "_validateCalibration resetting axis" << chan; - info->axisMin = _calDefaultMinValue; - info->axisMax = _calDefaultMaxValue; - info->axisTrim = info->axisMin + ((info->axisMax - info->axisMin) / 2); - } - switch (_rgAxisInfo[chan].function) { - case Joystick::throttleFunction: - case Joystick::yawFunction: - case Joystick::rollFunction: - case Joystick::pitchFunction: - // Make sure trim is within min/max - if (info->axisTrim < info->axisMin) { - info->axisTrim = info->axisMin; - } else if (info->axisTrim > info->axisMax) { - info->axisTrim = info->axisMax; - } - break; - default: - // Non-attitude control axis have calculated trim - info->axisTrim = info->axisMin + ((info->axisMax - info->axisMin) / 2); - break; - } - } else { - // Unavailable axiss are set to defaults - qCDebug(JoystickConfigControllerLog) << "_validateCalibration resetting unavailable axis" << chan; + // Validate Min/Max values. Although the axis appears as available we still may + // not have good min/max/trim values for it. Set to defaults if needed. + if (info->axisMin < _calValidMinValue || info->axisMax > _calValidMaxValue) { + qCDebug(JoystickConfigControllerLog) << "_validateCalibration resetting axis" << chan; info->axisMin = _calDefaultMinValue; info->axisMax = _calDefaultMaxValue; info->axisTrim = info->axisMin + ((info->axisMax - info->axisMin) / 2); - info->deadband = 0; - info->reversed = false; + } + switch (_rgAxisInfo[chan].function) { + case Joystick::throttleFunction: + case Joystick::yawFunction: + case Joystick::rollFunction: + case Joystick::pitchFunction: + case Joystick::gimbalPitchFunction: + case Joystick::gimbalYawFunction: + // Make sure trim is within min/max + if (info->axisTrim < info->axisMin) { + info->axisTrim = info->axisMin; + } else if (info->axisTrim > info->axisMax) { + info->axisTrim = info->axisMax; + } + break; + default: + // Non-attitude control axis have calculated trim + info->axisTrim = info->axisMin + ((info->axisMax - info->axisMin) / 2); + break; } } } @@ -543,12 +601,11 @@ void JoystickConfigController::_stopCalibration() _currentStep = -1; _activeJoystick->setCalibrationMode(false); _setInternalCalibrationValuesFromSettings(); - _statusText->setProperty("text", ""); + _setStatusText(""); _nextButton->setProperty("text", tr("Calibrate")); _nextButton->setEnabled(true); _cancelButton->setEnabled(false); _skipButton->setEnabled(false); - _setHelpImage(_imageCenter); emit calibratingChanged(); } @@ -565,47 +622,65 @@ void JoystickConfigController::_calSaveCurrentValues() void JoystickConfigController::_calSave() { _calState = calStateSave; - - _statusText->setProperty("text", - tr("The current calibration settings are now displayed for each axis on screen.\n\n" - "Click the Next button to upload calibration to board. Click Cancel if you don't want to save these values.")); - + _setStatusText(tr( + "The current calibration settings are now displayed for each axis on screen.\n\n" + "Click the Next button to upload calibration to board. Click Cancel if you don't want to save these values.")); _nextButton->setEnabled(true); _skipButton->setEnabled(false); _cancelButton->setEnabled(true); // This updates the internal values according to the validation rules. Then _updateView will tick and update ui - // such that the settings that will be written our are displayed. + // such that the settings that will be written out are displayed. _validateCalibration(); } -void JoystickConfigController::_setHelpImage(const char* imageFile) +void JoystickConfigController::_setStickPositions() { - QString file = _imageFilePrefix; - + _sticksCentered = stSticksCentered; switch(_transmitterMode) { case 1: - file += _imageFileMode1Dir; + _sticksThrottleUp = stRightStickUp; + _sticksThrottleDown = stRightStickDown; + _sticksYawLeft = stLeftStickLeft; + _sticksYawRight = stLeftStickRight; + _sticksRollLeft = stRightStickLeft; + _sticksRollRight = stRightStickRight; + _sticksPitchUp = stLeftStickDown; + _sticksPitchDown = stLeftStickUp; break; case 2: - file += _imageFileMode2Dir; + _sticksThrottleUp = stLeftStickUp; + _sticksThrottleDown = stLeftStickDown; + _sticksYawLeft = stLeftStickLeft; + _sticksYawRight = stLeftStickRight; + _sticksRollLeft = stRightStickLeft; + _sticksRollRight = stRightStickRight; + _sticksPitchUp = stRightStickDown; + _sticksPitchDown = stRightStickUp; break; case 3: - file += _imageFileMode3Dir; + _sticksThrottleUp = stRightStickUp; + _sticksThrottleDown = stRightStickDown; + _sticksYawLeft = stRightStickLeft; + _sticksYawRight = stRightStickRight; + _sticksRollLeft = stLeftStickLeft; + _sticksRollRight = stLeftStickRight; + _sticksPitchUp = stLeftStickDown; + _sticksPitchDown = stLeftStickUp; break; case 4: - file += _imageFileMode4Dir; + _sticksThrottleUp = stLeftStickUp; + _sticksThrottleDown = stLeftStickDown; + _sticksYawLeft = stRightStickLeft; + _sticksYawRight = stRightStickRight; + _sticksRollLeft = stLeftStickLeft; + _sticksRollRight = stLeftStickRight; + _sticksPitchUp = stRightStickDown; + _sticksPitchDown = stRightStickUp; break; default: Q_ASSERT(false); } - - file += imageFile; - - qCDebug(JoystickConfigControllerLog) << "_setHelpImage" << file; - - _imageHelp = file; - emit imageHelpChanged(file); } bool JoystickConfigController::rollAxisReversed() @@ -664,15 +739,12 @@ bool JoystickConfigController::gimbalYawAxisReversed() void JoystickConfigController::setTransmitterMode(int mode) { - if (mode > 0 && mode <= 4) { + // Mode selection is disabled during calibration + if (mode > 0 && mode <= 4 && _currentStep == -1) { _transmitterMode = mode; - if (_currentStep != -1) { // This should never be true, mode selection is disabled during calibration - const stateMachineEntry* state = _getStateMachineEntry(_currentStep); - _setHelpImage(state->image); - } else { - _activeJoystick->setTXMode(mode); - _setInternalCalibrationValuesFromSettings(); - } + _setStickPositions(); + _activeJoystick->setTXMode(mode); + _setInternalCalibrationValuesFromSettings(); } } @@ -708,6 +780,7 @@ void JoystickConfigController::_activeJoystickChanged(Joystick* joystick) delete[] _axisRawValue; _axisCount = 0; _activeJoystick = nullptr; + emit hasGimbalChanged(); } if (joystick) { @@ -722,6 +795,7 @@ void JoystickConfigController::_activeJoystickChanged(Joystick* joystick) _axisRawValue = new int[_axisCount]; _setInternalCalibrationValuesFromSettings(); connect(_activeJoystick, &Joystick::rawAxisValueChanged, this, &JoystickConfigController::_axisValueChanged); + emit hasGimbalChanged(); } } @@ -729,3 +803,9 @@ bool JoystickConfigController::_validAxis(int axis) { return axis >= 0 && axis < _axisCount; } + +void JoystickConfigController::_setStatusText(const QString& text) +{ + _statusText = text; + emit statusTextChanged(); +} diff --git a/src/VehicleSetup/JoystickConfigController.h b/src/VehicleSetup/JoystickConfigController.h index 1fb0a2946a01241bf9ed807cee022268c27508fc..ec2086faabcfd270951160dda27d14bc037a3845 100644 --- a/src/VehicleSetup/JoystickConfigController.h +++ b/src/VehicleSetup/JoystickConfigController.h @@ -7,10 +7,8 @@ * ****************************************************************************/ - - /// @file -/// @brief Radio Config Qml Controller +/// @brief Joystick Config Qml Controller /// @author Don Gagne stickPositions READ stickPositions NOTIFY stickPositionsChanged) + Q_PROPERTY(QList gimbalPositions READ gimbalPositions NOTIFY gimbalPositionsChanged) + Q_INVOKABLE void cancelButtonClicked (); Q_INVOKABLE void skipButtonClicked (); Q_INVOKABLE void nextButtonClicked (); Q_INVOKABLE void start (); Q_INVOKABLE void setDeadbandValue (int axis, int value); + QString statusText () { return _statusText; } + bool rollAxisMapped () { return _rgFunctionAxisMapping[Joystick::rollFunction] != _axisNoAxis; } bool pitchAxisMapped () { return _rgFunctionAxisMapping[Joystick::pitchFunction] != _axisNoAxis; } bool yawAxisMapped () { return _rgFunctionAxisMapping[Joystick::yawFunction] != _axisNoAxis; } @@ -89,6 +92,8 @@ public: bool gimbalPitchAxisReversed (); bool gimbalYawAxisReversed (); + bool hasGimbal () { return _axisCount > 5; } + bool getDeadbandToggle (); void setDeadbandToggle (bool); @@ -98,31 +103,40 @@ public: void setTransmitterMode (int mode); bool calibrating () { return _currentStep != -1; } - + + QList stickPositions () { return _currentStickPositions; } + QList gimbalPositions () { return _currentGimbalPositions; } + + struct stateStickPositions { + qreal leftX; + qreal leftY; + qreal rightX; + qreal rightY; + }; + signals: void axisValueChanged (int axis, int value); void axisDeadbandChanged (int axis, int value); - void rollAxisMappedChanged (bool mapped); void pitchAxisMappedChanged (bool mapped); void yawAxisMappedChanged (bool mapped); void throttleAxisMappedChanged (bool mapped); void gimbalPitchAxisMappedChanged (bool mapped); void gimbalYawAxisMappedChanged (bool mapped); - void rollAxisReversedChanged (bool reversed); void pitchAxisReversedChanged (bool reversed); void yawAxisReversedChanged (bool reversed); void throttleAxisReversedChanged (bool reversed); void gimbalPitchAxisReversedChanged (bool reversed); void gimbalYawAxisReversedChanged (bool reversed); - void deadbandToggled (bool value); - - void imageHelpChanged (QString source); void transmitterModeChanged (int mode); void calibratingChanged (); - + void stickPositionsChanged (); + void gimbalPositionsChanged (); + void hasGimbalChanged (); + void statusTextChanged (); + // @brief Signalled when in unit test mode and a message box should be displayed by the next button void nextButtonMessageBoxDisplayed (); @@ -143,13 +157,14 @@ private: calStateTrims, calStateSave }; - + typedef void (JoystickConfigController::*inputFn)(Joystick::AxisFunction_t function, int axis, int value); typedef void (JoystickConfigController::*buttonFn)(void); struct stateMachineEntry { Joystick::AxisFunction_t function; const char* instructions; - const char* image; + stateStickPositions stickPositions; + stateStickPositions gimbalPositions; inputFn rcInputFn; buttonFn nextFn; buttonFn skipFn; @@ -202,9 +217,11 @@ private: void _calSaveCurrentValues (); - void _setHelpImage(const char* imageFile); + void _setStickPositions (); void _signalAllAttitudeValueChanges(); + + void _setStatusText (const QString& text); // Member variables @@ -222,7 +239,20 @@ private: static const char* _imageRollRight; static const char* _imagePitchUp; static const char* _imagePitchDown; - + + stateStickPositions _sticksCentered; + stateStickPositions _sticksThrottleUp; + stateStickPositions _sticksThrottleDown; + stateStickPositions _sticksYawLeft; + stateStickPositions _sticksYawRight; + stateStickPositions _sticksRollLeft; + stateStickPositions _sticksRollRight; + stateStickPositions _sticksPitchUp; + stateStickPositions _sticksPitchDown; + + QList _currentStickPositions; + QList _currentGimbalPositions; + int _rgFunctionAxisMapping[Joystick::maxFunction]; ///< Maps from joystick function to axis index. _axisMax indicates axis not set for this function. static const int _attitudeControls = 5; @@ -258,13 +288,12 @@ private: QTime _stickDetectSettleElapsed; static const int _stickDetectSettleMSecs; - QQuickItem* _statusText = nullptr; + QString _statusText; + QQuickItem* _cancelButton = nullptr; QQuickItem* _nextButton = nullptr; QQuickItem* _skipButton = nullptr; - QString _imageHelp; - JoystickManager* _joystickManager; };