1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +01:00

UAVObjects GCS plug-in: test harness and bug fixes

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@316 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
vassilis 2010-03-15 01:50:52 +00:00 committed by vassilis
parent 8e873ec0e8
commit bc786ba52b
19 changed files with 1572 additions and 966 deletions

View File

@ -0,0 +1,12 @@
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include "uavobjectstest.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
UAVObjectsTest* test = new UAVObjectsTest();
return a.exec();
}

View File

@ -0,0 +1,51 @@
#include "testobject1.h"
const QString TestObject1::NAME = QString("TestObject1");
TestObject1::TestObject1(): UAVDataObject(OBJID, SINGLEINST, NAME)
{
// Create fields
QList<UAVObjectField*> fields;
fields.append(new UAVObjectField(QString("Field1"), QString("unit1"), UAVObjectField::FIELDTYPE_INT16, 1));
fields.append(new UAVObjectField(QString("Field2"), QString("unit2"), UAVObjectField::FIELDTYPE_FLOAT32, 3));
fields.append(new UAVObjectField(QString("Field3"), QString("unit3"), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("Field4"), QString("unit4"), UAVObjectField::FIELDTYPE_INT32, 1));
// Initialize object
initializeFields(fields, (quint8*)&data, NUMBYTES);
}
UAVObject::Metadata TestObject1::getDefaultMetadata()
{
// Create metadata
UAVObject::Metadata metadata;
metadata.ackRequired = true;
metadata.gcsTelemetryUpdateMode = UAVObject::UPDATEMODE_PERIODIC;
metadata.gcsTelemetryUpdatePeriod = 200;
metadata.flightTelemetryUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.flightTelemetryUpdatePeriod = 0;
metadata.loggingUpdateMode = UAVObject::UPDATEMODE_NEVER;
metadata.loggingUpdatePeriod = 0;
return metadata;
}
TestObject1::DataFields TestObject1::getData()
{
QMutexLocker locker(mutex);
return data;
}
void TestObject1::setData(DataFields& data)
{
QMutexLocker locker(mutex);
this->data = data;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
UAVDataObject* TestObject1::clone(quint32 instID)
{
TestObject1* obj = new TestObject1();
obj->initialize(instID, this->getMetaObject());
return obj;
}

View File

@ -0,0 +1,33 @@
#ifndef TESTOBJECT1_H
#define TESTOBJECT1_H
#include "..\uavdataobject.h"
class TestObject1: public UAVDataObject
{
public:
typedef struct {
qint16 field1;
float field2[3];
qint8 field3;
qint32 field4;
} __attribute__((packed)) DataFields;
static const quint32 OBJID = 0x0005;
static const QString NAME;
static const bool SINGLEINST = false;
static const quint32 NUMBYTES = sizeof(DataFields);
TestObject1();
DataFields getData();
void setData(DataFields& data);
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
private:
DataFields data;
};
#endif // TESTOBJECT1_H

View File

@ -0,0 +1,116 @@
#include "uavobjectstest.h"
UAVObjectsTest::UAVObjectsTest(): sout(stdout), done(false)
{
// Create object manager
objMngr = new UAVObjectManager();
connect(objMngr, SIGNAL(newObject(UAVObject*)), this, SLOT(newObject(UAVObject*)));
connect(objMngr, SIGNAL(newInstance(UAVObject*)), this, SLOT(newInstance(UAVObject*)));
// Create test objects
obj1 = new TestObject1();
connect(obj1, SIGNAL(objectUpdated(UAVObject*)), this, SLOT(objectUpdated(UAVObject*)));
connect(obj1, SIGNAL(objectUpdatedAuto(UAVObject*)), this, SLOT(objectUpdatedAuto(UAVObject*)));
connect(obj1, SIGNAL(objectUpdatedManual(UAVObject*)), this, SLOT(objectUpdatedManual(UAVObject*)));
connect(obj1, SIGNAL(objectUnpacked(UAVObject*)), this, SLOT(objectUnpacked(UAVObject*)));
connect(obj1, SIGNAL(updateRequested(UAVObject*)), this, SLOT(updateRequested(UAVObject*)));
objMngr->registerObject(obj1);
// Setup timer
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(runTest()));
timer->start(1000);
}
void UAVObjectsTest::objectUpdated(UAVObject* obj)
{
sout << QString("[Object Updated]\n%1").arg(obj->toString());
}
void UAVObjectsTest::objectUpdatedAuto(UAVObject* obj)
{
sout << QString("[Object Updated AUTO]\n%1").arg(obj->toString());
}
void UAVObjectsTest::objectUpdatedManual(UAVObject* obj)
{
sout << QString("[Object Updated MANUAL]\n%1").arg(obj->toString());
}
void UAVObjectsTest::objectUnpacked(UAVObject* obj)
{
sout << QString("[Object Updated UNPACKED]\n%1").arg(obj->toString());
}
void UAVObjectsTest::updateRequested(UAVObject* obj)
{
sout << QString("[Object Update Requested]\n%1").arg(obj->toString());
}
void UAVObjectsTest::newObject(UAVObject* obj)
{
sout << QString("[New object]\n%1").arg(obj->toString());
}
void UAVObjectsTest::newInstance(UAVObject* obj)
{
sout << QString("[New instance]\n%1").arg(obj->toString());
}
void UAVObjectsTest::runTest()
{
if (!done)
{
// Create a new instance
TestObject1* obj2 = new TestObject1();
objMngr->registerObject(obj2);
// Set data
TestObject1::DataFields data = obj1->getData();
data.field1 = 1;
data.field2[0] = 2.1;
data.field2[1] = 2.2;
data.field2[2] = 2.3;
data.field3 = 3;
data.field4 = 4;
obj1->setData(data);
// Set metadata
UAVObject::Metadata mdata = obj1->getMetadata();
mdata.gcsTelemetryUpdatePeriod = 123;
obj1->setMetadata(mdata);
// Print metadata of both instances
sout << "[Meta of obj1]\n";
sout << obj1->getMetaObject()->toString();
sout << "[Meta of obj2]\n";
sout << obj2->getMetaObject()->toString();
// Create a new instance using clone() and an out of order instance ID
UAVDataObject* obj3 = obj2->clone(5);
objMngr->registerObject(obj3);
// Pack, unpack testing
quint8* buf = new quint8[obj1->getNumBytes()];
obj1->pack(buf);
data.field1 = 10;
data.field2[0] = 20.1;
data.field2[1] = 20.2;
data.field2[2] = 20.3;
data.field3 = 30;
data.field4 = 40;
obj1->setData(data);
obj1->unpack(buf);
// Get all instances
QList<UAVObject*> objs = objMngr->getObjectInstances(TestObject1::OBJID);
for (int n = 0; n < objs.length(); ++n)
{
sout << "[Printing object instances]\n";
sout << objs[n]->toString();
}
// Done
done = true;
}
sout.flush();
}

View File

@ -0,0 +1,35 @@
#ifndef UAVOBJECTSTEST_H
#define UAVOBJECTSTEST_H
#include "..\UAVObjectManager.h"
#include "testobject1.h"
#include <QTimer>
#include <QTextStream>
class UAVObjectsTest: QObject
{
Q_OBJECT
public:
UAVObjectsTest();
private slots:
void objectUpdated(UAVObject* obj);
void objectUpdatedAuto(UAVObject* obj);
void objectUpdatedManual(UAVObject* obj);
void objectUnpacked(UAVObject* obj);
void updateRequested(UAVObject* obj);
void runTest();
void newObject(UAVObject* obj);
void newInstance(UAVObject* obj);
private:
UAVObjectManager* objMngr;
TestObject1* obj1;
QTimer* timer;
QTextStream sout;
bool done;
};
#endif // UAVOBJECTSTEST_H

View File

