1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-20 10:54:14 +01:00

GCS/Logging: First pass at a logging plugin. Data format is 32 bit timestamp (in ms from start of logging) then the UAVObject.pack. Still want to add a header to indicate the objects available. Next part will be writing a reader and then making a gadget to control playback (and to indicate recording status).

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@1478 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
peabody124 2010-08-31 09:09:16 +00:00 committed by peabody124
parent f906346795
commit 4f246c64ca
6 changed files with 362 additions and 6 deletions

View File

@ -0,0 +1,10 @@
<plugin name="LoggingGadget" version="1.0.0" compatVersion="1.0.0">
<vendor>The OpenPilot Project</vendor>
<copyright>(C) 2010 OpenPilot</copyright>
<license>The GNU Public License (GPL) Version 3</license>
<description>A plugin that logs all UAVObject updates to a binary file</description>
<url>http://www.openpilot.org</url>
<dependencyList>
<dependency name="Core" version="1.0.0"/>
</dependencyList>
</plugin>

View File

@ -0,0 +1,26 @@
TEMPLATE = lib
TARGET = LoggingGadget
DEFINES += LOGGING_LIBRARY
QT += svg
include(../../openpilotgcsplugin.pri)
include(../../plugins/uavobjects/uavobjects.pri)
include(logging_dependencies.pri)
HEADERS += loggingplugin.h
# logginggadgetwidget.h \
# loggingdialog.h \
# logginggadget.h \
# logginggadgetfactory.h \
# logginggadgetconfiguration.h
# logginggadgetoptionspage.h
SOURCES += loggingplugin.cpp
# logginggadgetwidget.cpp \
# loggingdialog.cpp \
# logginggadget.cpp \
# logginggadgetfactory.cpp \
# logginggadgetconfiguration.cpp \
# logginggadgetoptionspage.cpp
OTHER_FILES += LoggingGadget.pluginspec
#FORMS += logginggadgetoptionspage.ui \
# logginggadgetwidget.ui \
# loggingdialog.ui

View File

@ -0,0 +1 @@
include(../../plugins/coreplugin/coreplugin.pri)

View File

@ -0,0 +1,234 @@
/**
******************************************************************************
*
* @file logging.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @see The GNU Public License (GPL) Version 3
* @brief Import/Export Plugin
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup Logging
* @{
*
*****************************************************************************/
/*
* 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 "loggingplugin.h"
#include <QDebug>
#include <QtPlugin>
#include <QThread>
#include <QStringList>
#include <QDir>
#include <QFileDialog>
#include <QList>
#include <QErrorMessage>
#include <QWriteLocker>
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/icore.h>
#include <QKeySequence>
/**
* Sets the file to use for logging and takes the parent plugin
* to connect to stop logging signal
* @param[in] file File name to write to
* @param[in] parent plugin
*/
bool LoggingThread::openFile(QString file, LoggingPlugin * parent)
{
// TODO: Write a header at the beginng describing objects so that in future
// they can be read back if ID's change
logFile.setFileName(file);
if(logFile.open(QIODevice::WriteOnly) == FALSE)
{
qDebug() << "Unable to open " << file << " for logging";
return false;
}
connect(parent,SIGNAL(stopLoggingSignal()),this,SLOT(stopLogging()));
return true;
};
/**
* Logs an object update to the file. Data format is the
* timestamp as a 32 bit uint counting ms from start of
* file writing (flight time will be embedded in stream)
* the UAVtalk packed object.
*/
void LoggingThread::objectUpdated(UAVObject * obj)
{
quint32 timeStamp = myTime.elapsed();
quint32 objSize = obj->getNumBytes();
quint8 * buffer = new quint8[objSize+4];
if(buffer == NULL)
return;
obj->pack(&buffer[4]);
memcpy(buffer,&timeStamp,4);
QWriteLocker locker(&lock);
qint64 written = logFile.write((char *) buffer,objSize+4);
delete(buffer);
//qDebug() << obj->getName() << " logged at " << timeStamp << " size: " << objSize << " written " << written;
};
/**
* Connect signals from all the objects updates to the write routine then
* run event loop
*/
void LoggingThread::run()
{
ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
UAVObjectManager *objManager = pm->getObject<UAVObjectManager>();
QList< QList<UAVObject*> > list;
list = objManager->getObjects();
QList< QList<UAVObject*> >::const_iterator i;
QList<UAVObject*>::const_iterator j;
int objects = 0;
for (i = list.constBegin(); i != list.constEnd(); ++i)
{
for (j = (*i).constBegin(); j != (*i).constEnd(); ++j)
{
connect(*j, SIGNAL(objectUpdated(UAVObject*)), (LoggingThread*) this, SLOT(objectUpdated(UAVObject*)));
objects++;
//qDebug() << "Detected " << j[0];
}
}
myTime.restart();
exec();
}
/**
* Pass this command to the correct thread then close the file
*/
void LoggingThread::stopLogging()
{
QWriteLocker locker(&lock);
logFile.close();
qDebug() << "File " << logFile.fileName() << " closed";
quit();
}
LoggingPlugin::LoggingPlugin() : state(IDLE)
{
// Do nothing
}
LoggingPlugin::~LoggingPlugin()
{
// Do nothing
}
bool LoggingPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
// Add Menu entry
Core::ActionManager* am = Core::ICore::instance()->actionManager();
Core::ActionContainer* ac = am->actionContainer(Core::Constants::M_FILE);
Core::Command* cmd = am->registerAction(new QAction(this),
"LoggingPlugin.Logging",
QList<int>() <<
Core::Constants::C_GLOBAL_ID);
cmd->setDefaultKeySequence(QKeySequence("Ctrl+L"));
cmd->action()->setText("Logging...");
ac->menu()->addSeparator();
ac->appendGroup("Logging");
ac->addAction(cmd, "Logging");
connect(cmd->action(), SIGNAL(triggered(bool)), this, SLOT(toggleLogging()));
return true;
}
/**
* The action that is triggered by the menu item which opens the
* file and begins logging if successful
*/
void LoggingPlugin::toggleLogging()
{
if(state == IDLE)
{
QFileDialog * fd = new QFileDialog();
fd->setAcceptMode(QFileDialog::AcceptSave);
fd->setNameFilter("OpenPilot Log (*.opl)");
connect(fd, SIGNAL(fileSelected(QString)), this, SLOT(startLogging(QString)));
fd->exec();
}
else
{
stopLogging();
}
}
/**
* Starts the logging thread to a certain file
*/
void LoggingPlugin::startLogging(QString file)
{
qDebug() << "Logging to " << file;
LoggingThread *loggingThread = new LoggingThread();
if(loggingThread->openFile(file,this))
{
connect(loggingThread,SIGNAL(finished()),this,SLOT(loggingStopped()));
state = LOGGING;
loggingThread->start();
} else {
QErrorMessage err;
err.showMessage("Unable to open file for logging");
err.exec();
}
}
void LoggingPlugin::stopLogging()
{
emit stopLoggingSignal();
}
void LoggingPlugin::loggingStopped()
{
state = IDLE;
}
void LoggingPlugin::extensionsInitialized()
{
// Do nothing
}
void LoggingPlugin::shutdown()
{
// Do nothing
}
Q_EXPORT_PLUGIN(LoggingPlugin)
/**
* @}
* @}
*/

