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 <QDebug>
|
||||
|
||||
PlotData::PlotData(QString p_uavObject, QString p_uavField)
|
||||
PlotData::PlotData(QString objectName, QString fieldName, QString elementName,
|
||||
QwtPlotCurve *plotCurve, int scaleOrderFactor, int meanSamples,
|
||||
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)
|
||||
{
|
||||
uavObject = p_uavObject;
|
||||
m_plotCurve->setSamples(xData, yData);
|
||||
|
||||
if (p_uavField.contains("-")) {
|
||||
QStringList fieldSubfield = p_uavField.split("-", QString::SkipEmptyParts);
|
||||
uavField = fieldSubfield.at(0);
|
||||
uavSubField = fieldSubfield.at(1);
|
||||
haveSubField = true;
|
||||
} 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;
|
||||
m_meanSum = 0.0f;
|
||||
m_correctionSum = 0.0f;
|
||||
m_correctionCount = 0;
|
||||
m_yMin = 0;
|
||||
m_yMax = 0;
|
||||
}
|
||||
|
||||
double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
||||
@ -66,8 +51,8 @@ double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
||||
Q_UNUSED(obj);
|
||||
QVariant value;
|
||||
|
||||
if (haveSubField) {
|
||||
int indexOfSubField = field->getElementNames().indexOf(QRegExp(uavSubField, Qt::CaseSensitive, QRegExp::FixedString));
|
||||
if (!m_elementName.isEmpty()) {
|
||||
int indexOfSubField = field->getElementNames().indexOf(QRegExp(elementName(), Qt::CaseSensitive, QRegExp::FixedString));
|
||||
value = field->getValue(indexOfSubField);
|
||||
} else {
|
||||
value = field->getValue();
|
||||
@ -80,66 +65,67 @@ double PlotData::valueAsDouble(UAVObject *obj, UAVObjectField *field)
|
||||
|
||||
PlotData::~PlotData()
|
||||
{
|
||||
delete xData;
|
||||
delete yData;
|
||||
delete yDataHistory;
|
||||
m_plotCurve->detach();
|
||||
delete m_plotCurve;
|
||||
}
|
||||
|
||||
void PlotData::updatePlotCurveData()
|
||||
{
|
||||
m_plotCurve->setSamples(xData, yData);
|
||||
}
|
||||
|
||||
bool SequentialPlotData::append(UAVObject *obj)
|
||||
{
|
||||
if (uavObject == obj->getName()) {
|
||||
if (objectName() == obj->getName()) {
|
||||
// Get the field of interest
|
||||
UAVObjectField *field = obj->getField(uavField);
|
||||
UAVObjectField *field = obj->getField(fieldName());
|
||||
|
||||
if (field) {
|
||||
double currentValue = valueAsDouble(obj, field) * pow(10, scalePower);
|
||||
double currentValue = valueAsDouble(obj, field) * pow(10, m_scalePower);
|
||||
|
||||
// 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
|
||||
yDataHistory->append(currentValue);
|
||||
yDataHistory.append(currentValue);
|
||||
|
||||
// calculate average value
|
||||
meanSum += currentValue;
|
||||
if (yDataHistory->size() > meanSamples) {
|
||||
meanSum -= yDataHistory->first();
|
||||
yDataHistory->pop_front();
|
||||
m_meanSum += currentValue;
|
||||
if (yDataHistory.size() > m_meanSamples) {
|
||||
m_meanSum -= yDataHistory.first();
|
||||
yDataHistory.pop_front();
|
||||
}
|
||||
|
||||
// make sure to correct the sum every meanSamples steps to prevent it
|
||||
// from running away due to floating point rounding errors
|
||||
correctionSum += currentValue;
|
||||
if (++correctionCount >= meanSamples) {
|
||||
meanSum = correctionSum;
|
||||
correctionSum = 0.0f;
|
||||
correctionCount = 0;
|
||||
m_correctionSum += currentValue;
|
||||
if (++m_correctionCount >= m_meanSamples) {
|
||||
m_meanSum = m_correctionSum;
|
||||
m_correctionSum = 0.0f;
|
||||
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
|
||||
double stdSum = 0;
|
||||
for (int i = 0; i < yDataHistory->size(); i++) {
|
||||
stdSum += pow(yDataHistory->at(i) - boxcarAvg, 2) / (meanSamples - 1);
|
||||
for (int i = 0; i < yDataHistory.size(); i++) {
|
||||
stdSum += pow(yDataHistory.at(i) - boxcarAvg, 2) / (m_meanSamples - 1);
|
||||
}
|
||||
yData->append(sqrt(stdSum));
|
||||
yData.append(sqrt(stdSum));
|
||||
} else {
|
||||
yData->append(boxcarAvg);
|
||||
yData.append(boxcarAvg);
|
||||
}
|
||||
} else {
|
||||
yData->append(currentValue);
|
||||
yData.append(currentValue);
|
||||
}
|
||||
|
||||
if (yData->size() > m_xWindowSize) { // If new data overflows the window, remove old data...
|
||||
yData->pop_front();
|
||||
if (yData.size() > m_plotDataSize) { // If new data overflows the window, remove old data...
|
||||
yData.pop_front();
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -149,61 +135,58 @@ bool SequentialPlotData::append(UAVObject *obj)
|
||||
|
||||
bool ChronoPlotData::append(UAVObject *obj)
|
||||
{
|
||||
if (uavObject == obj->getName()) {
|
||||
if (objectName() == obj->getName()) {
|
||||
// Get the field of interest
|
||||
UAVObjectField *field = obj->getField(uavField);
|
||||
UAVObjectField *field = obj->getField(fieldName());
|
||||
// qDebug() << "uavObject: " << uavObject << ", uavField: " << uavField;
|
||||
|
||||
if (field) {
|
||||
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
|
||||
if (mathFunction == "Boxcar average" || mathFunction == "Standard deviation") {
|
||||
if (m_mathFunction == "Boxcar average" || m_mathFunction == "Standard deviation") {
|
||||
// Put the new value at the back
|
||||
yDataHistory->append(currentValue);
|
||||
yDataHistory.append(currentValue);
|
||||
|
||||
// calculate average value
|
||||
meanSum += currentValue;
|
||||
if (yDataHistory->size() > meanSamples) {
|
||||
meanSum -= yDataHistory->first();
|
||||
yDataHistory->pop_front();
|
||||
m_meanSum += currentValue;
|
||||
if (yDataHistory.size() > m_meanSamples) {
|
||||
m_meanSum -= yDataHistory.first();
|
||||
yDataHistory.pop_front();
|
||||
}
|
||||
// make sure to correct the sum every meanSamples steps to prevent it
|
||||
// from running away due to floating point rounding errors
|
||||
correctionSum += currentValue;
|
||||
if (++correctionCount >= meanSamples) {
|
||||
meanSum = correctionSum;
|
||||
correctionSum = 0.0f;
|
||||
correctionCount = 0;
|
||||
m_correctionSum += currentValue;
|
||||
if (++m_correctionCount >= m_meanSamples) {
|
||||
m_meanSum = m_correctionSum;
|
||||
m_correctionSum = 0.0f;
|
||||
m_correctionCount = 0;
|
||||
}
|
||||
|
||||
double boxcarAvg = meanSum / yDataHistory->size();
|
||||
// qDebug()<<mathFunction;
|
||||
if (mathFunction == "Standard deviation") {
|
||||
double boxcarAvg = m_meanSum / yDataHistory.size();
|
||||
// qDebug()<<mathFunction;
|
||||
if (m_mathFunction == "Standard deviation") {
|
||||
// Calculate square of sample standard deviation, with Bessel's correction
|
||||
double stdSum = 0;
|
||||
for (int i = 0; i < yDataHistory->size(); i++) {
|
||||
stdSum += pow(yDataHistory->at(i) - boxcarAvg, 2) / (meanSamples - 1);
|
||||
for (int i = 0; i < yDataHistory.size(); i++) {
|
||||
stdSum += pow(yDataHistory.at(i) - boxcarAvg, 2) / (m_meanSamples - 1);
|
||||
}
|
||||
yData->append(sqrt(stdSum));
|
||||
yData.append(sqrt(stdSum));
|
||||
} else {
|
||||
yData->append(boxcarAvg);
|
||||
yData.append(boxcarAvg);
|
||||
}
|
||||
} else {
|
||||
yData->append(currentValue);
|
||||
yData.append(currentValue);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// Remove stale data
|
||||
removeStaleData();
|
||||
|
||||
// notify the gui of chages in the data
|
||||
// dataChanged();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -217,16 +200,16 @@ void ChronoPlotData::removeStaleData()
|
||||
double oldestValue;
|
||||
|
||||
while (1) {
|
||||
if (xData->size() == 0) {
|
||||
if (xData.size() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
newestValue = xData->last();
|
||||
oldestValue = xData->first();
|
||||
newestValue = xData.last();
|
||||
oldestValue = xData.first();
|
||||
|
||||
if (newestValue - oldestValue > m_xWindowSize) {
|
||||
yData->pop_front();
|
||||
xData->pop_front();
|
||||
if (newestValue - oldestValue > m_plotDataSize) {
|
||||
yData.pop_front();
|
||||
xData.pop_front();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -238,12 +221,5 @@ void ChronoPlotData::removeStaleData()
|
||||
void ChronoPlotData::removeStaleDataTimeout()
|
||||
{
|
||||
removeStaleData();
|
||||
// dataChanged();
|
||||
// qDebug() << "removeStaleDataTimeout";
|
||||
}
|
||||
|
||||
bool UAVObjectPlotData::append(UAVObject *obj)
|
||||
{
|
||||
Q_UNUSED(obj);
|
||||
return false;
|
||||
}
|
||||
|
@ -43,13 +43,7 @@
|
||||
/*!
|
||||
\brief Defines the different type of plots.
|
||||
*/
|
||||
enum PlotType {
|
||||
SequentialPlot,
|
||||
ChronoPlot,
|
||||
UAVObjectPlot,
|
||||
|
||||
NPlotTypes
|
||||
};
|
||||
enum PlotType {SequentialPlot, ChronoPlot};
|
||||
|
||||
/*!
|
||||
\brief Base class that keeps the data for each curve in the plot.
|
||||
@ -58,29 +52,26 @@ class PlotData : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PlotData(QString uavObject, QString uavField);
|
||||
PlotData(QString objectName, QString fieldName, QString elementName,
|
||||
QwtPlotCurve *plotCurve, int scaleOrderFactor, int meanSamples,
|
||||
QString mathFunction, double plotDataSize);
|
||||
~PlotData();
|
||||
|
||||
QString uavObject;
|
||||
QString uavField;
|
||||
QString uavSubField;
|
||||
bool haveSubField;
|
||||
int scalePower; // This is the power to which each value must be raised
|
||||
int meanSamples;
|
||||
double meanSum;
|
||||
QString mathFunction;
|
||||
double correctionSum;
|
||||
int correctionCount;
|
||||
double yMinimum;
|
||||
double yMaximum;
|
||||
double m_xWindowSize;
|
||||
QwtPlotCurve *curve;
|
||||
QVector<double> *xData;
|
||||
QVector<double> *yData;
|
||||
QVector<double> *yDataHistory;
|
||||
QVector<double> xData;
|
||||
QVector<double> yData;
|
||||
QVector<double> yDataHistory;
|
||||
|
||||
QString objectName() const { return m_objectName; }
|
||||
QString fieldName() const { return m_fieldName; }
|
||||
QString elementName() const { return m_elementName; }
|
||||
|
||||
bool isVisible() const { return m_plotCurve->isVisible(); }
|
||||
|
||||
double yMin() const { return m_yMin;}
|
||||
double yMax() const { return m_yMax;}
|
||||
|
||||
virtual bool append(UAVObject *obj) = 0;
|
||||
virtual PlotType plotType() = 0;
|
||||
virtual PlotType plotType() const = 0;
|
||||
virtual void removeStaleData() = 0;
|
||||
|
||||
void updatePlotCurveData();
|
||||
@ -88,8 +79,22 @@ public:
|
||||
protected:
|
||||
double valueAsDouble(UAVObject *obj, UAVObjectField *field);
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
int m_scalePower; // This is the power to which each value must be raised
|
||||
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 {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SequentialPlotData(QString uavObject, QString uavField)
|
||||
: PlotData(uavObject, uavField) {}
|
||||
SequentialPlotData(QString objectName, QString fieldName, QString elementName,
|
||||
QwtPlotCurve *plotCurve, int scaleFactor, int meanSamples,
|
||||
QString mathFunction, double plotDataSize)
|
||||
: PlotData(objectName, fieldName, elementName, plotCurve, scaleFactor, meanSamples, mathFunction, plotDataSize) {}
|
||||
~SequentialPlotData() {}
|
||||
|
||||
/*!
|
||||
@ -111,7 +118,7 @@ public:
|
||||
/*!
|
||||
\brief The type of plot
|
||||
*/
|
||||
virtual PlotType plotType()
|
||||
PlotType plotType() const
|
||||
{
|
||||
return SequentialPlot;
|
||||
}
|
||||
@ -119,7 +126,7 @@ public:
|
||||
/*!
|
||||
\brief Removes the old data from the buffer
|
||||
*/
|
||||
virtual void removeStaleData() {}
|
||||
void removeStaleData() {}
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -128,47 +135,25 @@ public:
|
||||
class ChronoPlotData : public PlotData {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ChronoPlotData(QString uavObject, QString uavField)
|
||||
: PlotData(uavObject, uavField)
|
||||
ChronoPlotData(QString objectname, QString fieldname, QString elementName,
|
||||
QwtPlotCurve *plotCurve, int scaleFactor, int meanSamples,
|
||||
QString mathFunction, double plotDataSize)
|
||||
: PlotData(objectname, fieldname, elementName, plotCurve, scaleFactor, meanSamples, mathFunction, plotDataSize)
|
||||
{
|
||||
scalePower = 1;
|
||||
}
|
||||
~ChronoPlotData() {}
|
||||
|
||||
bool append(UAVObject *obj);
|
||||
|
||||
virtual PlotType plotType()
|
||||
PlotType plotType() const
|
||||
{
|
||||
return ChronoPlot;
|
||||
}
|
||||
|
||||
virtual void removeStaleData();
|
||||
|
||||
private:
|
||||
void removeStaleData();
|
||||
|
||||
private slots:
|
||||
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
|
||||
|
@ -40,7 +40,7 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration *config)
|
||||
ScopeGadgetConfiguration *sgConfig = qobject_cast<ScopeGadgetConfiguration *>(config);
|
||||
ScopeGadgetWidget *widget = qobject_cast<ScopeGadgetWidget *>(m_widget);
|
||||
|
||||
widget->setXWindowSize(sgConfig->dataSize());
|
||||
widget->setPlotDataSize(sgConfig->dataSize());
|
||||
widget->setRefreshInterval(sgConfig->refreshInterval());
|
||||
|
||||
if (sgConfig->plotType() == SequentialPlot) {
|
||||
|
@ -299,7 +299,7 @@ void ScopeGadgetWidget::setupSequentialPlot()
|
||||
//// setAxisTitle(QwtPlot::xBottom, "Index");
|
||||
|
||||
setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw());
|
||||
setAxisScale(QwtPlot::xBottom, 0, m_xWindowSize);
|
||||
setAxisScale(QwtPlot::xBottom, 0, m_plotDataSize);
|
||||
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
|
||||
@ -327,7 +327,7 @@ void ScopeGadgetWidget::setupChronoPlot()
|
||||
|
||||
setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw());
|
||||
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, 0.0);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
@ -371,45 +371,34 @@ void ScopeGadgetWidget::setupChronoPlot()
|
||||
// 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;
|
||||
|
||||
if (m_plotType == SequentialPlot) {
|
||||
plotData = new SequentialPlotData(uavObject, uavFieldSubField);
|
||||
} else if (m_plotType == ChronoPlot) {
|
||||
plotData = new ChronoPlotData(uavObject, uavFieldSubField);
|
||||
}
|
||||
// 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);
|
||||
QString fieldName = fieldPlusSubField;
|
||||
QString elementName;
|
||||
if (fieldPlusSubField.contains("-")) {
|
||||
QStringList fieldSubfield = fieldName.split("-", QString::SkipEmptyParts);
|
||||
fieldName = fieldSubfield.at(0);
|
||||
elementName = fieldSubfield.at(1);
|
||||
}
|
||||
|
||||
// Create the curve
|
||||
QString curveName = (plotData->uavObject) + "." + (plotData->uavField);
|
||||
if (plotData->haveSubField) {
|
||||
curveName = curveName.append("." + plotData->uavSubField);
|
||||
QString curveName = objectName + "." + fieldName;
|
||||
if (!elementName.isEmpty()) {
|
||||
curveName.append("." + elementName);
|
||||
}
|
||||
|
||||
// Get the uav object
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject *>(objManager->getObject((plotData->uavObject)));
|
||||
UAVDataObject *obj = dynamic_cast<UAVDataObject *>(objManager->getObject(objectName));
|
||||
if (!obj) {
|
||||
qDebug() << "Object " << plotData->uavObject << " is missing";
|
||||
qDebug() << "Object " << objectName << " is missing";
|
||||
return;
|
||||
}
|
||||
UAVObjectField *field = obj->getField(plotData->uavField);
|
||||
UAVObjectField *field = obj->getField(fieldName);
|
||||
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;
|
||||
}
|
||||
QString units = field->getUnits();
|
||||
@ -419,10 +408,10 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
||||
}
|
||||
|
||||
QString curveNameScaled;
|
||||
if (scaleOrderFactor == 0) {
|
||||
if (scaleFactor == 0) {
|
||||
curveNameScaled = curveName + " (" + units + ")";
|
||||
} else {
|
||||
curveNameScaled = curveName + " (x10^" + QString::number(scaleOrderFactor) + " " + units + ")";
|
||||
curveNameScaled = curveName + " (x10^" + QString::number(scaleFactor) + " " + units + ")";
|
||||
}
|
||||
|
||||
QwtPlotCurve *plotCurve = new QwtPlotCurve(curveNameScaled);
|
||||
@ -432,9 +421,22 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
||||
}
|
||||
|
||||
plotCurve->setPen(pen);
|
||||
plotCurve->setSamples(*plotData->xData, *plotData->yData);
|
||||
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
|
||||
m_curvesData.insert(curveNameScaled, plotData);
|
||||
@ -450,22 +452,6 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavFieldSubField
|
||||
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)
|
||||
{
|
||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||
@ -485,14 +471,14 @@ void ScopeGadgetWidget::replotNewData()
|
||||
QMutexLocker locker(&mutex);
|
||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||
plotData->removeStaleData();
|
||||
plotData->curve->setSamples(*plotData->xData, *plotData->yData);
|
||||
plotData->updatePlotCurveData();
|
||||
}
|
||||
|
||||
QDateTime NOW = QDateTime::currentDateTime();
|
||||
double toTime = NOW.toTime_t();
|
||||
toTime += NOW.time().msec() / 1000.0;
|
||||
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;
|
||||
@ -505,9 +491,6 @@ void ScopeGadgetWidget::replotNewData()
|
||||
void ScopeGadgetWidget::clearCurvePlots()
|
||||
{
|
||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||
plotData->curve->detach();
|
||||
|
||||
delete plotData->curve;
|
||||
delete plotData;
|
||||
}
|
||||
|
||||
@ -516,11 +499,12 @@ void ScopeGadgetWidget::clearCurvePlots()
|
||||
|
||||
void ScopeGadgetWidget::saveState(QSettings *qSettings)
|
||||
{
|
||||
/*
|
||||
// plot state
|
||||
int i = 1;
|
||||
|
||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||
bool plotVisible = plotData->curve->isVisible();
|
||||
bool plotVisible = plotData->isVisible();
|
||||
|
||||
if (!plotVisible) {
|
||||
qSettings->setValue(QString("plot%1").arg(i), plotVisible);
|
||||
@ -529,17 +513,19 @@ void ScopeGadgetWidget::saveState(QSettings *qSettings)
|
||||
}
|
||||
// legend state
|
||||
qSettings->setValue("legendVisible", legend() != NULL);
|
||||
*/
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::restoreState(QSettings *qSettings)
|
||||
{
|
||||
/*
|
||||
// plot state
|
||||
int i = 1;
|
||||
|
||||
foreach(PlotData * plotData, m_curvesData.values()) {
|
||||
bool visible = qSettings->value(QString("plot%1").arg(i), true).toBool();
|
||||
|
||||
showCurve(plotData->curve, !visible);
|
||||
showCurve(plotData->m_plotCurve, !visible);
|
||||
i++;
|
||||
}
|
||||
// legend state
|
||||
@ -549,6 +535,7 @@ void ScopeGadgetWidget::restoreState(QSettings *qSettings)
|
||||
} else {
|
||||
deleteLegend();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
@ -621,10 +608,10 @@ int ScopeGadgetWidget::csvLoggingInsertHeader()
|
||||
|
||||
foreach(PlotData * plotData2, m_curvesData.values()) {
|
||||
ts << ", ";
|
||||
ts << plotData2->uavObject;
|
||||
ts << "." << plotData2->uavField;
|
||||
if (plotData2->haveSubField) {
|
||||
ts << "." << plotData2->uavSubField;
|
||||
ts << plotData2->objectName();
|
||||
ts << "." << plotData2->fieldName();
|
||||
if (!plotData2->elementName().isEmpty()) {
|
||||
ts << "." << plotData2->elementName();
|
||||
}
|
||||
}
|
||||
ts << endl;
|
||||
@ -655,14 +642,14 @@ int ScopeGadgetWidget::csvLoggingAddData()
|
||||
|
||||
foreach(PlotData * plotData2, m_curvesData.values()) {
|
||||
ss << ", ";
|
||||
if (plotData2->xData->isEmpty()) {
|
||||
if (plotData2->xData.isEmpty()) {
|
||||
ss << ", ";
|
||||
if (plotData2->xData->isEmpty()) {} else {
|
||||
ss << QString().sprintf("%3.10g", plotData2->yData->last());
|
||||
if (plotData2->xData.isEmpty()) {} else {
|
||||
ss << QString().sprintf("%3.10g", plotData2->yData.last());
|
||||
m_csvLoggingDataValid = 1;
|
||||
}
|
||||
} else {
|
||||
ss << QString().sprintf("%3.10g", plotData2->yData->last());
|
||||
ss << QString().sprintf("%3.10g", plotData2->yData.last());
|
||||
m_csvLoggingDataValid = 1;
|
||||
}
|
||||
}
|
||||
|
@ -76,13 +76,13 @@ public:
|
||||
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)
|
||||
{
|
||||
@ -142,7 +142,7 @@ private:
|
||||
|
||||
PlotType m_plotType;
|
||||
|
||||
double m_xWindowSize;
|
||||
double m_plotDataSize;
|
||||
int m_refreshInterval;
|
||||
QList<QString> m_connectedUAVObjects;
|
||||
QMap<QString, PlotData *> m_curvesData;
|
||||
|
Loading…
x
Reference in New Issue
Block a user