@ -0,0 +1,23 @@
# -------------------------------------------------
# Project created by QtCreator 2010-03-13T15:17:38
# -------------------------------------------------
QT -= gui
TARGET = uavobjectstest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
../uavobjectmanager.cpp \
../uavobjectfield.cpp \
../uavobject.cpp \
../uavmetaobject.cpp \
../uavdataobject.cpp \
testobject1.cpp \
uavobjectstest.cpp
HEADERS += ../uavobjectmanager.h \
../uavobjectfield.h \
../uavobject.h \
../uavmetaobject.h \
../uavdataobject.h \
testobject1.h \
uavobjectstest.h

View File

@ -25,90 +25,67 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavdataobject.h"
UAVDataObject::UAVDataObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes):
UAVObject(objID, instID, isSingleInst, name, numBytes)
{
data = new quint8[numBytes]; // create data buffer, object fields are stored there as a packed structure
mobj = NULL;
}
void UAVDataObject::initialize(QList<UAVObjectField*> fields, Metadata& mdata)
{
UAVMetaObject* obj = new UAVMetaObject(objID+1, name.append("Meta"), mdata, this);
initialize(fields, obj);
}
void UAVDataObject::initialize(QList<UAVObjectField*> fields, UAVMetaObject* mobj)
{
// Initialize fields and create data buffer
this->mobj = mobj;
this->fields = fields;
quint32 offset = 0;
for (int n = 0; n < fields.length(); ++n)
{
fields.value(n)->initialize(data, offset, this);
offset += fields.value(n)->getNumBytes();
connect(fields.value(n), SIGNAL(fieldUpdated(UAVObjectField*)), this, SLOT(fieldUpdated(UAVObjectField*)));
}
}
void UAVDataObject::fieldUpdated(UAVObjectField* field)
{
emit objectUpdated(this, false); // trigger object updated event
}
qint32 UAVDataObject::getNumFields()
{
return fields.count();
}
QList<UAVObjectField*> UAVDataObject::getFields()
{
return fields;
}
UAVObjectField* UAVDataObject::getField(QString& name)
{
// Look for field
for (int n = 0; n < fields.length(); ++n)
{
if (name.compare(fields.value(n)->getName()) == 0)
{
return fields.value(n);
}
}
// If this point is reached then the field was not found
return NULL;
}
qint32 UAVDataObject::pack(quint8* dataOut)
{
QMutexLocker locker(mutex);
memcpy(dataOut, data, numBytes);
return numBytes;
}
qint32 UAVDataObject::unpack(const quint8* dataIn)
{
QMutexLocker locker(mutex);
memcpy(data, dataIn, numBytes);
emit objectUpdated(this, true); // trigger object updated event
return numBytes;
}
void UAVDataObject::setMetadata(const Metadata& mdata)
{
mobj->setData(mdata);
}
UAVObject::Metadata UAVDataObject::getMetadata(void)
{
return mobj->getData();
}
UAVMetaObject* UAVDataObject::getMetaObject()
{
return mobj;
}
#include "uavdataobject.h"
/**
* Constructor
*/
UAVDataObject::UAVDataObject(quint32 objID, bool isSingleInst, const QString& name):
UAVObject(objID, isSingleInst, name)
{
mobj = NULL;
}
/**
* Initialize instance ID and assign a metaobject
*/
void UAVDataObject::initialize(quint32 instID, UAVMetaObject* mobj)
{
QMutexLocker locker(mutex);
this->mobj = mobj;
UAVObject::initialize(instID);
}
/**
* Assign a metaobject
*/
void UAVDataObject::initialize(UAVMetaObject* mobj)
{
QMutexLocker locker(mutex);
this->mobj = mobj;
}
/**
* Set the object's metadata
*/
void UAVDataObject::setMetadata(const Metadata& mdata)
{
if ( mobj!=NULL )
{
mobj->setData(mdata);
}
}
/**
* Get the object's metadata
*/
UAVObject::Metadata UAVDataObject::getMetadata(void)
{
if ( mobj!=NULL)
{
return mobj->getData();
}
else
{
return getDefaultMetadata();
}
}
/**
* Get the metaobject
*/
UAVMetaObject* UAVDataObject::getMetaObject()
{
return mobj;
}

View File

@ -25,43 +25,30 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UAVDATAOBJECT_H
#define UAVDATAOBJECT_H
#include "uavobject.h"
#include "uavobjectfield.h"
#include "uavmetaobject.h"
#include <QList>
class UAVDataObject: public UAVObject
{
Q_OBJECT
public:
UAVDataObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes);
void initialize(QList<UAVObjectField*> fields, Metadata& mdata);
void initialize(QList<UAVObjectField*> fields, UAVMetaObject* mobj);
qint32 getNumFields();
QList<UAVObjectField*> getFields();
UAVObjectField* getField(QString& name);
qint32 pack(quint8* dataOut);
qint32 unpack(const quint8* dataIn);
void setMetadata(const Metadata& mdata);
Metadata getMetadata();
UAVMetaObject* getMetaObject();
private slots:
void fieldUpdated(UAVObjectField* field);
private:
quint8* data;
QList<UAVObjectField*> fields;
UAVMetaObject* mobj;
void initialize(QList<UAVObjectField*> fields);
};
#endif // UAVDATAOBJECT_H
#ifndef UAVDATAOBJECT_H
#define UAVDATAOBJECT_H
#include "uavobject.h"
#include "uavobjectfield.h"
#include "uavmetaobject.h"
#include <QList>
class UAVDataObject: public UAVObject
{
Q_OBJECT
public:
UAVDataObject(quint32 objID, bool isSingleInst, const QString& name);
void initialize(quint32 instID, UAVMetaObject* mobj);
void initialize(UAVMetaObject* mobj);
void setMetadata(const Metadata& mdata);
Metadata getMetadata();
UAVMetaObject* getMetaObject();
virtual UAVDataObject* clone(quint32 instID = 0) = 0;
private:
UAVMetaObject* mobj;
};
#endif // UAVDATAOBJECT_H

View File

