1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-01 09:24:10 +01:00

FlightPlan/Python: Updated object generator to create a Python file for each UAVObject. It is now possible to access all UAVObjects from the FlightPlan Python scripts.

Warning: The memory utilization when importing objects is unacceptably high making it unusable in the flight code at this point. It can be however used with the SITL simulator. Some more investigation is needed to understand why several kb of memory are used each time a module is imported (even before any functions are called or objects from the module are created). 


git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2938 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
vassilis 2011-03-03 02:22:50 +00:00 committed by vassilis
parent 870242d456
commit b084ea7ea1
11 changed files with 573 additions and 66 deletions

View File

@ -25,7 +25,7 @@
#ifndef _PLAT_H_
#define _PLAT_H_
#define PM_HEAP_SIZE 0x2000
#define PM_HEAP_SIZE 0x20000
#define PM_FLOAT_LITTLE_ENDIAN
#endif /* _PLAT_H_ */

View File

@ -91,8 +91,8 @@ static void flightPlanTask(void *parameters)
status.ErrorFileID = 0;
status.ErrorLineNum = 0;
status.ErrorType = FLIGHTPLANSTATUS_ERRORTYPE_NONE;
status.Debug1 = 0.0;
status.Debug2 = 0.0;
status.Debug[0] = 0.0;
status.Debug[1] = 0.0;
FlightPlanStatusSet(&status);
// Main thread loop
@ -261,8 +261,8 @@ static void objectUpdatedCb(UAVObjEvent * ev)
statusData.ErrorFileID = 0;
statusData.ErrorLineNum = 0;
statusData.ErrorType = FLIGHTPLANSTATUS_ERRORTYPE_NONE;
statusData.Debug1 = 0.0;
statusData.Debug2 = 0.0;
statusData.Debug[0] = 0.0;
statusData.Debug[1] = 0.0;
FlightPlanStatusSet(&statusData);
}
}

View File

@ -1,12 +1,37 @@
import openpilot
import sys
#mb = sys.heap()
#mb = mb[0]
import openpilot
#ma = sys.heap()
#ma = ma[0]
#print('import openpilot')
#print(mb-ma)
#mb = sys.heap()
#mb = mb[0]
import flightplanstatus
#ma = sys.heap()
#ma = ma[0]
#print('import flightplanstatus')
#print(mb-ma)
#mb = sys.heap()
#mb = mb[0]
import mixersettings
#ma = sys.heap()
#ma = ma[0]
#print('import mixersettings')
#print(mb-ma)
n = 0
timenow = openpilot.time()
timenow = sys.time()
fpStatus = flightplanstatus.FlightPlanStatus()
while n < 120:
n = n+1
openpilot.debug(n, timenow)
#openpilot.debug(n, timenow)
fpStatus.read()
fpStatus.Debug.value[0] = n
fpStatus.Debug.value[1] = timenow
fpStatus.write()
timenow = openpilot.delayUntil(timenow, 1000)
if openpilot.hasStopRequest():
sys.exit()

View File

