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:
parent
a075eafb98
commit
fdfd004634
@ -28,6 +28,7 @@
|
||||
|
||||
#include "plotdata.h"
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
|
||||
PlotData::PlotData(QString p_uavObject, QString p_uavField)
|
||||
{
|
||||
@ -67,7 +68,7 @@ bool SequencialPlotData::append(UAVObject* obj)
|
||||
xData->insert(xData->size(), xData->size());
|
||||
|
||||
//notify the gui of changes in the data
|
||||
dataChanged();
|
||||
//dataChanged();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -93,7 +94,7 @@ bool ChronoPlotData::append(UAVObject* obj)
|
||||
removeStaleData();
|
||||
|
||||
//notify the gui of chages in the data
|
||||
dataChanged();
|
||||
//dataChanged();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -119,12 +120,15 @@ void ChronoPlotData::removeStaleData()
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
//qDebug() << "removeStaleData ";
|
||||
}
|
||||
|
||||
void ChronoPlotData::removeStaleDataTimeout()
|
||||
{
|
||||
removeStaleData();
|
||||
dataChanged();
|
||||
//dataChanged();
|
||||
//qDebug() << "removeStaleDataTimeout";
|
||||
}
|
||||
|
||||
bool UAVObjectPlotData::append(UAVObject* obj)
|
||||
|
@ -77,6 +77,9 @@ public:
|
||||
|
||||
virtual bool append(UAVObject* obj) = 0;
|
||||
virtual PlotType plotType() = 0;
|
||||
virtual void removeStaleData() = 0;
|
||||
|
||||
void updatePlotCurveData();
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
@ -105,6 +108,11 @@ public:
|
||||
virtual PlotType plotType() {
|
||||
return SequencialPlot;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Removes the old data from the buffer
|
||||
*/
|
||||
virtual void removeStaleData(){}
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -114,16 +122,11 @@ class ChronoPlotData : public PlotData
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ChronoPlotData(QString uavObject, QString uavField, double refreshInterval)
|
||||
ChronoPlotData(QString uavObject, QString uavField)
|
||||
: PlotData(uavObject, uavField) {
|
||||
scalePower = 1;
|
||||
//Setup timer that removes stale data
|
||||
timer = new QTimer();
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(removeStaleDataTimeout()));
|
||||
timer->start(refreshInterval * 1000);
|
||||
}
|
||||
~ChronoPlotData() {
|
||||
delete timer;
|
||||
}
|
||||
|
||||
bool append(UAVObject* obj);
|
||||
@ -131,10 +134,10 @@ public:
|
||||
virtual PlotType plotType() {
|
||||
return ChronoPlot;
|
||||
}
|
||||
private:
|
||||
void removeStaleData();
|
||||
|
||||
QTimer *timer;
|
||||
virtual void removeStaleData();
|
||||
|
||||
private:
|
||||
|
||||
private slots:
|
||||
void removeStaleDataTimeout();
|
||||
@ -157,6 +160,8 @@ public:
|
||||
virtual PlotType plotType() {
|
||||
return UAVObjectPlot;
|
||||
}
|
||||
|
||||
virtual void removeStaleData(){}
|
||||
};
|
||||
|
||||
#endif // PLOTDATA_H
|
||||
|
@ -33,12 +33,14 @@
|
||||
|
||||
ScopeGadget::ScopeGadget(QString classId, ScopeGadgetWidget *widget, QWidget *parent) :
|
||||
IUAVGadget(classId, parent),
|
||||
m_widget(widget)
|
||||
m_widget(widget),
|
||||
configLoaded(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config)
|
||||
{
|
||||
|
||||
ScopeGadgetConfiguration *sgConfig = qobject_cast<ScopeGadgetConfiguration*>(config);
|
||||
ScopeGadgetWidget* widget = qobject_cast<ScopeGadgetWidget*>(m_widget);
|
||||
|
||||
@ -63,8 +65,7 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config)
|
||||
uavObject,
|
||||
uavField,
|
||||
scale,
|
||||
QPen(
|
||||
QBrush(QColor(color),Qt::SolidPattern),
|
||||
QPen( QBrush(QColor(color),Qt::SolidPattern),
|
||||
(qreal)2,
|
||||
Qt::SolidLine,
|
||||
Qt::SquareCap,
|
||||
|
@ -61,6 +61,8 @@ public:
|
||||
private:
|
||||
QWidget *m_widget;
|
||||
QList<int> m_context;
|
||||
|
||||
bool configLoaded;
|
||||
};
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, const QByteA
|
||||
IUAVGadgetConfiguration(classId, parent),
|
||||
m_plotType((int)ChronoPlot),
|
||||
m_dataSize(60),
|
||||
m_refreshInterval(1)
|
||||
m_refreshInterval(1000)
|
||||
{
|
||||
uint currentStreamVersion = 0;
|
||||
int plotCurveCount = 0;
|
||||
@ -71,6 +71,9 @@ ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, const QByteA
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>551</width>
|
||||
<height>231</height>
|
||||
<height>275</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
@ -97,16 +97,19 @@
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="spnRefreshInterval">
|
||||
<property name="suffix">
|
||||
<string> seconds</string>
|
||||
<string>ms</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>30</number>
|
||||
<number>30000</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>500</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>5</number>
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -49,15 +49,12 @@ TestDataGen* ScopeGadgetWidget::testDataGen;
|
||||
|
||||
ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
|
||||
{
|
||||
// if(testDataGen == 0)
|
||||
// testDataGen = new TestDataGen();
|
||||
// if(testDataGen == 0)
|
||||
// testDataGen = new TestDataGen();
|
||||
|
||||
setCanvasBackground(Qt::darkBlue);
|
||||
|
||||
QwtPlotGrid *grid = new QwtPlotGrid;
|
||||
grid->setMajPen(QPen(Qt::gray, 0, Qt::DashLine));
|
||||
grid->setMinPen(QPen(Qt::lightGray, 0 , Qt::DotLine));
|
||||
grid->attach(this);
|
||||
//Setup the timer that replots data
|
||||
replotTimer = new QTimer(this);
|
||||
connect(replotTimer, SIGNAL(timeout()), this, SLOT(replotNewData()));
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::preparePlot(PlotType plotType)
|
||||
@ -71,6 +68,14 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
|
||||
// Show a title
|
||||
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
|
||||
if (legend() == 0) {
|
||||
QwtLegend *legend = new QwtLegend();
|
||||
@ -80,6 +85,14 @@ void ScopeGadgetWidget::preparePlot(PlotType plotType)
|
||||
}
|
||||
|
||||
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)
|
||||
@ -110,8 +123,8 @@ void ScopeGadgetWidget::setupChronoPlot()
|
||||
setAxisTitle(QwtPlot::xBottom, "Time [h:m:s]");
|
||||
setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw());
|
||||
uint NOW = QDateTime::currentDateTime().toTime_t();
|
||||
setAxisScale(QwtPlot::xBottom, NOW - m_xWindowSize, NOW);
|
||||
setAxisLabelRotation(QwtPlot::xBottom, -50.0);
|
||||
setAxisScale(QwtPlot::xBottom, NOW - m_xWindowSize / 1000, NOW);
|
||||
setAxisLabelRotation(QwtPlot::xBottom, -15.0);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
|
||||
/*
|
||||
@ -135,7 +148,7 @@ void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavField, int sc
|
||||
if (m_plotType == SequencialPlot)
|
||||
plotData = new SequencialPlotData(uavObject, uavField);
|
||||
else if (m_plotType == ChronoPlot)
|
||||
plotData = new ChronoPlotData(uavObject, uavField, m_refreshInterval);
|
||||
plotData = new ChronoPlotData(uavObject, uavField);
|
||||
//else if (m_plotType == UAVObjectPlot)
|
||||
// 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(plotData, SIGNAL(dataChanged()), this, SLOT(replotNewData()));
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
@ -192,16 +203,24 @@ void ScopeGadgetWidget::uavObjectReceived(UAVObject* obj)
|
||||
{
|
||||
foreach(PlotData* plotData, m_curvesData.values()) {
|
||||
plotData->append(obj);
|
||||
plotData->curve->setData(*plotData->xData, *plotData->yData);
|
||||
}
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::replotNewData()
|
||||
{
|
||||
if (m_plotType == ChronoPlot) {
|
||||
uint NOW = QDateTime::currentDateTime().toTime_t();
|
||||
setAxisScale(QwtPlot::xBottom, NOW - m_xWindowSize, NOW);
|
||||
foreach(PlotData* plotData, m_curvesData.values()) {
|
||||
plotData->removeStaleData();
|
||||
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();
|
||||
}
|
||||
|
||||
@ -257,6 +276,11 @@ void ScopeGadgetWidget::setupExamplePlot()
|
||||
|
||||
ScopeGadgetWidget::~ScopeGadgetWidget()
|
||||
{
|
||||
if (replotTimer)
|
||||
replotTimer->stop();
|
||||
delete replotTimer;
|
||||
replotTimer = 0;
|
||||
|
||||
//Get the object to de-monitor
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
@ -281,6 +305,7 @@ void ScopeGadgetWidget::clearCurvePlots()
|
||||
m_curvesData.clear();
|
||||
}
|
||||
|
||||
|
||||
TestDataGen::TestDataGen()
|
||||
{
|
||||
// Get required UAVObjects
|
||||
@ -291,17 +316,20 @@ TestDataGen::TestDataGen()
|
||||
gps = PositionActual::GetInstance(objManager);
|
||||
|
||||
//Setup timer
|
||||
periodMs = 5;
|
||||
timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(genTestData()));
|
||||
timer->start(2);
|
||||
timer->start(periodMs);
|
||||
|
||||
debugCounter = 0;
|
||||
}
|
||||
|
||||
void TestDataGen::genTestData()
|
||||
{
|
||||
// Update AltitudeActual object
|
||||
AltitudeActual::DataFields altActualData;
|
||||
altActualData.Altitude = 500 * sin(0.1 * testTime) + 200 * cos(0.4 * testTime) + 800;
|
||||
altActualData.Temperature = 30 * sin(0.05 * testTime);
|
||||
altActualData.Altitude = 500 * sin(1 * testTime) + 200 * cos(4 * testTime) + 800;
|
||||
altActualData.Temperature = 30 * sin(0.5 * testTime);
|
||||
altActualData.Pressure = 100;
|
||||
altActual->setData(altActualData);
|
||||
|
||||
@ -316,7 +344,11 @@ void TestDataGen::genTestData()
|
||||
gpsData.Satellites = 10;
|
||||
gps->setData(gpsData);
|
||||
|
||||
testTime += 0.02;
|
||||
testTime += (periodMs / 1000.0);
|
||||
|
||||
debugCounter++;
|
||||
if (debugCounter % 100 == 0 )
|
||||
qDebug() << "Test Time = " << testTime;
|
||||
}
|
||||
|
||||
TestDataGen::~TestDataGen()
|
||||
|
@ -52,14 +52,17 @@ class TimeScaleDraw : public QwtScaleDraw
|
||||
{
|
||||
public:
|
||||
TimeScaleDraw() {
|
||||
baseTime = QDateTime::currentDateTime().toTime_t();
|
||||
//baseTime = QDateTime::currentDateTime().toTime_t();
|
||||
}
|
||||
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");
|
||||
}
|
||||
private:
|
||||
double baseTime;
|
||||
// double baseTime;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -80,6 +83,9 @@ private:
|
||||
|
||||
QTimer *timer;
|
||||
double testTime;
|
||||
int periodMs;
|
||||
|
||||
int debugCounter;
|
||||
|
||||
private slots:
|
||||
void genTestData();
|
||||
@ -128,6 +134,8 @@ private:
|
||||
QMap<QString, PlotData*> m_curvesData;
|
||||
|
||||
static TestDataGen* testDataGen;
|
||||
|
||||
QTimer *replotTimer;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user