@ -25,61 +25,90 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavmetaobject.h"
UAVMetaObject::UAVMetaObject(quint32 objID, QString& name, Metadata& mdata, UAVObject* parent):
UAVObject(objID, 0, true, name, sizeof(Metadata))
{
this->parentMetadata = mdata;
this->parent = parent;
ownMetadata.ackRequired = 1;
ownMetadata.flightTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
ownMetadata.flightTelemetryUpdatePeriod = 0;
ownMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
ownMetadata.gcsTelemetryUpdatePeriod = 0;
ownMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE;
ownMetadata.loggingUpdatePeriod = 0;
}
UAVObject* UAVMetaObject::getParentObject()
{
return parent;
}
qint32 UAVMetaObject::pack(quint8* dataOut)
{
QMutexLocker locker(mutex);
memcpy(dataOut, &parentMetadata, sizeof(Metadata));
return sizeof(Metadata);
}
qint32 UAVMetaObject::unpack(const quint8* dataIn)
{
QMutexLocker locker(mutex);
memcpy(&parentMetadata, dataIn, sizeof(Metadata));
emit objectUpdated(this, true); // trigger object updated event
return sizeof(Metadata);
}
void UAVMetaObject::setMetadata(const Metadata& mdata)
{
return; // can not update metaobject's metadata
}
UAVObject::Metadata UAVMetaObject::getMetadata()
{
return ownMetadata;
}
void UAVMetaObject::setData(const Metadata& mdata)
{
QMutexLocker locker(mutex);
parentMetadata = mdata;
emit objectUpdated(this, false); // trigger object updated event
}
UAVObject::Metadata UAVMetaObject::getData()
{
QMutexLocker locker(mutex);
return parentMetadata;
}
#include "uavmetaobject.h"
/**
* Constructor
*/
UAVMetaObject::UAVMetaObject(quint32 objID, const QString& name, UAVObject* parent):
UAVObject(objID, true, name)
{
this->parent = parent;
// Setup default metadata of metaobject (can not be changed)
ownMetadata.ackRequired = 1;
ownMetadata.flightTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
ownMetadata.flightTelemetryUpdatePeriod = 0;
ownMetadata.gcsTelemetryUpdateMode = UPDATEMODE_ONCHANGE;
ownMetadata.gcsTelemetryUpdatePeriod = 0;
ownMetadata.loggingUpdateMode = UPDATEMODE_ONCHANGE;
ownMetadata.loggingUpdatePeriod = 0;
// Setup fields
QList<UAVObjectField*> fields;
fields.append(new UAVObjectField(QString("AckRequired"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("FlightTelemetryUpdateMode"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("FlightTelemetryUpdatePeriod"), QString("ms"), UAVObjectField::FIELDTYPE_INT32, 1));
fields.append(new UAVObjectField(QString("GCSTelemetryUpdateMode"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("GCSTelemetryUpdatePeriod"), QString("ms"), UAVObjectField::FIELDTYPE_INT32, 1));
fields.append(new UAVObjectField(QString("LoggingUpdateMode"), QString(""), UAVObjectField::FIELDTYPE_INT8, 1));
fields.append(new UAVObjectField(QString("LoggingUpdatePeriod"), QString("ms"), UAVObjectField::FIELDTYPE_INT32, 1));
// Initialize parent
UAVObject::initialize(0);
UAVObject::initializeFields(fields, (quint8*)&parentMetadata, sizeof(Metadata));
// Setup metadata of parent
parentMetadata = parent->getDefaultMetadata();
}
/**
* Get the parent object
*/
UAVObject* UAVMetaObject::getParentObject()
{
return parent;
}
/**
* Set the metadata of the metaobject, this function will
* do nothing since metaobjects have read-only metadata.
*/
void UAVMetaObject::setMetadata(const Metadata& mdata)
{
return; // can not update metaobject's metadata
}
/**
* Get the metadata of the metaobject
*/
UAVObject::Metadata UAVMetaObject::getMetadata()
{
return ownMetadata;
}
/**
* Get the default metadata
*/
UAVObject::Metadata UAVMetaObject::getDefaultMetadata()
{
return ownMetadata;
}
/**
* Set the metadata held by the metaobject
*/
void UAVMetaObject::setData(const Metadata& mdata)
{
QMutexLocker locker(mutex);
parentMetadata = mdata;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
/**
* Get the metadata held by the metaobject
*/
UAVObject::Metadata UAVMetaObject::getData()
{
QMutexLocker locker(mutex);
return parentMetadata;
}

View File

@ -25,31 +25,29 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UAVMETAOBJECT_H
#define UAVMETAOBJECT_H
#include "uavobject.h"
class UAVMetaObject: public UAVObject
{
Q_OBJECT
public:
UAVMetaObject(quint32 objID, QString& name, Metadata& mdata, UAVObject* parent);
UAVObject* getParentObject();
qint32 pack(quint8* dataOut);
qint32 unpack(const quint8* dataIn);
void setMetadata(const Metadata& mdata);
Metadata getMetadata();
void setData(const Metadata& mdata);
Metadata getData();
private:
UAVObject* parent;
Metadata ownMetadata;
Metadata parentMetadata;
};
#endif // UAVMETAOBJECT_H
#ifndef UAVMETAOBJECT_H
#define UAVMETAOBJECT_H
#include "uavobject.h"
class UAVMetaObject: public UAVObject
{
Q_OBJECT
public:
UAVMetaObject(quint32 objID, const QString& name, UAVObject* parent);
UAVObject* getParentObject();
void setMetadata(const Metadata& mdata);
Metadata getMetadata();
Metadata getDefaultMetadata();
void setData(const Metadata& mdata);
Metadata getData();
private:
UAVObject* parent;
Metadata ownMetadata;
Metadata parentMetadata;
};
#endif // UAVMETAOBJECT_H

View File

@ -25,71 +25,259 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobject.h"
UAVObject::UAVObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes): QObject()
{
this->objID = objID;
this->instID = instID;
this->isSingleInst = isSingleInst;
this->name = name;
this->numBytes = numBytes;
this->mutex = new QMutex(QMutex::Recursive);
}
quint32 UAVObject::getObjID()
{
return objID;
}
quint32 UAVObject::getInstID()
{
return instID;
}
bool UAVObject::isSingleInstance()
{
return isSingleInst;
}
QString UAVObject::getName()
{
return name;
}
quint32 UAVObject::getNumBytes()
{
return numBytes;
}
void UAVObject::requestUpdate()
{
emit updateRequested(this);
}
void UAVObject::updated()
{
emit objectUpdated(this, false);
}
void UAVObject::lock()
{
mutex->lock();
}
void UAVObject::lock(int timeoutMs)
{
mutex->tryLock(timeoutMs);
}
void UAVObject::unlock()
{
mutex->unlock();
}
QMutex* UAVObject::getMutex()
{
return mutex;
}
#include "uavobject.h"
/**
* Constructor
* @param objID The object ID
* @param isSingleInst True if this object can only have a single instance
* @param name Object name
*/
UAVObject::UAVObject(quint32 objID, bool isSingleInst, const QString& name)
{
this->objID = objID;
this->instID = 0;
this->isSingleInst = isSingleInst;
this->name = name;
this->mutex = new QMutex(QMutex::Recursive);
}
/**
* Initialize object with its instance ID
*/
void UAVObject::initialize(quint32 instID)
{
QMutexLocker locker(mutex);
this->instID = instID;
}
/**
* Initialize objects' data fields
* @param fields List of fields held by the object
* @param data Pointer to that actual object data, this is needed by the fields to access the data
* @param numBytes Number of bytes in the object (total, including all fields)
*/
void UAVObject::initializeFields(QList<UAVObjectField*>& fields, quint8* data, quint32 numBytes)
{
QMutexLocker locker(mutex);
this->numBytes = numBytes;
this->data = data;
this->fields = fields;
// Initialize fields
quint32 offset = 0;
for (int n = 0; n < fields.length(); ++n)
{
fields[n]->initialize(data, offset, this);
offset += fields[n]->getNumBytes();
connect(fields[n], SIGNAL(fieldUpdated(UAVObjectField*)), this, SLOT(fieldUpdated(UAVObjectField*)));
}
}
/**
* Called from the fields each time they are updated
*/
void UAVObject::fieldUpdated(UAVObjectField* field)
{
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
/**
* Get the object ID
*/
quint32 UAVObject::getObjID()
{
return objID;
}
/**
* Get the instance ID
*/
quint32 UAVObject::getInstID()
{
return instID;
}
/**
* Returns true if this is a single instance object
*/
bool UAVObject::isSingleInstance()
{
return isSingleInst;
}
/**
* Get the name of the object
*/
QString UAVObject::getName()
{
return name;
}
/**
* Get the total number of bytes of the object's data
*/
quint32 UAVObject::getNumBytes()
{
return numBytes;
}
/**
* Request that this object is updated with the latest values from the autopilot
*/
void UAVObject::requestUpdate()
{
emit updateRequested(this);
}
/**
* Signal that the object has been updated
*/
void UAVObject::updated()
{
emit objectUpdatedManual(this);
emit objectUpdated(this);
}
/**
* Lock mutex of this object
*/
void UAVObject::lock()
{
mutex->lock();
}
/**
* Lock mutex of this object
*/
void UAVObject::lock(int timeoutMs)
{
mutex->tryLock(timeoutMs);
}
/**
* Unlock mutex of this object
*/
void UAVObject::unlock()
{
mutex->unlock();
}
/**
* Get object's mutex
*/
QMutex* UAVObject::getMutex()
{
return mutex;
}
/**
* Get the number of fields held by this object
*/
qint32 UAVObject::getNumFields()
{
QMutexLocker locker(mutex);
return fields.count();
}
/**
* Get the object's fields
*/
QList<UAVObjectField*> UAVObject::getFields()
{
QMutexLocker locker(mutex);
return fields;
}
/**
* Get a specific field
* @returns The field or NULL if not found
*/
UAVObjectField* UAVObject::getField(QString& name)
{
QMutexLocker locker(mutex);
// Look for field
for (int n = 0; n < fields.length(); ++n)
{
if (name.compare(fields[n]->getName()) == 0)
{
return fields[n];
}
}
// If this point is reached then the field was not found
return NULL;
}
/**
* Pack the object data into a byte array
* @returns The number of bytes copied
*/
qint32 UAVObject::pack(quint8* dataOut)
{
QMutexLocker locker(mutex);
qint32 offset = 0;
for (int n = 0; n < fields.length(); ++n)
{
fields[n]->pack(&dataOut[offset]);
offset += fields[n]->getNumBytes();
}
return numBytes;
}
/**
* Unpack the object data from a byte array
* @returns The number of bytes copied
*/
qint32 UAVObject::unpack(const quint8* dataIn)
{
QMutexLocker locker(mutex);
qint32 offset = 0;
for (int n = 0; n < fields.length(); ++n)
{
fields[n]->unpack(&dataIn[offset]);
offset += fields[n]->getNumBytes();
}
emit objectUnpacked(this); // trigger object updated event
emit objectUpdated(this);
return numBytes;
}
/**
* Return a string with the object information
*/
QString UAVObject::toString()
{
QString sout;
sout.append( toStringBrief() );
sout.append( toStringData() );
return sout;
}
/**
* Return a string with the object information (only the header)
*/
QString UAVObject::toStringBrief()
{
QString sout;
sout.append( QString("%1 (ID: %2, InstID: %3, NumBytes: %4, SInst: %5)\n")
.arg(getName())
.arg(getObjID())
.arg(getInstID())
.arg(getNumBytes())
.arg(isSingleInstance()) );
return sout;
}
/**
* Return a string with the object information (only the data)
*/
QString UAVObject::toStringData()
{
QString sout;
sout.append("Data:\n");
for (int n = 0; n < fields.length(); ++n)
{
sout.append( QString("\t%1").arg(fields[n]->toString()) );
}
return sout;
}

View File

@ -25,75 +25,96 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UAVOBJECT_H
#define UAVOBJECT_H
#include <QtGlobal>
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include <QString>
class UAVObject: public QObject
{
Q_OBJECT
public:
/**
* Object update mode
*/
typedef enum {
UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */
UPDATEMODE_ONCHANGE, /** Only update object when its data changes */
UPDATEMODE_MANUAL, /** Manually update object, by calling the updated() function */
UPDATEMODE_NEVER /** Object is never updated */
} UpdateMode;
/**
* Object metadata, each object has a meta object that holds its metadata. The metadata define
* properties for each object and can be used by multiple modules (e.g. telemetry and logger)
*/
typedef struct {
quint8 ackRequired; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */
UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot */
qint32 flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */
UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS */
qint32 gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
UpdateMode loggingUpdateMode; /** Update mode used by the logging module */
qint32 loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
} Metadata;
UAVObject(quint32 objID, quint32 instID, bool isSingleInst, QString& name, quint32 numBytes);
quint32 getObjID();
quint32 getInstID();
bool isSingleInstance();
QString getName();
quint32 getNumBytes();
virtual qint32 pack(quint8* dataOut) = 0;
virtual qint32 unpack(const quint8* dataIn) = 0;
virtual void setMetadata(const Metadata& mdata) = 0;
virtual Metadata getMetadata() = 0;
void requestUpdate();
void updated();
void lock();
void lock(int timeoutMs);
void unlock();
QMutex* getMutex();
signals:
void objectUpdated(UAVObject* obj, bool unpacked);
void updateRequested(UAVObject* obj);
protected:
quint32 objID;
quint32 instID;
bool isSingleInst;
QString name;
quint32 numBytes;
QMutex* mutex;
};
#endif // UAVOBJECT_H
#ifndef UAVOBJECT_H
#define UAVOBJECT_H
#include <QtGlobal>
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include <QString>
#include <QList>
#include "uavobjectfield.h"
class UAVObjectField;
class UAVObject: public QObject
{
Q_OBJECT
public:
/**
* Object update mode
*/
typedef enum {
UPDATEMODE_PERIODIC = 0, /** Automatically update object at periodic intervals */
UPDATEMODE_ONCHANGE = 1, /** Only update object when its data changes */
UPDATEMODE_MANUAL = 2, /** Manually update object, by calling the updated() function */
UPDATEMODE_NEVER = 3 /** Object is never updated */
} UpdateMode;
/**
* Object metadata, each object has a meta object that holds its metadata. The metadata define
* properties for each object and can be used by multiple modules (e.g. telemetry and logger)
*/
typedef struct {
quint8 ackRequired; /** Defines if an ack is required for the transactions of this object (1:acked, 0:not acked) */
quint8 flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */
qint32 flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */
quint8 gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */
qint32 gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
quint8 loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */
qint32 loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
} __attribute__((packed)) Metadata;
UAVObject(quint32 objID, bool isSingleInst, const QString& name);
void initialize(quint32 instID);
quint32 getObjID();
quint32 getInstID();
bool isSingleInstance();
QString getName();
quint32 getNumBytes();
virtual qint32 pack(quint8* dataOut);
virtual qint32 unpack(const quint8* dataIn);
virtual void setMetadata(const Metadata& mdata) = 0;
virtual Metadata getMetadata() = 0;
virtual Metadata getDefaultMetadata() = 0;
void requestUpdate();
void updated();
void lock();
void lock(int timeoutMs);
void unlock();
QMutex* getMutex();
qint32 getNumFields();
QList<UAVObjectField*> getFields();
UAVObjectField* getField(QString& name);
QString toString();
QString toStringBrief();
QString toStringData();
signals:
void objectUpdated(UAVObject* obj);
void objectUpdatedAuto(UAVObject* obj);
void objectUpdatedManual(UAVObject* obj);
void objectUnpacked(UAVObject* obj);
void updateRequested(UAVObject* obj);
private slots:
void fieldUpdated(UAVObjectField* field);
protected:
quint32 objID;
quint32 instID;
bool isSingleInst;
QString name;
quint32 numBytes;
QMutex* mutex;
quint8* data;
QList<UAVObjectField*> fields;
void initializeFields(QList<UAVObjectField*>& fields, quint8* data, quint32 numBytes);
};
#endif // UAVOBJECT_H

View File

@ -25,206 +25,280 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobjectfield.h"
#include <QtEndian>
UAVObjectField::UAVObjectField(QString& name, QString& units, FieldType type, quint32 numElements)
{
// Copy params
this->name = name;
this->units = units;
this->type = type;
this->numElements = numElements;
this->offset = 0;
this->data = NULL;
this->obj = NULL;
// Calculate the number of bytes per element based on the type
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
this->numBytesPerElement = 1;
break;
case FIELDTYPE_INT16:
this->numBytesPerElement = 2;
break;
case FIELDTYPE_INT32:
case FIELDTYPE_FLOAT32:
this->numBytesPerElement = 4;
break;
default:
this->numBytesPerElement = 0;
}
}
void UAVObjectField::initialize(quint8* data, quint32 dataOffset, UAVObject* obj)
{
this->data = data;
this->offset = dataOffset;
this->obj = obj;
clear();
}
UAVObject* UAVObjectField::getObject()
{
return obj;
}
void UAVObjectField::clear()
{
if (data != NULL)
{
QMutexLocker locker(obj->getMutex());
for (unsigned int n = 0; n < numBytesPerElement*numElements; ++n)
{
data[offset + n] = 0;
}
}
}
QString UAVObjectField::getName()
{
return name;
}
QString UAVObjectField::getUnits()
{
return units;
}
UAVObjectField::FieldType UAVObjectField::getType()
{
return type;
}
quint32 UAVObjectField::getNumElements()
{
return numElements;
}
double UAVObjectField::getValue(quint32 index)
{
double ret = 0.0;
// Check if index is out of bounds or no data available
if (index < numElements && data != NULL)
{
// Get value from data
QMutexLocker locker(obj->getMutex());
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
qint8 value8;
value8 = data[offset + numBytesPerElement*index];
ret = (double)value8;
break;
case FIELDTYPE_INT16:
qint16 value16;
value16 = (qint16)qFromBigEndian<qint16>(&data[offset + numBytesPerElement*index]);
ret = (double)value16;
break;
case FIELDTYPE_INT32:
qint32 value32;
value32 = (qint32)qFromBigEndian<qint32>(&data[offset + numBytesPerElement*index]);
ret = (double)value32;
break;
case FIELDTYPE_FLOAT32:
qint32 tmp;
float valuef;
tmp = (qint32)qFromBigEndian<qint32>(&data[offset + numBytesPerElement*index]);
memcpy(&valuef, &tmp, 4);
ret = (double)valuef;
break;
default:
ret = 0.0;
}
}
return ret;
}
void UAVObjectField::setValue(double value, quint32 index)
{
// Check if index is out of bounds or no data available
if (index < numElements && data != NULL)
{
// Set value
QMutexLocker locker(obj->getMutex());
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
data[offset + numBytesPerElement*index] = (qint8)value;
break;
case FIELDTYPE_INT16:
qToBigEndian<qint16>((qint16)value, &data[offset + numBytesPerElement*index]);
break;
case FIELDTYPE_INT32:
qToBigEndian<qint32>((qint32)value, &data[offset + numBytesPerElement*index]);
break;
case FIELDTYPE_FLOAT32:
qint32 tmp;
memcpy(&tmp, &value, 4);
qToBigEndian<qint32>((qint32)tmp, &data[offset + numBytesPerElement*index]);
break;
}
}
// Emit updated event
emit fieldUpdated(this);
}
double UAVObjectField::getValue()
{
return getValue(0);
}
void UAVObjectField::setValue(double value)
{
setValue(value, 0);
}
QString UAVObjectField::getString()
{
QString str;
if (data != NULL)
{
QMutexLocker locker(obj->getMutex());
data[offset + numElements - 1] = '\0'; // null terminate
if (type == FIELDTYPE_CHAR)
{
str.append((char*)&data[offset]);
}
}
return str;
}
void UAVObjectField::setString(QString& str)
{
QByteArray barray = str.toAscii();
if (data != NULL)
{
QMutexLocker locker(obj->getMutex());
for (int n = 0; n < barray.length() && n < (int)numElements; ++n)
{
data[offset+n] = barray[n];
}
data[offset + numElements - 1] = '\0'; // null terminate
}
}
quint32 UAVObjectField::getDataOffset()
{
return offset;
}
quint32 UAVObjectField::getNumBytes()
{
return numBytesPerElement * numElements;
}
quint32 UAVObjectField::getNumBytesElement()
{
return numBytesPerElement;
}
#include "uavobjectfield.h"
#include <QtEndian>
UAVObjectField::UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements)
{
// Copy params
this->name = name;
this->units = units;
this->type = type;
this->numElements = numElements;
this->offset = 0;
this->data = NULL;
this->obj = NULL;
// Calculate the number of bytes per element based on the type
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
this->numBytesPerElement = 1;
break;
case FIELDTYPE_INT16:
this->numBytesPerElement = 2;
break;
case FIELDTYPE_INT32:
case FIELDTYPE_FLOAT32:
this->numBytesPerElement = 4;
break;
default:
this->numBytesPerElement = 0;
}
}
void UAVObjectField::initialize(quint8* data, quint32 dataOffset, UAVObject* obj)
{
this->data = data;
this->offset = dataOffset;
this->obj = obj;
clear();
}
UAVObject* UAVObjectField::getObject()
{
return obj;
}
void UAVObjectField::clear()
{
if (data != NULL)
{
QMutexLocker locker(obj->getMutex());
for (unsigned int n = 0; n < numBytesPerElement*numElements; ++n)
{
data[offset + n] = 0;
}
}
}
QString UAVObjectField::getName()
{
return name;
}
QString UAVObjectField::getUnits()
{
return units;
}
UAVObjectField::FieldType UAVObjectField::getType()
{
return type;
}
quint32 UAVObjectField::getNumElements()
{
return numElements;
}
qint32 UAVObjectField::pack(quint8* dataOut)
{
QMutexLocker locker(obj->getMutex());
// Pack each element in output buffer
for (quint32 index = 0; index < numElements; ++index)
{
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
dataOut[numBytesPerElement*index] = data[offset + numBytesPerElement*index];
break;
case FIELDTYPE_INT16:
qint16 value16;
memcpy(&value16, &data[offset + numBytesPerElement*index], 2);
qToBigEndian<qint16>(value16, &dataOut[numBytesPerElement*index]);
break;
case FIELDTYPE_INT32:
case FIELDTYPE_FLOAT32:
qint32 value32;
memcpy(&value32, &data[offset + numBytesPerElement*index], 4);
qToBigEndian<qint32>(value32, &dataOut[numBytesPerElement*index]);
break;
default:
return 0;
}
}
// Done
return getNumBytes();
}
qint32 UAVObjectField::unpack(const quint8* dataIn)
{
QMutexLocker locker(obj->getMutex());
// Pack each element in output buffer
for (quint32 index = 0; index < numElements; ++index)
{
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
data[offset + numBytesPerElement*index] = dataIn[numBytesPerElement*index];
break;
case FIELDTYPE_INT16:
qint16 value16;
value16 = qFromBigEndian<qint16>(&dataIn[numBytesPerElement*index]);
memcpy(&data[offset + numBytesPerElement*index], &value16, 2);
break;
case FIELDTYPE_INT32:
case FIELDTYPE_FLOAT32:
qint32 value32;
value32 = qFromBigEndian<qint32>(&dataIn[numBytesPerElement*index]);
memcpy(&data[offset + numBytesPerElement*index], &value32, 4);
break;
default:
return 0;
}
}
// Done
return getNumBytes();
}
double UAVObjectField::getValue(quint32 index)
{
double ret = 0.0;
// Check if index is out of bounds or no data available
if (index < numElements && data != NULL)
{
// Get value from data
QMutexLocker locker(obj->getMutex());
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
qint8 value8;
value8 = data[offset + numBytesPerElement*index];
ret = (double)value8;
break;
case FIELDTYPE_INT16:
qint16 value16;
memcpy(&value16, &data[offset + numBytesPerElement*index], 2);
ret = (double)value16;
break;
case FIELDTYPE_INT32:
qint32 value32;
memcpy(&value32, &data[offset + numBytesPerElement*index], 4);
ret = (double)value32;
break;
case FIELDTYPE_FLOAT32:
float valuef;
memcpy(&valuef, &data[offset + numBytesPerElement*index], 4);
ret = (double)valuef;
break;
default:
ret = 0.0;
}
}
return ret;
}
void UAVObjectField::setValue(double value, quint32 index)
{
// Check if index is out of bounds or no data available
if (index < numElements && data != NULL)
{
// Set value
QMutexLocker locker(obj->getMutex());
switch (type) {
case FIELDTYPE_CHAR:
case FIELDTYPE_INT8:
data[offset + numBytesPerElement*index] = (qint8)value;
break;
case FIELDTYPE_INT16:
qint16 value16;
value16 = (qint16)value;
memcpy(&data[offset + numBytesPerElement*index], &value16, 2);
break;
case FIELDTYPE_INT32:
qint32 value32;
value32 = (qint32)value;
memcpy(&data[offset + numBytesPerElement*index], &value32, 4);
break;
case FIELDTYPE_FLOAT32:
float valuef;
valuef = (float)value;
memcpy(&data[offset + numBytesPerElement*index], &valuef, 4);
break;
}
}
// Emit updated event
emit fieldUpdated(this);
}
double UAVObjectField::getValue()
{
return getValue(0);
}
void UAVObjectField::setValue(double value)
{
setValue(value, 0);
}
QString UAVObjectField::getString()
{
QString str;
if (data != NULL)
{
QMutexLocker locker(obj->getMutex());
data[offset + numElements - 1] = '\0'; // null terminate
if (type == FIELDTYPE_CHAR)
{
str.append((char*)&data[offset]);
}
}
return str;
}
void UAVObjectField::setString(QString& str)
{
QByteArray barray = str.toAscii();
if (data != NULL)
{
QMutexLocker locker(obj->getMutex());
for (int n = 0; n < barray.length() && n < (int)numElements; ++n)
{
data[offset+n] = barray[n];
}
data[offset + numElements - 1] = '\0'; // null terminate
}
}
quint32 UAVObjectField::getDataOffset()
{
return offset;
}
quint32 UAVObjectField::getNumBytes()
{
return numBytesPerElement * numElements;
}
quint32 UAVObjectField::getNumBytesElement()
{
return numBytesPerElement;
}
QString UAVObjectField::toString()
{
QString sout;
sout.append ( QString("%1: [ ").arg(name) );
for (unsigned int n = 0; n < numElements; ++n)
{
sout.append( QString("%1 ").arg(getValue(n)) );
}
sout.append( QString("] %1\n").arg(units) );
return sout;
}

