diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 542cba60e2344caecfb98c3319c0dee5fb0d8c46..11a2959460abe38ab78c666262ead9db8ac1549f 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -89,6 +89,7 @@
src/QmlControls/KMLOrSHPFileDialog.qml
src/QmlControls/LogReplayStatusBar.qml
src/QmlControls/MainWindowSavedState.qml
+ src/QmlControls/MAVLinkChart.qml
src/QmlControls/MAVLinkMessageButton.qml
src/QmlControls/MissionCommandDialog.qml
src/PlanView/MissionItemEditor.qml
diff --git a/src/AnalyzeView/MAVLinkInspectorController.cc b/src/AnalyzeView/MAVLinkInspectorController.cc
index 3984ca7039ef80133b6c773156c9dc5f8eb4d656..6d03b0b8cbf2e0489024714f29eaff11471bdbad 100644
--- a/src/AnalyzeView/MAVLinkInspectorController.cc
+++ b/src/AnalyzeView/MAVLinkInspectorController.cc
@@ -18,6 +18,8 @@ QT_CHARTS_USE_NAMESPACE
Q_DECLARE_METATYPE(QAbstractSeries*)
+#define UPDATE_FREQUENCY (1000 / 15) // 15Hz
+
//-----------------------------------------------------------------------------
QGCMAVLinkMessageField::QGCMAVLinkMessageField(QGCMAVLinkMessage *parent, QString name, QString type)
: QObject(parent)
@@ -118,19 +120,25 @@ QGCMAVLinkMessageField::updateValue(QString newValue, qreal v)
_msg->msgCtl()->updateYRange(_left);
}
}
- _msg->msgCtl()->updateXRange();
- _updateSeries();
}
}
//-----------------------------------------------------------------------------
void
-QGCMAVLinkMessageField::_updateSeries()
+QGCMAVLinkMessageField::updateSeries()
{
int count = _values.count();
if (count > 1) {
+ QList s;
+ s.reserve(count);
+ int idx = _dataIndex;
+ for(int i = 0; i < count; i++, idx++) {
+ if(idx >= count) idx = 0;
+ QPointF p(_values[idx]);
+ s.append(p);
+ }
QLineSeries* lineSeries = static_cast(_pSeries);
- lineSeries->replace(_values);
+ lineSeries->replace(s);
}
}
@@ -512,8 +520,10 @@ MAVLinkInspectorController::MAVLinkInspectorController()
connect(multiVehicleManager, &MultiVehicleManager::vehicleRemoved, this, &MAVLinkInspectorController::_vehicleRemoved);
MAVLinkProtocol* mavlinkProtocol = qgcApp()->toolbox()->mavlinkProtocol();
connect(mavlinkProtocol, &MAVLinkProtocol::messageReceived, this, &MAVLinkInspectorController::_receiveMessage);
- connect(&_updateTimer, &QTimer::timeout, this, &MAVLinkInspectorController::_refreshFrequency);
- _updateTimer.start(1000);
+ connect(&_updateFrequencyTimer, &QTimer::timeout, this, &MAVLinkInspectorController::_refreshFrequency);
+ connect(&_updateSeriesTimer, &QTimer::timeout, this, &MAVLinkInspectorController::_refreshSeries);
+ _updateFrequencyTimer.start(1000);
+ _updateSeriesTimer.start(UPDATE_FREQUENCY);
MultiVehicleManager *manager = qgcApp()->toolbox()->multiVehicleManager();
connect(manager, &MultiVehicleManager::activeVehicleChanged, this, &MAVLinkInspectorController::_setActiveVehicle);
_timeScaleSt.append(new TimeScale_st(this, tr("5 Sec"), 5 * 1000));
@@ -570,13 +580,13 @@ MAVLinkInspectorController::setLeftRangeIdx(quint32 r)
{
if(r < static_cast(_rangeSt.count())) {
_leftRangeIndex = r;
- _timeRange = _rangeSt[static_cast(r)]->range;
+ qreal range = _rangeSt[static_cast(r)]->range;
emit leftRangeChanged();
//-- If not Auto, use defined range
if(_leftRangeIndex > 0) {
- _leftRangeMin = -_timeRange;
+ _leftRangeMin = -range;
emit leftRangeMinChanged();
- _leftRangeMax = _timeRange;
+ _leftRangeMax = range;
emit leftRangeMaxChanged();
}
}
@@ -588,13 +598,13 @@ MAVLinkInspectorController::setRightRangeIdx(quint32 r)
{
if(r < static_cast(_rangeSt.count())) {
_rightRangeIndex = r;
- _timeRange = _rangeSt[static_cast(r)]->range;
+ qreal range = _rangeSt[static_cast(r)]->range;
emit rightRangeChanged();
//-- If not Auto, use defined range
if(_rightRangeIndex > 0) {
- _rightRangeMin = -_timeRange;
+ _rightRangeMin = -range;
emit rightRangeMinChanged();
- _rightRangeMax = _timeRange;
+ _rightRangeMax = range;
emit rightRangeMaxChanged();
}
}
@@ -826,6 +836,7 @@ MAVLinkInspectorController::addSeries(QGCMAVLinkMessageField* field, QAbstractSe
{
if(field) {
field->addSeries(series, left);
+ _updateSeriesTimer.start(UPDATE_FREQUENCY);
}
}
@@ -836,19 +847,29 @@ MAVLinkInspectorController::delSeries(QGCMAVLinkMessageField* field)
if(field) {
field->delSeries();
}
- if(_leftChartFields.count() == 0) {
- _leftRangeMin = 0;
- _leftRangeMax = 1;
- emit leftRangeMinChanged();
- emit leftRangeMaxChanged();
- }
- if(_rightChartFields.count() == 0) {
- _rightRangeMin = 0;
- _rightRangeMax = 1;
- emit rightRangeMinChanged();
- emit rightRangeMaxChanged();
- }
if(_leftChartFields.count() == 0 && _rightChartFields.count() == 0) {
updateXRange();
+ _updateSeriesTimer.stop();
+ }
+}
+
+//-----------------------------------------------------------------------------
+void
+MAVLinkInspectorController::_refreshSeries()
+{
+ updateXRange();
+ for(int i = 0; i < _leftChartFields.count(); i++) {
+ QObject* object = qvariant_cast(_leftChartFields.at(i));
+ QGCMAVLinkMessageField* pField = qobject_cast(object);
+ if(pField) {
+ pField->updateSeries();
+ }
+ }
+ for(int i = 0; i < _rightChartFields.count(); i++) {
+ QObject* object = qvariant_cast(_rightChartFields.at(i));
+ QGCMAVLinkMessageField* pField = qobject_cast(object);
+ if(pField) {
+ pField->updateSeries();
+ }
}
}
diff --git a/src/AnalyzeView/MAVLinkInspectorController.h b/src/AnalyzeView/MAVLinkInspectorController.h
index 3052629db960bd35ecc143c58a9f11d289a6ba19..53ba832cdf46b6d226521e0db5afc1074880336d 100644
--- a/src/AnalyzeView/MAVLinkInspectorController.h
+++ b/src/AnalyzeView/MAVLinkInspectorController.h
@@ -56,6 +56,7 @@ public:
void addSeries (QAbstractSeries* series, bool left);
void delSeries ();
+ void updateSeries ();
signals:
void seriesChanged ();
@@ -63,10 +64,6 @@ signals:
void valueChanged ();
private:
- void _updateSeries ();
-
-private:
-
QString _type;
QString _name;
QString _value;
@@ -242,6 +239,7 @@ private slots:
void _vehicleRemoved (Vehicle* vehicle);
void _setActiveVehicle (Vehicle* vehicle);
void _refreshFrequency ();
+ void _refreshSeries ();
private:
QGCMAVLinkVehicle* _findVehicle (uint8_t id);
@@ -275,9 +273,9 @@ private:
qreal _rightRangeMin = 0;
qreal _rightRangeMax = 1;
quint32 _rightRangeIndex = 0; ///> Auto Range
- qreal _timeRange = 0;
QGCMAVLinkVehicle* _activeVehicle = nullptr;
- QTimer _updateTimer;
+ QTimer _updateFrequencyTimer;
+ QTimer _updateSeriesTimer;
QStringList _vehicleNames;
QmlObjectListModel _vehicles; ///< List of QGCMAVLinkVehicle
QVariantList _rightChartFields;
diff --git a/src/AnalyzeView/MAVLinkInspectorPage.qml b/src/AnalyzeView/MAVLinkInspectorPage.qml
index 71bc9f3c0927226989b1c37b6f8592d9b8e1c06d..444e192748d48a0f062132a4e8cb2b5591ab5e49 100644
--- a/src/AnalyzeView/MAVLinkInspectorPage.qml
+++ b/src/AnalyzeView/MAVLinkInspectorPage.qml
@@ -286,6 +286,7 @@ AnalyzePage {
Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 30
Layout.maximumWidth: ScreenTools.defaultFontPixelWidth * 30
text: object.value
+ elide: Text.ElideRight
}
}
Repeater {
@@ -301,14 +302,14 @@ AnalyzePage {
delegate: QGCCheckBox {
Layout.row: index
Layout.column: 3
- enabled: (object.series !== null && object.left) || (object.selectable && controller.seriesCount < chartView.maxSeriesCount)
+ enabled: (object.series !== null && object.left) || (object.selectable && controller.seriesCount < 12)
checked: enabled ? (object.series !== null && object.left) : false
onClicked: {
if(enabled) {
if(checked) {
- chartView.addDimension(object, true)
+ chart1.addDimension(object, true)
} else {
- chartView.delDimension(object)
+ chart1.delDimension(object)
}
}
}
@@ -319,14 +320,14 @@ AnalyzePage {
delegate: QGCCheckBox {
Layout.row: index
Layout.column: 4
- enabled: (object.series !== null && !object.left) || (object.selectable && controller.seriesCount < chartView.maxSeriesCount && (object.series === null && !object.left))
+ enabled: (object.series !== null && !object.left) || (object.selectable && controller.seriesCount < 12 && (object.series === null && !object.left))
checked: enabled ? (object.series !== null && !object.left) : false
onClicked: {
if(enabled) {
if(checked) {
- chartView.addDimension(object, false)
+ chart2.addDimension(object, false)
} else {
- chartView.delDimension(object)
+ chart2.delDimension(object)
}
}
}
@@ -334,135 +335,21 @@ AnalyzePage {
}
}
Item { height: ScreenTools.defaultFontPixelHeight * 0.25; width: 1 }
- ChartView {
- id: chartView
+ MAVLinkChart {
+ id: chart1
+ height: ScreenTools.defaultFontPixelHeight * 20
+ visible: controller.leftChartFields.length > 0
+ min: controller.leftRangeMin
+ max: controller.leftRangeMax
+ Layout.fillWidth: true
+ }
+ MAVLinkChart {
+ id: chart2
+ height: ScreenTools.defaultFontPixelHeight * 20
+ visible: controller.rightChartFields.length > 0
+ min: controller.rightRangeMin
+ max: controller.rightRangeMax
Layout.fillWidth: true
- height: ScreenTools.defaultFontPixelHeight * 20
- theme: ChartView.ChartThemeDark
- antialiasing: true
- visible: controller.leftChartFields.length > 0 || controller.rightChartFields.length > 0
- animationOptions: ChartView.NoAnimation
- legend.visible: false
- margins.bottom: ScreenTools.defaultFontPixelHeight * 1.5
- margins.top: chartHeader.height + (ScreenTools.defaultFontPixelHeight * 2)
-
- property int maxSeriesCount: seriesColors.length
- property var seriesColors: ["antiquewhite", "aqua", "chartreuse", "chocolate", "crimson", "darkturquoise", "aquamarine", "azure", "coral", "cornflowerblue", "darkorange", "gold", "hotpink", "lavenderblush", "lightskyblue"]
-
- function addDimension(field, left) {
- console.log(field.name + ' ' + field + ' AxisY1: ' + axisY1 + ' AxisY2: ' + axisY2)
- console.log(controller.seriesCount + ' ' + chartView.seriesColors[controller.seriesCount])
- var serie = createSeries(ChartView.SeriesTypeLine, field.label)
- serie.axisX = axisX
- if(left) {
- serie.axisY = axisY1
- } else {
- serie.axisYRight = axisY2
- }
- serie.useOpenGL = true
- serie.color = chartView.seriesColors[controller.seriesCount]
- controller.addSeries(field, serie, left)
- }
-
- function delDimension(field) {
- chartView.removeSeries(field.series)
- controller.delSeries(field)
- console.log('Remove: ' + controller.seriesCount + ' ' + field.name)
- }
-
- DateTimeAxis {
- id: axisX
- min: visible ? controller.rangeXMin : new Date()
- max: visible ? controller.rangeXMax : new Date()
- format: "hh:mm:ss"
- tickCount: 5
- gridVisible: true
- labelsFont.family: "Fixed"
- labelsFont.pixelSize: ScreenTools.smallFontPointSize
- }
-
- ValueAxis {
- id: axisY1
- min: visible ? controller.leftRangeMin : 0
- max: visible ? controller.leftRangeMax : 0
- visible: controller.leftChartFields.length > 0
- lineVisible: false
- labelsFont.family: "Fixed"
- labelsFont.pixelSize: ScreenTools.smallFontPointSize
- //labelsColor: qgcPal.colorRed
- }
-
- ValueAxis {
- id: axisY2
- min: visible ? controller.rightRangeMin : 0
- max: visible ? controller.rightRangeMax : 0
- visible: controller.rightChartFields.length > 0
- lineVisible: false
- labelsFont.family: "Fixed"
- labelsFont.pixelSize: ScreenTools.smallFontPointSize
- //labelsColor: qgcPal.colorGreen
- }
-
- RowLayout {
- id: chartHeader
- anchors.left: parent.left
- anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 4
- anchors.right: parent.right
- anchors.rightMargin:ScreenTools.defaultFontPixelWidth * 4
- anchors.top: parent.top
- anchors.topMargin: ScreenTools.defaultFontPixelHeight * 1.5
- spacing: 0
- QGCLabel {
- text: qsTr("Scale:");
- font.pixelSize: ScreenTools.smallFontPointSize
- Layout.alignment: Qt.AlignVCenter
- }
- QGCComboBox {
- id: timeScaleSelector
- width: ScreenTools.defaultFontPixelWidth * 10
- height: ScreenTools.defaultFontPixelHeight
- model: controller.timeScales
- currentIndex: controller.timeScale
- onActivated: controller.timeScale = index
- font.pixelSize: ScreenTools.smallFontPointSize
- Layout.alignment: Qt.AlignVCenter
- }
- GridLayout {
- columns: 2
- columnSpacing: ScreenTools.defaultFontPixelWidth
- rowSpacing: ScreenTools.defaultFontPixelHeight * 0.25
- Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
- Layout.fillWidth: true
- QGCLabel {
- text: qsTr("Range Left:");
- font.pixelSize: ScreenTools.smallFontPointSize
- Layout.alignment: Qt.AlignVCenter
- }
- QGCComboBox {
- Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 8
- height: ScreenTools.defaultFontPixelHeight * 1.5
- model: controller.rangeList
- currentIndex: controller.leftRangeIdx
- onActivated: controller.leftRangeIdx = index
- font.pixelSize: ScreenTools.smallFontPointSize
- Layout.alignment: Qt.AlignVCenter
- }
- QGCLabel {
- text: qsTr("Range Right:");
- font.pixelSize: ScreenTools.smallFontPointSize
- Layout.alignment: Qt.AlignVCenter
- }
- QGCComboBox {
- Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 8
- height: ScreenTools.defaultFontPixelHeight * 1.5
- model: controller.rangeList
- currentIndex: controller.rightRangeIdx
- onActivated: controller.rightRangeIdx = index
- font.pixelSize: ScreenTools.smallFontPointSize
- Layout.alignment: Qt.AlignVCenter
- }
- }
- }
}
}
}
diff --git a/src/QmlControls/MAVLinkChart.qml b/src/QmlControls/MAVLinkChart.qml
new file mode 100644
index 0000000000000000000000000000000000000000..8868371ed11a28a796508bca1d94dd497439393b
--- /dev/null
+++ b/src/QmlControls/MAVLinkChart.qml
@@ -0,0 +1,124 @@
+import QtQuick 2.11
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.11
+import QtCharts 2.3
+
+import QGroundControl 1.0
+import QGroundControl.Palette 1.0
+import QGroundControl.Controls 1.0
+import QGroundControl.Controllers 1.0
+import QGroundControl.ScreenTools 1.0
+
+ChartView {
+ id: chartView
+ theme: ChartView.ChartThemeDark
+ antialiasing: true
+ animationOptions: ChartView.NoAnimation
+ legend.visible: false
+ backgroundColor: qgcPal.window
+ backgroundRoundness: 0
+ margins.bottom: ScreenTools.defaultFontPixelHeight * 1.5
+ margins.top: chartHeader.height + (ScreenTools.defaultFontPixelHeight * 2)
+
+ property int maxSeriesCount: seriesColors.length
+ property var seriesColors: ["chartreuse", "chocolate", "yellowgreen", "thistle", "silver", "darkturquoise", "blue", "green"]
+ property alias max: axisY.max
+ property alias min: axisY.min
+
+ function addDimension(field, left) {
+ console.log(field.name + ' AxisY: ' + axisY)
+ console.log(chartView.count + ' ' + chartView.seriesColors[chartView.count])
+ var serie = createSeries(ChartView.SeriesTypeLine, field.label)
+ serie.axisX = axisX
+ serie.axisY = axisY
+ serie.useOpenGL = true
+ serie.color = chartView.seriesColors[chartView.count]
+ serie.width = 1
+ controller.addSeries(field, serie, left)
+ }
+
+ function delDimension(field) {
+ chartView.removeSeries(field.series)
+ controller.delSeries(field)
+ console.log('Remove: ' + chartView.count + ' ' + field.name)
+ }
+
+ DateTimeAxis {
+ id: axisX
+ min: controller.rangeXMin
+ max: controller.rangeXMax
+ format: "mm:ss.zzz"
+ tickCount: 5
+ gridVisible: true
+ labelsFont.family: "Fixed"
+ labelsFont.pixelSize: ScreenTools.smallFontPointSize
+ }
+
+ ValueAxis {
+ id: axisY
+ lineVisible: false
+ labelsFont.family: "Fixed"
+ labelsFont.pixelSize: ScreenTools.smallFontPointSize
+ }
+
+ RowLayout {
+ id: chartHeader
+ anchors.left: parent.left
+ anchors.leftMargin: ScreenTools.defaultFontPixelWidth * 4
+ anchors.right: parent.right
+ anchors.rightMargin: ScreenTools.defaultFontPixelWidth * 4
+ anchors.top: parent.top
+ anchors.topMargin: ScreenTools.defaultFontPixelHeight * 1.5
+ spacing: 0
+ QGCLabel {
+ text: qsTr("Scale:");
+ font.pixelSize: ScreenTools.smallFontPointSize
+ Layout.alignment: Qt.AlignVCenter
+ }
+ QGCComboBox {
+ id: timeScaleSelector
+ width: ScreenTools.defaultFontPixelWidth * 10
+ height: ScreenTools.defaultFontPixelHeight
+ model: controller.timeScales
+ currentIndex: controller.timeScale
+ onActivated: controller.timeScale = index
+ font.pixelSize: ScreenTools.smallFontPointSize
+ Layout.alignment: Qt.AlignVCenter
+ }
+ GridLayout {
+ columns: 2
+ columnSpacing: ScreenTools.defaultFontPixelWidth
+ rowSpacing: ScreenTools.defaultFontPixelHeight * 0.25
+ Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
+ Layout.fillWidth: true
+ QGCLabel {
+ text: qsTr("Range Left:");
+ font.pixelSize: ScreenTools.smallFontPointSize
+ Layout.alignment: Qt.AlignVCenter
+ }
+ QGCComboBox {
+ Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 8
+ height: ScreenTools.defaultFontPixelHeight * 1.5
+ model: controller.rangeList
+ currentIndex: controller.leftRangeIdx
+ onActivated: controller.leftRangeIdx = index
+ font.pixelSize: ScreenTools.smallFontPointSize
+ Layout.alignment: Qt.AlignVCenter
+ }
+ QGCLabel {
+ text: qsTr("Range Right:");
+ font.pixelSize: ScreenTools.smallFontPointSize
+ Layout.alignment: Qt.AlignVCenter
+ }
+ QGCComboBox {
+ Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 8
+ height: ScreenTools.defaultFontPixelHeight * 1.5
+ model: controller.rangeList
+ currentIndex: controller.rightRangeIdx
+ onActivated: controller.rightRangeIdx = index
+ font.pixelSize: ScreenTools.smallFontPointSize
+ Layout.alignment: Qt.AlignVCenter
+ }
+ }
+ }
+}
diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir
index fae59ca2d0aa2dbf6937ea1a1ba846b3c7feffae..33bd6924834dc0c8a9920b7ffd00c01c59ba6c2d 100644
--- a/src/QmlControls/QGroundControl/Controls/qmldir
+++ b/src/QmlControls/QGroundControl/Controls/qmldir
@@ -93,3 +93,4 @@ VehicleRotationCal 1.0 VehicleRotationCal.qml
VehicleSummaryRow 1.0 VehicleSummaryRow.qml
ViewWidget 1.0 ViewWidget.qml
QGCHoverButton 1.0 QGCHoverButton.qml
+MAVLinkChart 1.0 MAVLinkChart.qml