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

OP-294 Add logging to scope plugin.

First attempt to add logging to the scope gadget.
Logs a snapshot of data from the scope configuration at the same rate as the update timer set in the options page.
This has configurability via the options page for logging path.
File name is based on the configuration name and the date/time the logging starts.
This uses synchronous file writes in the update timer.

Tested to work on Win XP and Linux (Fedora 14)

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2634 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
andrew 2011-01-31 02:09:44 +00:00 committed by andrew
parent 880a68a788
commit 9c313ebb7a
8 changed files with 867 additions and 556 deletions

View File

@ -74,6 +74,15 @@ void ScopeGadget::loadConfiguration(IUAVGadgetConfiguration* config)
Qt::BevelJoin)
);
}
widget->setLoggingEnabled(sgConfig->getLoggingEnabled());
widget->setLoggingNewFileOnConnect(sgConfig->getLoggingNewFileOnConnect());
widget->setLoggingPath(sgConfig->getLoggingPath());
widget->csvLoggingStop();
widget->csvLoggingSetName(sgConfig->name());
widget->csvLoggingStart();
}
ScopeGadget::~ScopeGadget()

View File

@ -1,166 +1,183 @@
/**
******************************************************************************
*
* @file scopegadgetconfiguration.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 "scopegadgetconfiguration.h"
ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, QSettings* qSettings, QObject *parent) :
IUAVGadgetConfiguration(classId, parent),
m_plotType((int)ChronoPlot),
m_dataSize(60),
m_refreshInterval(1000)
{
uint currentStreamVersion = 0;
int plotCurveCount = 0;
//if a saved configuration exists load it
if(qSettings != 0) {
currentStreamVersion = qSettings->value("configurationStreamVersion").toUInt();
if(currentStreamVersion != m_configurationStreamVersion)
return;
m_plotType = qSettings->value("plotType").toInt();
m_dataSize = qSettings->value("dataSize").toInt();
m_refreshInterval = qSettings->value("refreshInterval").toInt();
plotCurveCount = qSettings->value("plotCurveCount").toInt();
for(int plotDatasLoadIndex = 0; plotDatasLoadIndex < plotCurveCount; plotDatasLoadIndex++)
{
QString uavObject;
QString uavField;
QRgb color;
qSettings->beginGroup(QString("plotCurve") + QString().number(plotDatasLoadIndex));
PlotCurveConfiguration* plotCurveConf = new PlotCurveConfiguration();
uavObject = qSettings->value("uavObject").toString();
plotCurveConf->uavObject = uavObject;
uavField = qSettings->value("uavField").toString();
plotCurveConf->uavField = uavField;
color = qSettings->value("color").value<QRgb>();
plotCurveConf->color = color;
plotCurveConf->yScalePower = qSettings->value("yScalePower").toInt();
plotCurveConf->yMinimum = qSettings->value("yMinimum").toDouble();
plotCurveConf->yMaximum = qSettings->value("yMaximum").toDouble();
m_PlotCurveConfigs.append(plotCurveConf);
qSettings->endGroup();
}
}
}
void ScopeGadgetConfiguration::clearPlotData()
{
PlotCurveConfiguration* poltCurveConfig;
while(m_PlotCurveConfigs.size() > 0)
{
poltCurveConfig = m_PlotCurveConfigs.first();
m_PlotCurveConfigs.pop_front();
delete poltCurveConfig;
}
}
/**
* Clones a configuration.
*
*/
IUAVGadgetConfiguration *ScopeGadgetConfiguration::clone()
{
int plotCurveCount = 0;
int plotDatasLoadIndex = 0;
ScopeGadgetConfiguration *m = new ScopeGadgetConfiguration(this->classId());
m->setPlotType(m_plotType);
m->setDataSize( m_dataSize);
m->setRefreashInterval( m_refreshInterval);
plotCurveCount = m_PlotCurveConfigs.size();
for(plotDatasLoadIndex = 0; plotDatasLoadIndex < plotCurveCount; plotDatasLoadIndex++)
{
PlotCurveConfiguration* currentPlotCurveConf = m_PlotCurveConfigs.at(plotDatasLoadIndex);
PlotCurveConfiguration* newPlotCurveConf = new PlotCurveConfiguration();
newPlotCurveConf->uavObject = currentPlotCurveConf->uavObject;
newPlotCurveConf->uavField = currentPlotCurveConf->uavField;
newPlotCurveConf->color = currentPlotCurveConf->color;
newPlotCurveConf->yScalePower = currentPlotCurveConf->yScalePower;
newPlotCurveConf->yMinimum = currentPlotCurveConf->yMinimum;
newPlotCurveConf->yMaximum = currentPlotCurveConf->yMaximum;
m->addPlotCurveConfig(newPlotCurveConf);
}
return m;
}
/**
* Saves a configuration.
*
*/
void ScopeGadgetConfiguration::saveConfig(QSettings* qSettings) const {
int plotCurveCount = m_PlotCurveConfigs.size();
int plotDatasLoadIndex = 0;
qSettings->setValue("configurationStreamVersion", m_configurationStreamVersion);
qSettings->setValue("plotType", m_plotType);
qSettings->setValue("dataSize", m_dataSize);
qSettings->setValue("refreshInterval", m_refreshInterval);
qSettings->setValue("plotCurveCount", plotCurveCount);
for(plotDatasLoadIndex = 0; plotDatasLoadIndex < plotCurveCount; plotDatasLoadIndex++)
{
qSettings->beginGroup(QString("plotCurve") + QString().number(plotDatasLoadIndex));
PlotCurveConfiguration* plotCurveConf = m_PlotCurveConfigs.at(plotDatasLoadIndex);
qSettings->setValue("uavObject", plotCurveConf->uavObject);
qSettings->setValue("uavField", plotCurveConf->uavField);
qSettings->setValue("color", plotCurveConf->color);
qSettings->setValue("yScalePower", plotCurveConf->yScalePower);
qSettings->setValue("yMinimum", plotCurveConf->yMinimum);
qSettings->setValue("yMaximum", plotCurveConf->yMaximum);
qSettings->endGroup();
}
}
void ScopeGadgetConfiguration::replacePlotCurveConfig(QList<PlotCurveConfiguration*> newPlotCurveConfigs)
{
clearPlotData();
m_PlotCurveConfigs.append(newPlotCurveConfigs);
}
ScopeGadgetConfiguration::~ScopeGadgetConfiguration()
{
clearPlotData();
}
/**
******************************************************************************
*
* @file scopegadgetconfiguration.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 "scopegadgetconfiguration.h"
ScopeGadgetConfiguration::ScopeGadgetConfiguration(QString classId, QSettings* qSettings, QObject *parent) :
IUAVGadgetConfiguration(classId, parent),
m_plotType((int)ChronoPlot),
m_dataSize(60),
m_refreshInterval(1000)
{
uint currentStreamVersion = 0;
int plotCurveCount = 0;
//if a saved configuration exists load it
if(qSettings != 0) {
currentStreamVersion = qSettings->value("configurationStreamVersion").toUInt();
if(currentStreamVersion != m_configurationStreamVersion)
return;
m_plotType = qSettings->value("plotType").toInt();
m_dataSize = qSettings->value("dataSize").toInt();
m_refreshInterval = qSettings->value("refreshInterval").toInt();
plotCurveCount = qSettings->value("plotCurveCount").toInt();
for(int plotDatasLoadIndex = 0; plotDatasLoadIndex < plotCurveCount; plotDatasLoadIndex++)
{
QString uavObject;
QString uavField;
QRgb color;
qSettings->beginGroup(QString("plotCurve") + QString().number(plotDatasLoadIndex));
PlotCurveConfiguration* plotCurveConf = new PlotCurveConfiguration();
uavObject = qSettings->value("uavObject").toString();
plotCurveConf->uavObject = uavObject;
uavField = qSettings->value("uavField").toString();
plotCurveConf->uavField = uavField;
color = qSettings->value("color").value<QRgb>();
plotCurveConf->color = color;
plotCurveConf->yScalePower = qSettings->value("yScalePower").toInt();
plotCurveConf->yMinimum = qSettings->value("yMinimum").toDouble();
plotCurveConf->yMaximum = qSettings->value("yMaximum").toDouble();
m_PlotCurveConfigs.append(plotCurveConf);
qSettings->endGroup();
}
m_LoggingEnabled = qSettings->value("LoggingEnabled").toBool();
m_LoggingNewFileOnConnect = qSettings->value("LoggingNewFileOnConnect").toBool();
m_LoggingPath = qSettings->value("LoggingPath").toString();
}
}
void ScopeGadgetConfiguration::clearPlotData()
{
PlotCurveConfiguration* poltCurveConfig;
while(m_PlotCurveConfigs.size() > 0)
{
poltCurveConfig = m_PlotCurveConfigs.first();
m_PlotCurveConfigs.pop_front();
delete poltCurveConfig;
}
}
/**
* Clones a configuration.
*
*/
IUAVGadgetConfiguration *ScopeGadgetConfiguration::clone()
{
int plotCurveCount = 0;
int plotDatasLoadIndex = 0;
ScopeGadgetConfiguration *m = new ScopeGadgetConfiguration(this->classId());
m->setPlotType(m_plotType);
m->setDataSize( m_dataSize);
m->setRefreashInterval( m_refreshInterval);
plotCurveCount = m_PlotCurveConfigs.size();
for(plotDatasLoadIndex = 0; plotDatasLoadIndex < plotCurveCount; plotDatasLoadIndex++)
{
PlotCurveConfiguration* currentPlotCurveConf = m_PlotCurveConfigs.at(plotDatasLoadIndex);
PlotCurveConfiguration* newPlotCurveConf = new PlotCurveConfiguration();
newPlotCurveConf->uavObject = currentPlotCurveConf->uavObject;
newPlotCurveConf->uavField = currentPlotCurveConf->uavField;
newPlotCurveConf->color = currentPlotCurveConf->color;
newPlotCurveConf->yScalePower = currentPlotCurveConf->yScalePower;
newPlotCurveConf->yMinimum = currentPlotCurveConf->yMinimum;
newPlotCurveConf->yMaximum = currentPlotCurveConf->yMaximum;
m->addPlotCurveConfig(newPlotCurveConf);
}
m->setLoggingEnabled(m_LoggingEnabled);
m->setLoggingNewFileOnConnect(m_LoggingNewFileOnConnect);
m->setLoggingPath(m_LoggingPath);
return m;
}
/**
* Saves a configuration.
*
*/
void ScopeGadgetConfiguration::saveConfig(QSettings* qSettings) const {
int plotCurveCount = m_PlotCurveConfigs.size();
int plotDatasLoadIndex = 0;
qSettings->setValue("configurationStreamVersion", m_configurationStreamVersion);
qSettings->setValue("plotType", m_plotType);
qSettings->setValue("dataSize", m_dataSize);
qSettings->setValue("refreshInterval", m_refreshInterval);
qSettings->setValue("plotCurveCount", plotCurveCount);
for(plotDatasLoadIndex = 0; plotDatasLoadIndex < plotCurveCount; plotDatasLoadIndex++)
{
qSettings->beginGroup(QString("plotCurve") + QString().number(plotDatasLoadIndex));
PlotCurveConfiguration* plotCurveConf = m_PlotCurveConfigs.at(plotDatasLoadIndex);
qSettings->setValue("uavObject", plotCurveConf->uavObject);
qSettings->setValue("uavField", plotCurveConf->uavField);
qSettings->setValue("color", plotCurveConf->color);
qSettings->setValue("yScalePower", plotCurveConf->yScalePower);
qSettings->setValue("yMinimum", plotCurveConf->yMinimum);
qSettings->setValue("yMaximum", plotCurveConf->yMaximum);
qSettings->endGroup();
}
qSettings->setValue("LoggingEnabled", m_LoggingEnabled);
qSettings->setValue("LoggingNewFileOnConnect", m_LoggingNewFileOnConnect);
qSettings->setValue("LoggingPath", m_LoggingPath);
}
void ScopeGadgetConfiguration::replacePlotCurveConfig(QList<PlotCurveConfiguration*> newPlotCurveConfigs)
{
clearPlotData();
m_PlotCurveConfigs.append(newPlotCurveConfigs);
}
ScopeGadgetConfiguration::~ScopeGadgetConfiguration()
{
clearPlotData();
}