View File

@ -25,60 +25,65 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UAVOBJECTFIELD_H
#define UAVOBJECTFIELD_H
#include "uavobject.h"
class UAVObjectField: public QObject
{
Q_OBJECT
public:
/**
* Recognized field types
*/
typedef enum {
FIELDTYPE_INT8 = 0,
FIELDTYPE_INT16,
FIELDTYPE_INT32,
FIELDTYPE_FLOAT32,
FIELDTYPE_CHAR
} FieldType;
UAVObjectField(QString& name, QString& units, FieldType type, quint32 numElements);
void initialize(quint8* data, quint32 dataOffset, UAVObject* obj);
UAVObject* getObject();
QString getName();
QString getUnits();
FieldType getType();
quint32 getNumElements();
double getValue();
void setValue(double value);
double getValue(quint32 index);
void setValue(double value, quint32 index);
QString getString();
void setString(QString& str);
quint32 getDataOffset();
quint32 getNumBytes();
quint32 getNumBytesElement();
signals:
void fieldUpdated(UAVObjectField* field);
private:
QString name;
QString units;
FieldType type;
quint32 numElements;
quint32 numBytesPerElement;
quint32 offset;
quint8* data;
UAVObject* obj;
void clear();
};
#endif // UAVOBJECTFIELD_H
#ifndef UAVOBJECTFIELD_H
#define UAVOBJECTFIELD_H
#include "uavobject.h"
class UAVObject;
class UAVObjectField: public QObject
{
Q_OBJECT
public:
/**
* Recognized field types
*/
typedef enum {
FIELDTYPE_INT8 = 0,
FIELDTYPE_INT16,
FIELDTYPE_INT32,
FIELDTYPE_FLOAT32,
FIELDTYPE_CHAR
} FieldType;
UAVObjectField(const QString& name, const QString& units, FieldType type, quint32 numElements);
void initialize(quint8* data, quint32 dataOffset, UAVObject* obj);
UAVObject* getObject();
QString getName();
QString getUnits();
FieldType getType();
quint32 getNumElements();
qint32 pack(quint8* dataOut);
qint32 unpack(const quint8* dataIn);
double getValue();
void setValue(double value);
double getValue(quint32 index);
void setValue(double value, quint32 index);
QString getString();
void setString(QString& str);
quint32 getDataOffset();
quint32 getNumBytes();
quint32 getNumBytesElement();
QString toString();
signals:
void fieldUpdated(UAVObjectField* field);
private:
QString name;
QString units;
FieldType type;
quint32 numElements;
quint32 numBytesPerElement;
quint32 offset;
quint8* data;
UAVObject* obj;
void clear();
};
#endif // UAVOBJECTFIELD_H

