1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-03-02 19:29:15 +01:00

OP-42 GCS/Scope: Plot can now show high frequency data effectively

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1286 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
banigreyling 2010-08-14 20:25:55 +00:00 committed by banigreyling
parent a075eafb98
commit fdfd004634
8 changed files with 365 additions and 307 deletions

View File

@ -28,6 +28,7 @@
#include "plotdata.h" #include "plotdata.h"
#include <math.h> #include <math.h>
#include <QDebug>
PlotData::PlotData(QString p_uavObject, QString p_uavField) PlotData::PlotData(QString p_uavObject, QString p_uavField)
{ {
@ -67,7 +68,7 @@ bool SequencialPlotData::append(UAVObject* obj)
xData->insert(xData->size(), xData->size()); xData->insert(xData->size(), xData->size());
//notify the gui of changes in the data //notify the gui of changes in the data
dataChanged(); //dataChanged();
return true; return true;
} }
} }
@ -93,7 +94,7 @@ bool ChronoPlotData::append(UAVObject* obj)
removeStaleData(); removeStaleData();
//notify the gui of chages in the data //notify the gui of chages in the data
dataChanged(); //dataChanged();
return true; return true;
} }
} }
@ -119,12 +120,15 @@ void ChronoPlotData::removeStaleData()
} else } else
break; break;
} }
//qDebug() << "removeStaleData ";
} }
void ChronoPlotData::removeStaleDataTimeout() void ChronoPlotData::removeStaleDataTimeout()
{ {
removeStaleData(); removeStaleData();
dataChanged(); //dataChanged();
//qDebug() << "removeStaleDataTimeout";
} }
bool UAVObjectPlotData::append(UAVObject* obj) bool UAVObjectPlotData::append(UAVObject* obj)

View File