@ -31,13 +31,6 @@
#include "flightplancontrol.h"
"""
import sys
# Get system time in ms
def time():
return sys.time()
# Delay (suspend VM thread) for timeToDelayMs ms
def delay(timeToDelayMs):
"""__NATIVE__
@ -147,9 +140,9 @@ def debug(val1, val2):
// Update debug1
pobj = NATIVE_GET_LOCAL(0);
if ( OBJ_GET_TYPE(pobj) == OBJ_TYPE_INT )
status.Debug1 = (float)(((pPmInt_t) pobj)->val);
status.Debug[0] = (float)(((pPmInt_t) pobj)->val);
else if ( OBJ_GET_TYPE(pobj) == OBJ_TYPE_FLT )
status.Debug1 = (float)(((pPmFloat_t) pobj)->val);
status.Debug[0] = (float)(((pPmFloat_t) pobj)->val);
else
{
PM_RAISE(retval, PM_RET_EX_TYPE);
@ -159,9 +152,9 @@ def debug(val1, val2):
// Update debug2
pobj = NATIVE_GET_LOCAL(1);
if ( OBJ_GET_TYPE(pobj) == OBJ_TYPE_INT )
status.Debug2 = (float)(((pPmInt_t) pobj)->val);
status.Debug[1] = (float)(((pPmInt_t) pobj)->val);
else if ( OBJ_GET_TYPE(pobj) == OBJ_TYPE_FLT )
status.Debug2 = (float)(((pPmFloat_t) pobj)->val);
status.Debug[1] = (float)(((pPmFloat_t) pobj)->val);
else
{
PM_RAISE(retval, PM_RET_EX_TYPE);

View File

@ -0,0 +1,425 @@
##
##############################################################################
#
# @file uavobject.py
# @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
# @brief Base classes for python UAVObject
#
# @see The GNU Public License (GPL) Version 3
#
#############################################################################/
#
# 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
#
"""__NATIVE__
#include "openpilot.h"
#define TYPE_INT8 0
#define TYPE_INT16 1
#define TYPE_INT32 2
#define TYPE_UINT8 3
#define TYPE_UINT16 4
#define TYPE_UINT32 5
#define TYPE_FLOAT32 6
#define TYPE_ENUM 7
"""
from list import append
class UAVObjectMetadata:
class UpdateMode:
PERIODIC = 0
ONCHANGE = 1
MANUAL = 2
NEVER = 3
class Access:
READWRITE = 0
READONLY = 1
def __init__(self, objId):
self.access = UAVObjectMetadata.Access.READWRITE
self.gcsAccess = UAVObjectMetadata.Access.READWRITE
self.telemetryAcked = False
self.telemetryUpdateMode = UAVObjectMetadata.UpdateMode.MANUAL
self.telemetryUpdatePeriod = 0
self.gcsTelemetryAcked = False
self.gcsTelemetryUpdateMode = UAVObjectMetadata.UpdateMode.MANUAL
self.gcsTelemetryUpdatePeriod = 0
self.loggingUpdateMode = 0
self.loggingUpdatePeriod = UAVObjectMetadata.UpdateMode.MANUAL
self.objId = objId
self.read()
def read(self):
pass
def write(self):
pass
class UAVObjectField:
class FType:
INT8 = 0
INT16 = 1
INT32 = 2
UINT8 = 3
UINT16 = 4
UINT32 = 5
FLOAT32 = 6
ENUM = 7
def __init__(self, ftype, numElements):
self.ftype = ftype
self.numElements = numElements
if ftype == UAVObjectField.FType.FLOAT32:
if numElements == 1:
self.value = 0.0
else:
self.value = []
for n in range(0, numElements):
append(self.value, 0.0)
else:
if numElements == 1:
self.value = 0
else:
self.value = []
for n in range(0, numElements):
append(self.value, 0)
class UAVObject:
def __init__(self, objId):
self.metadata = UAVObjectMetadata(objId)
self.objId = objId
self.instId = 0
self.fields = []
def addField(self, field):
append(self.fields, field)
def getName(self):
"""__NATIVE__
UAVObjHandle objHandle;
pPmObj_t nameObj;
pPmObj_t self;
pPmObj_t attrs;
pPmObj_t fieldName;
pPmObj_t field;
PmReturn_t retval;
uint32_t objId;
const char* name;
uint8_t const *tmpStr;
// Get dictionary of class attributes
self = NATIVE_GET_LOCAL(0);
attrs = (pPmObj_t)((pPmInstance_t)self)->cli_attrs;
// Get object ID
tmpStr = (uint8_t const *)"objId";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
objId = ((pPmInt_t) field)->val;
// Get name
objHandle = UAVObjGetByID(objId);
name = UAVObjGetName(objHandle);
// Create return object
retval = string_new(name, &nameObj); PM_RETURN_IF_ERROR(retval);
NATIVE_SET_TOS(nameObj);
return PM_RET_OK;
"""
pass
def read(self):
"""__NATIVE__
uint8_t numBytes;
UAVObjHandle objHandle;
uint32_t objId;
uint16_t instId;
pPmObj_t self;
pPmObj_t attrs;
pPmObj_t field;
pPmObj_t fields;
pPmObj_t fieldName;
pPmObj_t value;
PmReturn_t retval;
uint32_t numFields;
uint32_t fieldIdx;
uint32_t dataIdx;
uint32_t valueIdx;
uint32_t type;
uint32_t numElements;
uint8_t const *tmpStr;
int16_t *tmpInt16;
int32_t *tmpInt32;
float *tmpFloat;
// Get dictionary of class attributes
self = NATIVE_GET_LOCAL(0);
attrs = (pPmObj_t)((pPmInstance_t)self)->cli_attrs;
// Get object ID
tmpStr = (uint8_t const *)"objId";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
objId = ((pPmInt_t) field)->val;
// Get the instance ID
tmpStr = (uint8_t const *)"instId";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
instId = ((pPmInt_t) field)->val;
// Get handle and number of bytes in the object
objHandle = UAVObjGetByID(objId);
numBytes = UAVObjGetNumBytes(objHandle);
uint8_t data[numBytes];
// Read object data
UAVObjGetInstanceData(objHandle, instId, data);
// Get dictionary of fields
tmpStr = (uint8_t const *)"fields";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &fields); PM_RETURN_IF_ERROR(retval);
numFields = ((pPmList_t) fields)->length;
// Process each field
dataIdx = 0;
for (fieldIdx = 0; fieldIdx < numFields; ++fieldIdx)
{
// Get field
retval = list_getItem(fields, fieldIdx, &field); PM_RETURN_IF_ERROR(retval);
attrs = (pPmObj_t)((pPmInstance_t)field)->cli_attrs;
// Get type
tmpStr = (uint8_t const *)"ftype";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
type = ((pPmInt_t) field)->val;
// Get number of elements
tmpStr = (uint8_t const *)"numElements";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
numElements = ((pPmInt_t) field)->val;
// Get value
tmpStr = (uint8_t const *)"value";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
// Set value for each element
for (valueIdx = 0; valueIdx < numElements; ++valueIdx)
{
// Update value based on type
switch (type)
{
case TYPE_INT8:
case TYPE_UINT8:
case TYPE_ENUM:
retval = int_new(data[dataIdx], &value); PM_RETURN_IF_ERROR(retval);
dataIdx = dataIdx + 1;
break;
case TYPE_INT16:
case TYPE_UINT16:
tmpInt16 = (int16_t*)(&data[dataIdx]);
retval = int_new(*tmpInt16, &value); PM_RETURN_IF_ERROR(retval);
dataIdx = dataIdx + 2;
break;
case TYPE_INT32:
case TYPE_UINT32:
tmpInt32 = (int32_t*)(&data[dataIdx]);
retval = int_new(*tmpInt32, &value); PM_RETURN_IF_ERROR(retval);
dataIdx = dataIdx + 4;
break;
case TYPE_FLOAT32:
tmpFloat = (float*)(&data[dataIdx]);
retval = float_new(*tmpFloat, &value); PM_RETURN_IF_ERROR(retval);
dataIdx = dataIdx + 4;
break;
}
// Set value
if ( OBJ_GET_TYPE(field) == OBJ_TYPE_LST )
{
retval = list_setItem(field, valueIdx, value); PM_RETURN_IF_ERROR(retval);
}
else
{
tmpStr = (uint8_t const *)"value";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_setItem(attrs, fieldName, value); PM_RETURN_IF_ERROR(retval);
}
}
}
// Done
return PM_RET_OK;
"""
pass
def write(self):
"""__NATIVE__
uint8_t numBytes;
UAVObjHandle objHandle;
uint32_t objId;
uint16_t instId;
pPmObj_t self;
pPmObj_t attrs;
pPmObj_t field;
pPmObj_t fields;
pPmObj_t fieldName;
pPmObj_t value;
PmReturn_t retval;
uint32_t numFields;
uint32_t fieldIdx;
uint32_t dataIdx;
uint32_t valueIdx;
uint32_t type;
uint32_t numElements;
uint8_t const *tmpStr;
int8_t tmpInt8;
int16_t tmpInt16;
int32_t tmpInt32;
float tmpFloat;
// Get dictionary of class attributes
self = NATIVE_GET_LOCAL(0);
attrs = (pPmObj_t)((pPmInstance_t)self)->cli_attrs;
// Get object ID
tmpStr = (uint8_t const *)"objId";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
objId = ((pPmInt_t) field)->val;
// Get the instance ID
tmpStr = (uint8_t const *)"instId";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
instId = ((pPmInt_t) field)->val;
// Get handle and number of bytes in the object
objHandle = UAVObjGetByID(objId);
numBytes = UAVObjGetNumBytes(objHandle);
uint8_t data[numBytes];
// Get dictionary of fields
tmpStr = (uint8_t const *)"fields";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &fields); PM_RETURN_IF_ERROR(retval);
numFields = ((pPmList_t) fields)->length;
// Process each field
dataIdx = 0;
for (fieldIdx = 0; fieldIdx < numFields; ++fieldIdx)
{
// Get field
retval = list_getItem(fields, fieldIdx, &field); PM_RETURN_IF_ERROR(retval);
attrs = (pPmObj_t)((pPmInstance_t)field)->cli_attrs;
// Get type
tmpStr = (uint8_t const *)"ftype";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
type = ((pPmInt_t) field)->val;
// Get number of elements
tmpStr = (uint8_t const *)"numElements";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
numElements = ((pPmInt_t) field)->val;
// Get value
tmpStr = (uint8_t const *)"value";
retval = string_new(&tmpStr, &fieldName); PM_RETURN_IF_ERROR(retval);
retval = dict_getItem(attrs, fieldName, &field); PM_RETURN_IF_ERROR(retval);
// Set value for each element
for (valueIdx = 0; valueIdx < numElements; ++valueIdx)
{
// Get value
if ( OBJ_GET_TYPE(field) == OBJ_TYPE_LST )
{
retval = list_getItem(field, valueIdx, &value); PM_RETURN_IF_ERROR(retval);
}
else
value = field;
// Update value based on type
switch (type)
{
case TYPE_INT8:
case TYPE_UINT8:
case TYPE_ENUM:
if ( OBJ_GET_TYPE(value) == OBJ_TYPE_INT )
{
tmpInt8 = (int8_t)((pPmInt_t)value)->val;
}
else if ( OBJ_GET_TYPE(value) == OBJ_TYPE_FLT )
{
tmpInt8 = (int8_t)((pPmFloat_t)value)->val;
}
memcpy( &data[dataIdx], &tmpInt8, 1 );
dataIdx = dataIdx + 1;
break;
case TYPE_INT16:
case TYPE_UINT16:
if ( OBJ_GET_TYPE(value) == OBJ_TYPE_INT )
{
tmpInt16 = (int16_t)((pPmInt_t)value)->val;
}
else if ( OBJ_GET_TYPE(value) == OBJ_TYPE_FLT )
{
tmpInt16 = (int16_t)((pPmFloat_t)value)->val;
}
memcpy( &data[dataIdx], &tmpInt16, 2 );
dataIdx = dataIdx + 2;
break;
case TYPE_INT32:
case TYPE_UINT32:
if ( OBJ_GET_TYPE(value) == OBJ_TYPE_INT )
{
tmpInt32 = (int32_t)((pPmInt_t)value)->val;
}
else if ( OBJ_GET_TYPE(value) == OBJ_TYPE_FLT )
{
tmpInt32 = (int32_t)((pPmFloat_t)value)->val;
}
memcpy( &data[dataIdx], &tmpInt32, 4 );
dataIdx = dataIdx + 4;
break;
case TYPE_FLOAT32:
if ( OBJ_GET_TYPE(value) == OBJ_TYPE_INT )
{
tmpFloat = (float)((pPmInt_t)value)->val;
}
else if ( OBJ_GET_TYPE(value) == OBJ_TYPE_FLT )
{
tmpFloat = (float)((pPmFloat_t)value)->val;
}
memcpy( &data[dataIdx], &tmpFloat, 4 );
dataIdx = dataIdx + 4;
break;
}
}
}
// Write object data
UAVObjSetInstanceData(objHandle, instId, data);
// Done
return PM_RET_OK;
"""
pass

View File

@ -0,0 +1,60 @@
##
##############################################################################
#
# @file $(NAMELC).py
# @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
# @brief Implementation of the $(NAME) object. This file has been
# automatically generated by the UAVObjectGenerator. For use with
# the PyMite VM of the FlightPlan module.
#
# @note Object definition file: $(XMLFILE).
# This is an automatically generated file.
# DO NOT modify manually.
#
# @see The GNU Public License (GPL) Version 3
#
#############################################################################/
#
# 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
#
from uavobject import *
$(DATAFIELDS)
# Object $(NAME) definition
class $(NAME)(UAVObject):
# Object constants
OBJID = $(UOBJID)
# Constructor
def __init__(self):
UAVObject.__init__(self, $(NAME).OBJID)
# Create object fields
$(DATAFIELDINIT)
# Read field data
self.read()
self.metadata.read()

View File

@ -115,6 +115,7 @@ FLIGHTPLANLIB = $(OPMODULEDIR)/FlightPlan/lib
FLIGHTPLANS = $(OPMODULEDIR)/FlightPlan/flightplans
UAVOBJSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/flight
UAVOBJPYTHONSYNTHDIR = $(OUTDIR)/../uavobject-synthetics/python
# List C source files here. (C dependencies are automatically generated.)
# use file-extension c for "c-only"-files
@ -443,9 +444,9 @@ ${OUTDIR}/InitMods.c: Makefile.posix
@echo ${quote}}${quote} >> ${OUTDIR}/InitMods.c
# Generate code for PyMite
${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h: $(wildcard ${PYMITELIB}/*.py) $(wildcard ${PYMITEPLAT}/*.py) $(wildcard ${FLIGHTPLANLIB}/*.py) $(wildcard ${FLIGHTPLANS}/*.py)
${OUTDIR}/pmlib_img.c ${OUTDIR}/pmlib_nat.c ${OUTDIR}/pmlibusr_img.c ${OUTDIR}/pmlibusr_nat.c ${OUTDIR}/pmfeatures.h: $(wildcard ${PYMITELIB}/*.py) $(wildcard ${PYMITEPLAT}/*.py) $(wildcard ${FLIGHTPLANLIB}/*.py) $(wildcard ${FLIGHTPLANS}/*.py) $(wildcard $(UAVOBJPYTHONSYNTHDIR)/*.py)
@echo ${MSG_PYMITEINIT}
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -s --memspace=flash -o $(OUTDIR)/pmlib_img.c --native-file=$(OUTDIR)/pmlib_nat.c $(PYMITELIB)/list.py $(PYMITELIB)/dict.py $(PYMITELIB)/__bi.py $(PYMITELIB)/sys.py $(PYMITELIB)/string.py $(wildcard $(FLIGHTPLANLIB)/*.py)
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -s --memspace=flash -o $(OUTDIR)/pmlib_img.c --native-file=$(OUTDIR)/pmlib_nat.c $(PYMITELIB)/list.py $(PYMITELIB)/dict.py $(PYMITELIB)/__bi.py $(PYMITELIB)/sys.py $(PYMITELIB)/string.py $(wildcard $(FLIGHTPLANLIB)/*.py) $(wildcard $(UAVOBJPYTHONSYNTHDIR)/*.py)
@$(PYTHON) $(PYMITETOOLS)/pmGenPmFeatures.py $(PYMITEPLAT)/pmfeatures.py > $(OUTDIR)/pmfeatures.h
@$(PYTHON) $(PYMITETOOLS)/pmImgCreator.py -f $(PYMITEPLAT)/pmfeatures.py -c -u -o $(OUTDIR)/pmlibusr_img.c --native-file=$(OUTDIR)/pmlibusr_nat.c $(FLIGHTPLANS)/test.py

View File

@ -59,6 +59,8 @@ void replaceCommonTags(QString& out, ObjectInfo* info)
out.replace(QString("$(NAMEUC)"), info->name.toUpper());
// Replace $(OBJID) tag
out.replace(QString("$(OBJID)"), QString().setNum(info->id));
// Replace $(UOBJID) tag
out.replace(QString("$(UOBJID)"), QString().setNum((qint32)info->id));
// Replace $(OBJIDHEX) tag
out.replace(QString("$(OBJIDHEX)"),QString("0x")+ QString().setNum(info->id,16).toUpper());
// Replace $(ISSINGLEINST) tag

View File

@ -28,29 +28,20 @@
using namespace std;
bool UAVObjectGeneratorPython::generate(UAVObjectParser* parser,QString templatepath,QString outputpath) {
fieldTypeStrPython << "b" << "h" << "i" << "B" << "H" << "I" << "f" << "b";
pythonCodePath = QDir( templatepath + QString("ground/openpilotgcs/src/plugins/uavobjects"));
// Load template and setup output directory
pythonCodePath = QDir( templatepath + QString("flight/Modules/FlightPlan/lib"));
pythonOutputPath = QDir( outputpath + QString("python") );
pythonOutputPath.mkpath(pythonOutputPath.absolutePath());
pythonCodeTemplate = readFile( pythonCodePath.absoluteFilePath("uavobjecttemplate.py") );
QString pythonImport,pythonObjInit;
pythonCodeTemplate = readFile( pythonCodePath.absoluteFilePath("uavobjecttemplate.pyt") );
if (pythonCodeTemplate.isEmpty()) {
std::cerr << "Problem reading python templates" << endl;
return false;
}
// Process each object
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo* info=parser->getObjectByIndex(objidx);
process_object(info);
// check if they are needed - are never written atm ..
pythonImport.append("import " + info->namelc + "\n");
pythonObjInit.append("\tuavobjectsinit.uavobjects.append(" + info->name + "." + info->name + "())\n");
}
return true; // if we come here everything should be fine
@ -70,42 +61,54 @@ bool UAVObjectGeneratorPython::process_object(ObjectInfo* info)
// Replace common tags
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString fields;
fields.append(QString("[ \\\n"));
// Replace the ($DATAFIELDS) tag
QString datafields;
for (int n = 0; n < info->fields.length(); ++n)
{
fields.append(QString("\tuavobject.UAVObjectField(\n"));
fields.append(QString("\t\t'%1',\n").arg(info->fields[n]->name));
fields.append(QString("\t\t'%1',\n").arg(fieldTypeStrPython[info->fields[n]->type]));
fields.append(QString("\t\t%1,\n").arg(info->fields[n]->numElements));
QStringList elemNames = info->fields[n]->elementNames;
fields.append(QString("\t\t[\n"));
for (int m = 0; m < elemNames.length(); ++m)
{
fields.append(QString("\t\t\t'%1',\n").arg(elemNames[m]));
}
fields.append(QString("\t\t],\n"));
fields.append(QString("\t\t{\n"));
// Class header
datafields.append(QString("# Field %1 definition\n").arg(info->fields[n]->name));
datafields.append(QString("class %1Field(UAVObjectField):\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
datafields.append(QString("\t# Enumeration options\n"));
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m){
fields.append( QString("\t\t\t'%1' : '%2',\n")
.arg(m)
.arg( options[m] ) );
for (int m = 0; m < options.length(); ++m) {
QString name = options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "");
if (name[0].isDigit())
name = QString("N%1").arg(name);
datafields.append(QString("\t%1 = %2\n").arg(name).arg(m));
}
}
fields.append(QString("\t\t}\n"));
fields.append(QString("\t),\n"));
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames)
{
datafields.append(QString("\t# Array element names\n"));
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
{
QString name = elemNames[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), "");
if (name[0].isDigit())
name = QString("N%1").arg(name);
datafields.append(QString("\t%1 = %2\n").arg(name).arg(m));
}
fields.append(QString("]\n"));
outCode.replace(QString("$(DATAFIELDS)"), fields);
}
// Constructor
datafields.append(QString("\tdef __init__(self):\n"));
datafields.append(QString("\t\tUAVObjectField.__init__(self, %1, %2)\n\n").arg(info->fields[n]->type).arg(info->fields[n]->numElements));
}
outCode.replace(QString("$(DATAFIELDS)"), datafields);
// Replace the $(DATAFIELDINIT) tag
QString fields;
for (int n = 0; n < info->fields.length(); ++n)
{
fields.append(QString("\t\tself.%1 = %1Field()\n").arg(info->fields[n]->name));
fields.append(QString("\t\tself.addField(self.%1)\n").arg(info->fields[n]->name));
}
outCode.replace(QString("$(DATAFIELDINIT)"), fields);
// Write the Python code
bool res = writeFileIfDiffrent( pythonOutputPath.absolutePath() + "/" + info->namelc + ".py", outCode );

View File

@ -40,7 +40,6 @@ private:
QString pythonCodeTemplate;
QDir pythonCodePath;
QDir pythonOutputPath;
QStringList fieldTypeStrPython;
};
#endif

View File

@ -5,8 +5,7 @@
<field name="ErrorType" units="" type="enum" elements="1" options="None,VMInitError,Exception,IOError,DivByZero,AssertError,AttributeError,ImportError,IndexError,KeyError,MemoryError,NameError,SyntaxError,SystemError,TypeError,ValueError,StopIteration,Warning,UnknownError" defaultvalue="None"/>
<field name="ErrorFileID" units="" type="uint32" elements="1"/>
<field name="ErrorLineNum" units="" type="uint32" elements="1"/>
<field name="Debug1" units="" type="float" elements="1" defaultvalue="0.0"/>
<field name="Debug2" units="" type="float" elements="1" defaultvalue="0.0"/>
<field name="Debug" units="" type="float" elements="2" defaultvalue="0.0"/>
<access gcs="readwrite" flight="readwrite"/>
<telemetrygcs acked="false" updatemode="manual" period="0"/>
<telemetryflight acked="false" updatemode="periodic" period="2000"/>