View File

@ -25,278 +25,311 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobjectmanager.h"
UAVObjectManager::UAVObjectManager()
{
mutex = new QMutex(QMutex::Recursive);
}
bool UAVObjectManager::registerObject(UAVObject* obj)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0 && objects[objidx][0]->getObjID() == obj->getObjID())
{
// Check if the instance is already in the list
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
if ( objects[objidx][instidx]->getInstID() == obj->getInstID() )
{
// Object already registered, do not add
return false;
}
}
// If this point is reached, the object is not in the list, so now we can add it in the existing list
objects[objidx].append(obj);
emit newObject(obj);
return true;
}
}
// If this point is reached then this is the first time this object ID is added in the list
// create a new list of the instances and add in the object collection.
QList<UAVObject*> list;
list.append(obj);
objects.append(list);
emit newObject(obj);
return true;
}
UAVDataObject* UAVObjectManager::newObjectInstance(QString& name, quint32 instId)
{
return newObjectInstance(&name, 0, instId);
}
UAVDataObject* UAVObjectManager::newObjectInstance(quint32 objId, quint32 instId)
{
return newObjectInstance(NULL, objId, instId);
}
UAVDataObject* UAVObjectManager::newObjectInstance(QString* name, quint32 objId, quint32 instId)
{
QMutexLocker locker(mutex);
// Get object of the same name from collection
UAVObject* tmpObj;
if (name != NULL)
{
tmpObj = getObject(*name);
}
else
{
tmpObj = getObject(objId);
}
if (tmpObj == NULL)
{
return NULL;
}
// Make sure this is a data object
UAVDataObject* refObj = dynamic_cast<UAVDataObject*>(tmpObj);
if (refObj == NULL)
{
return NULL;
}
// Check if this is single instance object
if (refObj->isSingleInstance())
{
return NULL;
}
// Make a deep copy of the fields in the reference object
QList<UAVObjectField*> fields;
QList<UAVObjectField*> refFields = refObj->getFields();
for (int n = 0; n < refFields.length(); ++n)
{
QString fname = refFields[n]->getName();
QString funits = refFields[n]->getUnits();
UAVObjectField* field = new UAVObjectField(fname, funits, refFields[n]->getType(),
refFields[n]->getNumElements());
fields.append(field);
}
// Calculate instance ID, if the one specified is 0
// (the first object registered always gets the instance ID of zero, so any new instances will be >1)
if (instId == 0)
{
instId = getNumInstances(tmpObj->getObjID()) + 1;
}
// Create new instance, by using properties from reference object
QString oname = refObj->getName();
UAVDataObject* obj = new UAVDataObject(refObj->getObjID(), instId, refObj->isSingleInstance(),
oname, refObj->getNumBytes());
obj->initialize(fields, refObj->getMetaObject());
// Register
registerObject(obj);
// Trigger update
obj->updated();
return obj;
}
QList< QList<UAVObject*> > UAVObjectManager::getObjects()
{
QMutexLocker locker(mutex);
return objects;
}
QList< QList<UAVDataObject*> > UAVObjectManager::getDataObjects()
{
QMutexLocker locker(mutex);
QList< QList<UAVDataObject*> > dObjects;
// Go through objects and copy to new list when types match
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
if (objects[objidx].length() > 0)
{
// Check type
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objects[objidx][0]);
if (obj != NULL)
{
// Create instance list
QList<UAVDataObject*> list;
// Go through instances and cast them to UAVDataObject, then add to list
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
obj = dynamic_cast<UAVDataObject*>(objects[objidx][instidx]);
if (obj != NULL)
{
list.append(obj);
}
}
// Append to object list
dObjects.append(list);
}
}
}
// Done
return dObjects;
}
QList <QList<UAVMetaObject*> > UAVObjectManager::getMetaObjects()
{
QMutexLocker locker(mutex);
QList< QList<UAVMetaObject*> > mObjects;
// Go through objects and copy to new list when types match
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
if (objects[objidx].length() > 0)
{
// Check type
UAVMetaObject* obj = dynamic_cast<UAVMetaObject*>(objects[objidx][0]);
if (obj != NULL)
{
// Create instance list
QList<UAVMetaObject*> list;
// Go through instances and cast them to UAVMetaObject, then add to list
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
obj = dynamic_cast<UAVMetaObject*>(objects[objidx][instidx]);
if (obj != NULL)
{
list.append(obj);
}
}
// Append to object list
mObjects.append(list);
}
}
}
// Done
return mObjects;
}
UAVObject* UAVObjectManager::getObject(QString& name, quint32 instId)
{
return getObject(&name, 0, instId);
}
UAVObject* UAVObjectManager::getObject(quint32 objId, quint32 instId)
{
return getObject(NULL, objId, instId);
}
UAVObject* UAVObjectManager::getObject(QString* name, quint32 objId, quint32 instId)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0)
{
if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) )
{
// Look for the requested instance ID
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
if (objects[objidx][instidx]->getInstID() == instId)
{
return objects[objidx][instidx];
}
}
}
}
}
// If this point is reached then the requested object could not be found
return NULL;
}
QList<UAVObject*> UAVObjectManager::getObjectInstances(QString& name)
{
return getObjectInstances(&name, 0);
}
QList<UAVObject*> UAVObjectManager::getObjectInstances(quint32 objId)
{
return getObjectInstances(NULL, objId);
}
QList<UAVObject*> UAVObjectManager::getObjectInstances(QString* name, quint32 objId)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0)
{
if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) )
{
return objects[objidx];
}
}
}
// If this point is reached then the requested object could not be found
return QList<UAVObject*>();
}
qint32 UAVObjectManager::getNumInstances(QString& name)
{
return getNumInstances(&name, 0);
}
qint32 UAVObjectManager::getNumInstances(quint32 objId)
{
return getNumInstances(NULL, objId);
}
qint32 UAVObjectManager::getNumInstances(QString* name, quint32 objId)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0)
{
if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) )
{
return objects[objidx].length();
}
}
}
// If this point is reached then the requested object could not be found
return -1;
}
#include "uavobjectmanager.h"
/**
* Constructor
*/
UAVObjectManager::UAVObjectManager()
{
mutex = new QMutex(QMutex::Recursive);
}
/**
* Register an object with the manager. This function must be called for all newly created instances.
* A new instance can be created directly by instantiating a new object or by calling clone() of
* an existing object. The object will be registered and will be properly initialized so that it can accept
* updates.
*/
bool UAVObjectManager::registerObject(UAVDataObject* obj)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0 && objects[objidx][0]->getObjID() == obj->getObjID())
{
// Check if this is a single instance object, if yes we can not add a new instance
if (obj->isSingleInstance())
{
return false;
}
// The object type has alredy been added, so now we need to initialize the new instance with the appropriate id
// There is a single metaobject for all object instances of this type, so no need to create a new one
// Get object type metaobject from existing instance
UAVDataObject* refObj = dynamic_cast<UAVDataObject*>(objects[objidx][0]);
if (refObj == NULL)
{
return false;
}
UAVMetaObject* mobj = refObj->getMetaObject();
// If the instance ID is specified and not at the default value (0) then we need to make sure
// that there are no gaps in the instance list. If gaps are found then then additional instances
// will be created.
if ( (obj->getInstID() > 0) && (obj->getInstID() < MAX_INSTANCES) )
{
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
if ( objects[objidx][instidx]->getInstID() == obj->getInstID() )
{
// Instance conflict, do not add
return false;
}
}
// Check if there are any gaps between the requested instance ID and the ones in the list,
// if any then create the missing instances.
for (quint32 instidx = objects[objidx].length(); instidx < obj->getInstID(); ++instidx)
{
UAVDataObject* cobj = obj->clone(instidx);
cobj->initialize(mobj);
objects[objidx].append(cobj);
emit newInstance(cobj);
}
// Finally, initialize the actual object instance
obj->initialize(mobj);
}
else if (obj->getInstID() == 0)
{
// Assign the next available ID and initialize the object instance
obj->initialize(objects[objidx].length(), mobj);
}
else
{
return false;
}
// Add the actual object instance in the list
objects[objidx].append(obj);
emit newInstance(obj);
return true;
}
}
// If this point is reached then this is the first time this object type (ID) is added in the list
// create a new list of the instances, add in the object collection and create the object's metaobject
// Create metaobject
QString mname = obj->getName();
mname.append("Meta");
UAVMetaObject* mobj = new UAVMetaObject(obj->getObjID()+1, mname, obj);
// Initialize object
obj->initialize(0, mobj);
// Add to list
addObject(obj);
addObject(mobj);
return true;
}
void UAVObjectManager::addObject(UAVObject* obj)
{
// Add to list
QList<UAVObject*> list;
list.append(obj);
objects.append(list);
emit newObject(obj);
}
/**
* Get all objects. A two dimentional QList is returned. Objects are grouped by
* instances of the same object type.
*/
QList< QList<UAVObject*> > UAVObjectManager::getObjects()
{
QMutexLocker locker(mutex);
return objects;
}
/**
* Same as getObjects() but will only return DataObjects.
*/
QList< QList<UAVDataObject*> > UAVObjectManager::getDataObjects()
{
QMutexLocker locker(mutex);
QList< QList<UAVDataObject*> > dObjects;
// Go through objects and copy to new list when types match
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
if (objects[objidx].length() > 0)
{
// Check type
UAVDataObject* obj = dynamic_cast<UAVDataObject*>(objects[objidx][0]);
if (obj != NULL)
{
// Create instance list
QList<UAVDataObject*> list;
// Go through instances and cast them to UAVDataObject, then add to list
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
obj = dynamic_cast<UAVDataObject*>(objects[objidx][instidx]);
if (obj != NULL)
{
list.append(obj);
}
}
// Append to object list
dObjects.append(list);
}
}
}
// Done
return dObjects;
}
/**
* Same as getObjects() but will only return MetaObjects.
*/
QList <QList<UAVMetaObject*> > UAVObjectManager::getMetaObjects()
{
QMutexLocker locker(mutex);
QList< QList<UAVMetaObject*> > mObjects;
// Go through objects and copy to new list when types match
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
if (objects[objidx].length() > 0)
{
// Check type
UAVMetaObject* obj = dynamic_cast<UAVMetaObject*>(objects[objidx][0]);
if (obj != NULL)
{
// Create instance list
QList<UAVMetaObject*> list;
// Go through instances and cast them to UAVMetaObject, then add to list
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
obj = dynamic_cast<UAVMetaObject*>(objects[objidx][instidx]);
if (obj != NULL)
{
list.append(obj);
}
}
// Append to object list
mObjects.append(list);
}
}
}
// Done
return mObjects;
}
/**
* Get a specific object given its name and instance ID
* @returns The object is found or NULL if not
*/
UAVObject* UAVObjectManager::getObject(QString& name, quint32 instId)
{
return getObject(&name, 0, instId);
}
/**
* Get a specific object given its object and instance ID
* @returns The object is found or NULL if not
*/
UAVObject* UAVObjectManager::getObject(quint32 objId, quint32 instId)
{
return getObject(NULL, objId, instId);
}
/**
* Helper function for the public getObject() functions.
*/
UAVObject* UAVObjectManager::getObject(QString* name, quint32 objId, quint32 instId)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0)
{
if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) )
{
// Look for the requested instance ID
for (int instidx = 0; instidx < objects[objidx].length(); ++instidx)
{
if (objects[objidx][instidx]->getInstID() == instId)
{
return objects[objidx][instidx];
}
}
}
}
}
// If this point is reached then the requested object could not be found
return NULL;
}
/**
* Get all the instances of the object specified by name
*/
QList<UAVObject*> UAVObjectManager::getObjectInstances(QString& name)
{
return getObjectInstances(&name, 0);
}
/**
* Get all the instances of the object specified by its ID
*/
QList<UAVObject*> UAVObjectManager::getObjectInstances(quint32 objId)
{
return getObjectInstances(NULL, objId);
}
/**
* Helper function for the public getObjectInstances()
*/
QList<UAVObject*> UAVObjectManager::getObjectInstances(QString* name, quint32 objId)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0)
{
if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) )
{
return objects[objidx];
}
}
}
// If this point is reached then the requested object could not be found
return QList<UAVObject*>();
}
/**
* Get the number of instances for an object given its name
*/
qint32 UAVObjectManager::getNumInstances(QString& name)
{
return getNumInstances(&name, 0);
}
/**
* Get the number of instances for an object given its ID
*/
qint32 UAVObjectManager::getNumInstances(quint32 objId)
{
return getNumInstances(NULL, objId);
}
/**
* Helper function for public getNumInstances
*/
qint32 UAVObjectManager::getNumInstances(QString* name, quint32 objId)
{
QMutexLocker locker(mutex);
// Check if this object type is already in the list
for (int objidx = 0; objidx < objects.length(); ++objidx)
{
// Check if the object ID is in the list
if (objects[objidx].length() > 0)
{
if ( (name != NULL && objects[objidx][0]->getName().compare(name) == 0) || (name == NULL && objects[objidx][0]->getObjID() == objId) )
{
return objects[objidx].length();
}
}
}
// If this point is reached then the requested object could not be found
return -1;
}