View File

@ -1,86 +1,95 @@
/**
******************************************************************************
*
* @file scopegadgetconfiguration.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 SCOPEGADGETCONFIGURATION_H
#define SCOPEGADGETCONFIGURATION_H
#include "plotdata.h"
#include <coreplugin/iuavgadgetconfiguration.h>
#include <QVector>
using namespace Core;
struct PlotCurveConfiguration
{
QString uavObject;
QString uavField;
int yScalePower; //This is the power to which each value must be raised
QRgb color;
double yMinimum;
double yMaximum;
};
class ScopeGadgetConfiguration : public IUAVGadgetConfiguration
{
Q_OBJECT
public:
explicit ScopeGadgetConfiguration(QString classId, QSettings* qSettings = 0, QObject *parent = 0);
~ScopeGadgetConfiguration();
//configuration setter functions
void setPlotType(int value){m_plotType = value;}
void setDataSize(int value){m_dataSize = value;}
void setRefreashInterval(int value){m_refreshInterval = value;}
void addPlotCurveConfig(PlotCurveConfiguration* value){m_PlotCurveConfigs.append(value);}
void replacePlotCurveConfig(QList<PlotCurveConfiguration*> m_PlotCurveConfigs);
//configurations getter functions
int plotType(){return m_plotType;}
int dataSize(){return m_dataSize;}
int refreshInterval(){return m_refreshInterval;}
QList<PlotCurveConfiguration*> plotCurveConfigs(){return m_PlotCurveConfigs;}
void saveConfig(QSettings* settings) const;
IUAVGadgetConfiguration *clone();
private:
static const uint m_configurationStreamVersion = 1000;//Increment this if the stream format is not compatible with previous versions. This would cause existing configs to be discarded.
int m_plotType; //The type of the plot
int m_dataSize; //The size of the data buffer to render in the curve plot
int m_refreshInterval; //The interval to replot the curve widget. The data buffer is refresh as the data comes in.
QList<PlotCurveConfiguration*> m_PlotCurveConfigs;
void clearPlotData();
};
#endif // SCOPEGADGETCONFIGURATION_H
/**
******************************************************************************
*
* @file scopegadgetconfiguration.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 SCOPEGADGETCONFIGURATION_H
#define SCOPEGADGETCONFIGURATION_H
#include "plotdata.h"
#include <coreplugin/iuavgadgetconfiguration.h>
#include <QVector>
using namespace Core;
struct PlotCurveConfiguration
{
QString uavObject;
QString uavField;
int yScalePower; //This is the power to which each value must be raised
QRgb color;
double yMinimum;
double yMaximum;
};
class ScopeGadgetConfiguration : public IUAVGadgetConfiguration
{
Q_OBJECT
public:
explicit ScopeGadgetConfiguration(QString classId, QSettings* qSettings = 0, QObject *parent = 0);
~ScopeGadgetConfiguration();
//configuration setter functions
void setPlotType(int value){m_plotType = value;}
void setDataSize(int value){m_dataSize = value;}
void setRefreashInterval(int value){m_refreshInterval = value;}
void addPlotCurveConfig(PlotCurveConfiguration* value){m_PlotCurveConfigs.append(value);}
void replacePlotCurveConfig(QList<PlotCurveConfiguration*> m_PlotCurveConfigs);
//configurations getter functions
int plotType(){return m_plotType;}
int dataSize(){return m_dataSize;}
int refreshInterval(){return m_refreshInterval;}
QList<PlotCurveConfiguration*> plotCurveConfigs(){return m_PlotCurveConfigs;}
void saveConfig(QSettings* settings) const;
IUAVGadgetConfiguration *clone();
bool getLoggingEnabled(){return m_LoggingEnabled;};
bool getLoggingNewFileOnConnect(){return m_LoggingNewFileOnConnect;};
QString getLoggingPath(){return m_LoggingPath;};
void setLoggingEnabled(bool value){m_LoggingEnabled=value;};
void setLoggingNewFileOnConnect(bool value){m_LoggingNewFileOnConnect=value;};
void setLoggingPath(QString value){m_LoggingPath=value;};
private:
static const uint m_configurationStreamVersion = 1000;//Increment this if the stream format is not compatible with previous versions. This would cause existing configs to be discarded.
int m_plotType; //The type of the plot
int m_dataSize; //The size of the data buffer to render in the curve plot
int m_refreshInterval; //The interval to replot the curve widget. The data buffer is refresh as the data comes in.
QList<PlotCurveConfiguration*> m_PlotCurveConfigs;
void clearPlotData();
bool m_LoggingEnabled;
bool m_LoggingNewFileOnConnect;
QString m_LoggingPath;
};
#endif // SCOPEGADGETCONFIGURATION_H

View File

@ -116,6 +116,17 @@ QWidget* ScopeGadgetOptionsPage::createPage(QWidget *parent)
setYAxisWidgetFromPlotCurve();
//logging path setup
options_page->LoggingPath->setExpectedKind(Utils::PathChooser::Directory);
options_page->LoggingPath->setPromptDialogTitle(tr("Choose Logging Directory"));
options_page->LoggingPath->setPath(m_config->getLoggingPath());
options_page->LoggingConnect->setChecked(m_config->getLoggingNewFileOnConnect());
options_page->LoggingEnable->setChecked(m_config->getLoggingEnabled());
connect(options_page->LoggingEnable, SIGNAL(clicked()), this, SLOT(on_loggingEnable_clicked()));
on_loggingEnable_clicked();
return optionsPageWidget;
}
@ -226,6 +237,12 @@ void ScopeGadgetOptionsPage::apply()
}
m_config->replacePlotCurveConfig(plotCurveConfigs);
//save the logging config
m_config->setLoggingPath(options_page->LoggingPath->path());
m_config->setLoggingNewFileOnConnect(options_page->LoggingConnect->isChecked());
m_config->setLoggingEnabled(options_page->LoggingEnable->isChecked());
}
/*!
@ -309,3 +326,12 @@ void ScopeGadgetOptionsPage::on_lstCurves_currentRowChanged(int currentRow)
Q_UNUSED(currentRow);
setYAxisWidgetFromPlotCurve();
}
void ScopeGadgetOptionsPage::on_loggingEnable_clicked()
{
bool en = options_page->LoggingEnable->isChecked();
options_page->LoggingPath->setEnabled(en);
options_page->LoggingConnect->setEnabled(en);
options_page->LoggingLabel->setEnabled(en);
}

View File

@ -1,83 +1,85 @@
/**
******************************************************************************
*
* @file scopegadgetoptionspage.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 SCOPEGADGETOPTIONSPAGE_H
#define SCOPEGADGETOPTIONSPAGE_H
#include "coreplugin/dialogs/ioptionspage.h"
#include "scopegadgetconfiguration.h"
#include "ui_scopegadgetoptionspage.h"
#include <QString>
#include <QStringList>
#include <QDebug>
#include <QtGui/QColorDialog>
namespace Core
{
class IUAVGadgetConfiguration;
}
class ScopeGadgetConfiguration;
namespace Ui
{
class ScopeGadgetOptionsPage;
}
using namespace Core;
class ScopeGadgetOptionsPage : public IOptionsPage
{
Q_OBJECT
public:
explicit ScopeGadgetOptionsPage(ScopeGadgetConfiguration *config, QObject *parent = 0);
QWidget *createPage(QWidget *parent);
void apply();
void finish();
private:
Ui::ScopeGadgetOptionsPage *options_page;
ScopeGadgetConfiguration *m_config;
void addPlotCurveConfig(QString uavObject, QString uavField, int scale, QVariant varColor);
void setCurvePlotProperties(QListWidgetItem *listWidgetItem, QString uavObject, QString uavField, int scale, QVariant varColor);
void setYAxisWidgetFromPlotCurve();
void setButtonColor(const QColor &color);
private slots:
void on_lstCurves_currentRowChanged(int currentRow);
void on_btnRemoveCurve_clicked();
void on_btnAddCurve_clicked();
void on_cmbUAVObjects_currentIndexChanged(QString val);
void on_btnColor_clicked();
};
#endif // SCOPEGADGETOPTIONSPAGE_H
/**
******************************************************************************
*
* @file scopegadgetoptionspage.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 SCOPEGADGETOPTIONSPAGE_H
#define SCOPEGADGETOPTIONSPAGE_H
#include "coreplugin/dialogs/ioptionspage.h"
#include "scopegadgetconfiguration.h"
#include "ui_scopegadgetoptionspage.h"
#include <QString>
#include <QStringList>
#include <QDebug>
#include <QtGui/QColorDialog>
namespace Core
{
class IUAVGadgetConfiguration;
}
class ScopeGadgetConfiguration;
namespace Ui
{
class ScopeGadgetOptionsPage;
}
using namespace Core;
class ScopeGadgetOptionsPage : public IOptionsPage
{
Q_OBJECT
public:
explicit ScopeGadgetOptionsPage(ScopeGadgetConfiguration *config, QObject *parent = 0);
QWidget *createPage(QWidget *parent);
void apply();
void finish();
private:
Ui::ScopeGadgetOptionsPage *options_page;
ScopeGadgetConfiguration *m_config;
void addPlotCurveConfig(QString uavObject, QString uavField, int scale, QVariant varColor);
void setCurvePlotProperties(QListWidgetItem *listWidgetItem, QString uavObject, QString uavField, int scale, QVariant varColor);
void setYAxisWidgetFromPlotCurve();
void setButtonColor(const QColor &color);
private slots:
void on_lstCurves_currentRowChanged(int currentRow);
void on_btnRemoveCurve_clicked();
void on_btnAddCurve_clicked();
void on_cmbUAVObjects_currentIndexChanged(QString val);
void on_btnColor_clicked();
void on_loggingEnable_clicked();
};
#endif // SCOPEGADGETOPTIONSPAGE_H

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>653</width>
<height>580</height>
<width>550</width>
<height>290</height>
</rect>
</property>
<property name="windowTitle">
@ -16,249 +16,299 @@
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>611</width>
<height>241</height>
<x>10</x>
<y>10</y>
<width>541</width>
<height>271</height>
</rect>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>601</width>
<height>231</height>
<width>531</width>
<height>272</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>3</number>
</property>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="font">
<font>
<family>Bitstream Charter</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>X-Axis</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Plot Type:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cmbPlotType"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Data Size:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spnDataSize">
<property name="suffix">
<string> seconds</string>
</property>
<property name="maximum">
<number>5000</number>
</property>
<property name="singleStep">
<number>30</number>
</property>
<property name="value">
<number>300</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Update Interval:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spnRefreshInterval">
<property name="suffix">
<string>ms</string>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>30000</number>
</property>
<property name="singleStep">
<number>500</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="font">
<font>
<family>Bitstream Charter</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Plot curves</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>UAVObject:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="cmbUAVObjects"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>UAVField:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="cmbUAVField"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="btnColor">
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Scale:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="cmbScale">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
<item row="0" column="0">
<widget class="QLabel" name="label_9">
<property name="font">
<font>
<family>Bitstream Charter</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>X-Axis</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Plot Type:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="cmbPlotType"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Data Size:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="spnDataSize">
<property name="suffix">
<string> seconds</string>
</property>
<property name="maximum">
<number>5000</number>
</property>
<property name="singleStep">
<number>30</number>
</property>
<property name="value">
<number>300</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Update Interval:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spnRefreshInterval">
<property name="suffix">
<string>ms</string>
</property>
<property name="minimum">
<number>100</number>
</property>
<property name="maximum">
<number>30000</number>
</property>
<property name="singleStep">
<number>500</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="font">
<font>
<family>Bitstream Charter</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Plot curves</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>UAVObject:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="cmbUAVObjects"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>UAVField:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="cmbUAVField"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="btnColor">
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Scale:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="cmbScale">
<property name="editable">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="btnAddCurve">
<property name="toolTip">
<string>Add a new curve to the scope, or update it if the UAVObject and UAVField is the same.</string>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="text">
<string>Add
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnAddCurve">
<property name="toolTip">
<string>Add a new curve to the scope, or update it if the UAVObject and UAVField is the same.</string>
</property>
<property name="text">
<string>Add
Update</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRemoveCurve">
<property name="toolTip">
<string>Remove the curve from the scope.</string>
</property>
<property name="text">
<string>Remove
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRemoveCurve">
<property name="toolTip">
<string>Remove the curve from the scope.</string>
</property>
<property name="text">
<string>Remove
</string>
</property>
</widget>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>15</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>15</height>
</size>
</property>
</spacer>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QListWidget" name="lstCurves">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="batchSize">
<number>100</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QListWidget" name="lstCurves">
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="batchSize">
<number>100</number>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="LoggingEnable">
<property name="text">
<string>Log data to csv file</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="LoggingConnect">
<property name="text">
<string>New file on connect</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="LoggingLabel">
<property name="text">
<string>Logging path</string>
</property>
</widget>
</item>
<item>
<widget class="Utils::PathChooser" name="LoggingPath" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
@ -266,6 +316,14 @@ Update</string>
</widget>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>Utils::PathChooser</class>
<extends>QWidget</extends>
<header>utils/pathchooser.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -26,6 +26,7 @@
*/
#include <QDir>
#include "scopegadgetwidget.h"
#include "utils/stylehelper.h"
@ -70,6 +71,21 @@ ScopeGadgetWidget::ScopeGadgetWidget(QWidget *parent) : QwtPlot(parent)
connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(stopPlotting()));
connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(startPlotting()));
m_csvLoggingStarted=0;
m_csvLoggingEnabled=0;
m_csvLoggingHeaderSaved=0;
m_csvLoggingDataSaved=0;
m_csvLoggingNameSet=0;
m_csvLoggingConnected=0;
m_csvLoggingNewFileOnConnect=0;
m_csvLoggingPath = QString("./csvlogging/");
m_csvLoggingStartTime = QDateTime::currentDateTime();
//Listen to autopilot connection events
connect(cm, SIGNAL(deviceDisconnected()), this, SLOT(csvLoggingDisconnect()));
connect(cm, SIGNAL(deviceConnected(QIODevice*)), this, SLOT(csvLoggingConnect()));
}
/**
@ -267,7 +283,7 @@ void ScopeGadgetWidget::replotNewData()
setAxisScale(QwtPlot::xBottom, toTime - m_xWindowSize, toTime);
}
//qDebug() << "replotNewData from " << NOW.addSecs(- m_xWindowSize) << " to " << NOW;
csvLoggingInsertData();
replot();
}
@ -414,3 +430,151 @@ TestDataGen::~TestDataGen()
delete timer;
}
/*
int csvLoggingEnable;
int csvLoggingHeaderSaved;
int csvLoggingDataSaved;
QString csvLoggingPath;
QFile csvLoggingFile;
*/
int ScopeGadgetWidget::csvLoggingStart()
{
if (!m_csvLoggingStarted)
if (m_csvLoggingEnabled)
if ((!m_csvLoggingNewFileOnConnect)||(m_csvLoggingNewFileOnConnect && m_csvLoggingConnected))
{
QDateTime NOW = QDateTime::currentDateTime();
m_csvLoggingStartTime = NOW;
m_csvLoggingHeaderSaved=0;
m_csvLoggingDataSaved=0;
QDir PathCheck(m_csvLoggingPath);
if (!PathCheck.exists())
{
PathCheck.mkpath("./");
}
if (m_csvLoggingNameSet)
{
m_csvLoggingFile.setFileName(QString("%1/%2_%3_%4.csv").arg(m_csvLoggingPath).arg(m_csvLoggingName).arg(NOW.toString("yyyy-MM-dd")).arg(NOW.toString("hh-mm-ss")));
}
else
{
m_csvLoggingFile.setFileName(QString("%1/Log_%2_%3.csv").arg(m_csvLoggingPath).arg(NOW.toString("yyyy-MM-dd")).arg(NOW.toString("hh-mm-ss")));
}
QDir FileCheck(m_csvLoggingFile.fileName());
if (FileCheck.exists())
{
m_csvLoggingFile.setFileName("");
}
else
{
m_csvLoggingStarted=1;
csvLoggingInsertHeader();
}
}
return 0;
}
int ScopeGadgetWidget::csvLoggingStop()
{
m_csvLoggingStarted=0;
return 0;
}
int ScopeGadgetWidget::csvLoggingInsertHeader()
{
if (!m_csvLoggingStarted) return -1;
if (m_csvLoggingHeaderSaved) return -2;
if (m_csvLoggingDataSaved) return -3;
m_csvLoggingHeaderSaved=1;
if(m_csvLoggingFile.open(QIODevice::WriteOnly | QIODevice::Append)== FALSE)
{
qDebug() << "Unable to open " << m_csvLoggingFile.fileName() << " for csv logging Header";
}
else
{
QTextStream ts( &m_csvLoggingFile );
ts << "date" << ", " << "Time"<< ", " << "Sec since start"<< ", " << "Connected";
foreach(PlotData* plotData2, m_curvesData.values())
{
ts << ", ";
ts << plotData2->uavObject;
ts << "." << plotData2->uavField;
if (plotData2->haveSubField) ts << "." << plotData2->uavSubField;
}
ts << endl;
m_csvLoggingFile.close();
}
return 0;
}
int ScopeGadgetWidget::csvLoggingInsertData()
{
if (!m_csvLoggingStarted) return -1;
m_csvLoggingDataSaved=1;
m_csvLoggingDataValid=0;
QDateTime NOW = QDateTime::currentDateTime();
QString tempString;
if(m_csvLoggingFile.open(QIODevice::WriteOnly | QIODevice::Append)== FALSE)
{
qDebug() << "Unable to open " << m_csvLoggingFile.fileName() << " for csv logging Data";
}
else
{
QTextStream ss( &tempString );
ss << NOW.toString("yyyy-MM-dd") << ", " << NOW.toString("hh:mm:ss.z") << ", " << (NOW.toMSecsSinceEpoch() - m_csvLoggingStartTime.toMSecsSinceEpoch())/1000.00;
ss << ", " << m_csvLoggingConnected;
foreach(PlotData* plotData2, m_curvesData.values())
{
ss << ", ";
if (plotData2->xData->isEmpty ())
{
}
else
{
ss << QString().sprintf("%3.6g",plotData2->yData->last()/pow(10,plotData2->scalePower));
m_csvLoggingDataValid=1;
}
}
ss << endl;
if (m_csvLoggingDataValid)
{
QTextStream ts( &m_csvLoggingFile );
ts << tempString;
}
m_csvLoggingFile.close();
}
return 0;
}
void ScopeGadgetWidget::csvLoggingSetName(QString newName)
{
m_csvLoggingName = newName;
m_csvLoggingNameSet=1;
}
void ScopeGadgetWidget::csvLoggingConnect()
{
m_csvLoggingConnected=1;
if (m_csvLoggingNewFileOnConnect)csvLoggingStart();
return;
}
void ScopeGadgetWidget::csvLoggingDisconnect()
{
m_csvLoggingHeaderSaved=0;
m_csvLoggingConnected=0;
if (m_csvLoggingNewFileOnConnect)csvLoggingStop();
return;
}

