mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-01 09:24:10 +01:00
OP-42 GCS/Scope: Added feature to show/hide plot curves. Made background blue. Add grid lines to plot canvas.
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1255 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
4c98fc391f
commit
79fbc8b8fc
@ -29,6 +29,8 @@
|
||||
#include "scopegadgetconfiguration.h"
|
||||
#include "scopegadgetwidget.h"
|
||||
|
||||
#include <QtGui/qcolor.h>
|
||||
|
||||
ScopeGadget::ScopeGadget(QString classId, ScopeGadgetWidget *widget, QWidget *parent) :
|
||||
IUAVGadget(classId, parent),
|
||||
m_widget(widget)
|
||||
@ -57,11 +59,21 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config)
|
||||
int scale = plotCurveConfig->yScalePower;
|
||||
QRgb color = plotCurveConfig->color;
|
||||
|
||||
widget->addCurvePlot(uavObject,uavField,scale,QPen(QColor(color)));
|
||||
widget->addCurvePlot(
|
||||
uavObject,
|
||||
uavField,
|
||||
scale,
|
||||
QPen(
|
||||
QBrush(QColor(color),Qt::SolidPattern),
|
||||
(qreal)2,
|
||||
Qt::SolidLine,
|
||||
Qt::SquareCap,
|
||||
Qt::BevelJoin)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ScopeGadget::~ScopeGadget()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -64,4 +64,4 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#endif // SCOPEGADGET_H_
|
||||
#endif // SCOPEGADGET_H_
|
||||
|
@ -1,282 +1,282 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file scopegadgetoptionspage.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ScopePlugin Scope Gadget Plugin
|
||||
* @{
|
||||
* @brief The scope Gadget, graphically plots the states of UAVObjects
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "scopegadgetoptionspage.h"
|
||||
#include "scopegadgetconfiguration.h"
|
||||
#include "ui_scopegadgetoptionspage.h"
|
||||
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "uavobjects/uavdataobject.h"
|
||||
|
||||
|
||||
|
||||
ScopeGadgetOptionsPage::ScopeGadgetOptionsPage(ScopeGadgetConfiguration *config, QObject *parent) :
|
||||
IOptionsPage(parent),
|
||||
m_config(config)
|
||||
{
|
||||
//nothing to do here...
|
||||
}
|
||||
|
||||
//creates options page widget (uses the UI file)
|
||||
QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent)
|
||||
{
|
||||
options_page = new Ui::ScopeGadgetOptionsPage();
|
||||
//main widget
|
||||
QWidget *optionsPageWidget = new QWidget;
|
||||
//main layout
|
||||
options_page->setupUi(optionsPageWidget);
|
||||
|
||||
options_page->cmbPlotType->addItem("Sequencial Plot","");
|
||||
options_page->cmbPlotType->addItem("Chronological Plot","");
|
||||
|
||||
// Fills the combo boxes for the UAVObjects
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
QList< QList<UAVDataObject*> > objList = objManager->getDataObjects();
|
||||
foreach (QList<UAVDataObject*> list, objList) {
|
||||
foreach (UAVDataObject* obj, list) {
|
||||
options_page->cmbUAVObjects->addItem(obj->getName());
|
||||
}
|
||||
}
|
||||
|
||||
//Connect signals to slots cmbUAVObjects.currentIndexChanged
|
||||
connect(options_page->cmbUAVObjects, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_cmbUAVObjects_currentIndexChanged(QString)));
|
||||
|
||||
if(options_page->cmbUAVObjects->currentIndex() >= 0)
|
||||
on_cmbUAVObjects_currentIndexChanged(options_page->cmbUAVObjects->currentText());
|
||||
|
||||
options_page->cmbScale->addItem("E-9", -9);
|
||||
options_page->cmbScale->addItem("E-6", -6);
|
||||
options_page->cmbScale->addItem("E-5",-5);
|
||||
options_page->cmbScale->addItem("E-4",-4);
|
||||
options_page->cmbScale->addItem("E-3",-3);
|
||||
options_page->cmbScale->addItem("E-2",-2);
|
||||
options_page->cmbScale->addItem("E-1",-1);
|
||||
options_page->cmbScale->addItem("E0",0);
|
||||
options_page->cmbScale->addItem("E1",1);
|
||||
options_page->cmbScale->addItem("E2",2);
|
||||
options_page->cmbScale->addItem("E3",3);
|
||||
options_page->cmbScale->addItem("E4",4);
|
||||
options_page->cmbScale->addItem("E5",5);
|
||||
options_page->cmbScale->addItem("E6",6);
|
||||
options_page->cmbScale->addItem("E9",9);
|
||||
options_page->cmbScale->addItem("E12",12);
|
||||
options_page->cmbScale->setCurrentIndex(7);
|
||||
|
||||
//Set widget values from settings
|
||||
options_page->cmbPlotType->setCurrentIndex(m_config->plotType());
|
||||
options_page->spnDataSize->setValue(m_config->dataSize());
|
||||
options_page->spnRefreshInterval->setValue(m_config->refreshInterval());
|
||||
|
||||
//add the configured curves
|
||||
foreach (PlotCurveConfiguration* plotData, m_config->plotCurveConfigs()) {
|
||||
|
||||
QString uavObject = plotData->uavObject;
|
||||
QString uavField = plotData->uavField;
|
||||
int scale = plotData->yScalePower;
|
||||
QVariant varColor = plotData->color;
|
||||
|
||||
addPlotCurveConfig(uavObject,uavField,scale,varColor);
|
||||
}
|
||||
|
||||
if(m_config->plotCurveConfigs().count() > 0)
|
||||
options_page->lstCurves->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
|
||||
|
||||
connect(options_page->btnAddCurve, SIGNAL(clicked()), this, SLOT(on_btnAddCurve_clicked()));
|
||||
connect(options_page->btnRemoveCurve, SIGNAL(clicked()), this, SLOT(on_btnRemoveCurve_clicked()));
|
||||
connect(options_page->lstCurves, SIGNAL(currentRowChanged(int)), this, SLOT(on_lstCurves_currentRowChanged(int)));
|
||||
connect(options_page->btnColor, SIGNAL(clicked()), this, SLOT(on_btnColor_clicked()));
|
||||
|
||||
setYAxisWidgetFromPlotCurve();
|
||||
|
||||
return optionsPageWidget;
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::on_btnColor_clicked()
|
||||
{
|
||||
QColor color = QColorDialog::getColor( QColor(options_page->btnColor->text()), options_page->widget);
|
||||
if (color.isValid()) {
|
||||
setButtonColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Populate the widgets that containts the configs for the Y-Axis from
|
||||
the selected plot curve
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::setYAxisWidgetFromPlotCurve()
|
||||
{
|
||||
bool parseOK = false;
|
||||
QListWidgetItem* listItem = options_page->lstCurves->currentItem();
|
||||
|
||||
if(listItem == 0)
|
||||
return;
|
||||
|
||||
int currentIndex = options_page->cmbUAVObjects->findText( listItem->data(Qt::UserRole + 0).toString());
|
||||
options_page->cmbUAVObjects->setCurrentIndex(currentIndex);
|
||||
|
||||
currentIndex = options_page->cmbUAVField->findText( listItem->data(Qt::UserRole + 1).toString());
|
||||
options_page->cmbUAVField->setCurrentIndex(currentIndex);
|
||||
|
||||
currentIndex = options_page->cmbScale->findData( listItem->data(Qt::UserRole + 2), Qt::UserRole, Qt::MatchExactly);
|
||||
options_page->cmbScale->setCurrentIndex(currentIndex);
|
||||
|
||||
QVariant varColor = listItem->data(Qt::UserRole + 3);
|
||||
int rgb = varColor.toInt(&parseOK);
|
||||
|
||||
setButtonColor(QColor((QRgb)rgb));
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::setButtonColor(const QColor &color)
|
||||
{
|
||||
options_page->btnColor->setText(color.name());
|
||||
options_page->btnColor->setPalette(QPalette(color));
|
||||
options_page->btnColor->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief When a new UAVObject is selected, populate the UAVObject field combo box with the correct values.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_cmbUAVObjects_currentIndexChanged(QString val)
|
||||
{
|
||||
options_page->cmbUAVField->clear();
|
||||
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>( objManager->getObject(val) );
|
||||
|
||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
||||
foreach (UAVObjectField* field, fieldList) {
|
||||
options_page->cmbUAVField->addItem(field->getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user presses apply or OK.
|
||||
*
|
||||
* Saves the current values
|
||||
*
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::apply()
|
||||
{
|
||||
bool parseOK = false;
|
||||
|
||||
//Apply configuration changes
|
||||
m_config->setPlotType(options_page->cmbPlotType->currentIndex());
|
||||
m_config->setDataSize(options_page->spnDataSize->value());
|
||||
m_config->setRefreashInterval(options_page->spnRefreshInterval->value());
|
||||
|
||||
QList<PlotCurveConfiguration*> m_PlotCurveConfigs;
|
||||
for(int iIndex = 0; iIndex < options_page->lstCurves->count();iIndex++) {
|
||||
QListWidgetItem* listItem = options_page->lstCurves->item(iIndex);
|
||||
|
||||
PlotCurveConfiguration* newPlotCurveConfigs = new PlotCurveConfiguration();
|
||||
newPlotCurveConfigs->uavObject = listItem->data(Qt::UserRole + 0).toString();
|
||||
newPlotCurveConfigs->uavField = listItem->data(Qt::UserRole + 1).toString();
|
||||
newPlotCurveConfigs->yScalePower = listItem->data(Qt::UserRole + 2).toInt(&parseOK);
|
||||
if(!parseOK)
|
||||
newPlotCurveConfigs->yScalePower = 0;
|
||||
|
||||
QVariant varColor = listItem->data(Qt::UserRole + 3);
|
||||
int rgb = varColor.toInt(&parseOK);
|
||||
if(!parseOK)
|
||||
newPlotCurveConfigs->color = QColor(Qt::black).rgb();
|
||||
else
|
||||
newPlotCurveConfigs->color = (QRgb)rgb;
|
||||
|
||||
m_PlotCurveConfigs.append(newPlotCurveConfigs);
|
||||
}
|
||||
|
||||
m_config->replacePlotCurveConfig(m_PlotCurveConfigs);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Add a new curve to the plot.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_btnAddCurve_clicked()
|
||||
{
|
||||
bool parseOK = false;
|
||||
QString uavObject = options_page->cmbUAVObjects->currentText();
|
||||
QString uavField = options_page->cmbUAVField->currentText();
|
||||
int scale = options_page->cmbScale->itemData(options_page->cmbScale->currentIndex()).toInt(&parseOK);
|
||||
|
||||
if(!parseOK)
|
||||
scale = 0;
|
||||
|
||||
//TODO: Find an existing plot curve config based on the uavobject and uav field. If it
|
||||
//exists, update it, else add a new one.
|
||||
|
||||
QVariant varColor = (int)QColor(options_page->btnColor->text()).rgb();
|
||||
|
||||
addPlotCurveConfig(uavObject,uavField,scale,varColor);
|
||||
|
||||
options_page->lstCurves->setCurrentRow(options_page->lstCurves->count() - 1);
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::addPlotCurveConfig(QString uavObject, QString uavField, int scale, QVariant varColor)
|
||||
{
|
||||
bool parseOK = false;
|
||||
|
||||
//Add a new curve config to the list
|
||||
QString listItemDisplayText = uavObject + "." + uavField;
|
||||
options_page->lstCurves->addItem(listItemDisplayText);
|
||||
QListWidgetItem *listWidgetItem = options_page->lstCurves->item(options_page->lstCurves->count() - 1);
|
||||
|
||||
//Set the properties of the newly added list item
|
||||
QRgb rgbColor = (QRgb)varColor.toInt(&parseOK);
|
||||
QColor color = QColor( rgbColor );
|
||||
listWidgetItem->setText(listItemDisplayText);
|
||||
listWidgetItem->setTextColor( color );
|
||||
|
||||
//Store some additional data for the plot curve on the list item
|
||||
listWidgetItem->setData(Qt::UserRole + 0,QVariant(uavObject));
|
||||
listWidgetItem->setData(Qt::UserRole + 1,QVariant(uavField));
|
||||
listWidgetItem->setData(Qt::UserRole + 2,QVariant(scale));
|
||||
listWidgetItem->setData(Qt::UserRole + 3,varColor);
|
||||
}
|
||||
|
||||
/*!
|
||||
Remove a curve config from the plot.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_btnRemoveCurve_clicked()
|
||||
{
|
||||
options_page->lstCurves->takeItem(options_page->lstCurves->currentIndex().row());
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::finish()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
When a different plot curve config is selected, populate its values into the widgets.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_lstCurves_currentRowChanged(int currentRow)
|
||||
{
|
||||
setYAxisWidgetFromPlotCurve();
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file scopegadgetoptionspage.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ScopePlugin Scope Gadget Plugin
|
||||
* @{
|
||||
* @brief The scope Gadget, graphically plots the states of UAVObjects
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "scopegadgetoptionspage.h"
|
||||
#include "scopegadgetconfiguration.h"
|
||||
#include "ui_scopegadgetoptionspage.h"
|
||||
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "uavobjects/uavdataobject.h"
|
||||
|
||||
|
||||
|
||||
ScopeGadgetOptionsPage::ScopeGadgetOptionsPage(ScopeGadgetConfiguration *config, QObject *parent) :
|
||||
IOptionsPage(parent),
|
||||
m_config(config)
|
||||
{
|
||||
//nothing to do here...
|
||||
}
|
||||
|
||||
//creates options page widget (uses the UI file)
|
||||
QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent)
|
||||
{
|
||||
options_page = new Ui::ScopeGadgetOptionsPage();
|
||||
//main widget
|
||||
QWidget *optionsPageWidget = new QWidget;
|
||||
//main layout
|
||||
options_page->setupUi(optionsPageWidget);
|
||||
|
||||
options_page->cmbPlotType->addItem("Sequencial Plot","");
|
||||
options_page->cmbPlotType->addItem("Chronological Plot","");
|
||||
|
||||
// Fills the combo boxes for the UAVObjects
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
QList< QList<UAVDataObject*> > objList = objManager->getDataObjects();
|
||||
foreach (QList<UAVDataObject*> list, objList) {
|
||||
foreach (UAVDataObject* obj, list) {
|
||||
options_page->cmbUAVObjects->addItem(obj->getName());
|
||||
}
|
||||
}
|
||||
|
||||
//Connect signals to slots cmbUAVObjects.currentIndexChanged
|
||||
connect(options_page->cmbUAVObjects, SIGNAL(currentIndexChanged(QString)), this, SLOT(on_cmbUAVObjects_currentIndexChanged(QString)));
|
||||
|
||||
if(options_page->cmbUAVObjects->currentIndex() >= 0)
|
||||
on_cmbUAVObjects_currentIndexChanged(options_page->cmbUAVObjects->currentText());
|
||||
|
||||
options_page->cmbScale->addItem("E-9", -9);
|
||||
options_page->cmbScale->addItem("E-6", -6);
|
||||
options_page->cmbScale->addItem("E-5",-5);
|
||||
options_page->cmbScale->addItem("E-4",-4);
|
||||
options_page->cmbScale->addItem("E-3",-3);
|
||||
options_page->cmbScale->addItem("E-2",-2);
|
||||
options_page->cmbScale->addItem("E-1",-1);
|
||||
options_page->cmbScale->addItem("E0",0);
|
||||
options_page->cmbScale->addItem("E1",1);
|
||||
options_page->cmbScale->addItem("E2",2);
|
||||
options_page->cmbScale->addItem("E3",3);
|
||||
options_page->cmbScale->addItem("E4",4);
|
||||
options_page->cmbScale->addItem("E5",5);
|
||||
options_page->cmbScale->addItem("E6",6);
|
||||
options_page->cmbScale->addItem("E9",9);
|
||||
options_page->cmbScale->addItem("E12",12);
|
||||
options_page->cmbScale->setCurrentIndex(7);
|
||||
|
||||
//Set widget values from settings
|
||||
options_page->cmbPlotType->setCurrentIndex(m_config->plotType());
|
||||
options_page->spnDataSize->setValue(m_config->dataSize());
|
||||
options_page->spnRefreshInterval->setValue(m_config->refreshInterval());
|
||||
|
||||
//add the configured curves
|
||||
foreach (PlotCurveConfiguration* plotData, m_config->plotCurveConfigs()) {
|
||||
|
||||
QString uavObject = plotData->uavObject;
|
||||
QString uavField = plotData->uavField;
|
||||
int scale = plotData->yScalePower;
|
||||
QVariant varColor = plotData->color;
|
||||
|
||||
addPlotCurveConfig(uavObject,uavField,scale,varColor);
|
||||
}
|
||||
|
||||
if(m_config->plotCurveConfigs().count() > 0)
|
||||
options_page->lstCurves->setCurrentRow(0, QItemSelectionModel::ClearAndSelect);
|
||||
|
||||
connect(options_page->btnAddCurve, SIGNAL(clicked()), this, SLOT(on_btnAddCurve_clicked()));
|
||||
connect(options_page->btnRemoveCurve, SIGNAL(clicked()), this, SLOT(on_btnRemoveCurve_clicked()));
|
||||
connect(options_page->lstCurves, SIGNAL(currentRowChanged(int)), this, SLOT(on_lstCurves_currentRowChanged(int)));
|
||||
connect(options_page->btnColor, SIGNAL(clicked()), this, SLOT(on_btnColor_clicked()));
|
||||
|
||||
setYAxisWidgetFromPlotCurve();
|
||||
|
||||
return optionsPageWidget;
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::on_btnColor_clicked()
|
||||
{
|
||||
QColor color = QColorDialog::getColor( QColor(options_page->btnColor->text()), options_page->widget);
|
||||
if (color.isValid()) {
|
||||
setButtonColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Populate the widgets that containts the configs for the Y-Axis from
|
||||
the selected plot curve
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::setYAxisWidgetFromPlotCurve()
|
||||
{
|
||||
bool parseOK = false;
|
||||
QListWidgetItem* listItem = options_page->lstCurves->currentItem();
|
||||
|
||||
if(listItem == 0)
|
||||
return;
|
||||
|
||||
int currentIndex = options_page->cmbUAVObjects->findText( listItem->data(Qt::UserRole + 0).toString());
|
||||
options_page->cmbUAVObjects->setCurrentIndex(currentIndex);
|
||||
|
||||
currentIndex = options_page->cmbUAVField->findText( listItem->data(Qt::UserRole + 1).toString());
|
||||
options_page->cmbUAVField->setCurrentIndex(currentIndex);
|
||||
|
||||
currentIndex = options_page->cmbScale->findData( listItem->data(Qt::UserRole + 2), Qt::UserRole, Qt::MatchExactly);
|
||||
options_page->cmbScale->setCurrentIndex(currentIndex);
|
||||
|
||||
QVariant varColor = listItem->data(Qt::UserRole + 3);
|
||||
int rgb = varColor.toInt(&parseOK);
|
||||
|
||||
setButtonColor(QColor((QRgb)rgb));
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::setButtonColor(const QColor &color)
|
||||
{
|
||||
options_page->btnColor->setText(color.name());
|
||||
options_page->btnColor->setPalette(QPalette(color));
|
||||
options_page->btnColor->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief When a new UAVObject is selected, populate the UAVObject field combo box with the correct values.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_cmbUAVObjects_currentIndexChanged(QString val)
|
||||
{
|
||||
options_page->cmbUAVField->clear();
|
||||
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>( objManager->getObject(val) );
|
||||
|
||||
QList<UAVObjectField*> fieldList = obj->getFields();
|
||||
foreach (UAVObjectField* field, fieldList) {
|
||||
options_page->cmbUAVField->addItem(field->getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user presses apply or OK.
|
||||
*
|
||||
* Saves the current values
|
||||
*
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::apply()
|
||||
{
|
||||
bool parseOK = false;
|
||||
|
||||
//Apply configuration changes
|
||||
m_config->setPlotType(options_page->cmbPlotType->currentIndex());
|
||||
m_config->setDataSize(options_page->spnDataSize->value());
|
||||
m_config->setRefreashInterval(options_page->spnRefreshInterval->value());
|
||||
|
||||
QList<PlotCurveConfiguration*> m_PlotCurveConfigs;
|
||||
for(int iIndex = 0; iIndex < options_page->lstCurves->count();iIndex++) {
|
||||
QListWidgetItem* listItem = options_page->lstCurves->item(iIndex);
|
||||
|
||||
PlotCurveConfiguration* newPlotCurveConfigs = new PlotCurveConfiguration();
|
||||
newPlotCurveConfigs->uavObject = listItem->data(Qt::UserRole + 0).toString();
|
||||
newPlotCurveConfigs->uavField = listItem->data(Qt::UserRole + 1).toString();
|
||||
newPlotCurveConfigs->yScalePower = listItem->data(Qt::UserRole + 2).toInt(&parseOK);
|
||||
if(!parseOK)
|
||||
newPlotCurveConfigs->yScalePower = 0;
|
||||
|
||||
QVariant varColor = listItem->data(Qt::UserRole + 3);
|
||||
int rgb = varColor.toInt(&parseOK);
|
||||
if(!parseOK)
|
||||
newPlotCurveConfigs->color = QColor(Qt::black).rgb();
|
||||
else
|
||||
newPlotCurveConfigs->color = (QRgb)rgb;
|
||||
|
||||
m_PlotCurveConfigs.append(newPlotCurveConfigs);
|
||||
}
|
||||
|
||||
m_config->replacePlotCurveConfig(m_PlotCurveConfigs);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Add a new curve to the plot.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_btnAddCurve_clicked()
|
||||
{
|
||||
bool parseOK = false;
|
||||
QString uavObject = options_page->cmbUAVObjects->currentText();
|
||||
QString uavField = options_page->cmbUAVField->currentText();
|
||||
int scale = options_page->cmbScale->itemData(options_page->cmbScale->currentIndex()).toInt(&parseOK);
|
||||
|
||||
if(!parseOK)
|
||||
scale = 0;
|
||||
|
||||
//TODO: Find an existing plot curve config based on the uavobject and uav field. If it
|
||||
//exists, update it, else add a new one.
|
||||
|
||||
QVariant varColor = (int)QColor(options_page->btnColor->text()).rgb();
|
||||
|
||||
addPlotCurveConfig(uavObject,uavField,scale,varColor);
|
||||
|
||||
options_page->lstCurves->setCurrentRow(options_page->lstCurves->count() - 1);
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::addPlotCurveConfig(QString uavObject, QString uavField, int scale, QVariant varColor)
|
||||
{
|
||||
bool parseOK = false;
|
||||
|
||||
//Add a new curve config to the list
|
||||
QString listItemDisplayText = uavObject + "." + uavField;
|
||||
options_page->lstCurves->addItem(listItemDisplayText);
|
||||
QListWidgetItem *listWidgetItem = options_page->lstCurves->item(options_page->lstCurves->count() - 1);
|
||||
|
||||
//Set the properties of the newly added list item
|
||||
QRgb rgbColor = (QRgb)varColor.toInt(&parseOK);
|
||||
QColor color = QColor( rgbColor );
|
||||
listWidgetItem->setText(listItemDisplayText);
|
||||
listWidgetItem->setTextColor( color );
|
||||
|
||||
//Store some additional data for the plot curve on the list item
|
||||
listWidgetItem->setData(Qt::UserRole + 0,QVariant(uavObject));
|
||||
listWidgetItem->setData(Qt::UserRole + 1,QVariant(uavField));
|
||||
listWidgetItem->setData(Qt::UserRole + 2,QVariant(scale));
|
||||
listWidgetItem->setData(Qt::UserRole + 3,varColor);
|
||||
}
|
||||
|
||||
/*!
|
||||
Remove a curve config from the plot.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_btnRemoveCurve_clicked()
|
||||
{
|
||||
options_page->lstCurves->takeItem(options_page->lstCurves->currentIndex().row());
|
||||
}
|
||||
|
||||
void ScopeGadgetOptionsPage::finish()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
When a different plot curve config is selected, populate its values into the widgets.
|
||||
*/
|
||||
void ScopeGadgetOptionsPage::on_lstCurves_currentRowChanged(int currentRow)
|
||||
{
|
||||
setYAxisWidgetFromPlotCurve();
|
||||
}
|
||||
|
@ -1,300 +1,328 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file scopegadgetwidget.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ScopePlugin Scope Gadget Plugin
|
||||
* @{
|
||||
* @brief The scope Gadget, graphically plots the states of UAVObjects
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "scopegadgetwidget.h"
|
||||
|
||||
#include "qwt/src/qwt_plot_curve.h"
|
||||
#include "qwt/src/qwt_legend.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
|
||||
|
||||
TestDataGen* ScopeGadgetWidget::testDataGen;
|
||||
|
||||
ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
|
||||
{
|
||||
// if(testDataGen == 0)
|
||||
// testDataGen = new TestDataGen();
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::preparePlot(PlotType plotType)
|
||||
{
|
||||
m_plotType = plotType;
|
||||
|
||||
clearCurvePlots();
|
||||
|
||||
setMinimumSize(64, 64);
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
// Show a title
|
||||
setTitle("Scope");
|
||||
|
||||
// Show a legend at the bottom
|
||||
if (legend() == 0) {
|
||||
QwtLegend *legend = new QwtLegend();
|
||||
legend->setFrameStyle(QFrame::Box | QFrame::Sunken);
|
||||
insertLegend(legend, QwtPlot::BottomLegend);
|
||||
}
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::setupSequencialPlot()
|
||||
{
|
||||
preparePlot(SequencialPlot);
|
||||
|
||||
setAxisTitle(QwtPlot::xBottom, "Index");
|
||||
setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw());
|
||||
setAxisScale(QwtPlot::xBottom, 0, m_xWindowSize);
|
||||
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::setupChronoPlot()
|
||||
{
|
||||
preparePlot(ChronoPlot);
|
||||
|
||||
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);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
|
||||
/*
|
||||
In situations, when there is a label at the most right position of the
|
||||
scale, additional space is needed to display the overlapping part
|
||||
of the label would be taken by reducing the width of scale and canvas.
|
||||
To avoid this "jumping canvas" effect, we add a permanent margin.
|
||||
We don't need to do the same for the left border, because there
|
||||
is enough space for the overlapping label below the left scale.
|
||||
*/
|
||||
|
||||
QwtScaleWidget *scaleWidget = axisWidget(QwtPlot::xBottom);
|
||||
const int fmh = QFontMetrics(scaleWidget->font()).height();
|
||||
scaleWidget->setMinBorderDist(0, fmh / 2);
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavField, int scaleOrderFactor, QPen pen)
|
||||
{
|
||||
PlotData* plotData;
|
||||
|
||||
if (m_plotType == SequencialPlot)
|
||||
plotData = new SequencialPlotData(uavObject, uavField);
|
||||
else if (m_plotType == ChronoPlot)
|
||||
plotData = new ChronoPlotData(uavObject, uavField, m_refreshInterval);
|
||||
//else if (m_plotType == UAVObjectPlot)
|
||||
// plotData = new UAVObjectPlotData(uavObject, uavField);
|
||||
|
||||
plotData->m_xWindowSize = m_xWindowSize;
|
||||
plotData->scalePower = scaleOrderFactor;
|
||||
|
||||
//If the y-bounds are supplied, set them
|
||||
if (plotData->yMinimum != plotData->yMaximum)
|
||||
setAxisScale(QwtPlot::yLeft, plotData->yMinimum, plotData->yMaximum);
|
||||
|
||||
//Create the curve
|
||||
QString curveName = (plotData->uavObject) + "." + (plotData->uavField);
|
||||
QwtPlotCurve* plotCurve = new QwtPlotCurve(curveName);
|
||||
plotCurve->setPen(pen);
|
||||
plotCurve->setData(*plotData->xData, *plotData->yData);
|
||||
plotCurve->attach(this);
|
||||
plotData->curve = plotCurve;
|
||||
|
||||
//Keep the curve details for later
|
||||
m_curvesData.insert(curveName, plotData);
|
||||
|
||||
//Get the object to monitor
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject((plotData->uavObject)));
|
||||
|
||||
//Link to the signal of new data only if this UAVObject has not been to connected yet
|
||||
if (!m_connectedUAVObjects.contains(obj->getName())) {
|
||||
m_connectedUAVObjects.append(obj->getName());
|
||||
connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*)));
|
||||
}
|
||||
|
||||
connect(plotData, SIGNAL(dataChanged()), this, SLOT(replotNewData()));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
replot();
|
||||
}
|
||||
|
||||
|
||||
void ScopeGadgetWidget::setupExamplePlot()
|
||||
{
|
||||
preparePlot(SequencialPlot);
|
||||
|
||||
// Show the axes
|
||||
|
||||
setAxisTitle(xBottom, "x");
|
||||
setAxisTitle(yLeft, "y");
|
||||
|
||||
// Calculate the data, 500 points each
|
||||
const int points = 500;
|
||||
double x[ points ];
|
||||
double sn[ points ];
|
||||
double cs[ points ];
|
||||
double sg[ points ];
|
||||
|
||||
for (int i = 0; i < points; i++) {
|
||||
x[i] = (3.0 * 3.14 / double(points)) * double(i);
|
||||
sn[i] = 2.0 * sin(x[i]);
|
||||
cs[i] = 3.0 * cos(x[i]);
|
||||
sg[i] = (sn[i] > 0) ? 1 : ((sn[i] < 0) ? -1 : 0);
|
||||
}
|
||||
|
||||
// add curves
|
||||
QwtPlotCurve *curve1 = new QwtPlotCurve("Curve 1");
|
||||
curve1->setPen(QPen(Qt::blue));
|
||||
QwtPlotCurve *curve2 = new QwtPlotCurve("Curve 2");
|
||||
curve2->setPen(QPen(Qt::red));
|
||||
QwtPlotCurve *curve3 = new QwtPlotCurve("Curve 3");
|
||||
curve3->setPen(QPen(Qt::green));
|
||||
|
||||
// copy the data into the curves
|
||||
curve1->setData(x, sn, points);
|
||||
curve2->setData(x, cs, points);
|
||||
curve3->setData(x, sg, points);
|
||||
|
||||
|
||||
|
||||
curve1->attach(this);
|
||||
curve2->attach(this);
|
||||
curve3->attach(this);
|
||||
|
||||
|
||||
|
||||
// finally, refresh the plot
|
||||
replot();
|
||||
}
|
||||
|
||||
|
||||
ScopeGadgetWidget::~ScopeGadgetWidget()
|
||||
{
|
||||
//Get the object to de-monitor
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
foreach(QString uavObjName, m_connectedUAVObjects) {
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(uavObjName));
|
||||
disconnect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*)));
|
||||
}
|
||||
|
||||
clearCurvePlots();
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::clearCurvePlots()
|
||||
{
|
||||
foreach(PlotData* plotData, m_curvesData.values()) {
|
||||
plotData->curve->detach();
|
||||
|
||||
delete plotData->curve;
|
||||
delete plotData;
|
||||
}
|
||||
|
||||
m_curvesData.clear();
|
||||
}
|
||||
|
||||
TestDataGen::TestDataGen()
|
||||
{
|
||||
// Get required UAVObjects
|
||||
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager* objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
altActual = AltitudeActual::GetInstance(objManager);
|
||||
gps = PositionActual::GetInstance(objManager);
|
||||
|
||||
//Setup timer
|
||||
timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(genTestData()));
|
||||
timer->start(5000);
|
||||
}
|
||||
|
||||
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.Pressure = 100;
|
||||
altActual->setData(altActualData);
|
||||
|
||||
|
||||
// Update gps objects
|
||||
PositionActual::DataFields gpsData;
|
||||
gpsData.Altitude = 0;
|
||||
gpsData.Heading = 0;
|
||||
gpsData.Groundspeed = 0;
|
||||
gpsData.Latitude = 0;
|
||||
gpsData.Longitude = 0;
|
||||
gpsData.Satellites = 10;
|
||||
gps->setData(gpsData);
|
||||
|
||||
testTime++;
|
||||
}
|
||||
|
||||
TestDataGen::~TestDataGen()
|
||||
{
|
||||
if (timer)
|
||||
timer->stop();
|
||||
|
||||
delete timer;
|
||||
}
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file scopegadgetwidget.cpp
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ScopePlugin Scope Gadget Plugin
|
||||
* @{
|
||||
* @brief The scope Gadget, graphically plots the states of UAVObjects
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "uavobjects/uavobjectmanager.h"
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "scopegadgetwidget.h"
|
||||
|
||||
#include "qwt/src/qwt_plot_curve.h"
|
||||
#include "qwt/src/qwt_legend.h"
|
||||
#include "qwt/src/qwt_legend_item.h"
|
||||
#include "qwt/src/qwt_plot_grid.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <QDebug>
|
||||
#include <QColor>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QPushButton>
|
||||
|
||||
|
||||
TestDataGen* ScopeGadgetWidget::testDataGen;
|
||||
|
||||
ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::preparePlot(PlotType plotType)
|
||||
{
|
||||
m_plotType = plotType;
|
||||
|
||||
clearCurvePlots();
|
||||
|
||||
setMinimumSize(64, 64);
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
// Show a title
|
||||
setTitle("Scope");
|
||||
|
||||
// Show a legend at the bottom
|
||||
if (legend() == 0) {
|
||||
QwtLegend *legend = new QwtLegend();
|
||||
legend->setItemMode(QwtLegend::CheckableItem);
|
||||
legend->setFrameStyle(QFrame::Box | QFrame::Sunken);
|
||||
insertLegend(legend, QwtPlot::BottomLegend);
|
||||
}
|
||||
|
||||
connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)),this, SLOT(showCurve(QwtPlotItem *, bool)));
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::showCurve(QwtPlotItem *item, bool on)
|
||||
{
|
||||
item->setVisible(!on);
|
||||
QWidget *w = legend()->find(item);
|
||||
if ( w && w->inherits("QwtLegendItem") )
|
||||
((QwtLegendItem *)w)->setChecked(on);
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::setupSequencialPlot()
|
||||
{
|
||||
preparePlot(SequencialPlot);
|
||||
|
||||
setAxisTitle(QwtPlot::xBottom, "Index");
|
||||
setAxisScaleDraw(QwtPlot::xBottom, new QwtScaleDraw());
|
||||
setAxisScale(QwtPlot::xBottom, 0, m_xWindowSize);
|
||||
setAxisLabelRotation(QwtPlot::xBottom, 0.0);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::setupChronoPlot()
|
||||
{
|
||||
preparePlot(ChronoPlot);
|
||||
|
||||
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);
|
||||
setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
|
||||
|
||||
/*
|
||||
In situations, when there is a label at the most right position of the
|
||||
scale, additional space is needed to display the overlapping part
|
||||
of the label would be taken by reducing the width of scale and canvas.
|
||||
To avoid this "jumping canvas" effect, we add a permanent margin.
|
||||
We don't need to do the same for the left border, because there
|
||||
is enough space for the overlapping label below the left scale.
|
||||
*/
|
||||
|
||||
QwtScaleWidget *scaleWidget = axisWidget(QwtPlot::xBottom);
|
||||
const int fmh = QFontMetrics(scaleWidget->font()).height();
|
||||
scaleWidget->setMinBorderDist(0, fmh / 2);
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::addCurvePlot(QString uavObject, QString uavField, int scaleOrderFactor, QPen pen)
|
||||
{
|
||||
PlotData* plotData;
|
||||
|
||||
if (m_plotType == SequencialPlot)
|
||||
plotData = new SequencialPlotData(uavObject, uavField);
|
||||
else if (m_plotType == ChronoPlot)
|
||||
plotData = new ChronoPlotData(uavObject, uavField, m_refreshInterval);
|
||||
//else if (m_plotType == UAVObjectPlot)
|
||||
// plotData = new UAVObjectPlotData(uavObject, uavField);
|
||||
|
||||
plotData->m_xWindowSize = m_xWindowSize;
|
||||
plotData->scalePower = scaleOrderFactor;
|
||||
|
||||
//If the y-bounds are supplied, set them
|
||||
if (plotData->yMinimum != plotData->yMaximum)
|
||||
setAxisScale(QwtPlot::yLeft, plotData->yMinimum, plotData->yMaximum);
|
||||
|
||||
//Create the curve
|
||||
QString curveName = (plotData->uavObject) + "." + (plotData->uavField);
|
||||
QwtPlotCurve* plotCurve = new QwtPlotCurve(curveName);
|
||||
plotCurve->setPen(pen);
|
||||
plotCurve->setData(*plotData->xData, *plotData->yData);
|
||||
plotCurve->attach(this);
|
||||
plotData->curve = plotCurve;
|
||||
|
||||
|
||||
//Keep the curve details for later
|
||||
m_curvesData.insert(curveName, plotData);
|
||||
|
||||
//Get the object to monitor
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject((plotData->uavObject)));
|
||||
|
||||
//Link to the signal of new data only if this UAVObject has not been to connected yet
|
||||
if (!m_connectedUAVObjects.contains(obj->getName())) {
|
||||
m_connectedUAVObjects.append(obj->getName());
|
||||
connect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*)));
|
||||
}
|
||||
|
||||
connect(plotData, SIGNAL(dataChanged()), this, SLOT(replotNewData()));
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
replot();
|
||||
}
|
||||
|
||||
|
||||
void ScopeGadgetWidget::setupExamplePlot()
|
||||
{
|
||||
preparePlot(SequencialPlot);
|
||||
|
||||
// Show the axes
|
||||
|
||||
setAxisTitle(xBottom, "x");
|
||||
setAxisTitle(yLeft, "y");
|
||||
|
||||
// Calculate the data, 500 points each
|
||||
const int points = 500;
|
||||
double x[ points ];
|
||||
double sn[ points ];
|
||||
double cs[ points ];
|
||||
double sg[ points ];
|
||||
|
||||
for (int i = 0; i < points; i++) {
|
||||
x[i] = (3.0 * 3.14 / double(points)) * double(i);
|
||||
sn[i] = 2.0 * sin(x[i]);
|
||||
cs[i] = 3.0 * cos(x[i]);
|
||||
sg[i] = (sn[i] > 0) ? 1 : ((sn[i] < 0) ? -1 : 0);
|
||||
}
|
||||
|
||||
// add curves
|
||||
QwtPlotCurve *curve1 = new QwtPlotCurve("Curve 1");
|
||||
curve1->setPen(QPen(Qt::blue));
|
||||
QwtPlotCurve *curve2 = new QwtPlotCurve("Curve 2");
|
||||
curve2->setPen(QPen(Qt::red));
|
||||
QwtPlotCurve *curve3 = new QwtPlotCurve("Curve 3");
|
||||
curve3->setPen(QPen(Qt::green));
|
||||
|
||||
// copy the data into the curves
|
||||
curve1->setData(x, sn, points);
|
||||
curve2->setData(x, cs, points);
|
||||
curve3->setData(x, sg, points);
|
||||
|
||||
|
||||
|
||||
curve1->attach(this);
|
||||
curve2->attach(this);
|
||||
curve3->attach(this);
|
||||
|
||||
|
||||
|
||||
// finally, refresh the plot
|
||||
replot();
|
||||
}
|
||||
|
||||
|
||||
ScopeGadgetWidget::~ScopeGadgetWidget()
|
||||
{
|
||||
//Get the object to de-monitor
|
||||
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
foreach(QString uavObjName, m_connectedUAVObjects) {
|
||||
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objManager->getObject(uavObjName));
|
||||
disconnect(obj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(uavObjectReceived(UAVObject*)));
|
||||
}
|
||||
|
||||
clearCurvePlots();
|
||||
}
|
||||
|
||||
void ScopeGadgetWidget::clearCurvePlots()
|
||||
{
|
||||
foreach(PlotData* plotData, m_curvesData.values()) {
|
||||
plotData->curve->detach();
|
||||
|
||||
delete plotData->curve;
|
||||
delete plotData;
|
||||
}
|
||||
|
||||
m_curvesData.clear();
|
||||
}
|
||||
|
||||
TestDataGen::TestDataGen()
|
||||
{
|
||||
// Get required UAVObjects
|
||||
ExtensionSystem::PluginManager* pm = ExtensionSystem::PluginManager::instance();
|
||||
UAVObjectManager* objManager = pm->getObject<UAVObjectManager>();
|
||||
|
||||
altActual = AltitudeActual::GetInstance(objManager);
|
||||
gps = PositionActual::GetInstance(objManager);
|
||||
|
||||
//Setup timer
|
||||
timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), this, SLOT(genTestData()));
|
||||
timer->start(2);
|
||||
}
|
||||
|
||||
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.Pressure = 100;
|
||||
altActual->setData(altActualData);
|
||||
|
||||
|
||||
// Update gps objects
|
||||
PositionActual::DataFields gpsData;
|
||||
gpsData.Altitude = 0;
|
||||
gpsData.Heading = 0;
|
||||
gpsData.Groundspeed = 0;
|
||||
gpsData.Latitude = 0;
|
||||
gpsData.Longitude = 0;
|
||||
gpsData.Satellites = 10;
|
||||
gps->setData(gpsData);
|
||||
|
||||
testTime += 0.02;
|
||||
}
|
||||
|
||||
TestDataGen::~TestDataGen()
|
||||
{
|
||||
if (timer)
|
||||
timer->stop();
|
||||
|
||||
delete timer;
|
||||
}
|
||||
|
@ -1,133 +1,134 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file scopegadgetwidget.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @addtogroup GCSPlugins GCS Plugins
|
||||
* @{
|
||||
* @addtogroup ScopePlugin Scope Gadget Plugin
|
||||
* @{
|
||||
* @brief The scope Gadget, graphically plots the states of UAVObjects
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SCOPEGADGETWIDGET_H_
|
||||
#define SCOPEGADGETWIDGET_H_
|
||||
|
||||
#include "plotdata.h"
|
||||
#include "uavobjects/uavobject.h"
|
||||
#include "uavobjects/altitudeactual.h"
|
||||
#include "uavobjects/positionactual.h"
|
||||
|
||||
|
||||
#include "qwt/src/qwt.h"
|
||||
#include "qwt/src/qwt_plot.h"
|
||||
#include "qwt/src/qwt_plot_curve.h"
|
||||
#include "qwt/src/qwt_scale_draw.h"
|
||||
#include "qwt/src/qwt_scale_widget.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
#include <QVector>
|
||||
|
||||
/*!
|
||||
\brief This class is used to render the time values on the horizontal axis for the
|
||||
ChronoPlot.
|
||||
*/
|
||||
class TimeScaleDraw : public QwtScaleDraw
|
||||
{
|
||||
public:
|
||||
TimeScaleDraw() {
|
||||
baseTime = QDateTime::currentDateTime().toTime_t();
|
||||
}
|
||||
virtual QwtText label(double v) const {
|
||||
QDateTime upTime = QDateTime::fromTime_t((uint)v);
|
||||
return upTime.toLocalTime().toString("hh:mm:ss");
|
||||
}
|
||||
private:
|
||||
double baseTime;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief This class is used to inject UAVTalk messages for testing.
|
||||
*/
|
||||
class TestDataGen : QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
TestDataGen();
|
||||
~TestDataGen();
|
||||
|
||||
private:
|
||||
AltitudeActual* altActual;
|
||||
PositionActual* gps;
|
||||
|
||||
QTimer *timer;
|
||||
double testTime;
|
||||
|
||||
private slots:
|
||||
void genTestData();
|
||||
};
|
||||
|
||||
|
||||
class ScopeGadgetWidget : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScopeGadgetWidget(QWidget *parent = 0);
|
||||
~ScopeGadgetWidget();
|
||||
|
||||
void setupSequencialPlot();
|
||||
void setupChronoPlot();
|
||||
void setupUAVObjectPlot();
|
||||
PlotType plotType(){return m_plotType;}
|
||||
|
||||
void setXWindowSize(double xWindowSize){m_xWindowSize = xWindowSize;}
|
||||
double xWindowSize(){return m_xWindowSize;}
|
||||
void setRefreshInterval(double refreshInterval){m_refreshInterval = refreshInterval;}
|
||||
int refreshInterval(){return m_refreshInterval;}
|
||||
|
||||
|
||||
void addCurvePlot(QString uavObject, QString uavField, int scaleOrderFactor = 0, QPen pen = QPen(Qt::black));
|
||||
void removeCurvePlot(QString uavObject, QString uavField);
|
||||
void clearCurvePlots();
|
||||
|
||||
|
||||
private slots:
|
||||
void uavObjectReceived(UAVObject*);
|
||||
void replotNewData();
|
||||
|
||||
private:
|
||||
|
||||
void preparePlot(PlotType plotType);
|
||||
void setupExamplePlot();
|
||||
|
||||
PlotType m_plotType;
|
||||
|
||||
double m_xWindowSize;
|
||||
int m_refreshInterval;
|
||||
QList<QString> m_connectedUAVObjects;
|
||||
QMap<QString, PlotData*> m_curvesData;
|
||||
|
||||
static TestDataGen* testDataGen;
|
||||
};
|
||||
|
||||
|
||||
#endif /* SCOPEGADGETWIDGET_H_ */
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file scopegadgetwidget.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Scope Plugin Gadget Widget
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup scopeplugin
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SCOPEGADGETWIDGET_H_
|
||||
#define SCOPEGADGETWIDGET_H_
|
||||
|
||||
#include "plotdata.h"
|
||||
#include "uavobjects/uavobject.h"
|
||||
#include "uavobjects/altitudeactual.h"
|
||||
#include "uavobjects/positionactual.h"
|
||||
|
||||
|
||||
#include "qwt/src/qwt.h"
|
||||
#include "qwt/src/qwt_plot.h"
|
||||
#include "qwt/src/qwt_plot_curve.h"
|
||||
#include "qwt/src/qwt_scale_draw.h"
|
||||
#include "qwt/src/qwt_scale_widget.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QTime>
|
||||
#include <QVector>
|
||||
|
||||
/*!
|
||||
\brief This class is used to render the time values on the horizontal axis for the
|
||||
ChronoPlot.
|
||||
*/
|
||||
class TimeScaleDraw : public QwtScaleDraw
|
||||
{
|
||||
public:
|
||||
TimeScaleDraw() {
|
||||
baseTime = QDateTime::currentDateTime().toTime_t();
|
||||
}
|
||||
virtual QwtText label(double v) const {
|
||||
QDateTime upTime = QDateTime::fromTime_t((uint)v);
|
||||
return upTime.toLocalTime().toString("hh:mm:ss");
|
||||
}
|
||||
private:
|
||||
double baseTime;
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief This class is used to inject UAVTalk messages for testing.
|
||||
*/
|
||||
class TestDataGen : QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
TestDataGen();
|
||||
~TestDataGen();
|
||||
|
||||
private:
|
||||
AltitudeActual* altActual;
|
||||
PositionActual* gps;
|
||||
|
||||
QTimer *timer;
|
||||
double testTime;
|
||||
|
||||
private slots:
|
||||
void genTestData();
|
||||
};
|
||||
|
||||
|
||||
class ScopeGadgetWidget : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScopeGadgetWidget(QWidget *parent = 0);
|
||||
~ScopeGadgetWidget();
|
||||
|
||||
void setupSequencialPlot();
|
||||
void setupChronoPlot();
|
||||
void setupUAVObjectPlot();
|
||||
PlotType plotType(){return m_plotType;}
|
||||
|
||||
void setXWindowSize(double xWindowSize){m_xWindowSize = xWindowSize;}
|
||||
double xWindowSize(){return m_xWindowSize;}
|
||||
void setRefreshInterval(double refreshInterval){m_refreshInterval = refreshInterval;}
|
||||
int refreshInterval(){return m_refreshInterval;}
|
||||
|
||||
|
||||
void addCurvePlot(QString uavObject, QString uavField, int scaleOrderFactor = 0, QPen pen = QPen(Qt::black));
|
||||
void removeCurvePlot(QString uavObject, QString uavField);
|
||||
void clearCurvePlots();
|
||||
|
||||
|
||||
private slots:
|
||||
void uavObjectReceived(UAVObject*);
|
||||
void replotNewData();
|
||||
void showCurve(QwtPlotItem *item, bool on);
|
||||
|
||||
private:
|
||||
|
||||
void preparePlot(PlotType plotType);
|
||||
void setupExamplePlot();
|
||||
|
||||
PlotType m_plotType;
|
||||
|
||||
double m_xWindowSize;
|
||||
int m_refreshInterval;
|
||||
QList<QString> m_connectedUAVObjects;
|
||||
QMap<QString, PlotData*> m_curvesData;
|
||||
|
||||
static TestDataGen* testDataGen;
|
||||
};
|
||||
|
||||
|
||||
#endif /* SCOPEGADGETWIDGET_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user