View File

@ -25,47 +25,49 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef UAVOBJECTMANAGER_H
#define UAVOBJECTMANAGER_H
#include "uavobject.h"
#include "uavdataobject.h"
#include "uavmetaobject.h"
#include <QList>
#include <QMutex>
class UAVObjectManager: public QObject
{
Q_OBJECT
public:
UAVObjectManager();
bool registerObject(UAVObject* obj);
UAVDataObject* newObjectInstance(QString& name, quint32 instId = 0);
UAVDataObject* newObjectInstance(quint32 objId, quint32 instId = 0);
QList< QList<UAVObject*> > getObjects();
QList< QList<UAVDataObject*> > getDataObjects();
QList< QList<UAVMetaObject*> > getMetaObjects();
UAVObject* getObject(QString& name, quint32 instId = 0);
UAVObject* getObject(quint32 objId, quint32 instId = 0);
QList<UAVObject*> getObjectInstances(QString& name);
QList<UAVObject*> getObjectInstances(quint32 objId);
qint32 getNumInstances(QString& name);
qint32 getNumInstances(quint32 objId);
signals:
void newObject(UAVObject* obj);
private:
QList< QList<UAVObject*> > objects;
QMutex* mutex;
UAVDataObject* newObjectInstance(QString* name, quint32 objId, quint32 instId);
UAVObject* getObject(QString* name, quint32 objId, quint32 instId);
QList<UAVObject*> getObjectInstances(QString* name, quint32 objId);
qint32 getNumInstances(QString* name, quint32 objId);
};
#endif // UAVOBJECTMANAGER_H
#ifndef UAVOBJECTMANAGER_H
#define UAVOBJECTMANAGER_H
#include "uavobject.h"
#include "uavdataobject.h"
#include "uavmetaobject.h"
#include <QList>
#include <QMutex>
#include <QMutexLocker>
class UAVObjectManager: public QObject
{
Q_OBJECT
public:
UAVObjectManager();
bool registerObject(UAVDataObject* obj);
QList< QList<UAVObject*> > getObjects();
QList< QList<UAVDataObject*> > getDataObjects();
QList< QList<UAVMetaObject*> > getMetaObjects();
UAVObject* getObject(QString& name, quint32 instId = 0);
UAVObject* getObject(quint32 objId, quint32 instId = 0);
QList<UAVObject*> getObjectInstances(QString& name);
QList<UAVObject*> getObjectInstances(quint32 objId);
qint32 getNumInstances(QString& name);
qint32 getNumInstances(quint32 objId);
signals:
void newObject(UAVObject* obj);
void newInstance(UAVObject* obj);
private:
static const quint32 MAX_INSTANCES = 1000;
QList< QList<UAVObject*> > objects;
QMutex* mutex;
void addObject(UAVObject* obj);
UAVObject* getObject(QString* name, quint32 objId, quint32 instId);
QList<UAVObject*> getObjectInstances(QString* name, quint32 objId);
qint32 getNumInstances(QString* name, quint32 objId);
};
#endif // UAVOBJECTMANAGER_H

