diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index fded1e00dee298b48229b0bf51a7198408f1d545..2c13d66a944a9b221846c4689d4a3ff978dabecd 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -86,6 +86,7 @@ src/QmlControls/PageView.qml src/QmlControls/ParameterEditor.qml src/QmlControls/ParameterEditorDialog.qml + src/QmlControls/PIDTuning.qml src/PlanView/PlanToolBar.qml src/QmlControls/QGCButton.qml src/QmlControls/QGCCheckListItem.qml diff --git a/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml b/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml index 2b780bf0842cb88a46bc4e30785865fd71eca576..4c57ab20399f02f8fff24b6de755f77cd72db68c 100644 --- a/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml +++ b/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml @@ -93,47 +93,11 @@ SetupPage { Component { id: advancePageComponent - // Advanced page - RowLayout { - anchors.left: parent.left - anchors.right: parent.right - layoutDirection: Qt.RightToLeft - - property real _chartHeight: ScreenTools.defaultFontPixelHeight * 20 - property real _margins: ScreenTools.defaultFontPixelHeight / 2 - property string _currentTuneType: _tuneList[0] - property real _roll: _activeVehicle.roll.value - property real _rollSetpoint: _activeVehicle.setpoint.roll.value - property real _rollRate: _activeVehicle.rollRate.value - property real _rollRateSetpoint: _activeVehicle.setpoint.rollRate.value - property real _pitch: _activeVehicle.pitch.value - property real _pitchSetpoint: _activeVehicle.setpoint.pitch.value - property real _pitchRate: _activeVehicle.pitchRate.value - property real _pitchRateSetpoint: _activeVehicle.setpoint.pitchRate.value - property real _yaw: _activeVehicle.heading.value - property real _yawSetpoint: _activeVehicle.setpoint.yaw.value - property real _yawRate: _activeVehicle.yawRate.value - property real _yawRateSetpoint: _activeVehicle.setpoint.yawRate.value - property var _valueXAxis: valueXAxis - property var _valueRateXAxis: valueRateXAxis - property var _valueYAxis: valueYAxis - property var _valueRateYAxis: valueRateYAxis - property int _msecs: 0 - property var _savedTuningParamValues: [ ] - - // The following are set when getValues is called - property real _value - property real _valueSetpoint - property real _valueRate - property real _valueRateSetpoint - - readonly property int _tickSeparation: 5 - readonly property int _maxTickSections: 10 - readonly property int _tuneListRollIndex: 0 - readonly property int _tuneListPitchIndex: 1 - readonly property int _tuneListYawIndex: 2 - readonly property var _tuneList: [ qsTr("Roll"), qsTr("Pitch"), qsTr("Yaw") ] - readonly property var _params: [ + PIDTuning { + anchors.left: parent.left + anchors.right: parent.right + tuneList: [ qsTr("Roll"), qsTr("Pitch"), qsTr("Yaw") ] + params: [ [ controller.getParameterFact(-1, "MC_ROLL_P"), controller.getParameterFact(-1, "MC_ROLLRATE_P"), controller.getParameterFact(-1, "MC_ROLLRATE_I"), @@ -150,376 +114,7 @@ SetupPage { controller.getParameterFact(-1, "MC_YAWRATE_D"), controller.getParameterFact(-1, "MC_YAW_FF"), controller.getParameterFact(-1, "MC_YAWRATE_FF") ] ] - - function adjustYAxisMin(yAxis, newValue) { - var newMin = Math.min(yAxis.min, newValue) - if (newMin % 5 != 0) { - newMin -= 5 - newMin = Math.floor(newMin / _tickSeparation) * _tickSeparation - } - yAxis.min = newMin - } - - function adjustYAxisMax(yAxis, newValue) { - var newMax = Math.max(yAxis.max, newValue) - if (newMax % 5 != 0) { - newMax += 5 - newMax = Math.floor(newMax / _tickSeparation) * _tickSeparation - } - yAxis.max = newMax - } - - function getValues() { - if (_currentTuneType === _tuneList[_tuneListRollIndex]) { - _value = _roll - _valueSetpoint = _rollSetpoint - _valueRate = _rollRate - _valueRateSetpoint = _rollRateSetpoint - } else if (_currentTuneType === _tuneList[_tuneListPitchIndex]) { - _value = _pitch - _valueSetpoint = _pitchSetpoint - _valueRate = _pitchRate - _valueRateSetpoint = _pitchRateSetpoint - } else if (_currentTuneType === _tuneList[_tuneListYawIndex]) { - _value = _yaw - _valueSetpoint = _yawSetpoint - _valueRate = _yawRate - _valueRateSetpoint = _yawRateSetpoint - } - } - - function resetGraphs() { - valueSeries.removePoints(0, valueSeries.count) - valueSetpointSeries.removePoints(0, valueSetpointSeries.count) - valueRateSeries.removePoints(0, valueRateSeries.count) - valueRateSetpointSeries.removePoints(0, valueRateSetpointSeries.count) - _valueXAxis.min = 0 - _valueXAxis.max = 0 - _valueRateXAxis.min = 0 - _valueRateXAxis.max = 0 - _valueYAxis.min = 0 - _valueYAxis.max = 10 - _valueRateYAxis.min = 0 - _valueRateYAxis.max = 10 - _msecs = 0 - } - - function currentTuneTypeIndex() { - if (_currentTuneType === _tuneList[_tuneListRollIndex]) { - return _tuneListRollIndex - } else if (_currentTuneType === _tuneList[_tuneListPitchIndex]) { - return _tuneListPitchIndex - } else if (_currentTuneType === _tuneList[_tuneListYawIndex]) { - return _tuneListYawIndex - } - } - - // Save the current set of tuning values so we can reset to them - function saveTuningParamValues() { - var tuneTypeIndex = currentTuneTypeIndex() - - _savedTuningParamValues = [ ] - var currentTuneParams = _params[tuneTypeIndex] - for (var i=0; i _maxPointCount) { - valueSeries.remove(0) - valueSetpointSeries.remove(0) - valueRateSeries.remove(0) - valueRateSetpointSeries.remove(0) - valueXAxis.min = valueSeries.at(0).x - valueRateXAxis.min = valueSeries.at(0).x - } - */ - } - - property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle - property int _maxPointCount: 10000 / interval - } - - Column { - spacing: _margins - Layout.alignment: Qt.AlignTop - - QGCLabel { text: qsTr("Tuning Axis:") } - - RowLayout { - spacing: _margins - - Repeater { - model: _tuneList - QGCRadioButton { - text: modelData - checked: _currentTuneType === modelData - exclusiveGroup: tuneTypeRadios - - onClicked: _currentTuneType = modelData - } - } - } - - Item { width: 1; height: 1 } - - QGCLabel { text: qsTr("Tuning Values:") } - - GridLayout { - rows: factList.length - flow: GridLayout.TopToBottom - rowSpacing: _margins - columnSpacing: _margins - - property var factList: _params[_tuneList.indexOf(_currentTuneType)] - - Repeater { - model: parent.factList - - QGCLabel { text: modelData.name } - } - - Repeater { - model: parent.factList - - QGCButton { - text: "-" - onClicked: { - var value = modelData.value - modelData.value -= value * adjustPercentModel.get(adjustPercentCombo.currentIndex).value - } - } - } - - Repeater { - model: parent.factList - - FactTextField { - Layout.fillWidth: true - fact: modelData - showUnits: false - } - } - - Repeater { - model: parent.factList - - QGCButton { - text: "+" - onClicked: { - var value = modelData.value - modelData.value += value * adjustPercentModel.get(adjustPercentCombo.currentIndex).value - } - } - } - } - - RowLayout { - QGCLabel { text: qsTr("Increment/Decrement %") } - - QGCComboBox { - id: adjustPercentCombo - model: ListModel { - id: adjustPercentModel - ListElement { text: "5"; value: 0.05 } - ListElement { text: "10"; value: 0.10 } - ListElement { text: "15"; value: 0.15 } - ListElement { text: "20"; value: 0.20 } - } - } - } - Item { width: 1; height: 1 } - - QGCLabel { text: qsTr("Saved Tuning Values:") } - - GridLayout { - rows: savedRepeater.model.length - flow: GridLayout.TopToBottom - rowSpacing: _margins - columnSpacing: _margins - - Repeater { - model: _params[_tuneList.indexOf(_currentTuneType)] - - QGCLabel { text: modelData.name } - } - - Repeater { - id: savedRepeater - - QGCLabel { text: modelData } - } - } - - RowLayout { - spacing: _margins - - QGCButton { - text: qsTr("Save Values") - onClicked: saveTuningParamValues() - } - - QGCButton { - text: qsTr("Reset To Saved Values") - onClicked: resetToSavedTuningParamValues() - } - } - - Item { width: 1; height: 1 } - - QGCLabel { text: qsTr("Chart:") } - - RowLayout { - spacing: _margins - - QGCButton { - text: qsTr("Clear") - onClicked: resetGraphs() - } - - QGCButton { - text: dataTimer.running ? qsTr("Stop") : qsTr("Start") - onClicked: dataTimer.running = !dataTimer.running - } - } - } - - Column { - Layout.fillWidth: true - - ChartView { - anchors.left: parent.left - anchors.right: parent.right - height: availableHeight / 2 - title: _currentTuneType - antialiasing: true - legend.alignment: Qt.AlignRight - - LineSeries { - id: valueSeries - name: "Response" - axisY: valueYAxis - axisX: valueXAxis - } - - LineSeries { - id: valueSetpointSeries - name: "Command" - axisY: valueYAxis - axisX: valueXAxis - } - } - - ChartView { - anchors.left: parent.left - anchors.right: parent.right - height: availableHeight / 2 - title: _currentTuneType + qsTr(" Rate") - antialiasing: true - legend.alignment: Qt.AlignRight - - LineSeries { - id: valueRateSeries - name: "Response" - axisY: valueRateYAxis - axisX: valueRateXAxis - } - - LineSeries { - id: valueRateSetpointSeries - name: "Command" - axisY: valueRateYAxis - axisX: valueRateXAxis - } - } - } - } // RowLayout - Advanced Page + } } // Component - Advanced Page } // Column } // Component - pageComponent diff --git a/src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml b/src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml index 40fa8ba467a70e50e9a4b0055b440494e68fdf78..bc3a4916966d681d6afe8bce68b7c272ab7f9ef1 100644 --- a/src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml +++ b/src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml @@ -7,11 +7,16 @@ * ****************************************************************************/ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtCharts 2.2 +import QtQuick.Layouts 1.2 -import QtQuick 2.3 -import QtQuick.Controls 1.2 - -import QGroundControl.Controls 1.0 +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.ScreenTools 1.0 SetupPage { id: tuningPage @@ -20,47 +25,64 @@ SetupPage { Component { id: pageComponent - FactSliderPanel { - width: availableWidth - qgcViewPanel: tuningPage.viewPanel + Column { + width: availableWidth - sliderModel: ListModel { - ListElement { - title: qsTr("Roll sensitivity") - description: qsTr("Slide to the left to make roll control faster and more accurate. Slide to the right if roll oscillates or is too twitchy.") - param: "FW_R_TC" - min: 0.2 - max: 0.8 - step: 0.01 - } + Component.onCompleted: { + showAdvanced = !ScreenTools.isMobile + } - ListElement { - title: qsTr("Pitch sensitivity") - description: qsTr("Slide to the left to make pitch control faster and more accurate. Slide to the right if pitch oscillates or is too twitchy.") - param: "FW_P_TC" - min: 0.2 - max: 0.8 - step: 0.01 - } + FactPanelController { + id: controller + factPanel: tuningPage.viewPanel + } - ListElement { - title: qsTr("Cruise throttle") - description: qsTr("This is the throttle setting required to achieve the desired cruise speed. Most planes need 50-60%.") - param: "FW_THR_CRUISE" - min: 20 - max: 80 - step: 1 - } + // Standard tuning page + FactSliderPanel { + width: availableWidth + qgcViewPanel: tuningPage.viewPanel + visible: !advanced - ListElement { - title: qsTr("Mission mode sensitivity") - description: qsTr("Slide to the left to make position control more accurate and more aggressive. Slide to the right to make flight in mission mode smoother and less twitchy.") - param: "FW_L1_PERIOD" - min: 12 - max: 50 - step: 0.5 + sliderModel: ListModel { + ListElement { + title: qsTr("Cruise throttle") + description: qsTr("This is the throttle setting required to achieve the desired cruise speed. Most planes need 50-60%.") + param: "FW_THR_CRUISE" + min: 20 + max: 80 + step: 1 + } } } - } - } -} + + + Loader { + anchors.left: parent.left + anchors.right: parent.right + sourceComponent: advanced ? advancePageComponent : undefined + } + + Component { + id: advancePageComponent + + PIDTuning { + anchors.left: parent.left + anchors.right: parent.right + tuneList: [ qsTr("Roll"), qsTr("Pitch"), qsTr("Yaw") ] + params: [ + [ controller.getParameterFact(-1, "FW_RR_P"), + controller.getParameterFact(-1, "FW_RR_I"), + controller.getParameterFact(-1, "FW_RR_FF"), + controller.getParameterFact(-1, "FW_R_TC"),], + [ controller.getParameterFact(-1, "FW_PR_P"), + controller.getParameterFact(-1, "FW_PR_I"), + controller.getParameterFact(-1, "FW_PR_FF"), + controller.getParameterFact(-1, "FW_P_TC") ], + [ controller.getParameterFact(-1, "FW_YR_P"), + controller.getParameterFact(-1, "FW_YR_I"), + controller.getParameterFact(-1, "FW_YR_FF") ] ] + } + } // Component - Advanced Page + } // Column + } // Component - pageComponent +} // SetupPage diff --git a/src/QmlControls/PIDTuning.qml b/src/QmlControls/PIDTuning.qml new file mode 100644 index 0000000000000000000000000000000000000000..6467ce0109451f4ce55df7fc6264c6d63ef1dda2 --- /dev/null +++ b/src/QmlControls/PIDTuning.qml @@ -0,0 +1,429 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtCharts 2.2 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.ScreenTools 1.0 + +RowLayout { + layoutDirection: Qt.RightToLeft + + property var tuneList + property var params + + property real _chartHeight: ScreenTools.defaultFontPixelHeight * 20 + property real _margins: ScreenTools.defaultFontPixelHeight / 2 + property string _currentTuneType: tuneList[0] + property real _roll: _activeVehicle.roll.value + property real _rollSetpoint: _activeVehicle.setpoint.roll.value + property real _rollRate: _activeVehicle.rollRate.value + property real _rollRateSetpoint: _activeVehicle.setpoint.rollRate.value + property real _pitch: _activeVehicle.pitch.value + property real _pitchSetpoint: _activeVehicle.setpoint.pitch.value + property real _pitchRate: _activeVehicle.pitchRate.value + property real _pitchRateSetpoint: _activeVehicle.setpoint.pitchRate.value + property real _yaw: _activeVehicle.heading.value + property real _yawSetpoint: _activeVehicle.setpoint.yaw.value + property real _yawRate: _activeVehicle.yawRate.value + property real _yawRateSetpoint: _activeVehicle.setpoint.yawRate.value + property var _valueXAxis: valueXAxis + property var _valueRateXAxis: valueRateXAxis + property var _valueYAxis: valueYAxis + property var _valueRateYAxis: valueRateYAxis + property int _msecs: 0 + property var _savedTuningParamValues: [ ] + + // The following are set when getValues is called + property real _value + property real _valueSetpoint + property real _valueRate + property real _valueRateSetpoint + + readonly property int _tickSeparation: 5 + readonly property int _maxTickSections: 10 + readonly property int _tuneListRollIndex: 0 + readonly property int _tuneListPitchIndex: 1 + readonly property int _tuneListYawIndex: 2 + + function adjustYAxisMin(yAxis, newValue) { + var newMin = Math.min(yAxis.min, newValue) + if (newMin % 5 != 0) { + newMin -= 5 + newMin = Math.floor(newMin / _tickSeparation) * _tickSeparation + } + yAxis.min = newMin + } + + function adjustYAxisMax(yAxis, newValue) { + var newMax = Math.max(yAxis.max, newValue) + if (newMax % 5 != 0) { + newMax += 5 + newMax = Math.floor(newMax / _tickSeparation) * _tickSeparation + } + yAxis.max = newMax + } + + function getValues() { + if (_currentTuneType === tuneList[_tuneListRollIndex]) { + _value = _roll + _valueSetpoint = _rollSetpoint + _valueRate = _rollRate + _valueRateSetpoint = _rollRateSetpoint + } else if (_currentTuneType === tuneList[_tuneListPitchIndex]) { + _value = _pitch + _valueSetpoint = _pitchSetpoint + _valueRate = _pitchRate + _valueRateSetpoint = _pitchRateSetpoint + } else if (_currentTuneType === tuneList[_tuneListYawIndex]) { + _value = _yaw + _valueSetpoint = _yawSetpoint + _valueRate = _yawRate + _valueRateSetpoint = _yawRateSetpoint + } + } + + function resetGraphs() { + valueSeries.removePoints(0, valueSeries.count) + valueSetpointSeries.removePoints(0, valueSetpointSeries.count) + valueRateSeries.removePoints(0, valueRateSeries.count) + valueRateSetpointSeries.removePoints(0, valueRateSetpointSeries.count) + _valueXAxis.min = 0 + _valueXAxis.max = 0 + _valueRateXAxis.min = 0 + _valueRateXAxis.max = 0 + _valueYAxis.min = 0 + _valueYAxis.max = 10 + _valueRateYAxis.min = 0 + _valueRateYAxis.max = 10 + _msecs = 0 + } + + function currentTuneTypeIndex() { + if (_currentTuneType === tuneList[_tuneListRollIndex]) { + return _tuneListRollIndex + } else if (_currentTuneType === tuneList[_tuneListPitchIndex]) { + return _tuneListPitchIndex + } else if (_currentTuneType === tuneList[_tuneListYawIndex]) { + return _tuneListYawIndex + } + } + + // Save the current set of tuning values so we can reset to them + function saveTuningParamValues() { + var tuneTypeIndex = currentTuneTypeIndex() + + _savedTuningParamValues = [ ] + var currentTuneParams = params[tuneTypeIndex] + for (var i=0; i _maxPointCount) { + valueSeries.remove(0) + valueSetpointSeries.remove(0) + valueRateSeries.remove(0) + valueRateSetpointSeries.remove(0) + valueXAxis.min = valueSeries.at(0).x + valueRateXAxis.min = valueSeries.at(0).x + } + */ + } + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property int _maxPointCount: 10000 / interval + } + + Column { + spacing: _margins + Layout.alignment: Qt.AlignTop + + QGCLabel { text: qsTr("Tuning Axis:") } + + RowLayout { + spacing: _margins + + Repeater { + model: tuneList + QGCRadioButton { + text: modelData + checked: _currentTuneType === modelData + exclusiveGroup: tuneTypeRadios + + onClicked: _currentTuneType = modelData + } + } + } + + Item { width: 1; height: 1 } + + QGCLabel { text: qsTr("Tuning Values:") } + + GridLayout { + rows: factList.length + flow: GridLayout.TopToBottom + rowSpacing: _margins + columnSpacing: _margins + + property var factList: params[tuneList.indexOf(_currentTuneType)] + + Repeater { + model: parent.factList + + QGCLabel { text: modelData.name } + } + + Repeater { + model: parent.factList + + QGCButton { + text: "-" + onClicked: { + var value = modelData.value + modelData.value -= value * adjustPercentModel.get(adjustPercentCombo.currentIndex).value + } + } + } + + Repeater { + model: parent.factList + + FactTextField { + Layout.fillWidth: true + fact: modelData + showUnits: false + } + } + + Repeater { + model: parent.factList + + QGCButton { + text: "+" + onClicked: { + var value = modelData.value + modelData.value += value * adjustPercentModel.get(adjustPercentCombo.currentIndex).value + } + } + } + } + + RowLayout { + QGCLabel { text: qsTr("Increment/Decrement %") } + + QGCComboBox { + id: adjustPercentCombo + model: ListModel { + id: adjustPercentModel + ListElement { text: "5"; value: 0.05 } + ListElement { text: "10"; value: 0.10 } + ListElement { text: "15"; value: 0.15 } + ListElement { text: "20"; value: 0.20 } + } + } + } + Item { width: 1; height: 1 } + + QGCLabel { text: qsTr("Saved Tuning Values:") } + + GridLayout { + rows: savedRepeater.model.length + flow: GridLayout.TopToBottom + rowSpacing: _margins + columnSpacing: _margins + + Repeater { + model: params[tuneList.indexOf(_currentTuneType)] + + QGCLabel { text: modelData.name } + } + + Repeater { + id: savedRepeater + + QGCLabel { text: modelData } + } + } + + RowLayout { + spacing: _margins + + QGCButton { + text: qsTr("Save Values") + onClicked: saveTuningParamValues() + } + + QGCButton { + text: qsTr("Reset To Saved Values") + onClicked: resetToSavedTuningParamValues() + } + } + + Item { width: 1; height: 1 } + + QGCLabel { text: qsTr("Chart:") } + + RowLayout { + spacing: _margins + + QGCButton { + text: qsTr("Clear") + onClicked: resetGraphs() + } + + QGCButton { + text: dataTimer.running ? qsTr("Stop") : qsTr("Start") + onClicked: dataTimer.running = !dataTimer.running + } + } + } + + Column { + Layout.fillWidth: true + + ChartView { + anchors.left: parent.left + anchors.right: parent.right + height: availableHeight / 2 + title: _currentTuneType + antialiasing: true + legend.alignment: Qt.AlignRight + + LineSeries { + id: valueSeries + name: "Response" + axisY: valueYAxis + axisX: valueXAxis + } + + LineSeries { + id: valueSetpointSeries + name: "Command" + axisY: valueYAxis + axisX: valueXAxis + } + } + + ChartView { + anchors.left: parent.left + anchors.right: parent.right + height: availableHeight / 2 + title: _currentTuneType + qsTr(" Rate") + antialiasing: true + legend.alignment: Qt.AlignRight + + LineSeries { + id: valueRateSeries + name: "Response" + axisY: valueRateYAxis + axisX: valueRateXAxis + } + + LineSeries { + id: valueRateSetpointSeries + name: "Command" + axisY: valueRateYAxis + axisX: valueRateXAxis + } + } + } +} // RowLayout diff --git a/src/QmlControls/QGroundControl.Controls.qmldir b/src/QmlControls/QGroundControl.Controls.qmldir index 22e8f166b9ef3bc29e8157778f170071aaa34dfb..9277f3f2471a9ab4bc9db0e046c55dc2894c9334 100644 --- a/src/QmlControls/QGroundControl.Controls.qmldir +++ b/src/QmlControls/QGroundControl.Controls.qmldir @@ -32,6 +32,7 @@ OfflineMapButton 1.0 OfflineMapButton.qml PageView 1.0 PageView.qml ParameterEditor 1.0 ParameterEditor.qml ParameterEditorDialog 1.0 ParameterEditorDialog.qml +PIDTuning 1.0 PIDTuning.qml PlanToolBar 1.0 PlanToolBar.qml QGCButton 1.0 QGCButton.qml QGCCheckListItem 1.0 QGCCheckListItem.qml