mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-03-16 08:29:15 +01:00
OP-1554 Scope re-factoring to prepare for enum plot.
This commit is contained in:
parent
21820045a4
commit
b156f86de0
@ -30,35 +30,20 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
PlotData::PlotData(QString p_uavObject, QString p_uavField)
|
PlotData::PlotData(QString objectName, QString fieldName, QString elementName,
|
||||||
{
|
QwtPlotCurve *plotCurve, int scaleOrderFactor, int meanSamples,
|
||||||
uavObject = p_uavObject;
|
QString mathFunction, double plotDataSize) :
|
||||||
|
m_objectName(objectName), m_fieldName(fieldName), m_elementName(elementName),
|
||||||
|
m_plotCurve(plotCurve), m_scalePower(scaleOrderFactor), m_meanSamples(meanSamples),
|
||||||
|
m_mathFunction(mathFunction), m_plotDataSize(plotDataSize)
|
||||||
|
{
|
||||||
|
m_plotCurve->setSamples(xData, yData);
|
||||||
|
|
||||||
if (p_uavField.contains("-")) {
|
m_meanSum = 0.0f;
|
||||||
QStringList fieldSubfield = p_uavField.split("-", QString::SkipEmptyParts);
|
m_correctionSum = 0.0f;
|
||||||
uavField = fieldSubfield.at(0);
|
m_correctionCount = 0;
|
||||||
uavSubField = fieldSubfield.at(1);
|
m_yMin = 0;
|
||||||
haveSubField = true;
|
m_yMax = 0;
|
||||||
} else {
|
|
||||||
uavField = p_uavField;
|
|
||||||
haveSubField = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
xData = new QVector<double>();
|
|
||||||
yData = new QVector<double>();
|
|
||||||
yDataHistory = new QVector<double>();
|
|
||||||
|
|
||||||
curve = 0;
|
|
||||||
scalePower = 0;
|
|
||||||
meanSamples = 1;
|
|
||||||
meanSum = 0.0f;
|
|
||||||
// mathFunction=0;
|
|
||||||
correctionSum = 0.0f;
|
|
||||||
correctionCount = 0;
|
|
||||||
yMinimum = 0;
|
|
||||||
yMaximum = 0;
|
|
||||||
|
|
||||||
m_xWindowSize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
||||||
@ -66,8 +51,8 @@ double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
|||||||
Q_UNUSED(obj);
|
Q_UNUSED(obj);
|
||||||
QVariant value;
|
QVariant value;
|
||||||
|
|
||||||
if (haveSubField) {
|
if (!m_elementName.isEmpty()) {
|
||||||
int indexOfSubField = field->getElementNames().indexOf(QRegExp(uavSubField, Qt::CaseSensitive, QRegExp::FixedString));
|
int indexOfSubField = field->getElementNames().indexOf(QRegExp(elementName(), Qt::CaseSensitive, QRegExp::FixedString));
|
||||||
value = field->getValue(indexOfSubField);
|
value = field->getValue(indexOfSubField);
|
||||||
} else {
|
} else {
|
||||||
value = field->getValue();
|
value = field->getValue();
|
||||||
@ -80,66 +65,67 @@ double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
|||||||
|
|
||||||
PlotData::~PlotData()
|
PlotData::~PlotData()
|
||||||
{
|
{
|
||||||
delete xData;
|
m_plotCurve->detach();
|
||||||
delete yData;
|
delete m_plotCurve;
|
||||||
delete yDataHistory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlotData::updatePlotCurveData()
|
||||||
|
{
|
||||||
|
m_plotCurve->setSamples(xData, yData);
|
||||||
|
}
|
||||||
|
|
||||||
bool SequentialPlotData::append(UAVObject *obj)
|
bool SequentialPlotData::append(UAVObject *obj)
|
||||||
{
|
{
|
||||||
if (uavObject == obj->getName()) {
|
if (objectName() == obj->getName()) {
|
||||||
// Get the field of interest
|
// Get the field of interest
|
||||||
UAVObjectField *field = obj->getField(uavField);
|
UAVObjectField *field = obj->getField(fieldName());
|
||||||
|
|
||||||
if (field) {
|
if (field) {
|
||||||
double currentValue = valueAsDouble(obj, field) * pow(10, scalePower);
|
double currentValue = valueAsDouble(obj, field) * pow(10, m_scalePower);
|
||||||
|
|
||||||
// Perform scope math, if necessary
|
// Perform scope math, if necessary
|
||||||
if (mathFunction == "Boxcar average" || mathFunction == "Standard deviation") {
|
if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") {
|
||||||
// Put the new value at the front
|
// Put the new value at the front
|
||||||
yDataHistory->append(currentValue);
|
yDataHistory.append(currentValue);
|
||||||
|
|
||||||
// calculate average value
|
// calculate average value
|
||||||
meanSum += currentValue;
|
m_meanSum += currentValue;
|
||||||
if (yDataHistory->size() > meanSamples) {
|
if (yDataHistory.size() > m_meanSamples) {
|
||||||
meanSum -= yDataHistory->first();
|
m_meanSum -= yDataHistory.first();
|
||||||
yDataHistory->pop_front();
|
yDataHistory.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure to correct the sum every meanSamples steps to prevent it
|
// make sure to correct the sum every meanSamples steps to prevent it
|
||||||
// from running away due to floating point rounding errors
|
// from running away due to floating point rounding errors
|
||||||
correctionSum += currentValue;
|
m_correctionSum += currentValue;
|
||||||
if (++correctionCount >= meanSamples) {
|
if (++m_correctionCount >= m_meanSamples) {
|
||||||
meanSum = correctionSum;
|
m_meanSum = m_correctionSum;
|
||||||
correctionSum = 0.0f;
|
m_correctionSum = 0.0f;
|
||||||
correctionCount = 0;
|
m_correctionCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double boxcarAvg = meanSum / yDataHistory->size();
|
double boxcarAvg = m_meanSum / yDataHistory.size();
|
||||||
|
|
||||||
if (mathFunction == "Standard deviation") {
|
if (m_mathFunction == "Standard deviation") {
|
||||||
// Calculate square of sample standard deviation, with Bessel's correction
|
// Calculate square of sample standard deviation, with Bessel's correction
|
||||||
double stdSum = 0;
|
double stdSum = 0;
|
||||||
for (int i = 0; i < yDataHistory->size(); i++) {
|
for (int i = 0; i < yDataHistory.size(); i++) {
|
||||||
stdSum += pow(yDataHistory->at(i) - boxcarAvg, 2) / (meanSamples - 1);
|
stdSum += pow(yDataHistory.at(i) - boxcarAvg, 2) / (m_meanSamples - 1);
|
||||||
}
|
}
|
||||||
yData->append(sqrt(stdSum));
|
yData.append(sqrt(stdSum));
|
||||||
} else {
|
} else {
|
||||||
yData->append(boxcarAvg);
|
yData.append(boxcarAvg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yData->append(currentValue);
|
yData.append(currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yData->size() > m_xWindowSize) { // If new data overflows the window, remove old data...
|
if (yData.size() > m_plotDataSize) { // If new data overflows the window, remove old data...
|
||||||
yData->pop_front();
|
yData.pop_front();
|
||||||
} else { // ...otherwise, add a new y point at position xData
|
} else { // ...otherwise, add a new y point at position xData
|
||||||
xData->insert(xData->size(), xData->size());
|
xData.insert(xData.size(), xData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// notify the gui of changes in the data
|
|
||||||
// dataChanged();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,61 +135,58 @@ bool SequentialPlotData::append(UAVObject *obj)
|
|||||||
|
|
||||||
bool ChronoPlotData::append(UAVObject *obj)
|
bool ChronoPlotData::append(UAVObject *obj)
|
||||||
{
|
{
|
||||||
if (uavObject == obj->getName()) {
|
if (objectName() == obj->getName()) {
|
||||||
// Get the field of interest
|
// Get the field of interest
|
||||||
UAVObjectField *field = obj->getField(uavField);
|
UAVObjectField *field = obj->getField(fieldName());
|
||||||
// qDebug() << "uavObject: " << uavObject << ", uavField: " << uavField;
|
// qDebug() << "uavObject: " << uavObject << ", uavField: " << uavField;
|
||||||
|
|
||||||
if (field) {
|
if (field) {
|
||||||
QDateTime NOW = QDateTime::currentDateTime(); // THINK ABOUT REIMPLEMENTING THIS TO SHOW UAVO TIME, NOT SYSTEM TIME
|
QDateTime NOW = QDateTime::currentDateTime(); // THINK ABOUT REIMPLEMENTING THIS TO SHOW UAVO TIME, NOT SYSTEM TIME
|
||||||
double currentValue = valueAsDouble(obj, field) * pow(10, scalePower);
|
double currentValue = valueAsDouble(obj, field) * pow(10, m_scalePower);
|
||||||
|
|
||||||
// Perform scope math, if necessary
|
// Perform scope math, if necessary
|
||||||
if (mathFunction == "Boxcar average" || mathFunction == "Standard deviation") {
|
if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") {
|
||||||
// Put the new value at the back
|
// Put the new value at the back
|
||||||
yDataHistory->append(currentValue);
|
yDataHistory.append(currentValue);
|
||||||
|
|
||||||
// calculate average value
|
// calculate average value
|
||||||
meanSum += currentValue;
|
m_meanSum += currentValue;
|
||||||
if (yDataHistory->size() > meanSamples) {
|
if (yDataHistory.size() > m_meanSamples) {
|
||||||
meanSum -= yDataHistory->first();
|
m_meanSum -= yDataHistory.first();
|
||||||
yDataHistory->pop_front();
|
yDataHistory.pop_front();
|
||||||
}
|
}
|
||||||
// make sure to correct the sum every meanSamples steps to prevent it
|
// make sure to correct the sum every meanSamples steps to prevent it
|
||||||
// from running away due to floating point rounding errors
|
// from running away due to floating point rounding errors
|
||||||
correctionSum += currentValue;
|
m_correctionSum += currentValue;
|
||||||
if (++correctionCount >= meanSamples) {
|
if (++m_correctionCount >= m_meanSamples) {
|
||||||
meanSum = correctionSum;
|
m_meanSum = m_correctionSum;
|
||||||
correctionSum = 0.0f;
|
m_correctionSum = 0.0f;
|
||||||
correctionCount = 0;
|
m_correctionCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double boxcarAvg = meanSum / yDataHistory->size();
|
double boxcarAvg = m_meanSum / yDataHistory.size();
|
||||||
// qDebug()<<mathFunction;
|
// qDebug()<<mathFunction;
|
||||||
if (mathFunction == "Standard deviation") {
|
if (m_mathFunction == "Standard deviation") {
|
||||||
// Calculate square of sample standard deviation, with Bessel's correction
|
// Calculate square of sample standard deviation, with Bessel's correction
|
||||||
double stdSum = 0;
|
double stdSum = 0;
|
||||||
for (int i = 0; i < yDataHistory->size(); i++) {
|
for (int i = 0; i < yDataHistory.size(); i++) {
|
||||||
stdSum += pow(yDataHistory->at(i) - boxcarAvg, 2) / (meanSamples - 1);
|
stdSum += pow(yDataHistory.at(i) - boxcarAvg, 2) / (m_meanSamples - 1);
|
||||||
}
|
}
|
||||||
yData->append(sqrt(stdSum));
|
yData.append(sqrt(stdSum));
|
||||||
} else {
|
} else {
|
||||||
yData->append(boxcarAvg);
|
yData.append(boxcarAvg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yData->append(currentValue);
|
yData.append(currentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
double valueX = NOW.toTime_t() + NOW.time().msec() / 1000.0;
|
double valueX = NOW.toTime_t() + NOW.time().msec() / 1000.0;
|
||||||
xData->append(valueX);
|
xData.append(valueX);
|
||||||
|
|
||||||
// qDebug() << "Data " << uavObject << "." << field->getName() << " X,Y:" << valueX << "," << valueY;
|
// qDebug() << "Data " << uavObject << "." << field->getName() << " X,Y:" << valueX << "," << valueY;
|
||||||
|
|
||||||
// Remove stale data
|
// Remove stale data
|
||||||
removeStaleData();
|
removeStaleData();
|
||||||
|
|
||||||
// notify the gui of chages in the data
|
|
||||||
// dataChanged();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,16 +200,16 @@ void ChronoPlotData::removeStaleData()
|
|||||||
double oldestValue;
|
double oldestValue;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (xData->size() == 0) {
|
if (xData.size() == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
newestValue = xData->last();
|
newestValue = xData.last();
|
||||||
oldestValue = xData->first();
|
oldestValue = xData.first();
|
||||||
|
|
||||||
if (newestValue - oldestValue > m_xWindowSize) {
|
if (newestValue - oldestValue > m_plotDataSize) {
|
||||||
yData->pop_front();
|
yData.pop_front();
|
||||||
xData->pop_front();
|
xData.pop_front();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -238,12 +221,5 @@ void ChronoPlotData::removeStaleData()
|
|||||||
void ChronoPlotData::removeStaleDataTimeout()
|
void ChronoPlotData::removeStaleDataTimeout()
|
||||||
{
|
{
|
||||||
removeStaleData();
|
removeStaleData();
|
||||||
// dataChanged();
|
|
||||||
// qDebug() << "removeStaleDataTimeout";
|
// qDebug() << "removeStaleDataTimeout";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UAVObjectPlotData::append(UAVObject *obj)
|
|
||||||
{
|
|
||||||
Q_UNUSED(obj);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
@ -43,13 +43,7 @@
|
|||||||
/*!
|
/*!
|
||||||
\brief Defines the different type of plots.
|
\brief Defines the different type of plots.
|
||||||
*/
|
*/
|
||||||
enum PlotType {
|
enum PlotType {SequentialPlot, ChronoPlot};
|
||||||
SequentialPlot,
|
|
||||||
ChronoPlot,
|
|
||||||
UAVObjectPlot,
|
|
||||||
|
|
||||||
NPlotTypes
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\brief Base class that keeps the data for each curve in the plot.
|
\brief Base class that keeps the data for each curve in the plot.
|
||||||
@ -58,29 +52,26 @@ class PlotData : public QObject {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlotData(QString uavObject, QString uavField);
|
PlotData(QString objectName, QString fieldName, QString elementName,
|
||||||
|
QwtPlotCurve *plotCurve, int scaleOrderFactor, int meanSamples,
|
||||||
|
QString mathFunction, double plotDataSize);
|
||||||
~PlotData();
|
~PlotData();
|
||||||
|
|
||||||
QString uavObject;
|
QVector<double> xData;
|
||||||
QString uavField;
|
QVector<double> yData;
|
||||||
QString uavSubField;
|
QVector<double> yDataHistory;
|
||||||
bool haveSubField;
|
|
||||||
int scalePower; // This is the power to which each value must be raised
|
QString objectName() const { return m_objectName; }
|
||||||
int meanSamples;
|
QString fieldName() const { return m_fieldName; }
|
||||||
double meanSum;
|
QString elementName() const { return m_elementName; }
|
||||||
QString mathFunction;
|
|
||||||
double correctionSum;
|
bool isVisible() const { return m_plotCurve->isVisible(); }
|
||||||
int correctionCount;
|
|
||||||
double yMinimum;
|
double yMin() const { return m_yMin;}
|
||||||
double yMaximum;
|
double yMax() const { return m_yMax;}
|
||||||
double m_xWindowSize;
|
|
||||||
QwtPlotCurve *curve;
|
|
||||||
QVector<double> *xData;
|
|
||||||
QVector<double> *yData;
|
|
||||||
QVector<double> *yDataHistory;
|
|
||||||
|
|
||||||
virtual bool append(UAVObject *obj) = 0;
|
virtual bool append(UAVObject *obj) = 0;
|
||||||
virtual PlotType plotType() = 0;
|
virtual PlotType plotType() const = 0;
|
||||||
virtual void removeStaleData() = 0;
|
virtual void removeStaleData() = 0;
|
||||||
|
|
||||||
void updatePlotCurveData();
|
void updatePlotCurveData();
|
||||||
@ -88,8 +79,22 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
double valueAsDouble(UAVObject *obj, UAVObjectField *field);
|
double valueAsDouble(UAVObject *obj, UAVObjectField *field);
|
||||||
|
|
||||||
signals:
|
int m_scalePower; // This is the power to which each value must be raised
|
||||||
void dataChanged();
|
int m_meanSamples;
|
||||||
|
double m_meanSum;
|
||||||
|
QString m_mathFunction;
|
||||||
|
double m_correctionSum;
|
||||||
|
int m_correctionCount;
|
||||||
|
double m_plotDataSize;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_objectName;
|
||||||
|
QString m_fieldName;
|
||||||
|
QString m_elementName;
|
||||||
|
double m_yMin;
|
||||||
|
double m_yMax;
|
||||||
|
QwtPlotCurve *m_plotCurve;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -99,8 +104,10 @@ signals:
|
|||||||
class SequentialPlotData : public PlotData {
|
class SequentialPlotData : public PlotData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SequentialPlotData(QString uavObject, QString uavField)
|
SequentialPlotData(QString objectName, QString fieldName, QString elementName,
|
||||||
: PlotData(uavObject, uavField) {}
|
QwtPlotCurve *plotCurve, int scaleFactor, int meanSamples,
|
||||||
|
QString mathFunction, double plotDataSize)
|
||||||
|
: PlotData(objectName, fieldName, elementName, plotCurve, scaleFactor, meanSamples, mathFunction, plotDataSize) {}
|
||||||
~SequentialPlotData() {}
|
~SequentialPlotData() {}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -111,7 +118,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\brief The type of plot
|
\brief The type of plot
|
||||||
*/
|
*/
|
||||||
virtual PlotType plotType()
|
PlotType plotType() const
|
||||||
{
|
{
|
||||||
return SequentialPlot;
|
return SequentialPlot;
|
||||||
}
|
}
|
||||||
@ -119,7 +126,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\brief Removes the old data from the buffer
|
\brief Removes the old data from the buffer
|
||||||
*/
|
*/
|
||||||
virtual void removeStaleData() {}
|
void removeStaleData() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -128,47 +135,25 @@ public:
|
|||||||
class ChronoPlotData : public PlotData {
|
class ChronoPlotData : public PlotData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ChronoPlotData(QString uavObject, QString uavField)
|
ChronoPlotData(QString objectname, QString fieldname, QString elementName,
|
||||||
: PlotData(uavObject, uavField)
|
QwtPlotCurve *plotCurve, int scaleFactor, int meanSamples,
|
||||||
|
QString mathFunction, double plotDataSize)
|
||||||
|
: PlotData(objectname, fieldname, elementName, plotCurve, scaleFactor, meanSamples, mathFunction, plotDataSize)
|
||||||
{
|
{
|
||||||
scalePower = 1;
|
|
||||||
}
|
}
|
||||||
~ChronoPlotData() {}
|
~ChronoPlotData() {}
|
||||||
|
|
||||||
bool append(UAVObject *obj);
|
bool append(UAVObject *obj);
|
||||||
|
|
||||||
virtual PlotType plotType()
|
PlotType plotType() const
|
||||||
{
|
{
|
||||||
return ChronoPlot;
|
return ChronoPlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void removeStaleData();
|
void removeStaleData();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void removeStaleDataTimeout();
|
void removeStaleDataTimeout();
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
|
||||||
\brief UAVObject plot use a fixed size buffer of data, where the horizontal axis values come from
|
|
||||||
a UAVObject field.
|
|
||||||
*/
|
|
||||||
class UAVObjectPlotData : public PlotData {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
UAVObjectPlotData(QString uavObject, QString uavField)
|
|
||||||
: PlotData(uavObject, uavField) {}
|
|
||||||
~UAVObjectPlotData() {}
|
|
||||||
|
|
||||||
bool append(UAVObject *obj);
|
|
||||||
|
|
||||||
virtual PlotType plotType()
|
|
||||||
{
|
|
||||||
return UAVObjectPlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void removeStaleData() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PLOTDATA_H
|
#endif // PLOTDATA_H
|
||||||
|
@ -40,7 +40,7 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration *config)
|
|||||||
ScopeGadgetConfiguration *sgConfig = qobject_cast<ScopeGadgetConfiguration *>(config);
|
ScopeGadgetConfiguration *sgConfig = qobject_cast<ScopeGadgetConfiguration *>(config);
|
||||||
ScopeGadgetWidget *widget = qobject_cast<ScopeGadgetWidget *>(m_widget);
|
ScopeGadgetWidget *widget = qobject_cast<ScopeGadgetWidget *>(m_widget);
|
||||||
|
|
||||||
widget->setXWindowSize(sgConfig->dataSize());
|
widget->setPlotDataSize(sgConfig->dataSize());
|
||||||
widget->setRefreshInterval(sgConfig->refreshInterval());
|
widget->setRefreshInterval(sgConfig->refreshInterval());
|
||||||
|
|
||||||
if (sgConfig->plotType() == SequentialPlot) {
|
if (sgConfig->plotType() == SequentialPlot) {
|
||||||
|
@ -299,7 +299,7 @@ void ScopeGadgetWidget::setupSequentialPlot()
|
|||||||
//// setAxisTitle(QwtPlot::xBottom, "Index");
|
//// setAxisTitle(QwtPlot::xBottom, "Index");
|
||||||
|
|
||||||
setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw());
|
setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw());
|
||||||
setAxisScale(QwtPlot::xBottom, 0, m_xWindowSize);
|
setAxisScale(QwtPlot::xBottom, 0, m_plotDataSize);
|
||||||
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
||||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
|
|
||||||
@ -327,7 +327,7 @@ void ScopeGadgetWidget::setupChronoPlot()
|
|||||||
|
|
||||||
setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw());
|
setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw());
|
||||||
uint NOW = QDateTime::currentDateTime().toTime_t();
|
uint NOW = QDateTime::currentDateTime().toTime_t();
|
||||||
setAxisScale(QwtPlot::xBottom, NOW - m_xWindowSize / 1000, NOW);
|
setAxisScale(QwtPlot::xBottom, NOW - m_plotDataSize / 1000, NOW);
|
||||||
// setAxisLabelRotation(QwtPlot::xBottom, -15.0);
|
// setAxisLabelRotation(QwtPlot::xBottom, -15.0);
|
||||||
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
||||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
@ -371,45 +371,34 @@ void ScopeGadgetWidget::setupChronoPlot()
|
|||||||
// scaleWidget->setMinBorderDist(0, fmw);
|
// scaleWidget->setMinBorderDist(0, fmw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor, int meanSamples, QString mathFunction, QPen pen, bool antialiased)
|
void ScopeGadgetWidget::addCurvePlot(QString objectName, QString fieldPlusSubField, int scaleFactor, int meanSamples, QString mathFunction, QPen pen, bool antialiased)
|
||||||
{
|
{
|
||||||
PlotData *plotData;
|
QString fieldName = fieldPlusSubField;
|
||||||
|
QString elementName;
|
||||||
if (m_plotType == SequentialPlot) {
|
if (fieldPlusSubField.contains("-")) {
|
||||||
plotData = new SequentialPlotData(uavObject, uavFieldSubField);
|
QStringList fieldSubfield = fieldName.split("-", QString::SkipEmptyParts);
|
||||||
} else if (m_plotType == ChronoPlot) {
|
fieldName = fieldSubfield.at(0);
|
||||||
plotData = new ChronoPlotData(uavObject, uavFieldSubField);
|
elementName = fieldSubfield.at(1);
|
||||||
}
|
|
||||||
// else if (m_plotType == UAVObjectPlot)
|
|
||||||
// plotData = new UAVObjectPlotData(uavObject, uavField);
|
|
||||||
|
|
||||||
plotData->m_xWindowSize = m_xWindowSize;
|
|
||||||
plotData->scalePower = scaleOrderFactor;
|
|
||||||
plotData->meanSamples = meanSamples;
|
|
||||||
plotData->mathFunction = mathFunction;
|
|
||||||
|
|
||||||
// If the y-bounds are supplied, set them
|
|
||||||
if (plotData->yMinimum != plotData->yMaximum) {
|
|
||||||
setAxisScale(QwtPlot::yLeft, plotData->yMinimum, plotData->yMaximum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the curve
|
// Create the curve
|
||||||
QString curveName = (plotData->uavObject) + "." + (plotData->uavField);
|
QString curveName = objectName + "." + fieldName;
|
||||||
if (plotData->haveSubField) {
|
if (!elementName.isEmpty()) {
|
||||||
curveName = curveName.append("." + plotData->uavSubField);
|
curveName.append("." + elementName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the uav object
|
// Get the uav object
|
||||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||||
UAVDataObject *obj = dynamic_cast<UAVDataObject *>(objManager->getObject((plotData->uavObject)));
|
UAVDataObject *obj = dynamic_cast<UAVDataObject *>(objManager->getObject(objectName));
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
qDebug() << "Object " << plotData->uavObject << " is missing";
|
qDebug() << "Object " << objectName << " is missing";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UAVObjectField *field = obj->getField(plotData->uavField);
|
UAVObjectField *field = obj->getField(fieldName);
|
||||||
if (!field) {
|
if (!field) {
|
||||||
qDebug() << "In scope gadget, in fields loaded from GCS config file, field" << plotData->uavField << " of object " << plotData->uavObject << " is missing";
|
qDebug() << "In scope gadget, in fields loaded from GCS config file, field" <<
|
||||||
|
fieldName << " of object " << objectName << " is missing";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString units = field->getUnits();
|
QString units = field->getUnits();
|
||||||
@ -419,10 +408,10 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString curveNameScaled;
|
QString curveNameScaled;
|
||||||
if (scaleOrderFactor == 0) {
|
if (scaleFactor == 0) {
|
||||||
curveNameScaled = curveName + " (" + units + ")";
|
curveNameScaled = curveName + " (" + units + ")";
|
||||||
} else {
|
} else {
|
||||||
curveNameScaled = curveName + " (x10^" + QString::number(scaleOrderFactor) + " " + units + ")";
|
curveNameScaled = curveName + " (x10^" + QString::number(scaleFactor) + " " + units + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
QwtPlotCurve *plotCurve = new QwtPlotCurve(curveNameScaled);
|
QwtPlotCurve *plotCurve = new QwtPlotCurve(curveNameScaled);
|
||||||
@ -432,9 +421,22 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
|||||||
}
|
}
|
||||||
|
|
||||||
plotCurve->setPen(pen);
|
plotCurve->setPen(pen);
|
||||||
plotCurve->setSamples(*plotData->xData, *plotData->yData);
|
|
||||||
plotCurve->attach(this);
|
plotCurve->attach(this);
|
||||||
plotData->curve = plotCurve;
|
|
||||||
|
PlotData *plotData;
|
||||||
|
|
||||||
|
if (m_plotType == SequentialPlot) {
|
||||||
|
plotData = new SequentialPlotData(objectName, fieldName, elementName, plotCurve, scaleFactor,
|
||||||
|
meanSamples, mathFunction, m_plotDataSize);
|
||||||
|
} else if (m_plotType == ChronoPlot) {
|
||||||
|
plotData = new ChronoPlotData(objectName, fieldName, elementName, plotCurve, scaleFactor,
|
||||||
|
meanSamples, mathFunction, m_plotDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the y-bounds are supplied, set them
|
||||||
|
if (plotData->yMin() != plotData->yMax()) {
|
||||||
|
setAxisScale(QwtPlot::yLeft, plotData->yMin(), plotData->yMax());
|
||||||
|
}
|
||||||
|
|
||||||
// Keep the curve details for later
|
// Keep the curve details for later
|
||||||
m_curvesData.insert(curveNameScaled, plotData);
|
m_curvesData.insert(curveNameScaled, plotData);
|
||||||
@ -450,22 +452,6 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
|||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// void ScopeGadgetWidget::removeCurvePlot(QString uavObject, QString uavField)
|
|
||||||
// {
|
|
||||||
// QString curveName = uavObject + "." + uavField;
|
|
||||||
//
|
|
||||||
// PlotData* plotData = m_curvesData.take(curveName);
|
|
||||||
// m_curvesData.remove(curveName);
|
|
||||||
// plotData->curve->detach();
|
|
||||||
//
|
|
||||||
// delete plotData->curve;
|
|
||||||
// delete plotData;
|
|
||||||
//
|
|
||||||
// mutex.lock();
|
|
||||||
// replot();
|
|
||||||
// mutex.unlock();
|
|
||||||
// }
|
|
||||||
|
|
||||||
void ScopeGadgetWidget::uavObjectReceived(UAVObject *obj)
|
void ScopeGadgetWidget::uavObjectReceived(UAVObject *obj)
|
||||||
{
|
{
|
||||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||||
@ -485,14 +471,14 @@ void ScopeGadgetWidget::replotNewData()
|
|||||||
QMutexLocker locker(&mutex);
|
QMutexLocker locker(&mutex);
|
||||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||||
plotData->removeStaleData();
|
plotData->removeStaleData();
|
||||||
plotData->curve->setSamples(*plotData->xData, *plotData->yData);
|
plotData->updatePlotCurveData();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime NOW = QDateTime::currentDateTime();
|
QDateTime NOW = QDateTime::currentDateTime();
|
||||||
double toTime = NOW.toTime_t();
|
double toTime = NOW.toTime_t();
|
||||||
toTime += NOW.time().msec() / 1000.0;
|
toTime += NOW.time().msec() / 1000.0;
|
||||||
if (m_plotType == ChronoPlot) {
|
if (m_plotType == ChronoPlot) {
|
||||||
setAxisScale(QwtPlot::xBottom, toTime - m_xWindowSize, toTime);
|
setAxisScale(QwtPlot::xBottom, toTime - m_plotDataSize, toTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// qDebug() << "replotNewData from " << NOW.addSecs(- m_xWindowSize) << " to " << NOW;
|
// qDebug() << "replotNewData from " << NOW.addSecs(- m_xWindowSize) << " to " << NOW;
|
||||||
@ -505,9 +491,6 @@ void ScopeGadgetWidget::replotNewData()
|
|||||||
void ScopeGadgetWidget::clearCurvePlots()
|
void ScopeGadgetWidget::clearCurvePlots()
|
||||||
{
|
{
|
||||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||||
plotData->curve->detach();
|
|
||||||
|
|
||||||
delete plotData->curve;
|
|
||||||
delete plotData;
|
delete plotData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,11 +499,12 @@ void ScopeGadgetWidget::clearCurvePlots()
|
|||||||
|
|
||||||
void ScopeGadgetWidget::saveState(QSettings *qSettings)
|
void ScopeGadgetWidget::saveState(QSettings *qSettings)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
// plot state
|
// plot state
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||||
bool plotVisible = plotData->curve->isVisible();
|
bool plotVisible = plotData->isVisible();
|
||||||
|
|
||||||
if (!plotVisible) {
|
if (!plotVisible) {
|
||||||
qSettings->setValue(QString("plot%1").arg(i), plotVisible);
|
qSettings->setValue(QString("plot%1").arg(i), plotVisible);
|
||||||
@ -529,17 +513,19 @@ void ScopeGadgetWidget::saveState(QSettings *qSettings)
|
|||||||
}
|
}
|
||||||
// legend state
|
// legend state
|
||||||
qSettings->setValue("legendVisible", legend() != NULL);
|
qSettings->setValue("legendVisible", legend() != NULL);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopeGadgetWidget::restoreState(QSettings *qSettings)
|
void ScopeGadgetWidget::restoreState(QSettings *qSettings)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
// plot state
|
// plot state
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||||
bool visible = qSettings->value(QString("plot%1").arg(i), true).toBool();
|
bool visible = qSettings->value(QString("plot%1").arg(i), true).toBool();
|
||||||
|
|
||||||
showCurve(plotData->curve, !visible);
|
showCurve(plotData->m_plotCurve, !visible);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
// legend state
|
// legend state
|
||||||
@ -549,6 +535,7 @@ void ScopeGadgetWidget::restoreState(QSettings *qSettings)
|
|||||||
} else {
|
} else {
|
||||||
deleteLegend();
|
deleteLegend();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -621,10 +608,10 @@ int ScopeGadgetWidget::csvLoggingInsertHeader()
|
|||||||
|
|
||||||
foreach(PlotData * plotData2, m_curvesData.values()) {
|
foreach(PlotData * plotData2, m_curvesData.values()) {
|
||||||
ts << ", ";
|
ts << ", ";
|
||||||
ts << plotData2->uavObject;
|
ts << plotData2->objectName();
|
||||||
ts << "." << plotData2->uavField;
|
ts << "." << plotData2->fieldName();
|
||||||
if (plotData2->haveSubField) {
|
if (!plotData2->elementName().isEmpty()) {
|
||||||
ts << "." << plotData2->uavSubField;
|
ts << "." << plotData2->elementName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ts << endl;
|
ts << endl;
|
||||||
@ -655,14 +642,14 @@ int ScopeGadgetWidget::csvLoggingAddData()
|
|||||||
|
|
||||||
foreach(PlotData * plotData2, m_curvesData.values()) {
|
foreach(PlotData * plotData2, m_curvesData.values()) {
|
||||||
ss << ", ";
|
ss << ", ";
|
||||||
if (plotData2->xData->isEmpty()) {
|
if (plotData2->xData.isEmpty()) {
|
||||||
ss << ", ";
|
ss << ", ";
|
||||||
if (plotData2->xData->isEmpty()) {} else {
|
if (plotData2->xData.isEmpty()) {} else {
|
||||||
ss << QString().sprintf("%3.10g", plotData2->yData->last());
|
ss << QString().sprintf("%3.10g", plotData2->yData.last());
|
||||||
m_csvLoggingDataValid = 1;
|
m_csvLoggingDataValid = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ss << QString().sprintf("%3.10g", plotData2->yData->last());
|
ss << QString().sprintf("%3.10g", plotData2->yData.last());
|
||||||
m_csvLoggingDataValid = 1;
|
m_csvLoggingDataValid = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,13 +76,13 @@ public:
|
|||||||
return m_plotType;
|
return m_plotType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setXWindowSize(double xWindowSize)
|
void setPlotDataSize(double plotDataSize)
|
||||||
{
|
{
|
||||||
m_xWindowSize = xWindowSize;
|
m_plotDataSize = plotDataSize;
|
||||||
}
|
}
|
||||||
double xWindowSize()
|
double plotDataSize()
|
||||||
{
|
{
|
||||||
return m_xWindowSize;
|
return m_plotDataSize;
|
||||||
}
|
}
|
||||||
void setRefreshInterval(double refreshInterval)
|
void setRefreshInterval(double refreshInterval)
|
||||||
{
|
{
|
||||||
@ -142,7 +142,7 @@ private:
|
|||||||
|
|
||||||
PlotType m_plotType;
|
PlotType m_plotType;
|
||||||
|
|
||||||
double m_xWindowSize;
|
double m_plotDataSize;
|
||||||
int m_refreshInterval;
|
int m_refreshInterval;
|
||||||
QList<QString> m_connectedUAVObjects;
|
QList<QString> m_connectedUAVObjects;
|
||||||
QMap<QString, PlotData *> m_curvesData;
|
QMap<QString, PlotData *> m_curvesData;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user