1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-18 03:52:11 +01:00

OP-4 GCS/Telemetry Implemented telemetry connection manager, persistent objects are now automatically retrieved each time a new connection is established (to ensure that the GCS objects are in sync with the Flight objects), minor telemetry bug fixes

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@579 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
vassilis 2010-05-04 01:31:06 +00:00 committed by vassilis
parent e10a16f1c3
commit e22aaa939e
34 changed files with 519 additions and 73 deletions

View File

@ -135,3 +135,11 @@ UAVDataObject* ExampleObject1::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
ExampleObject1* ExampleObject1::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<ExampleObject1*>(objMngr->getObject(ExampleObject1::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define EXAMPLEOBJECT1_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT ExampleObject1: public UAVDataObject
{
@ -81,6 +82,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static ExampleObject1* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -120,3 +120,11 @@ UAVDataObject* ExampleObject2::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
ExampleObject2* ExampleObject2::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<ExampleObject2*>(objMngr->getObject(ExampleObject2::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define EXAMPLEOBJECT2_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT ExampleObject2: public UAVDataObject
{
@ -71,6 +72,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static ExampleObject2* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -120,3 +120,11 @@ UAVDataObject* ExampleSettings::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
ExampleSettings* ExampleSettings::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<ExampleSettings*>(objMngr->getObject(ExampleSettings::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define EXAMPLESETTINGS_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT ExampleSettings: public UAVDataObject
{
@ -69,6 +70,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static ExampleSettings* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -40,12 +40,14 @@ FlightTelemetryStats::FlightTelemetryStats(): UAVDataObject(OBJID, ISSINGLEINST,
{
// Create fields
QList<UAVObjectField*> fields;
QStringList ConnectedElemNames;
ConnectedElemNames.append("0");
QStringList ConnectedEnumOptions;
ConnectedEnumOptions.append("True");
ConnectedEnumOptions.append("False");
fields.append(new UAVObjectFieldEnum(QString("Connected"), QString("bool"), ConnectedElemNames, ConnectedEnumOptions));
QStringList StatusElemNames;
StatusElemNames.append("0");
QStringList StatusEnumOptions;
StatusEnumOptions.append("Disconnected");
StatusEnumOptions.append("HandshakeReq");
StatusEnumOptions.append("HandshakeAck");
StatusEnumOptions.append("Connected");
fields.append(new UAVObjectFieldEnum(QString("Status"), QString(""), StatusElemNames, StatusEnumOptions));
QStringList TxDataRateElemNames;
TxDataRateElemNames.append("0");
fields.append(new UAVObjectFieldFloat(QString("TxDataRate"), QString("bytes/sec"), TxDataRateElemNames));
@ -75,7 +77,7 @@ UAVObject::Metadata FlightTelemetryStats::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.gcsTelemetryAcked = 1;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.flightTelemetryAcked = 1;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
@ -126,3 +128,11 @@ UAVDataObject* FlightTelemetryStats::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
FlightTelemetryStats* FlightTelemetryStats::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<FlightTelemetryStats*>(objMngr->getObject(FlightTelemetryStats::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define FLIGHTTELEMETRYSTATS_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT FlightTelemetryStats: public UAVDataObject
{
@ -40,7 +41,7 @@ class UAVOBJECTS_EXPORT FlightTelemetryStats: public UAVDataObject
public:
// Field structure
typedef struct {
quint8 Connected;
quint8 Status;
float TxDataRate;
float RxDataRate;
quint32 TxFailures;
@ -50,9 +51,9 @@ public:
} __attribute__((packed)) DataFields;
// Field information
// Field Connected information
/* Enumeration options for field Connected */
typedef enum { CONNECTED_TRUE=0, CONNECTED_FALSE=1, } ConnectedOptions;
// Field Status information
/* Enumeration options for field Status */
typedef enum { STATUS_DISCONNECTED=0, STATUS_HANDSHAKEREQ=1, STATUS_HANDSHAKEACK=2, STATUS_CONNECTED=3, } StatusOptions;
// Field TxDataRate information
// Field RxDataRate information
// Field TxFailures information
@ -61,7 +62,7 @@ public:
// Constants
static const quint32 OBJID = 766280320U;
static const quint32 OBJID = 1712072286U;
static const QString NAME;
static const bool ISSINGLEINST = 1;
static const bool ISSETTINGS = 0;
@ -75,6 +76,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static FlightTelemetryStats* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -40,12 +40,14 @@ GCSTelemetryStats::GCSTelemetryStats(): UAVDataObject(OBJID, ISSINGLEINST, ISSET
{
// Create fields
QList<UAVObjectField*> fields;
QStringList ConnectedElemNames;
ConnectedElemNames.append("0");
QStringList ConnectedEnumOptions;
ConnectedEnumOptions.append("True");
ConnectedEnumOptions.append("False");
fields.append(new UAVObjectFieldEnum(QString("Connected"), QString("bool"), ConnectedElemNames, ConnectedEnumOptions));
QStringList StatusElemNames;
StatusElemNames.append("0");
QStringList StatusEnumOptions;
StatusEnumOptions.append("Disconnected");
StatusEnumOptions.append("HandshakeReq");
StatusEnumOptions.append("HandshakeAck");
StatusEnumOptions.append("Connected");
fields.append(new UAVObjectFieldEnum(QString("Status"), QString(""), StatusElemNames, StatusEnumOptions));
QStringList TxDataRateElemNames;
TxDataRateElemNames.append("0");
fields.append(new UAVObjectFieldFloat(QString("TxDataRate"), QString("bytes/sec"), TxDataRateElemNames));
@ -75,10 +77,10 @@ UAVObject::Metadata GCSTelemetryStats::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.gcsTelemetryAcked = 1;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
metadata.gcsTelemetryUpdatePeriod = 5000;
metadata.flightTelemetryAcked = 1;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
metadata.flightTelemetryUpdatePeriod = 0;
metadata.loggingUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.loggingUpdatePeriod = 0;
@ -126,3 +128,11 @@ UAVDataObject* GCSTelemetryStats::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
GCSTelemetryStats* GCSTelemetryStats::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<GCSTelemetryStats*>(objMngr->getObject(GCSTelemetryStats::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define GCSTELEMETRYSTATS_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT GCSTelemetryStats: public UAVDataObject
{
@ -40,7 +41,7 @@ class UAVOBJECTS_EXPORT GCSTelemetryStats: public UAVDataObject
public:
// Field structure
typedef struct {
quint8 Connected;
quint8 Status;
float TxDataRate;
float RxDataRate;
quint32 TxFailures;
@ -50,9 +51,9 @@ public:
} __attribute__((packed)) DataFields;
// Field information
// Field Connected information
/* Enumeration options for field Connected */
typedef enum { CONNECTED_TRUE=0, CONNECTED_FALSE=1, } ConnectedOptions;
// Field Status information
/* Enumeration options for field Status */
typedef enum { STATUS_DISCONNECTED=0, STATUS_HANDSHAKEREQ=1, STATUS_HANDSHAKEACK=2, STATUS_CONNECTED=3, } StatusOptions;
// Field TxDataRate information
// Field RxDataRate information
// Field TxFailures information
@ -61,7 +62,7 @@ public:
// Constants
static const quint32 OBJID = 607270704U;
static const quint32 OBJID = 1998458950U;
static const QString NAME;
static const bool ISSINGLEINST = 1;
static const bool ISSETTINGS = 0;
@ -75,6 +76,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static GCSTelemetryStats* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -69,7 +69,7 @@ UAVObject::Metadata GpsObject::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.gcsTelemetryAcked = 1;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.flightTelemetryAcked = 1;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
@ -120,3 +120,11 @@ UAVDataObject* GpsObject::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
GpsObject* GpsObject::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<GpsObject*>(objMngr->getObject(GpsObject::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define GPSOBJECT_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT GpsObject: public UAVDataObject
{
@ -71,6 +72,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static GpsObject* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -45,6 +45,7 @@ ObjectPersistence::ObjectPersistence(): UAVDataObject(OBJID, ISSINGLEINST, ISSET
QStringList OperationEnumOptions;
OperationEnumOptions.append("Load");
OperationEnumOptions.append("Save");
OperationEnumOptions.append("Delete");
fields.append(new UAVObjectFieldEnum(QString("Operation"), QString(""), OperationElemNames, OperationEnumOptions));
QStringList ObjectsElemNames;
ObjectsElemNames.append("0");
@ -118,3 +119,11 @@ UAVDataObject* ObjectPersistence::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
ObjectPersistence* ObjectPersistence::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<ObjectPersistence*>(objMngr->getObject(ObjectPersistence::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define OBJECTPERSISTENCE_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT ObjectPersistence: public UAVDataObject
{
@ -48,7 +49,7 @@ public:
// Field information
// Field Operation information
/* Enumeration options for field Operation */
typedef enum { OPERATION_LOAD=0, OPERATION_SAVE=1, } OperationOptions;
typedef enum { OPERATION_LOAD=0, OPERATION_SAVE=1, OPERATION_DELETE=2, } OperationOptions;
// Field Objects information
/* Enumeration options for field Objects */
typedef enum { OBJECTS_ALL=0, OBJECTS_SETTINGS=1, OBJECTS_METAOBJECTS=2, } ObjectsOptions;
@ -69,6 +70,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static ObjectPersistence* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -118,3 +118,11 @@ UAVDataObject* SystemAlarms::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
SystemAlarms* SystemAlarms::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<SystemAlarms*>(objMngr->getObject(SystemAlarms::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define SYSTEMALARMS_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT SystemAlarms: public UAVDataObject
{
@ -69,6 +70,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static SystemAlarms* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -63,7 +63,7 @@ UAVObject::Metadata SystemStats::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.gcsTelemetryAcked = 1;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_MANUAL;
metadata.gcsTelemetryUpdatePeriod = 0;
metadata.flightTelemetryAcked = 1;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
@ -114,3 +114,11 @@ UAVDataObject* SystemStats::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
SystemStats* SystemStats::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<SystemStats*>(objMngr->getObject(SystemStats::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define SYSTEMSTATS_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT SystemStats: public UAVDataObject
{
@ -67,6 +68,8 @@ public:
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static SystemStats* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -428,3 +428,11 @@ QString UAVObject::toStringData()
}
return sout;
}
/**
* Emit the transactionCompleted event (used by the UAVTalk plugin)
*/
void UAVObject::emitTransactionCompleted(bool success)
{
emit transactionCompleted(this, success);
}

View File

@ -100,6 +100,7 @@ public:
QString toString();
QString toStringBrief();
QString toStringData();
void emitTransactionCompleted(bool success);
signals:
void objectUpdated(UAVObject* obj);
@ -107,6 +108,7 @@ signals:
void objectUpdatedManual(UAVObject* obj);
void objectUnpacked(UAVObject* obj);
void updateRequested(UAVObject* obj);
void transactionCompleted(UAVObject* obj, bool success);
private slots:
void fieldUpdated(UAVObjectField* field);

View File

@ -105,3 +105,11 @@ UAVDataObject* $(NAME)::clone(quint32 instID)
obj->initialize(instID, this->getMetaObject());
return obj;
}
/**
* Static function to retrieve an instance of the object.
*/
$(NAME)* $(NAME)::GetInstance(UAVObjectManager* objMngr, quint32 instID)
{
return dynamic_cast<$(NAME)*>(objMngr->getObject($(NAME)::OBJID, instID));
}

View File

@ -32,6 +32,7 @@
#define $(NAMEUC)_H
#include "uavdataobject.h"
#include "uavobjectmanager.h"
class UAVOBJECTS_EXPORT $(NAME): public UAVDataObject
{
@ -61,6 +62,8 @@ $(DATAFIELDINFO)
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
static $(NAME)* GetInstance(UAVObjectManager* objMngr, quint32 instID = 0);
private:
DataFields data;

View File

@ -27,6 +27,7 @@
*/
#include "telemetry.h"
#include "qxtlogger.h"
#include <QTime>
/**
@ -59,12 +60,8 @@ Telemetry::Telemetry(UAVTalk* utalk, UAVObjectManager* objMngr)
connect(updateTimer, SIGNAL(timeout()), this, SLOT(processPeriodicUpdates()));
updateTimer->start(1000);
// Setup and start the stats timer
statsObj = dynamic_cast<GCSTelemetryStats*>( objMngr->getObject(GCSTelemetryStats::NAME) );
txErrors = 0;
txRetries = 0;
statsTimer = new QTimer(this);
connect(statsTimer, SIGNAL(timeout()), this, SLOT(processStatsUpdates()));
statsTimer->start(STATS_UPDATE_PERIOD_MS);
}
/**
@ -211,6 +208,8 @@ void Telemetry::transactionCompleted(UAVObject* obj)
// Check if there is a pending transaction and the objects match
if ( transPending && transInfo.obj->getObjID() == obj->getObjID() )
{
// Send signal
obj->emitTransactionCompleted(true);
// Complete transaction
transTimer->stop();
transPending = false;
@ -237,6 +236,8 @@ void Telemetry::transactionTimeout()
}
else
{
// Send signal
transInfo.obj->emitTransactionCompleted(false);
// Terminate transaction
utalk->cancelTransaction();
transPending = false;
@ -281,13 +282,6 @@ void Telemetry::processObjectTransaction()
*/
void Telemetry::processObjectUpdates(UAVObject* obj, EventMask event, bool allInstances, bool priority)
{
// Check if queue is full
if ( objQueue.length() > MAX_QUEUE_SIZE )
{
++txErrors;
return;
}
// Push event into queue
ObjectQueueInfo objInfo;
objInfo.obj = obj;
@ -302,6 +296,7 @@ void Telemetry::processObjectUpdates(UAVObject* obj, EventMask event, bool allIn
else
{
++txErrors;
qxtLog->warning(tr("Telemetry: priority event queue is full, event lost (%1)").arg(obj->getName()));
}
}
else
@ -328,6 +323,13 @@ void Telemetry::processObjectUpdates(UAVObject* obj, EventMask event, bool allIn
*/
void Telemetry::processObjectQueue()
{
// Don nothing if a transaction is already in progress (should not happen)
if (transPending)
{
qxtLog->error("Telemetry: Dequeue while a transaction pending!");
return;
}
// Get object information from queue (first the priority and then the regular queue)
ObjectQueueInfo objInfo;
if ( !objPriorityQueue.isEmpty() )
@ -429,32 +431,35 @@ void Telemetry::processPeriodicUpdates()
updateTimer->start(timeToNextUpdateMs);
}
void Telemetry::processStatsUpdates()
Telemetry::TelemetryStats Telemetry::getStats()
{
QMutexLocker locker(mutex);
// Get UAVTalk stats
UAVTalk::ComStats utalkStats = utalk->getStats();
utalk->resetStats();
// Update stats object
GCSTelemetryStats::DataFields stats = statsObj->getData();
if (utalkStats.rxBytes > 0)
{
stats.Connected = GCSTelemetryStats::CONNECTED_TRUE;
}
else
{
stats.Connected = GCSTelemetryStats::CONNECTED_FALSE;
}
stats.RxDataRate = (float)utalkStats.rxBytes / ((float)STATS_UPDATE_PERIOD_MS/1000.0);
stats.TxDataRate = (float)utalkStats.txBytes / ((float)STATS_UPDATE_PERIOD_MS/1000.0);
stats.RxFailures += utalkStats.rxErrors;
stats.TxFailures += txErrors;
stats.TxRetries += txRetries;
// Update stats
TelemetryStats stats;
stats.txBytes = utalkStats.txBytes;
stats.rxBytes = utalkStats.rxBytes;
stats.txObjectBytes = utalkStats.txObjectBytes;
stats.rxObjectBytes = utalkStats.rxObjectBytes;
stats.rxObjects = utalkStats.rxObjects;
stats.txObjects = utalkStats.txObjects;
stats.txErrors = utalkStats.txErrors + txErrors;
stats.rxErrors = utalkStats.rxErrors;
stats.txRetries = txRetries;
// Done
return stats;
}
void Telemetry::resetStats()
{
QMutexLocker locker(mutex);
utalk->resetStats();
txErrors = 0;
txRetries = 0;
statsObj->setData(stats);
}
void Telemetry::objectUpdatedAuto(UAVObject* obj)

View File

@ -31,7 +31,6 @@
#include "uavtalk.h"
#include "uavobjects/uavobjectmanager.h"
#include "uavobjects/gcstelemetrystats.h"
#include <QMutex>
#include <QMutexLocker>
#include <QTimer>
@ -42,7 +41,22 @@ class Telemetry: public QObject
Q_OBJECT
public:
typedef struct {
quint32 txBytes;
quint32 rxBytes;
quint32 txObjectBytes;
quint32 rxObjectBytes;
quint32 rxObjects;
quint32 txObjects;
quint32 txErrors;
quint32 rxErrors;
quint32 txRetries;
} TelemetryStats;
Telemetry(UAVTalk* utalk, UAVObjectManager* objMngr);
TelemetryStats getStats();
void resetStats();
signals:
@ -56,7 +70,6 @@ private slots:
void processPeriodicUpdates();
void transactionCompleted(UAVObject* obj);
void transactionTimeout();
void processStatsUpdates();
private:
// Constants
@ -64,7 +77,6 @@ private:
static const int MAX_RETRIES = 3;
static const int MAX_UPDATE_PERIOD_MS = 1000;
static const int MIN_UPDATE_PERIOD_MS = 1;
static const int STATS_UPDATE_PERIOD_MS = 5000;
static const int MAX_QUEUE_SIZE = 20;
// Types
@ -113,7 +125,6 @@ private:
qint32 timeToNextUpdateMs;
quint32 txErrors;
quint32 txRetries;
GCSTelemetryStats* statsObj;
// Methods
void registerObject(UAVObject* obj);

View File

@ -0,0 +1,227 @@
/**
******************************************************************************
*
* @file telemetrymonitor.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup
* @{
*
*****************************************************************************/
/*
* 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 "telemetrymonitor.h"
#include "qxtlogger.h"
/**
* Constructor
*/
TelemetryMonitor::TelemetryMonitor(UAVObjectManager* objMngr, Telemetry* tel)
{
this->objMngr = objMngr;
this->tel = tel;
this->objPending = NULL;
// Create mutex
mutex = new QMutex(QMutex::Recursive);
// Get stats objects
gcsStatsObj = GCSTelemetryStats::GetInstance(objMngr);
flightStatsObj = FlightTelemetryStats::GetInstance(objMngr);
// Listen for flight stats updates
connect(flightStatsObj, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(flightStatsUpdated(UAVObject*)));
// Start update timer
statsTimer = new QTimer(this);
connect(statsTimer, SIGNAL(timeout()), this, SLOT(processStatsUpdates()));
statsTimer->start(STATS_CONNECT_PERIOD_MS);
}
/**
* Initiate object retrieval, initialize queue with objects to be retrieved.
*/
void TelemetryMonitor::startRetrievingObjects()
{
// Clear object queue
queue.clear();
// Get all objects, add metaobjects, settings and data objects with OnChange update mode to the queue
QList< QList<UAVObject*> > objs = objMngr->getObjects();
for (int n = 0; n < objs.length(); ++n)
{
UAVObject* obj = objs[n][0];
UAVMetaObject* mobj = dynamic_cast<UAVMetaObject*>(obj);
UAVDataObject* dobj = dynamic_cast<UAVDataObject*>(obj);
UAVObject::Metadata mdata = obj->getMetadata();
if ( mdata.gcsTelemetryUpdateMode != UAVObject::UPDATEMODE_NEVER )
{
if ( mobj != NULL )
{
queue.enqueue(obj);
}
else if ( dobj != NULL )
{
if ( dobj->isSettings() )
{
queue.enqueue(obj);
}
else
{
if ( mdata.flightTelemetryUpdateMode == UAVObject::UPDATEMODE_ONCHANGE )
{
queue.enqueue(obj);
}
}
}
}
}
// Start retrieving
qxtLog->debug(tr("Starting to retrieve meta and settings objects from the autopilot (%1 objects)")
.arg( queue.length()) );
retrieveNextObject();
}
/**
* Cancel the object retrieval
*/
void TelemetryMonitor::stopRetrievingObjects()
{
qxtLog->debug("Object retrieval has been cancelled");
queue.clear();
}
/**
* Retrieve the next object in the queue
*/
void TelemetryMonitor::retrieveNextObject()
{
// If queue is empty return
if ( queue.isEmpty() )
{
qxtLog->debug("Object retrieval completed");
return;
}
// Get next object from the queue
UAVObject* obj = queue.dequeue();
//qxtLog->trace( tr("Retrieving object: %1").arg(obj->getName()) );
// Connect to object
connect(obj, SIGNAL(transactionCompleted(UAVObject*,bool)), this, SLOT(transactionCompleted(UAVObject*,bool)));
// Request update
obj->requestUpdate();
objPending = obj;
}
/**
* Called by the retrieved object when a transaction is completed.
*/
void TelemetryMonitor::transactionCompleted(UAVObject* obj, bool success)
{
QMutexLocker locker(mutex);
// Disconnect from sending object
obj->disconnect(this);
objPending = NULL;
// Process next object if telemetry is still available
GCSTelemetryStats::DataFields gcsStats = gcsStatsObj->getData();
if ( gcsStats.Status == GCSTelemetryStats::STATUS_CONNECTED )
{
retrieveNextObject();
}
else
{
stopRetrievingObjects();
}
}
/**
* Called each time the flight stats object is updated by the autopilot
*/
void TelemetryMonitor::flightStatsUpdated(UAVObject* obj)
{
QMutexLocker locker(mutex);
// Force update if not yet connected
GCSTelemetryStats::DataFields gcsStats = gcsStatsObj->getData();
FlightTelemetryStats::DataFields flightStats = flightStatsObj->getData();
if ( gcsStats.Status != GCSTelemetryStats::STATUS_CONNECTED ||
flightStats.Status != FlightTelemetryStats::STATUS_CONNECTED )
{
processStatsUpdates();
}
}
/**
* Called periodically to update the statistics and connection status.
*/
void TelemetryMonitor::processStatsUpdates()
{
QMutexLocker locker(mutex);
// Get telemetry stats
GCSTelemetryStats::DataFields gcsStats = gcsStatsObj->getData();
FlightTelemetryStats::DataFields flightStats = flightStatsObj->getData();
Telemetry::TelemetryStats telStats = tel->getStats();
tel->resetStats();
// Update stats object
gcsStats.RxDataRate = (float)telStats.rxBytes / ((float)statsTimer->interval()/1000.0);
gcsStats.TxDataRate = (float)telStats.txBytes / ((float)statsTimer->interval()/1000.0);
gcsStats.RxFailures += telStats.rxErrors;
gcsStats.TxFailures += telStats.txErrors;
gcsStats.TxRetries += telStats.txRetries;
// Update connection state
if ( gcsStats.Status == GCSTelemetryStats::STATUS_DISCONNECTED )
{
// Request connection
gcsStats.Status = GCSTelemetryStats::STATUS_HANDSHAKEREQ;
statsTimer->setInterval(STATS_CONNECT_PERIOD_MS);
qxtLog->info("Trying to connect to the autopilot");
}
else if ( gcsStats.Status == GCSTelemetryStats::STATUS_HANDSHAKEREQ )
{
// Check for connection acknowledge
if ( flightStats.Status == FlightTelemetryStats::STATUS_HANDSHAKEACK )
{
gcsStats.Status = GCSTelemetryStats::STATUS_CONNECTED;
statsTimer->setInterval(STATS_UPDATE_PERIOD_MS);
qxtLog->info("Connection with the autopilot established");
startRetrievingObjects();
}
}
else if ( gcsStats.Status == GCSTelemetryStats::STATUS_CONNECTED )
{
// Check if the connection is still active and the the autopilot is still connected
if (flightStats.Status == FlightTelemetryStats::STATUS_DISCONNECTED || telStats.rxBytes == 0)
{
gcsStats.Status = GCSTelemetryStats::STATUS_DISCONNECTED;
qxtLog->info("Connection with the autopilot lost");
}
}
// Set data
gcsStatsObj->setData(gcsStats);
// Force telemetry update if not yet connected
if ( gcsStats.Status != GCSTelemetryStats::STATUS_CONNECTED ||
flightStats.Status != FlightTelemetryStats::STATUS_CONNECTED )
{
gcsStatsObj->updated();
}
}

View File

@ -0,0 +1,73 @@
/**
******************************************************************************
*
* @file telemetrymonitor.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* Parts by Nokia Corporation (qt-info@nokia.com) Copyright (C) 2009.
* @brief
* @see The GNU Public License (GPL) Version 3
* @defgroup
* @{
*
*****************************************************************************/
/*
* 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 TELEMETRYMONITOR_H
#define TELEMETRYMONITOR_H
#include <QObject>
#include <QQueue>
#include <QTimer>
#include <QMutex>
#include <QMutexLocker>
#include "uavobjects/uavobjectmanager.h"
#include "uavobjects/gcstelemetrystats.h"
#include "uavobjects/flighttelemetrystats.h"
#include "uavobjects/systemstats.h"
#include "telemetry.h"
class TelemetryMonitor : public QObject
{
Q_OBJECT
public:
TelemetryMonitor(UAVObjectManager* objMngr, Telemetry* tel);
public slots:
void transactionCompleted(UAVObject* obj, bool success);
void processStatsUpdates();
void flightStatsUpdated(UAVObject* obj);
private:
static const int STATS_UPDATE_PERIOD_MS = 5000;
static const int STATS_CONNECT_PERIOD_MS = 1000;
UAVObjectManager* objMngr;
Telemetry* tel;
QQueue<UAVObject*> queue;
GCSTelemetryStats* gcsStatsObj;
FlightTelemetryStats* flightStatsObj;
QTimer* statsTimer;
UAVObject* objPending;
QMutex* mutex;
void startRetrievingObjects();
void retrieveNextObject();
void stopRetrievingObjects();
};
#endif // TELEMETRYMONITOR_H

View File

@ -2,11 +2,12 @@ TEMPLATE = lib
TARGET = UAVTalk
include(../../openpilotgcsplugin.pri)
include(uavtalk_dependencies.pri)
HEADERS += uavtalk.h \
uavtalkplugin.h
uavtalkplugin.h \
telemetrymonitor.h
SOURCES += uavtalk.cpp \
uavtalkplugin.cpp
uavtalkplugin.cpp \
telemetrymonitor.cpp
HEADERS += telemetry.h
SOURCES += telemetry.cpp
OTHER_FILES += UAVTalk.pluginspec

View File

@ -71,10 +71,12 @@ void UAVTalkPlugin::onDeviceConnect(QIODevice *dev)
{
utalk = new UAVTalk(dev, objMngr);
telemetry = new Telemetry(utalk, objMngr);
telemetryMon = new TelemetryMonitor(objMngr, telemetry);
}
void UAVTalkPlugin::onDeviceDisconnect()
{
delete telemetryMon;
delete telemetry;
delete utalk;
}

View File

@ -31,6 +31,7 @@
#include <extensionsystem/iplugin.h>
#include <extensionsystem/pluginmanager.h>
#include <QtPlugin>
#include "telemetrymonitor.h"
#include "telemetry.h"
#include "uavtalk.h"
#include "uavobjects/uavobjectmanager.h"
@ -55,6 +56,7 @@ private:
UAVObjectManager* objMngr;
UAVTalk* utalk;
Telemetry* telemetry;
TelemetryMonitor* telemetryMon;
};
#endif // UAVTALKPLUGIN_H

View File

@ -1,12 +1,12 @@
<xml>
<object name="FlightTelemetryStats" singleinstance="true" settings="false">
<field name="Connected" units="bool" type="enum" elements="1" options="True, False"/>
<field name="Status" units="" type="enum" elements="1" options="Disconnected,HandshakeReq,HandshakeAck,Connected"/>
<field name="TxDataRate" units="bytes/sec" type="float" elements="1"/>
<field name="RxDataRate" units="bytes/sec" type="float" elements="1"/>
<field name="TxFailures" units="count" type="uint32" elements="1"/>
<field name="RxFailures" units="count" type="uint32" elements="1"/>
<field name="TxRetries" units="count" type="uint32" elements="1"/>
<telemetrygcs acked="true" updatemode="never" period="0"/>
<telemetrygcs acked="true" updatemode="manual" period="0"/>
<telemetryflight acked="true" updatemode="periodic" period="5000"/>
<logging updatemode="periodic" period="5000"/>
</object>

View File

@ -1,13 +1,13 @@
<xml>
<object name="GCSTelemetryStats" singleinstance="true" settings="false">
<field name="Connected" units="bool" type="enum" elements="1" options="True, False"/>
<field name="Status" units="" type="enum" elements="1" options="Disconnected,HandshakeReq,HandshakeAck,Connected"/>
<field name="TxDataRate" units="bytes/sec" type="float" elements="1"/>
<field name="RxDataRate" units="bytes/sec" type="float" elements="1"/>
<field name="TxFailures" units="count" type="uint32" elements="1"/>
<field name="RxFailures" units="count" type="uint32" elements="1"/>
<field name="TxRetries" units="count" type="uint32" elements="1"/>
<telemetrygcs acked="true" updatemode="never" period="0"/>
<telemetryflight acked="true" updatemode="never" period="0"/>
<telemetrygcs acked="true" updatemode="periodic" period="5000"/>
<telemetryflight acked="true" updatemode="manual" period="0"/>
<logging updatemode="never" period="0"/>
</object>
</xml>

View File

@ -5,7 +5,7 @@
<field name="Altitude" units="meters" type="float" elements="1"/>
<field name="Satellites" units="" type="int8" elements="1"/>
<field name="Updates" units="" type="uint16" elements="1"/>
<telemetrygcs acked="true" updatemode="never" period="0"/>
<telemetrygcs acked="true" updatemode="manual" period="0"/>
<telemetryflight acked="true" updatemode="periodic" period="1000"/>
<logging updatemode="periodic" period="1000"/>
</object>

View File

@ -1,6 +1,6 @@
<xml>
<object name="ObjectPersistence" singleinstance="true" settings="false">
<field name="Operation" units="" type="enum" elements="1" options="Load,Save"/>
<field name="Operation" units="" type="enum" elements="1" options="Load,Save,Delete"/>
<field name="Objects" units="" type="enum" elements="1" options="All,Settings,MetaObjects"/>
<telemetrygcs acked="true" updatemode="manual" period="0"/>
<telemetryflight acked="true" updatemode="manual" period="0"/>

View File

@ -3,7 +3,7 @@
<field name="FlightTime" units="ms" type="uint32" elements="1"/>
<field name="HeapRemaining" units="bytes" type="uint16" elements="1"/>
<field name="CPULoad" units="%" type="uint8" elements="1"/>
<telemetrygcs acked="true" updatemode="never" period="0"/>
<telemetrygcs acked="true" updatemode="manual" period="0"/>
<telemetryflight acked="true" updatemode="periodic" period="1000"/>
<logging updatemode="periodic" period="1000"/>
</object>