diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index dd06a037add326dbed44965e70f8327fa119e17c..40f0871f666064b7b223e552cf6e8c5acd05b2ae 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -224,6 +224,7 @@ src/Vehicle/ClockFact.json src/Vehicle/GPSFact.json src/Vehicle/GPSRTKFact.json + src/Vehicle/SetpointFact.json src/Vehicle/SubmarineFact.json src/Vehicle/TemperatureFact.json src/Vehicle/VehicleFact.json diff --git a/src/AutoPilotPlugins/Common/SetupPage.qml b/src/AutoPilotPlugins/Common/SetupPage.qml index 82dc1ddef72f957d49518b5ef26d295a7a889fdb..891b6f1fabfd87ada3fb85548a41f150ca9fce8b 100644 --- a/src/AutoPilotPlugins/Common/SetupPage.qml +++ b/src/AutoPilotPlugins/Common/SetupPage.qml @@ -10,6 +10,7 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 import QGroundControl 1.0 import QGroundControl.FactSystem 1.0 @@ -30,6 +31,8 @@ QGCView { property string pageDescription: vehicleComponent ? vehicleComponent.description : "" property real availableWidth: width - pageLoader.x property real availableHeight: height - pageLoader.y + property bool showAdvanced: false + property alias advanced: advancedCheckBox.checked property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _vehicleArmed: _activeVehicle ? _activeVehicle.armed : false @@ -53,31 +56,45 @@ QGCView { contentHeight: pageLoader.y + pageLoader.item.height clip: true - Column { - id: headingColumn - width: setupPanel.width + RowLayout { + id: headingRow + anchors.left: parent.left + anchors.right: parent.right spacing: _margins + layoutDirection: Qt.RightToLeft - QGCLabel { - font.pointSize: ScreenTools.largeFontPointSize - text: !setupView.enabled ? _pageTitle + "" + qsTr(" (Disabled while the vehicle is %1)").arg(_disableReason) + "" : _pageTitle - visible: !ScreenTools.isShortScreen + QGCCheckBox { + id: advancedCheckBox + text: qsTr("Advanced") + visible: showAdvanced } - QGCLabel { - anchors.left: parent.left - anchors.right: parent.right - wrapMode: Text.WordWrap - text: pageDescription - visible: !ScreenTools.isShortScreen + Column { + spacing: _margins + Layout.fillWidth: true + + QGCLabel { + font.pointSize: ScreenTools.largeFontPointSize + text: !setupView.enabled ? _pageTitle + "" + qsTr(" (Disabled while the vehicle is %1)").arg(_disableReason) + "" : _pageTitle + visible: !ScreenTools.isShortScreen + } + + QGCLabel { + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + text: pageDescription + visible: !ScreenTools.isShortScreen + } } } Loader { id: pageLoader anchors.topMargin: _margins - anchors.top: headingColumn.bottom + anchors.top: headingRow.bottom } + // Overlay to display when vehicle is armed and this setup page needs // to be disabled Rectangle { diff --git a/src/AutoPilotPlugins/PX4/PX4TuningComponent.h b/src/AutoPilotPlugins/PX4/PX4TuningComponent.h index 3080b965c83f3ac77cc2f9961822e20fa413c805..5fe989dde16416afabbf069094485b301fb7f1f0 100644 --- a/src/AutoPilotPlugins/PX4/PX4TuningComponent.h +++ b/src/AutoPilotPlugins/PX4/PX4TuningComponent.h @@ -32,6 +32,7 @@ public: QUrl setupSource(void) const final; QUrl summaryQmlSource(void) const final; bool allowSetupWhileArmed(void) const final { return true; } + bool allowSetupWhileFlying(void) const final { return true; } private: const QString _name; diff --git a/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml b/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml index 56980007f6e5eae06a24e833232feb33d96f9687..999c1a8b4ffcf554c48b9064b1bd3a52c96b0ca6 100644 --- a/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml +++ b/src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.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,486 @@ SetupPage { Component { id: pageComponent - FactSliderPanel { - width: availableWidth - qgcViewPanel: tuningPage.viewPanel - - sliderModel: ListModel { - ListElement { - title: qsTr("Hover Throttle") - description: qsTr("Adjust throttle so hover is at mid-throttle. Slide to the left if hover is lower than throttle center. Slide to the right if hover is higher than throttle center.") - param: "MPC_THR_HOVER" - min: 20 - max: 80 - step: 1 + Column { + width: availableWidth + + 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 _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: [ + [ controller.getParameterFact(-1, "MC_ROLL_P"), + controller.getParameterFact(-1, "MC_ROLLRATE_P"), + controller.getParameterFact(-1, "MC_ROLLRATE_I"), + controller.getParameterFact(-1, "MC_ROLLRATE_D"), + controller.getParameterFact(-1, "MC_ROLLRATE_FF") ], + [ controller.getParameterFact(-1, "MC_PITCH_P"), + controller.getParameterFact(-1, "MC_PITCHRATE_P"), + controller.getParameterFact(-1, "MC_PITCHRATE_I"), + controller.getParameterFact(-1, "MC_PITCHRATE_D"), + controller.getParameterFact(-1, "MC_PITCHRATE_FF") ], + [ controller.getParameterFact(-1, "MC_YAW_P"), + controller.getParameterFact(-1, "MC_YAWRATE_P"), + controller.getParameterFact(-1, "MC_YAWRATE_I"), + 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() - ListElement { - title: qsTr("Manual minimum throttle") - description: qsTr("Slide to the left to start the motors with less idle power. Slide to the right if descending in manual flight becomes unstable.") - param: "MPC_MANTHR_MIN" - min: 0 - max: 15 - step: 1 + _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 + } + + // Standard tuning page + FactSliderPanel { + width: availableWidth + qgcViewPanel: tuningPage.viewPanel + visible: !advanced + + sliderModel: ListModel { + ListElement { + title: qsTr("Hover Throttle") + description: qsTr("Adjust throttle so hover is at mid-throttle. Slide to the left if hover is lower than throttle center. Slide to the right if hover is higher than throttle center.") + param: "MPC_THR_HOVER" + min: 20 + max: 80 + step: 1 + } - 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: "MC_PITCH_TC" - min: 0.15 - max: 0.25 - step: 0.01 + ListElement { + title: qsTr("Manual minimum throttle") + description: qsTr("Slide to the left to start the motors with less idle power. Slide to the right if descending in manual flight becomes unstable.") + param: "MPC_MANTHR_MIN" + min: 0 + max: 15 + step: 1 + } +/* + These seem to have disappeared from PX4 firmware! + 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: "MC_ROLL_TC" + min: 0.15 + max: 0.25 + step: 0.01 + } + + 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: "MC_PITCH_TC" + min: 0.15 + max: 0.25 + step: 0.01 + } +*/ } } - } - } // Component + + // Advanced page + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + layoutDirection: Qt.RightToLeft + visible: advanced + + 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 + } // Column + } // Component - pageComponent } // SetupPage diff --git a/src/Vehicle/SetpointFact.json b/src/Vehicle/SetpointFact.json new file mode 100644 index 0000000000000000000000000000000000000000..58fea58334a8866ee4661454452bee925e16a99d --- /dev/null +++ b/src/Vehicle/SetpointFact.json @@ -0,0 +1,44 @@ +[ +{ + "name": "roll", + "shortDescription": "Roll Setpoint", + "type": "double", + "decimalPlaces": 1, + "units": "deg" +}, +{ + "name": "pitch", + "shortDescription": "Pitch Setpoint", + "type": "double", + "decimalPlaces": 1, + "units": "deg" +}, +{ + "name": "yaw", + "shortDescription": "Yaw Setpoint", + "type": "double", + "decimalPlaces": 1, + "units": "deg" +}, +{ + "name": "rollRate", + "shortDescription": "Roll Rate Setpoint", + "type": "double", + "decimalPlaces": 1, + "units": "deg/s" +}, +{ + "name": "pitchRate", + "shortDescription": "Pitch Rate Setpoint", + "type": "double", + "decimalPlaces": 1, + "units": "deg/s" +}, +{ + "name": "yawRate", + "shortDescription": "Yaw Rate Setpoint", + "type": "double", + "decimalPlaces": 1, + "units": "deg/s" +} +] diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index a5f2d06c4bead036732157749f0c35a857940a49..fbd986bfb7816f69b487e0ae6b83e921627a2e1e 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include "Vehicle.h" #include "MAVLinkProtocol.h" @@ -54,6 +55,9 @@ const char* Vehicle::_joystickEnabledSettingsKey = "JoystickEnabled"; const char* Vehicle::_rollFactName = "roll"; const char* Vehicle::_pitchFactName = "pitch"; const char* Vehicle::_headingFactName = "heading"; +const char* Vehicle::_rollRateFactName = "rollRate"; +const char* Vehicle::_pitchRateFactName = "pitchRate"; +const char* Vehicle::_yawRateFactName = "yawRate"; const char* Vehicle::_airSpeedFactName = "airSpeed"; const char* Vehicle::_groundSpeedFactName = "groundSpeed"; const char* Vehicle::_climbRateFactName = "climbRate"; @@ -166,6 +170,9 @@ Vehicle::Vehicle(LinkInterface* link, , _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble) , _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble) , _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble) + , _rollRateFact (0, _rollRateFactName, FactMetaData::valueTypeDouble) + , _pitchRateFact (0, _pitchRateFactName, FactMetaData::valueTypeDouble) + , _yawRateFact (0, _yawRateFactName, FactMetaData::valueTypeDouble) , _groundSpeedFact (0, _groundSpeedFactName, FactMetaData::valueTypeDouble) , _airSpeedFact (0, _airSpeedFactName, FactMetaData::valueTypeDouble) , _climbRateFact (0, _climbRateFactName, FactMetaData::valueTypeDouble) @@ -353,6 +360,9 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, , _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble) , _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble) , _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble) + , _rollRateFact (0, _rollRateFactName, FactMetaData::valueTypeDouble) + , _pitchRateFact (0, _pitchRateFactName, FactMetaData::valueTypeDouble) + , _yawRateFact (0, _yawRateFactName, FactMetaData::valueTypeDouble) , _groundSpeedFact (0, _groundSpeedFactName, FactMetaData::valueTypeDouble) , _airSpeedFact (0, _airSpeedFactName, FactMetaData::valueTypeDouble) , _climbRateFact (0, _climbRateFactName, FactMetaData::valueTypeDouble) @@ -413,6 +423,9 @@ void Vehicle::_commonInit(void) _addFact(&_rollFact, _rollFactName); _addFact(&_pitchFact, _pitchFactName); _addFact(&_headingFact, _headingFactName); + _addFact(&_rollRateFact, _rollRateFactName); + _addFact(&_pitchRateFact, _pitchRateFactName); + _addFact(&_yawRateFact, _yawRateFactName); _addFact(&_groundSpeedFact, _groundSpeedFactName); _addFact(&_airSpeedFact, _airSpeedFactName); _addFact(&_climbRateFact, _climbRateFactName); @@ -696,6 +709,12 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes case MAVLINK_MSG_ID_HIGH_LATENCY2: _handleHighLatency2(message); break; + case MAVLINK_MSG_ID_ATTITUDE: + _handleAttitude(message); + break; + case MAVLINK_MSG_ID_ATTITUDE_TARGET: + _handleAttitudeTarget(message); + break; case MAVLINK_MSG_ID_SERIAL_CONTROL: { @@ -760,6 +779,35 @@ void Vehicle::_handleVfrHud(mavlink_message_t& message) _climbRateFact.setRawValue(qIsNaN(vfrHud.climb) ? 0 : vfrHud.climb); } +void Vehicle::_handleAttitudeTarget(mavlink_message_t& message) +{ + mavlink_attitude_target_t attitudeTarget; + + mavlink_msg_attitude_target_decode(&message, &attitudeTarget); + + float roll, pitch, yaw; + mavlink_quaternion_to_euler(attitudeTarget.q, &roll, &pitch, &yaw); + + _setpointFactGroup.roll()->setRawValue(roll); + _setpointFactGroup.pitch()->setRawValue(pitch); + _setpointFactGroup.yaw()->setRawValue(yaw); + + _setpointFactGroup.rollRate()->setRawValue(qRadiansToDegrees(attitudeTarget.body_roll_rate)); + _setpointFactGroup.pitchRate()->setRawValue(qRadiansToDegrees(attitudeTarget.body_pitch_rate)); + _setpointFactGroup.yawRate()->setRawValue(qRadiansToDegrees(attitudeTarget.body_yaw_rate)); +} + +void Vehicle::_handleAttitude(mavlink_message_t& message) +{ + mavlink_attitude_t attitude; + + mavlink_msg_attitude_decode(&message, &attitude); + + rollRate()->setRawValue(qRadiansToDegrees(attitude.rollspeed)); + pitchRate()->setRawValue(qRadiansToDegrees(attitude.pitchspeed)); + yawRate()->setRawValue(qRadiansToDegrees(attitude.yawspeed)); +} + void Vehicle::_handleGpsRawInt(mavlink_message_t& message) { mavlink_gps_raw_int_t gpsRawInt; @@ -869,18 +917,6 @@ void Vehicle::_handleHighLatency2(mavlink_message_t& message) { HL_FAILURE_FLAG_3D_ACCEL, MAV_SYS_STATUS_SENSOR_3D_ACCEL }, { HL_FAILURE_FLAG_3D_GYRO, MAV_SYS_STATUS_SENSOR_3D_GYRO }, { HL_FAILURE_FLAG_3D_MAG, MAV_SYS_STATUS_SENSOR_3D_MAG }, -#if 0 - // FIXME: These don't currently map to existing sensor health bits. Support needs to be added to show them - // on health page of instrument panel as well. - { HL_FAILURE_FLAG_TERRAIN=64, /* Terrain subsystem failure. | */ - { HL_FAILURE_FLAG_BATTERY=128, /* Battery failure/critical low battery. | */ - { HL_FAILURE_FLAG_RC_RECEIVER=256, /* RC receiver failure/no rc connection. | */ - { HL_FAILURE_FLAG_OFFBOARD_LINK=512, /* Offboard link failure. | */ - { HL_FAILURE_FLAG_ENGINE=1024, /* Engine failure. | */ - { HL_FAILURE_FLAG_GEOFENCE=2048, /* Geofence violation. | */ - { HL_FAILURE_FLAG_ESTIMATOR=4096, /* Estimator failure, for example measurement rejection or large variances. | */ - { HL_FAILURE_FLAG_MISSION=8192, /* Mission failure. | */ -#endif }; // Map from MAV_FAILURE bits to standard SYS_STATUS message handling @@ -3217,7 +3253,6 @@ VehicleVibrationFactGroup::VehicleVibrationFactGroup(QObject* parent) _zAxisFact.setRawValue(std::numeric_limits::quiet_NaN()); } - const char* VehicleTemperatureFactGroup::_temperature1FactName = "temperature1"; const char* VehicleTemperatureFactGroup::_temperature2FactName = "temperature2"; const char* VehicleTemperatureFactGroup::_temperature3FactName = "temperature3"; @@ -3261,3 +3296,35 @@ void VehicleClockFactGroup::_updateAllValues(void) FactGroup::_updateAllValues(); } + +const char* VehicleSetpointFactGroup::_rollFactName = "roll"; +const char* VehicleSetpointFactGroup::_pitchFactName = "pitch"; +const char* VehicleSetpointFactGroup::_yawFactName = "yaw"; +const char* VehicleSetpointFactGroup::_rollRateFactName = "rollRate"; +const char* VehicleSetpointFactGroup::_pitchRateFactName = "pitchRate"; +const char* VehicleSetpointFactGroup::_yawRateFactName = "yawRate"; + +VehicleSetpointFactGroup::VehicleSetpointFactGroup(QObject* parent) + : FactGroup (1000, ":/json/Vehicle/SetpointFact.json", parent) + , _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble) + , _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble) + , _yawFact (0, _yawFactName, FactMetaData::valueTypeDouble) + , _rollRateFact (0, _rollRateFactName, FactMetaData::valueTypeDouble) + , _pitchRateFact(0, _pitchRateFactName, FactMetaData::valueTypeDouble) + , _yawRateFact (0, _yawRateFactName, FactMetaData::valueTypeDouble) +{ + _addFact(&_rollFact, _rollFactName); + _addFact(&_pitchFact, _pitchFactName); + _addFact(&_yawFact, _yawFactName); + _addFact(&_rollRateFact, _rollRateFactName); + _addFact(&_pitchRateFact, _pitchRateFactName); + _addFact(&_yawRateFact, _yawRateFactName); + + // Start out as not available "--.--" + _rollFact.setRawValue(std::numeric_limits::quiet_NaN()); + _pitchFact.setRawValue(std::numeric_limits::quiet_NaN()); + _yawFact.setRawValue(std::numeric_limits::quiet_NaN()); + _rollRateFact.setRawValue(std::numeric_limits::quiet_NaN()); + _pitchRateFact.setRawValue(std::numeric_limits::quiet_NaN()); + _yawRateFact.setRawValue(std::numeric_limits::quiet_NaN()); +} diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index ba867511334781bb2cd8a4251c59709ebc10fc23..65d4b5ec21928bbce91e4dade8acebcd201720e2 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -40,6 +40,43 @@ Q_DECLARE_LOGGING_CATEGORY(VehicleLog) class Vehicle; +class VehicleSetpointFactGroup : public FactGroup +{ + Q_OBJECT + +public: + VehicleSetpointFactGroup(QObject* parent = NULL); + + Q_PROPERTY(Fact* roll READ roll CONSTANT) + Q_PROPERTY(Fact* pitch READ pitch CONSTANT) + Q_PROPERTY(Fact* yaw READ yaw CONSTANT) + Q_PROPERTY(Fact* rollRate READ rollRate CONSTANT) + Q_PROPERTY(Fact* pitchRate READ pitchRate CONSTANT) + Q_PROPERTY(Fact* yawRate READ yawRate CONSTANT) + + Fact* roll (void) { return &_rollFact; } + Fact* pitch (void) { return &_pitchFact; } + Fact* yaw (void) { return &_yawFact; } + Fact* rollRate (void) { return &_rollRateFact; } + Fact* pitchRate (void) { return &_pitchRateFact; } + Fact* yawRate (void) { return &_yawRateFact; } + + static const char* _rollFactName; + static const char* _pitchFactName; + static const char* _yawFactName; + static const char* _rollRateFactName; + static const char* _pitchRateFactName; + static const char* _yawRateFactName; + +private: + Fact _rollFact; + Fact _pitchFact; + Fact _yawFact; + Fact _rollRateFact; + Fact _pitchRateFact; + Fact _yawRateFact; +}; + class VehicleVibrationFactGroup : public FactGroup { Q_OBJECT @@ -370,6 +407,9 @@ public: Q_PROPERTY(Fact* roll READ roll CONSTANT) Q_PROPERTY(Fact* pitch READ pitch CONSTANT) Q_PROPERTY(Fact* heading READ heading CONSTANT) + Q_PROPERTY(Fact* rollRate READ rollRate CONSTANT) + Q_PROPERTY(Fact* pitchRate READ pitchRate CONSTANT) + Q_PROPERTY(Fact* yawRate READ yawRate CONSTANT) Q_PROPERTY(Fact* groundSpeed READ groundSpeed CONSTANT) Q_PROPERTY(Fact* airSpeed READ airSpeed CONSTANT) Q_PROPERTY(Fact* climbRate READ climbRate CONSTANT) @@ -385,6 +425,7 @@ public: Q_PROPERTY(FactGroup* vibration READ vibrationFactGroup CONSTANT) Q_PROPERTY(FactGroup* temperature READ temperatureFactGroup CONSTANT) Q_PROPERTY(FactGroup* clock READ clockFactGroup CONSTANT) + Q_PROPERTY(FactGroup* setpoint READ setpointFactGroup CONSTANT) Q_PROPERTY(int firmwareMajorVersion READ firmwareMajorVersion NOTIFY firmwareVersionChanged) Q_PROPERTY(int firmwareMinorVersion READ firmwareMinorVersion NOTIFY firmwareVersionChanged) @@ -645,8 +686,11 @@ public: unsigned maxProtoVersion () const { return _maxProtoVersion; } Fact* roll (void) { return &_rollFact; } - Fact* heading (void) { return &_headingFact; } Fact* pitch (void) { return &_pitchFact; } + Fact* heading (void) { return &_headingFact; } + Fact* rollRate (void) { return &_rollRateFact; } + Fact* pitchRate (void) { return &_pitchRateFact; } + Fact* yawRate (void) { return &_yawRateFact; } Fact* airSpeed (void) { return &_airSpeedFact; } Fact* groundSpeed (void) { return &_groundSpeedFact; } Fact* climbRate (void) { return &_climbRateFact; } @@ -662,6 +706,7 @@ public: FactGroup* vibrationFactGroup (void) { return &_vibrationFactGroup; } FactGroup* temperatureFactGroup (void) { return &_temperatureFactGroup; } FactGroup* clockFactGroup (void) { return &_clockFactGroup; } + FactGroup* setpointFactGroup (void) { return &_setpointFactGroup; } void setConnectionLostEnabled(bool connectionLostEnabled); @@ -916,6 +961,8 @@ private: void _handleScaledPressure2(mavlink_message_t& message); void _handleScaledPressure3(mavlink_message_t& message); void _handleHighLatency2(mavlink_message_t& message); + void _handleAttitude(mavlink_message_t& message); + void _handleAttitudeTarget(mavlink_message_t& message); // ArduPilot dialect messages #if !defined(NO_ARDUPILOT_DIALECT) void _handleCameraFeedback(const mavlink_message_t& message); @@ -1106,6 +1153,9 @@ private: Fact _rollFact; Fact _pitchFact; Fact _headingFact; + Fact _rollRateFact; + Fact _pitchRateFact; + Fact _yawRateFact; Fact _groundSpeedFact; Fact _airSpeedFact; Fact _climbRateFact; @@ -1122,10 +1172,14 @@ private: VehicleVibrationFactGroup _vibrationFactGroup; VehicleTemperatureFactGroup _temperatureFactGroup; VehicleClockFactGroup _clockFactGroup; + VehicleSetpointFactGroup _setpointFactGroup; static const char* _rollFactName; static const char* _pitchFactName; static const char* _headingFactName; + static const char* _rollRateFactName; + static const char* _pitchRateFactName; + static const char* _yawRateFactName; static const char* _groundSpeedFactName; static const char* _airSpeedFactName; static const char* _climbRateFactName; diff --git a/src/Vehicle/VehicleFact.json b/src/Vehicle/VehicleFact.json index ae6d59c50df1eedad6ff82c6ecbaced37120cabe..b385571291d9761568ca574c5c22ede9a3b3334c 100644 --- a/src/Vehicle/VehicleFact.json +++ b/src/Vehicle/VehicleFact.json @@ -20,6 +20,27 @@ "decimalPlaces": 0, "units": "deg" }, +{ + "name": "rollRate", + "shortDescription": "Roll Rate", + "type": "double", + "decimalPlaces": 1, + "units": "deg/s" +}, +{ + "name": "pitchRate", + "shortDescription": "Pitch Rate", + "type": "double", + "decimalPlaces": 1, + "units": "deg/s" +}, +{ + "name": "yawRate", + "shortDescription": "Yaw Rate", + "type": "double", + "decimalPlaces": 1, + "units": "deg/s" +}, { "name": "groundSpeed", "shortDescription": "Ground Speed",