From 3e6c5debc51853dbd7d8b48e393519ff93463418 Mon Sep 17 00:00:00 2001 From: m_thread Date: Thu, 30 Oct 2014 16:46:39 +0100 Subject: [PATCH] OP-1554 Added functionality to add fields with enum type and have markers added to scopes. Still a few smallish things to fix. --- .../src/plugins/scope/plotdata.cpp | 133 +++++++++++++----- .../openpilotgcs/src/plugins/scope/plotdata.h | 23 +-- .../plugins/scope/scopegadgetoptionspage.cpp | 2 +- .../src/plugins/scope/scopegadgetwidget.cpp | 5 +- .../src/plugins/scope/scopegadgetwidget.h | 2 + 5 files changed, 118 insertions(+), 47 deletions(-) diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp index 14aabc7b1..f76047b41 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.cpp +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.cpp @@ -34,14 +34,15 @@ PlotData::PlotData(UAVObject *object, UAVObjectField *field, int element, int scaleOrderFactor, int meanSamples, QString mathFunction, double plotDataSize, QPen pen, bool antialiased) : m_scalePower(scaleOrderFactor), m_meanSamples(meanSamples), - m_mathFunction(mathFunction), m_plotDataSize(plotDataSize), - m_object(object), m_field(field), m_element(element) + m_meanSum(0.0f), m_mathFunction(mathFunction), m_correctionSum(0.0f), + m_correctionCount(0), m_plotDataSize(plotDataSize), + m_object(object), m_field(field), m_element(element), + m_plotCurve(NULL), m_isVisible(true), m_pen(pen), isEnumPlot(false) { if (!m_field->getNumElements() > 1) { m_elementName = m_field->getElementNames().at(m_element); } - // Create the curve m_plotName.append(QString("%1.%2").arg(m_object->getName()).arg(m_field->getName())); if (!m_elementName.isEmpty()) { m_plotName.append(QString(".%1").arg(m_elementName)); @@ -53,26 +54,38 @@ PlotData::PlotData(UAVObject *object, UAVObjectField *field, int element, m_plotName.append(QString(" (x10^%1 %2)").arg(m_scalePower).arg(m_field->getUnits())); } + // Create the curve m_plotCurve = new QwtPlotCurve(m_plotName); if (antialiased) { m_plotCurve->setRenderHint(QwtPlotCurve::RenderAntialiased); } - m_plotCurve->setPen(pen); + m_plotCurve->setPen(m_pen); m_plotCurve->setSamples(m_xDataEntries, m_yDataEntries); - - m_meanSum = 0.0f; - m_correctionSum = 0.0f; - m_correctionCount = 0; + isEnumPlot = m_field->getType() == UAVObjectField::ENUM; } PlotData::~PlotData() { + while (!m_enumMarkerList.isEmpty()) { + QwtPlotMarker *marker = m_enumMarkerList.takeFirst(); + marker->detach(); + delete marker; + } m_plotCurve->detach(); delete m_plotCurve; } +bool PlotData::isVisible() const { + return m_plotCurve->isVisible(); +} + +void PlotData::setVisible(bool visible) { + m_plotCurve->setVisible(visible); + visibilityChanged(m_plotCurve); +} + void PlotData::updatePlotData() { m_plotCurve->setSamples(m_xDataEntries, m_yDataEntries); @@ -83,6 +96,15 @@ void PlotData::attach(QwtPlot *plot) m_plotCurve->attach(plot); } +void PlotData::visibilityChanged(QwtPlotItem *item) +{ + if (m_plotCurve == item) { + foreach (QwtPlotMarker* marker, m_enumMarkerList) { + m_plotCurve->isVisible() ? marker->attach(m_plotCurve->plot()) : marker->detach(); + } + } +} + void PlotData::calcMathFunction(double currentValue) { // Put the new value at the back @@ -116,50 +138,85 @@ void PlotData::calcMathFunction(double currentValue) } } -bool SequentialPlotData::append(UAVObject *obj) +bool SequentialPlotData::append(UAVObject *obj, QwtPlot *plot) { if (m_object == obj && m_field) { - double currentValue = m_field->getValue(m_element).toDouble() * pow(10, m_scalePower); + if (!isEnumPlot) { + double currentValue = m_field->getValue(m_element).toDouble() * pow(10, m_scalePower); - // Perform scope math, if necessary - if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") { - calcMathFunction(currentValue); - } else { - m_yDataEntries.append(currentValue); - } + // Perform scope math, if necessary + if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") { + calcMathFunction(currentValue); + } else { + m_yDataEntries.append(currentValue); + } - if (m_yDataEntries.size() > m_plotDataSize) { - // If new data overflows the window, remove old data... - m_yDataEntries.pop_front(); + if (m_yDataEntries.size() > m_plotDataSize) { + // If new data overflows the window, remove old data... + m_yDataEntries.pop_front(); + } else { + // ...otherwise, add a new y point at position xData + m_xDataEntries.insert(m_xDataEntries.size(), m_xDataEntries.size()); + } + return true; } else { - // ...otherwise, add a new y point at position xData - m_xDataEntries.insert(m_xDataEntries.size(), m_xDataEntries.size()); + } - return true; } return false; } -bool ChronoPlotData::append(UAVObject *obj) +bool ChronoPlotData::append(UAVObject *obj, QwtPlot *plot) { if (m_object == obj && m_field) { // Get the field of interest QDateTime NOW = QDateTime::currentDateTime(); // THINK ABOUT REIMPLEMENTING THIS TO SHOW UAVO TIME, NOT SYSTEM TIME - double currentValue = m_field->getValue(m_element).toDouble() * pow(10, m_scalePower); - // Perform scope math, if necessary - if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") { - calcMathFunction(currentValue); + double xValue = NOW.toTime_t() + NOW.time().msec() / 1000.0; + if (!isEnumPlot) { + double currentValue = m_field->getValue(m_element).toDouble() * pow(10, m_scalePower); + + // Perform scope math, if necessary + if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") { + calcMathFunction(currentValue); + } else { + m_yDataEntries.append(currentValue); + } + + m_xDataEntries.append(xValue); + + // Remove stale data + removeStaleData(); + return true; } else { - m_yDataEntries.append(currentValue); + // Enum markers + QString value = m_field->getValue(m_element).toString(); + + QwtPlotMarker *marker = m_enumMarkerList.isEmpty() ? NULL : m_enumMarkerList.last(); + if (!marker || marker->title() != value) { + marker = new QwtPlotMarker(value); + QwtText label(QString(" %1 ").arg(value)); + label.setColor(QColor(Qt::black)); + label.setBorderPen(QPen(QColor(Qt::black), 1)); + label.setBorderRadius(3); + QColor labelBackColor = QColor(Qt::white); + labelBackColor.setAlpha(160); + label.setBackgroundBrush(labelBackColor); + label.font().setPointSize(7); + marker->setLabel(label); + marker->setTitle(value); + marker->setLabelOrientation(Qt::Vertical); + marker->setLabelAlignment(Qt::AlignTop); + marker->setLineStyle(QwtPlotMarker::VLine); + marker->setXValue(xValue); + marker->setLinePen(QPen(m_pen.color(), 1, Qt::DashLine)); + if (m_plotCurve->isVisible()) { + marker->attach(plot); + } + m_enumMarkerList.append(marker); + } + removeStaleData(); } - - double valueX = NOW.toTime_t() + NOW.time().msec() / 1000.0; - m_xDataEntries.append(valueX); - - // Remove stale data - removeStaleData(); - return true; } return false; } @@ -171,4 +228,10 @@ void ChronoPlotData::removeStaleData() m_yDataEntries.pop_front(); m_xDataEntries.pop_front(); } + while (!m_enumMarkerList.isEmpty() && + (m_enumMarkerList.last()->xValue() - m_enumMarkerList.first()->xValue()) > m_plotDataSize) { + QwtPlotMarker* marker = m_enumMarkerList.takeFirst(); + marker->detach(); + delete marker; + } } diff --git a/ground/openpilotgcs/src/plugins/scope/plotdata.h b/ground/openpilotgcs/src/plugins/scope/plotdata.h index 4d974b1e6..603d7071f 100644 --- a/ground/openpilotgcs/src/plugins/scope/plotdata.h +++ b/ground/openpilotgcs/src/plugins/scope/plotdata.h @@ -35,6 +35,7 @@ #include "qwt/src/qwt_plot_curve.h" #include "qwt/src/qwt_scale_draw.h" #include "qwt/src/qwt_scale_widget.h" +#include #include #include @@ -64,10 +65,10 @@ public: int element() const { return m_element; } QString elementName() const { return m_elementName; } - bool isVisible() const { return m_plotCurve->isVisible(); } - void setVisible(bool visible) { return m_plotCurve->setVisible(visible); } + bool isVisible() const; + void setVisible(bool visible); - virtual bool append(UAVObject *obj) = 0; + virtual bool append(UAVObject *obj, QwtPlot* plot) = 0; virtual PlotType plotType() const = 0; virtual void removeStaleData() = 0; @@ -78,6 +79,9 @@ public: void attach(QwtPlot *plot); +public slots: + void visibilityChanged(QwtPlotItem *item); + protected: // This is the power to which each value must be raised int m_scalePower; @@ -96,12 +100,13 @@ protected: UAVObjectField *m_field; int m_element; QString m_elementName; - - virtual void calcMathFunction(double currentValue); - -private: QwtPlotCurve *m_plotCurve; QString m_plotName; + QList m_enumMarkerList; + bool m_isVisible; + QPen m_pen; + bool isEnumPlot; + virtual void calcMathFunction(double currentValue); }; /*! @@ -118,7 +123,7 @@ public: mathFunction, plotDataSize, pen, antialiased) {} ~SequentialPlotData() {} - bool append(UAVObject *obj); + bool append(UAVObject *obj, QwtPlot* plot); PlotType plotType() const { return SequentialPlot; } void removeStaleData() {} }; @@ -138,7 +143,7 @@ public: } ~ChronoPlotData() {} - bool append(UAVObject *obj); + bool append(UAVObject *obj, QwtPlot* plot); PlotType plotType() const { return ChronoPlot; } void removeStaleData(); }; diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp index 513ab5e06..fe080c984 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetoptionspage.cpp @@ -246,7 +246,7 @@ void ScopeGadgetOptionsPage::on_cmbUAVObjects_currentIndexChanged(QString val) } QList fieldList = obj->getFields(); foreach(UAVObjectField * field, fieldList) { - if (field->getType() == UAVObjectField::STRING || field->getType() == UAVObjectField::ENUM) { + if (field->getType() == UAVObjectField::STRING) { continue; } diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp index da129f3c4..a8838084b 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.cpp @@ -270,6 +270,7 @@ void ScopeGadgetWidget::showCurve(QVariant itemInfo, bool visible, int index) Q_UNUSED(index); QwtPlotItem *item = infoToItem(itemInfo); item->setVisible(!visible); + emit visibilityChanged(item); if (m_plotLegend) { QWidget *legendItem = legend()->find((WId)item); if (legendItem && legendItem->inherits("QwtLegendLabel")) { @@ -364,7 +365,7 @@ void ScopeGadgetWidget::addCurvePlot(QString objectName, QString fieldPlusSubFie meanSamples, mathFunction, m_plotDataSize, pen, antialiased); } - + connect(this, SIGNAL(visibilityChanged(QwtPlotItem*)), plotData, SLOT(visibilityChanged(QwtPlotItem*))); plotData->attach(this); // Keep the curve details for later @@ -384,7 +385,7 @@ void ScopeGadgetWidget::addCurvePlot(QString objectName, QString fieldPlusSubFie void ScopeGadgetWidget::uavObjectReceived(UAVObject *obj) { foreach(PlotData * plotData, m_curvesData.values()) { - if (plotData->append(obj)) { + if (plotData->append(obj, this)) { m_csvLoggingDataUpdated = 1; } } diff --git a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h index 60f72780e..10f8efbc0 100644 --- a/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/scope/scopegadgetwidget.h @@ -118,6 +118,8 @@ public: { m_csvLoggingPath = value; } +signals: + void visibilityChanged(QwtPlotItem *item); protected: void mousePressEvent(QMouseEvent *e);