View File

@ -25,9 +25,13 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobjectsinit.h"
void UAVObjectsInitialize(UAVObjectManager* objMngr)
{
//objMngr->registerObject( new TestObject() );
}
#include "uavobjectsinit.h"
/**
* Static function used to initialize the first instance of each object.
* For each object class an entry should be made here.
*/
void UAVObjectsInitialize(UAVObjectManager* objMngr)
{
//objMngr->registerObject( new TestObject() );
}

View File

@ -25,36 +25,52 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "uavobjecttemplate.h"
#include "$(NAMELC).h"
$(NAME)::$(NAME)(): UAVDataObject(OBJID, 0, SINGLEINST, NAME, NUMBYTES)
const QString $(NAME)::NAME = QString("$(NAME)");
$(NAME)::$(NAME)(): UAVDataObject(OBJID, SINGLEINST, NAME)
{
// Create fields
QList<UAVObjectField*> fields;
$(FIELDS)
// fields.append(new UAVObjectField($(FIELD_NAME), $(FIELD_UNITS), $(FIELD_TYPE), $(FIELD_NUMELEM));
// Create metadata
UAVObject::Metadata metadata;
metadata.ackRequired = $(ACK);
metadata.gcsTelemetryUpdateMode = $(GCSTELEM_UPDATEMODE);
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
metadata.flightTelemetryUpdateMode = $(FLIGHTTELEM_UPDATEMODE);
metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
metadata.loggingUpdateMode = $(LOGGING_UPDATEMODE);
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
// fields.append(new UAVObjectField(QString("$(FIELD_NAME)"), QString("$(FIELD_UNITS)", UAVObjectField::$(FIELD_TYPE), $(FIELD_NUMELEM));
// Initialize object
initialize(fields, metadata);
initializeFields(fields, (quint8*)&data, NUMBYTES);
}
$(NAME)Data $(NAME)::getData()
UAVObject::Metadata $(NAME)::getDefaultMetadata()
{
UAVObject::Metadata metadata;
metadata.ackRequired = $(ACK);
metadata.gcsTelemetryUpdateMode = UAVObject::$(GCSTELEM_UPDATEMODE);
metadata.gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
metadata.flightTelemetryUpdateMode = UAVObject::$(FLIGHTTELEM_UPDATEMODE);
metadata.flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
metadata.loggingUpdateMode = UAVObject::$(LOGGING_UPDATEMODE);
metadata.loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
return metadata;
}
$(NAME)::DataFields $(NAME)::getData()
{
QMutexLocker locker(mutex);
return data;
}
void $(NAME)::setData($(NAME)Data& data)
void $(NAME)::setData(DataFields& data)
{
QMutexLocker locker(mutex);
this->data = data;
emit objectUpdatedAuto(this); // trigger object updated event
emit objectUpdated(this);
}
UAVDataObject* $(NAME)::clone(quint32 instID)
{
$(NAME)* obj = new $(NAME)();
obj->initialize(instID, this->getMetaObject());
return obj;
}

View File

@ -30,25 +30,27 @@
#include "uavdataobject.h"
class $(NAME): UAVDataObject
class $(NAME): public UAVDataObject
{
public:
static const quint32 OBJID = $(OBJID);
static const QString NAME = QString($(NAME));
static const bool SINGLEINST = $(SINGLEINST);
static const quint32 NUMBYTES = sizeof($(NAME)Data);
public:
typedef struct {
$(DATAFIELDS)
} __attribute__((packed)) $(NAME)Data;
} __attribute__((packed)) DataFields;
static const quint32 OBJID = $(OBJID);
static const QString NAME;
static const bool SINGLEINST = $(SINGLEINST);
static const quint32 NUMBYTES = sizeof(DataFields);
$(NAME)();
$(NAME)Data getData();
void setData($(NAME)Data& data);
DataFields getData();
void setData(DataFields& data);
Metadata getDefaultMetadata();
UAVDataObject* clone(quint32 instID);
private:
$(NAME)Data data;
DataFields data;
};