View File

@ -0,0 +1,86 @@
/**
******************************************************************************
* @file loggingplugin.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @see The GNU Public License (GPL) Version 3
* @addtogroup GCSPlugins GCS Plugins
* @{
* @addtogroup loggingplugin
* @{
*****************************************************************************/
/*
* 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 LOGGINGPLUGIN_H_
#define LOGGINGPLUGIN_H_
#include <extensionsystem/iplugin.h>
#include <uavobjects/uavobjectmanager.h>
#include <QThread>
#include <QTime>
#include <QReadWriteLock>
class LoggingPlugin;
class LoggingThread : public QThread
{
Q_OBJECT
public:
bool openFile(QString file, LoggingPlugin * parent);
private slots:
void objectUpdated(UAVObject * obj);
public slots:
void stopLogging();
protected:
void run();
QFile logFile;
QTime myTime;
QReadWriteLock lock;
};
class LoggingPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
LoggingPlugin();
~LoggingPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
signals:
void stopLoggingSignal(void);
protected:
enum {IDLE, LOGGING} state;
LoggingThread * loggingThread;
private slots:
void toggleLogging();
void startLogging(QString file);
void stopLogging();
void loggingStopped();
};
#endif /* LoggingPLUGIN_H_ */
/**
* @}
* @}
*/

View File

@ -111,12 +111,6 @@ plugin_config.depends = plugin_coreplugin
plugin_config.depends = plugin_uavobjects
SUBDIRS += plugin_config
# Export and Import GCS Configuration.
#plugin_importexport.subdir = importexport
#plugin_importexport.depends = plugin_coreplugin
#SUBDIRS += plugin_importexport
#GPS Display Gadget
plugin_gpsdisplay.subdir = gpsdisplay
plugin_gpsdisplay.depends = plugin_coreplugin
@ -147,6 +141,11 @@ plugin_importexport.subdir = importexport
plugin_importexport.depends = plugin_coreplugin
SUBDIRS += plugin_importexport
# Export and Import GCS Configuration.
plugin_logging.subdir = logging
plugin_logging.depends = plugin_coreplugin
SUBDIRS += plugin_logging
#GCS Control of UAV Gadget
plugin_gcscontrol.subdir = gcscontrol
plugin_gcscontrol.depends = plugin_coreplugin