@ -77,6 +77,9 @@ public:
virtual bool append(UAVObject* obj) = 0; virtual bool append(UAVObject* obj) = 0;
virtual PlotType plotType() = 0; virtual PlotType plotType() = 0;
virtual void removeStaleData() = 0;
void updatePlotCurveData();
signals: signals:
void dataChanged(); void dataChanged();
@ -105,6 +108,11 @@ public:
virtual PlotType plotType() { virtual PlotType plotType() {
return SequencialPlot; return SequencialPlot;
} }
/*!
\brief Removes the old data from the buffer
*/
virtual void removeStaleData(){}
}; };
/*! /*!
@ -114,16 +122,11 @@ class ChronoPlotData : public PlotData
{ {
Q_OBJECT Q_OBJECT
public: public:
ChronoPlotData(QString uavObject, QString uavField, double refreshInterval) ChronoPlotData(QString uavObject, QString uavField)
: PlotData(uavObject, uavField) { : PlotData(uavObject, uavField) {
scalePower = 1; scalePower = 1;
//Setup timer that removes stale data
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(removeStaleDataTimeout()));
timer->start(refreshInterval * 1000);
} }
~ChronoPlotData() { ~ChronoPlotData() {
delete timer;
} }
bool append(UAVObject* obj); bool append(UAVObject* obj);
@ -131,10 +134,10 @@ public:
virtual PlotType plotType() { virtual PlotType plotType() {
return ChronoPlot; return ChronoPlot;
} }
private:
void removeStaleData();
QTimer *timer; virtual void removeStaleData();
private:
private slots: private slots:
void removeStaleDataTimeout(); void removeStaleDataTimeout();
@ -157,6 +160,8 @@ public:
virtual PlotType plotType() { virtual PlotType plotType() {
return UAVObjectPlot; return UAVObjectPlot;
} }
virtual void removeStaleData(){}
}; };
#endif // PLOTDATA_H #endif // PLOTDATA_H

View File

@ -33,12 +33,14 @@
ScopeGadget::ScopeGadget(QString classId, ScopeGadgetWidget *widget, QWidget *parent) : ScopeGadget::ScopeGadget(QString classId, ScopeGadgetWidget *widget, QWidget *parent) :
IUAVGadget(classId, parent), IUAVGadget(classId, parent),
m_widget(widget) m_widget(widget),
configLoaded(false)
{ {
} }
void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config) 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);
@ -63,12 +65,11 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config)
uavObject, uavObject,
uavField, uavField,
scale, scale,
QPen( QPen( QBrush(QColor(color),Qt::SolidPattern),
QBrush(QColor(color),Qt::SolidPattern), (qreal)2,
(qreal)2, Qt::SolidLine,
Qt::SolidLine, Qt::SquareCap,
Qt::SquareCap, Qt::BevelJoin)
Qt::BevelJoin)
); );
} }
} }

View File

@ -61,6 +61,8 @@ public:
private: private:
QWidget *m_widget; QWidget *m_widget;
QList<int> m_context; QList<int> m_context;
bool configLoaded;
}; };

View File

@ -33,7 +33,7 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, const QByteA
IUAVGadgetConfiguration(classId, parent), IUAVGadgetConfiguration(classId, parent),
m_plotType((int)ChronoPlot), m_plotType((int)ChronoPlot),
m_dataSize(60), m_dataSize(60),
m_refreshInterval(1) m_refreshInterval(1000)
{ {
uint currentStreamVersion = 0; uint currentStreamVersion = 0;
int plotCurveCount = 0; int plotCurveCount = 0;
@ -71,6 +71,9 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, const QByteA
m_PlotCurveConfigs.append(plotCurveConf); m_PlotCurveConfigs.append(plotCurveConf);
} }
//The value is converted to milliseconds, so if it is < 100, it is still seconds
if(m_refreshInterval < 100)
m_refreshInterval *= 1000;
} }
} }

View File

@ -28,7 +28,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>551</width> <width>551</width>
<height>231</height> <height>275</height>
</rect> </rect>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
@ -97,16 +97,19 @@
<item row="3" column="1"> <item row="3" column="1">
<widget class="QSpinBox" name="spnRefreshInterval"> <widget class="QSpinBox" name="spnRefreshInterval">
<property name="suffix"> <property name="suffix">
<string> seconds</string> <string>ms</string>
</property> </property>
<property name="minimum"> <property name="minimum">
<number>1</number> <number>100</number>
</property> </property>
<property name="maximum"> <property name="maximum">
<number>30</number> <number>30000</number>
</property>
<property name="singleStep">
<number>500</number>
</property> </property>
<property name="value"> <property name="value">
<number>5</number> <number>1000</number>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -49,15 +49,12 @@ TestDataGen* ScopeGadgetWidget::testDataGen;
ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent) ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
{ {
// if(testDataGen == 0) // if(testDataGen == 0)
// testDataGen = new TestDataGen(); // testDataGen = new TestDataGen();
setCanvasBackground(Qt::darkBlue); //Setup the timer that replots data
replotTimer = new QTimer(this);
QwtPlotGrid *grid = new QwtPlotGrid; connect(replotTimer, SIGNAL(timeout()), this, SLOT(replotNewData()));
grid->setMajPen(QPen(Qt::gray, 0, Qt::DashLine));
grid->setMinPen(QPen(Qt::lightGray, 0 , Qt::DotLine));
grid->attach(this);
} }
void ScopeGadgetWidget::preparePlot(PlotType plotType) void ScopeGadgetWidget::preparePlot(PlotType plotType)
@ -71,6 +68,14 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
// Show a title // Show a title
setTitle("Scope"); setTitle("Scope");
setCanvasBackground(Qt::darkBlue);
//Add grid lines
QwtPlotGrid *grid = new QwtPlotGrid;
grid->setMajPen(QPen(Qt::gray, 0, Qt::DashLine));
grid->setMinPen(QPen(Qt::lightGray, 0 , Qt::DotLine));
grid->attach(this);
// Show a legend at the bottom // Show a legend at the bottom
if (legend() == 0) { if (legend() == 0) {
QwtLegend *legend = new QwtLegend(); QwtLegend *legend = new QwtLegend();
@ -80,6 +85,14 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
} }
connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)),this, SLOT(showCurve(QwtPlotItem *, bool))); connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)),this, SLOT(showCurve(QwtPlotItem *, bool)));
if(!replotTimer->isActive())
replotTimer->start(m_refreshInterval);
else
{
replotTimer->setInterval(m_refreshInterval);
}
} }
void ScopeGadgetWidget::showCurve(QwtPlotItem *item, bool on) void ScopeGadgetWidget::showCurve(QwtPlotItem *item, bool on)
@ -110,8 +123,8 @@ void ScopeGadgetWidget::setupChronoPlot()
setAxisTitle(QwtPlot::xBottom, "Time [h:m:s]"); setAxisTitle(QwtPlot::xBottom, "Time [h:m:s]");
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, NOW); setAxisScale(QwtPlot::xBottom, NOW - m_xWindowSize / 1000, NOW);
setAxisLabelRotation(QwtPlot::xBottom, -50.0); setAxisLabelRotation(QwtPlot::xBottom, -15.0);
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom); setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
/* /*
@ -135,7 +148,7 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavField, int sc
if (m_plotType == SequencialPlot) if (m_plotType == SequencialPlot)
plotData = new SequencialPlotData(uavObject, uavField); plotData = new SequencialPlotData(uavObject, uavField);
else if (m_plotType == ChronoPlot) else if (m_plotType == ChronoPlot)
plotData = new ChronoPlotData(uavObject, uavField, m_refreshInterval); plotData = new ChronoPlotData(uavObject, uavField);
//else if (m_plotType == UAVObjectPlot) //else if (m_plotType == UAVObjectPlot)
// plotData = new UAVObjectPlotData(uavObject, uavField); // plotData = new UAVObjectPlotData(uavObject, uavField);
@ -169,8 +182,6 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavField, int sc
connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*))); connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*)));
} }
connect(plotData, SIGNAL(dataChanged()), this, SLOT(replotNewData()));
replot(); replot();
} }
@ -192,16 +203,24 @@ void ScopeGadgetWidget::uavObjectReceived(UAVObject* obj)
{ {
foreach(PlotData* plotData, m_curvesData.values()) { foreach(PlotData* plotData, m_curvesData.values()) {
plotData->append(obj); plotData->append(obj);
plotData->curve->setData(*plotData->xData, *plotData->yData);
} }
} }
void ScopeGadgetWidget::replotNewData() void ScopeGadgetWidget::replotNewData()
{ {
if (m_plotType == ChronoPlot) { foreach(PlotData* plotData, m_curvesData.values()) {
uint NOW = QDateTime::currentDateTime().toTime_t(); plotData->removeStaleData();
setAxisScale(QwtPlot::xBottom, NOW - m_xWindowSize, NOW); plotData->curve->setData(*plotData->xData, *plotData->yData);
} }
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);
}
//qDebug() << "replotNewData from " << NOW.addSecs(- m_xWindowSize) << " to " << NOW;
replot(); replot();
} }
@ -257,6 +276,11 @@ void ScopeGadgetWidget::setupExamplePlot()
ScopeGadgetWidget::~ScopeGadgetWidget() ScopeGadgetWidget::~ScopeGadgetWidget()
{ {
if (replotTimer)
replotTimer->stop();
delete replotTimer;
replotTimer = 0;
//Get the object to de-monitor //Get the object to de-monitor
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>(); UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
@ -281,6 +305,7 @@ void ScopeGadgetWidget::clearCurvePlots()
m_curvesData.clear(); m_curvesData.clear();
} }
TestDataGen::TestDataGen() TestDataGen::TestDataGen()
{ {
// Get required UAVObjects // Get required UAVObjects
@ -291,17 +316,20 @@ TestDataGen::TestDataGen()
gps = PositionActual::GetInstance(objManager); gps = PositionActual::GetInstance(objManager);
//Setup timer //Setup timer
periodMs = 5;
timer = new QTimer(this); timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(genTestData())); connect(timer, SIGNAL(timeout()), this, SLOT(genTestData()));
timer->start(2); timer->start(periodMs);
debugCounter = 0;
} }
void TestDataGen::genTestData() void TestDataGen::genTestData()
{ {
// Update AltitudeActual object // Update AltitudeActual object
AltitudeActual::DataFields altActualData; AltitudeActual::DataFields altActualData;
altActualData.Altitude = 500 * sin(0.1 * testTime) + 200 * cos(0.4 * testTime) + 800; altActualData.Altitude = 500 * sin(1 * testTime) + 200 * cos(4 * testTime) + 800;
altActualData.Temperature = 30 * sin(0.05 * testTime); altActualData.Temperature = 30 * sin(0.5 * testTime);
altActualData.Pressure = 100; altActualData.Pressure = 100;
altActual->setData(altActualData); altActual->setData(altActualData);
@ -316,7 +344,11 @@ void TestDataGen::genTestData()
gpsData.Satellites = 10; gpsData.Satellites = 10;
gps->setData(gpsData); gps->setData(gpsData);
testTime += 0.02; testTime += (periodMs / 1000.0);
debugCounter++;
if (debugCounter % 100 == 0 )
qDebug() << "Test Time = " << testTime;
} }
TestDataGen::~TestDataGen() TestDataGen::~TestDataGen()

View File

@ -52,14 +52,17 @@ class TimeScaleDraw : public QwtScaleDraw
{ {
public: public:
TimeScaleDraw() { TimeScaleDraw() {
baseTime = QDateTime::currentDateTime().toTime_t(); //baseTime = QDateTime::currentDateTime().toTime_t();
} }
virtual QwtText label(double v) const { virtual QwtText label(double v) const {
QDateTime upTime = QDateTime::fromTime_t((uint)v); uint seconds = (uint)(v);
QDateTime upTime = QDateTime::fromTime_t(seconds);
QTime timePart = upTime.time().addMSecs((v - seconds )* 1000);
upTime.setTime(timePart);
return upTime.toLocalTime().toString("hh:mm:ss"); return upTime.toLocalTime().toString("hh:mm:ss");
} }
private: private:
double baseTime; // double baseTime;
}; };
/*! /*!
@ -80,6 +83,9 @@ private:
QTimer *timer; QTimer *timer;
double testTime; double testTime;
int periodMs;
int debugCounter;
private slots: private slots:
void genTestData(); void genTestData();
@ -128,6 +134,8 @@ private:
QMap<QString, PlotData*> m_curvesData; QMap<QString, PlotData*> m_curvesData;
static TestDataGen* testDataGen; static TestDataGen* testDataGen;
QTimer *replotTimer;
}; };