View File

@ -114,7 +114,12 @@ public:
void addCurvePlot(QString uavObject, QString uavFieldSubField, int scaleOrderFactor = 0, QPen pen = QPen(Qt::black));
//void removeCurvePlot(QString uavObject, QString uavField);
void clearCurvePlots();
int csvLoggingStart();
int csvLoggingStop();
void csvLoggingSetName(QString);
void setLoggingEnabled(bool value){m_csvLoggingEnabled=value;};
void setLoggingNewFileOnConnect(bool value){m_csvLoggingNewFileOnConnect=value;};
void setLoggingPath(QString value){m_csvLoggingPath=value;};
private slots:
void uavObjectReceived(UAVObject*);
@ -122,6 +127,8 @@ private slots:
void showCurve(QwtPlotItem *item, bool on);
void startPlotting();
void stopPlotting();
void csvLoggingConnect();
void csvLoggingDisconnect();
private:
@ -138,6 +145,25 @@ private:
static TestDataGen* testDataGen;
QTimer *replotTimer;
bool m_csvLoggingStarted;
bool m_csvLoggingEnabled;
bool m_csvLoggingHeaderSaved;
bool m_csvLoggingDataSaved;
bool m_csvLoggingNameSet;
bool m_csvLoggingDataValid;
bool m_csvLoggingConnected;
bool m_csvLoggingNewFileOnConnect;
QDateTime m_csvLoggingStartTime;
QString m_csvLoggingName;
QString m_csvLoggingPath;
QFile m_csvLoggingFile;
int csvLoggingInsertHeader();
int csvLoggingInsertData();
};