Unverified Commit 2d8ae582 authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #7407 from DonLakeFlyer/PIDTuning

Pid Tuning: Stream rate adjustment, Automatic flight mode switching
parents 1ee48046 dab6ec1f
...@@ -61,26 +61,6 @@ SetupPage { ...@@ -61,26 +61,6 @@ SetupPage {
max: 15 max: 15
step: 1 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
}
*/
} }
} }
......
...@@ -34,6 +34,8 @@ Column { ...@@ -34,6 +34,8 @@ Column {
property real _margins: ScreenTools.defaultFontPixelHeight property real _margins: ScreenTools.defaultFontPixelHeight
property bool _loadComplete: false property bool _loadComplete: false
Component.onCompleted: _loadComplete = true
FactPanelController { FactPanelController {
id: controller id: controller
factPanel: qgcViewPanel factPanel: qgcViewPanel
...@@ -71,10 +73,22 @@ Column { ...@@ -71,10 +73,22 @@ Column {
font.family: ScreenTools.demiboldFontFamily font.family: ScreenTools.demiboldFontFamily
} }
FactValueSlider { Slider {
digitCount: fact.maxString.length anchors.left: parent.left
incrementSlots: 3 anchors.right: parent.right
fact: controller.getParameterFact(-1, param) minimumValue: min
maximumValue: max
stepSize: step
tickmarksEnabled: true
value: _fact.value
property Fact _fact: controller.getParameterFact(-1, param)
onValueChanged: {
if (_loadComplete) {
_fact.value = value
}
}
} }
QGCLabel { QGCLabel {
......
...@@ -142,16 +142,11 @@ RowLayout { ...@@ -142,16 +142,11 @@ RowLayout {
} }
Component.onCompleted: { Component.onCompleted: {
// Stop deferring updates to vehicle values. We need them as fast as we can for charting. _activeVehicle.setPIDTuningTelemetryMode(true)
_activeVehicle.setLiveUpdates(true)
_activeVehicle.setpoint.setLiveUpdates(true)
saveTuningParamValues() saveTuningParamValues()
} }
Component.onDestruction: { Component.onDestruction: _activeVehicle.setPIDTuningTelemetryMode(false)
_activeVehicle.setLiveUpdates(false)
_activeVehicle.setpoint.setLiveUpdates(true)
}
on_CurrentTuneTypeChanged: { on_CurrentTuneTypeChanged: {
saveTuningParamValues() saveTuningParamValues()
...@@ -202,14 +197,6 @@ RowLayout { ...@@ -202,14 +197,6 @@ RowLayout {
running: false running: false
repeat: true repeat: true
function startOrStop() {
if (dataTimer.running) {
dataTimer.stop()
} else {
dataTimer.start()
}
}
onTriggered: { onTriggered: {
_valueXAxis.max = _msecs _valueXAxis.max = _msecs
_valueRateXAxis.max = _msecs _valueRateXAxis.max = _msecs
...@@ -243,25 +230,25 @@ RowLayout { ...@@ -243,25 +230,25 @@ RowLayout {
spacing: _margins spacing: _margins
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
QGCLabel { text: qsTr("Tuning Axis:") } Column {
QGCLabel { text: qsTr("Tuning Axis:") }
RowLayout { RowLayout {
spacing: _margins spacing: _margins
Repeater { Repeater {
model: tuneList model: tuneList
QGCRadioButton { QGCRadioButton {
text: modelData text: modelData
checked: _currentTuneType === modelData checked: _currentTuneType === modelData
exclusiveGroup: tuneTypeRadios exclusiveGroup: tuneTypeRadios
onClicked: _currentTuneType = modelData onClicked: _currentTuneType = modelData
}
} }
} }
} }
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Tuning Values:") } QGCLabel { text: qsTr("Tuning Values:") }
GridLayout { GridLayout {
...@@ -333,26 +320,27 @@ RowLayout { ...@@ -333,26 +320,27 @@ RowLayout {
} }
} }
} }
Item { width: 1; height: 1 }
QGCLabel { text: qsTr("Clipboard Values:") } Column {
QGCLabel { text: qsTr("Clipboard Values:") }
GridLayout { GridLayout {
rows: savedRepeater.model.length rows: savedRepeater.model.length
flow: GridLayout.TopToBottom flow: GridLayout.TopToBottom
rowSpacing: _margins rowSpacing: 0
columnSpacing: _margins columnSpacing: _margins
Repeater { Repeater {
model: params[tuneList.indexOf(_currentTuneType)] model: params[tuneList.indexOf(_currentTuneType)]
QGCLabel { text: modelData.name } QGCLabel { text: modelData.name }
} }
Repeater { Repeater {
id: savedRepeater id: savedRepeater
QGCLabel { text: modelData } QGCLabel { text: modelData }
}
} }
} }
...@@ -384,7 +372,30 @@ RowLayout { ...@@ -384,7 +372,30 @@ RowLayout {
QGCButton { QGCButton {
text: dataTimer.running ? qsTr("Stop") : qsTr("Start") text: dataTimer.running ? qsTr("Stop") : qsTr("Start")
onClicked: dataTimer.startOrStop() onClicked: {
dataTimer.running = !dataTimer.running
if (autoModeChange.checked) {
_activeVehicle.flightMode = dataTimer.running ? "Stabilized" : _activeVehicle.pauseFlightMode
}
}
}
}
QGCCheckBox {
id: autoModeChange
text: qsTr("Automatic Flight Mode Switching")
}
Column {
visible: autoModeChange.checked
QGCLabel {
text: qsTr("Switches to 'Stabilized' when you click Start.")
font.pointSize: ScreenTools.smallFontPointSize
}
QGCLabel {
text: qsTr("Switches to '%1' when you click Stop.").arg(_activeVehicle.pauseFlightMode)
font.pointSize: ScreenTools.smallFontPointSize
} }
} }
} }
......
...@@ -185,6 +185,8 @@ Vehicle::Vehicle(LinkInterface* link, ...@@ -185,6 +185,8 @@ Vehicle::Vehicle(LinkInterface* link,
, _lastAnnouncedLowBatteryPercent(100) , _lastAnnouncedLowBatteryPercent(100)
, _priorityLinkCommanded(false) , _priorityLinkCommanded(false)
, _orbitActive(false) , _orbitActive(false)
, _pidTuningTelemetryMode(false)
, _pidTuningWaitingForRates(false)
, _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble) , _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble)
, _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble) , _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble)
, _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble) , _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble)
...@@ -386,6 +388,8 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType, ...@@ -386,6 +388,8 @@ Vehicle::Vehicle(MAV_AUTOPILOT firmwareType,
, _uid(0) , _uid(0)
, _lastAnnouncedLowBatteryPercent(100) , _lastAnnouncedLowBatteryPercent(100)
, _orbitActive(false) , _orbitActive(false)
, _pidTuningTelemetryMode(false)
, _pidTuningWaitingForRates(false)
, _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble) , _rollFact (0, _rollFactName, FactMetaData::valueTypeDouble)
, _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble) , _pitchFact (0, _pitchFactName, FactMetaData::valueTypeDouble)
, _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble) , _headingFact (0, _headingFactName, FactMetaData::valueTypeDouble)
...@@ -519,6 +523,8 @@ void Vehicle::_commonInit(void) ...@@ -519,6 +523,8 @@ void Vehicle::_commonInit(void)
} }
} }
#endif #endif
_pidTuningMessages << MAVLINK_MSG_ID_ATTITUDE << MAVLINK_MSG_ID_ATTITUDE_TARGET;
} }
Vehicle::~Vehicle() Vehicle::~Vehicle()
...@@ -794,7 +800,9 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes ...@@ -794,7 +800,9 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes
case MAVLINK_MSG_ID_ORBIT_EXECUTION_STATUS: case MAVLINK_MSG_ID_ORBIT_EXECUTION_STATUS:
_handleOrbitExecutionStatus(message); _handleOrbitExecutionStatus(message);
break; break;
case MAVLINK_MSG_ID_MESSAGE_INTERVAL:
_handleMessageInterval(message);
break;
case MAVLINK_MSG_ID_PING: case MAVLINK_MSG_ID_PING:
_handlePing(link, message); _handlePing(link, message);
break; break;
...@@ -3859,6 +3867,74 @@ int Vehicle::versionCompare(int major, int minor, int patch) ...@@ -3859,6 +3867,74 @@ int Vehicle::versionCompare(int major, int minor, int patch)
return _firmwarePlugin->versionCompare(this, major, minor, patch); return _firmwarePlugin->versionCompare(this, major, minor, patch);
} }
void Vehicle::_handleMessageInterval(const mavlink_message_t& message)
{
if (_pidTuningWaitingForRates) {
mavlink_message_interval_t messageInterval;
mavlink_msg_message_interval_decode(&message, &messageInterval);
int msgId = messageInterval.message_id;
if (_pidTuningMessages.contains(msgId)) {
_pidTuningMessageRatesUsecs[msgId] = messageInterval.interval_us;
}
if (_pidTuningMessageRatesUsecs.count() == _pidTuningMessages.count()) {
// We have back all the rates we requested
_pidTuningWaitingForRates = false;
_pidTuningAdjustRates(true);
}
}
}
void Vehicle::setPIDTuningTelemetryMode(bool pidTuning)
{
if (pidTuning) {
if (!_pidTuningTelemetryMode) {
// First step is to get the current message rates before we adjust them
_pidTuningTelemetryMode = true;
_pidTuningWaitingForRates = true;
_pidTuningMessageRatesUsecs.clear();
for (int telemetry: _pidTuningMessages) {
sendMavCommand(defaultComponentId(),
MAV_CMD_GET_MESSAGE_INTERVAL,
true, // show error
telemetry);
}
}
} else {
if (_pidTuningTelemetryMode) {
_pidTuningTelemetryMode = false;
if (_pidTuningWaitingForRates) {
// We never finished waiting for previous rates
_pidTuningWaitingForRates = false;
} else {
_pidTuningAdjustRates(false);
}
}
}
}
void Vehicle::_pidTuningAdjustRates(bool setRatesForTuning)
{
int requestedRate = (int)(1000000.0 / 30.0); // 30 Hz in usecs
for (int telemetry: _pidTuningMessages) {
if (requestedRate < _pidTuningMessageRatesUsecs[telemetry]) {
sendMavCommand(defaultComponentId(),
MAV_CMD_SET_MESSAGE_INTERVAL,
true, // show error
telemetry,
setRatesForTuning ? requestedRate : _pidTuningMessageRatesUsecs[telemetry]);
}
}
setLiveUpdates(setRatesForTuning);
_setpointFactGroup.setLiveUpdates(setRatesForTuning);
}
#if !defined(NO_ARDUPILOT_DIALECT) #if !defined(NO_ARDUPILOT_DIALECT)
void Vehicle::flashBootloader(void) void Vehicle::flashBootloader(void)
{ {
......
...@@ -758,6 +758,8 @@ public: ...@@ -758,6 +758,8 @@ public:
/// @param percent 0-no power, 100-full power /// @param percent 0-no power, 100-full power
Q_INVOKABLE void motorTest(int motor, int percent); Q_INVOKABLE void motorTest(int motor, int percent);
Q_INVOKABLE void setPIDTuningTelemetryMode(bool pidTuning);
#if !defined(NO_ARDUPILOT_DIALECT) #if !defined(NO_ARDUPILOT_DIALECT)
Q_INVOKABLE void flashBootloader(void); Q_INVOKABLE void flashBootloader(void);
#endif #endif
...@@ -1265,6 +1267,7 @@ private: ...@@ -1265,6 +1267,7 @@ private:
void _handleEstimatorStatus(mavlink_message_t& message); void _handleEstimatorStatus(mavlink_message_t& message);
void _handleStatusText(mavlink_message_t& message, bool longVersion); void _handleStatusText(mavlink_message_t& message, bool longVersion);
void _handleOrbitExecutionStatus(const mavlink_message_t& message); void _handleOrbitExecutionStatus(const mavlink_message_t& message);
void _handleMessageInterval(const mavlink_message_t& message);
// ArduPilot dialect messages // ArduPilot dialect messages
#if !defined(NO_ARDUPILOT_DIALECT) #if !defined(NO_ARDUPILOT_DIALECT)
void _handleCameraFeedback(const mavlink_message_t& message); void _handleCameraFeedback(const mavlink_message_t& message);
...@@ -1291,6 +1294,7 @@ private: ...@@ -1291,6 +1294,7 @@ private:
void _setCapabilities(uint64_t capabilityBits); void _setCapabilities(uint64_t capabilityBits);
void _updateArmed(bool armed); void _updateArmed(bool armed);
bool _apmArmingNotRequired(void); bool _apmArmingNotRequired(void);
void _pidTuningAdjustRates(bool setRatesForTuning);
int _id; ///< Mavlink system id int _id; ///< Mavlink system id
int _defaultComponentId; int _defaultComponentId;
...@@ -1473,6 +1477,12 @@ private: ...@@ -1473,6 +1477,12 @@ private:
QTimer _orbitTelemetryTimer; QTimer _orbitTelemetryTimer;
static const int _orbitTelemetryTimeoutMsecs = 3000; // No telemetry for this amount and orbit will go inactive static const int _orbitTelemetryTimeoutMsecs = 3000; // No telemetry for this amount and orbit will go inactive
// PID Tuning telemetry mode
bool _pidTuningTelemetryMode;
bool _pidTuningWaitingForRates;
QList<int> _pidTuningMessages;
QMap<int, int> _pidTuningMessageRatesUsecs;
// FactGroup facts // FactGroup facts
Fact _rollFact; Fact _rollFact;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment