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

splitting uavobject generation by language and cleanup:

- all languages to generate where processed everytime. In most runs only flight and/or gcs was needed but also matlab and python code was generated - now uavobjectgenerator has command line arguments to specify which languages to build and there are also new targets in the makefile.
 - generation code for all languages was in the parser section - was bit of a mess in general - now all splitted
 - its now more easy for new devs to add a new language or find relevant code for the language he is interested in

initial java generation:
 - uavobjectgenerator can now generate java code for uavobjects

git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@2392 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
ligi 2011-01-13 02:26:00 +00:00 committed by ligi
parent cb2aa1d389
commit dbc5d26605
24 changed files with 2205 additions and 1352 deletions

View File

@ -53,7 +53,9 @@ areyousureyoushouldberunningthis:
@echo
@echo " [GCS and UAVObjects]"
@echo " gcs - Build the Ground Control System application"
@echo " uavobjects - Generate the gcs and openpilot source files from the UAVObject definition XML files"
@echo " uavobjects - Generate source files from the UAVObject definition XML files"
@echo " uavobjects_gcs - Generate groundstation source files from the UAVObject definition XML files"
@echo " uavobjects_flight - Generate flight source files from the UAVObject definition XML files"
@echo
@echo " Note: All tools will be installed into $(TOOLS_DIR)"
@echo " All build output will be placed in $(BUILD_DIR)"
@ -191,7 +193,7 @@ all_ground: uavobjgenerator openpilotgcs
gcs: openpilotgcs
.PHONY: openpilotgcs
openpilotgcs: uavobjects
openpilotgcs: uavobjects_gcs
mkdir -p $(BUILD_DIR)/$@
( cd $(BUILD_DIR)/$@ ; \
$(QMAKE) $(ROOT_DIR)/ground/openpilotgcs.pro -spec $(QT_SPEC) -r CONFIG+=debug ; \
@ -206,11 +208,20 @@ uavobjgenerator:
$(MAKE) -w ; \
)
.PHONY: uavobjects
uavobjects: uavobjgenerator
.PHONY: build_dir
bzild_dir:
mkdir -p $(BUILD_DIR)/$@
.PHONY:uavobjects
uavobjects: build_dir uavobjgenerator
$(UAVOBJGENERATOR) "$(ROOT_DIR)/"
uavobjects_gcs: build_dir uavobjgenerator
$(UAVOBJGENERATOR) -gcs "$(ROOT_DIR)/"
uavobjects_flight: build_dir uavobjgenerator
$(UAVOBJGENERATOR) -flight "$(ROOT_DIR)/"
##############################
#
# Flight related components
@ -223,7 +234,7 @@ all_flight: openpilot_elf ahrs_elf
.PHONY: openpilot
openpilot: openpilot_elf
openpilot_%: uavobjects
openpilot_%: uavobjects_flight
mkdir -p $(BUILD_DIR)/openpilot
$(MAKE) OUTDIR="$(BUILD_DIR)/openpilot" TCHAIN_PREFIX="$(ARM_SDK_PREFIX)" REMOVE_CMD="$(RM)" OOCD_EXE="$(OPENOCD)" -C $(ROOT_DIR)/flight/OpenPilot $*
@ -237,13 +248,13 @@ ahrs_%:
.PHONY: sim_posix
sim_posix: sim_posix_elf
sim_posix_%: uavobjects
sim_posix_%: uavobjects_flight
mkdir -p $(BUILD_DIR)/simulation
$(MAKE) OUTDIR="$(BUILD_DIR)/simulation" -C $(ROOT_DIR)/flight/OpenPilot --file=$(ROOT_DIR)/flight/OpenPilot/Makefile.posix $*
.PHONY: sim_win32
sim_win32: sim_win32_exe
sim_win32_%: uavobjects
sim_win32_%: uavobjects_flight
mkdir -p $(BUILD_DIR)/simulation
$(MAKE) OUTDIR="$(BUILD_DIR)/simulation" -C $(ROOT_DIR)/flight/OpenPilot --file=$(ROOT_DIR)/flight/OpenPilot/Makefile.win32 $*

View File

@ -0,0 +1,2 @@
compile with ant
depends on juavtalk and the generated java code from uavobjgenerator in the build dir

View File

@ -0,0 +1,42 @@
<project default="package">
<property name="version.num" value="0.1.1" />
<property name="build.dir" value="../../../../build/"/>
<property name="jar.file" value="${build.dir}/juavobjects/juavobjects.jar"/>
<property name="src.dir" value="${build.dir}/juavobjects/src"/>
<property name="classes.dir" value="${build.dir}/juavobjects/classes"/>
<target name="compile" depends="clean">
<mkdir dir="${build.dir}" />
<mkdir dir="${classes.dir}" />
<javac srcdir="${src.dir}" destdir="${classes.dir}" classpath="${build.dir}/juavtalk/juavtalk.jar" />
</target>
<target name="jar" depends="compile">
<manifest file="MANIFEST.MF">
<attribute name="Built-By" value="${user.name}" />
<attribute name="Implementation-Version"
value="${version.num}"/>
</manifest>
<jar destfile="${jar.file}"
basedir="${classes.dir}"
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>
<target name="clean">
<delete dir="build" />
<delete>
<fileset dir="." includes="${jar.file}"/>
<fileset file="MANIFEST.MF"/>
</delete>
</target>
<target name="package" depends="compile,jar" />
</project>

View File

@ -0,0 +1,75 @@
/**
******************************************************************************
*
*
* @file uavobjectsinittemplate.java
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief the template for the uavobjects init part
* $(GENERATEDWARNING)
*
* @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
*/
package org.openpilot.uavtalk;
import org.openpilot.uavtalk.uavobjects.*;
import org.openpilot.uavtalk.UAVObject;
import java.util.HashMap;
public class UAVObjects {
private static UAVObject[] uavobjects=null;
private static HashMap id2obj;
public static void init() {
if (uavobjects==null) {
uavobjects=new UAVObject[] {
$(OBJINIT)
};
id2obj=new HashMap();
for (int i=0;i< uavobjects.length;i++)
id2obj.put(uavobjects[i].getObjID(),i);
}
}
public static UAVObject[] getUAVObjectArray() {
return uavobjects;
}
public static boolean hasObjectWithID(int id) {
return id2obj.containsKey(id);
}
public static UAVObject getObjectByID(int id) {
if (!hasObjectWithID(id))
return null;
return uavobjects[(Integer)id2obj.get(id)];
}
public static UAVObject getObjectByName(String name) {
return uavobjects[0];
}
public static void printAll() {
for (UAVObject obj : uavobjects)
System.out.println(obj.getObjName());
}
$(OBJGETTER)
}

View File

@ -0,0 +1,73 @@
/**
******************************************************************************
*
* @file uavobjecttemplate.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief Template for an uavobject in java
* $(GENERATEDWARNING)
* $(DESCRIPTION)
*
* @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
*/
package org.openpilot.uavtalk.uavobjects;
import org.openpilot.uavtalk.UAVObject;
import org.openpilot.uavtalk.UAVObjectMetaData;
import org.openpilot.uavtalk.UAVObjectFieldDescription;
/**
$(DESCRIPTION)
generated from $(XMLFILE)
**/
public class $(NAME) extends UAVObject{
$(FIELDSINIT)
public void setGeneratedMetaData() {
getMetaData().gcsAccess = UAVObjectMetaData.$(GCSACCESS);
getMetaData().gcsTelemetryAcked = UAVObjectMetaData.$(GCSTELEM_ACKEDTF);
getMetaData().gcsTelemetryUpdateMode = UAVObjectMetaData.$(GCSTELEM_UPDATEMODE);
getMetaData().gcsTelemetryUpdatePeriod = $(GCSTELEM_UPDATEPERIOD);
getMetaData().flightAccess = UAVObjectMetaData.$(FLIGHTACCESS);
getMetaData().flightTelemetryAcked = UAVObjectMetaData.$(FLIGHTTELEM_ACKEDTF);
getMetaData().flightTelemetryUpdateMode = UAVObjectMetaData.$(FLIGHTTELEM_UPDATEMODE);
getMetaData().flightTelemetryUpdatePeriod = $(FLIGHTTELEM_UPDATEPERIOD);
getMetaData().loggingUpdateMode = UAVObjectMetaData.$(LOGGING_UPDATEMODE);
getMetaData().loggingUpdatePeriod = $(LOGGING_UPDATEPERIOD);
}
public int getObjID() {
return $(OBJIDHEX);
}
public String getObjName() {
return "$(NAME)";
}
public String getObjDescription() {
return "$(DESCRIPTION)";
}
$(GETTERSETTER)
}

View File

@ -0,0 +1,239 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorflight.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce flight code for uavobjects
*
* @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
*/
#include "uavobjectgeneratorflight.h"
using namespace std;
bool UAVObjectGeneratorFlight::generate(UAVObjectParser* parser,QString basepath) {
fieldTypeStrC << "int8_t" << "int16_t" << "int32_t" <<"uint8_t"
<<"uint16_t" << "uint32_t" << "float" << "uint8_t";
QString flightObjInit,objInc;
flightCodePath = QDir( basepath + QString("flight/OpenPilot/UAVObjects"));
flightCodeTemplate = readFile( flightCodePath.absoluteFilePath("uavobjecttemplate.c") );
flightIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/uavobjecttemplate.h") );
flightInitTemplate = readFile( flightCodePath.absoluteFilePath("uavobjectsinittemplate.c") );
if ( flightCodeTemplate.isNull() || flightIncludeTemplate.isNull() || flightInitTemplate.isNull()) {
cerr << "Error: Could not open flight template files." << endl;
return false;
}
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo* info=parser->getObjectByIndex(objidx);
process_object(info);
flightObjInit.append(" " + info->name + "Initialize();\n");
objInc.append("#include \"" + info->namelc + ".h\"\n");
}
// Write the flight object inialization files
flightInitTemplate.replace( QString("$(OBJINC)"), objInc);
flightInitTemplate.replace( QString("$(OBJINIT)"), flightObjInit);
bool res = writeFileIfDiffrent( flightCodePath.absolutePath() + "/uavobjectsinit.c",
flightInitTemplate );
if (!res) {
cout << "Error: Could not write flight object init files" << endl;
return false;
}
return true; // if we come here everything should be fine
}
/**
* Generate the Flight object files
**/
bool UAVObjectGeneratorFlight::process_object(ObjectInfo* info)
{
if (info == NULL)
return false;
// Prepare output strings
QString outInclude = flightIncludeTemplate;
QString outCode = flightCodeTemplate;
// Replace common tags
replaceCommonTags(outInclude, info);
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString type;
QString fields;
for (int n = 0; n < info->fields.length(); ++n)
{
// Determine type
type = fieldTypeStrC[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
{
fields.append( QString(" %1 %2[%3];\n").arg(type)
.arg(info->fields[n]->name).arg(info->fields[n]->numElements) );
}
else
{
fields.append( QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name) );
}
}
outInclude.replace(QString("$(DATAFIELDS)"), fields);
// Replace the $(DATAFIELDINFO) tag
QString enums;
for (int n = 0; n < info->fields.length(); ++n)
{
enums.append(QString("// Field %1 information\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
enums.append(QString("/* Enumeration options for field %1 */\n").arg(info->fields[n]->name));
enums.append("typedef enum { ");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString s = (m == (options.length()-1)) ? "%1_%2_%3=%4" : "%1_%2_%3=%4, ";
enums.append( s
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( options[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1%2Options;\n")
.arg( info->name )
.arg( info->fields[n]->name ) );
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames)
{
enums.append(QString("/* Array element names for field %1 */\n").arg(info->fields[n]->name));
enums.append("typedef enum { ");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
{
QString s = (m != (elemNames.length()-1)) ? "%1_%2_%3=%4, " : "%1_%2_%3=%4";
enums.append( s
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( elemNames[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1%2Elem;\n")
.arg( info->name )
.arg( info->fields[n]->name ) );
}
// Generate array information
if (info->fields[n]->numElements > 1)
{
enums.append(QString("/* Number of elements for field %1 */\n").arg(info->fields[n]->name));
enums.append( QString("#define %1_%2_NUMELEM %3\n")
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( info->fields[n]->numElements ) );
}
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
// Replace the $(INITFIELDS) tag
QString initfields;
for (int n = 0; n < info->fields.length(); ++n)
{
if (!info->fields[n]->defaultValues.isEmpty() )
{
// For non-array fields
if ( info->fields[n]->numElements == 1)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString("\tdata.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString("\tdata.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toFloat() ) );
}
else
{
initfields.append( QString("\tdata.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toInt() ) );
}
}
else
{
// Initialize all fields in the array
for (int idx = 0; idx < info->fields[n]->numElements; ++idx)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString("\tdata.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString("\tdata.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toFloat() ) );
}
else
{
initfields.append( QString("\tdata.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toInt() ) );
}
}
}
}
}
outCode.replace(QString("$(INITFIELDS)"), initfields);
// Write the flight code
bool res = writeFileIfDiffrent( flightCodePath.absolutePath() + "/" + info->namelc + ".c", outCode );
if (!res) {
cout << "Error: Could not write flight code files" << endl;
return false;
}
res = writeFileIfDiffrent( flightCodePath.absolutePath() + "/inc/" + info->namelc + ".h", outInclude );
if (!res) {
cout << "Error: Could not write flight include files" << endl;
return false;
}
return true;
}

View File

@ -0,0 +1,46 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorflight.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce flight code for uavobjects
*
* @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
*/
#ifndef UAVOBJECTGENERATORFLIGHT_H
#define UAVOBJECTGENERATORFLIGHT_H
#include "../generator_common.h"
class UAVObjectGeneratorFlight
{
public:
bool generate(UAVObjectParser* gen,QString basepath);
QStringList fieldTypeStrC;
QString flightCodeTemplate, flightIncludeTemplate, flightInitTemplate;
QDir flightCodePath;
private:
bool process_object(ObjectInfo* info);
};
#endif

View File

@ -0,0 +1,269 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorgcs.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce gcs code for uavobjects
*
* @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
*/
#include "uavobjectgeneratorgcs.h"
using namespace std;
bool UAVObjectGeneratorGCS::generate(UAVObjectParser* parser,QString basepath) {
fieldTypeStrCPP << "qint8" << "qint16" << "qint32" <<
"quint8" << "quint16" << "quint32" << "float" << "quint8";
fieldTypeStrCPPClass << "INT8" << "INT16" << "INT32"
<< "UINT8" << "UINT16" << "UINT32" << "FLOAT32" << "ENUM";
gcsCodePath = QDir( basepath + QString(GCS_CODE_DIR));
gcsCodeTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjecttemplate.cpp") );
gcsIncludeTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjecttemplate.h") );
QString gcsInitTemplate = readFile( gcsCodePath.absoluteFilePath("uavobjectsinittemplate.cpp") );
if (gcsCodeTemplate.isEmpty() || gcsIncludeTemplate.isEmpty() || gcsInitTemplate.isEmpty()) {
std::cerr << "Problem reading gcs code templates" << endl;
return false;
}
QString objInc;
QString gcsObjInit;
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo* info=parser->getObjectByIndex(objidx);
process_object(info);
gcsObjInit.append(" objMngr->registerObject( new " + info->name + "() );\n");
objInc.append("#include \"" + info->namelc + ".h\"\n");
}
// Write the gcs object inialization files
gcsInitTemplate.replace( QString("$(OBJINC)"), objInc);
gcsInitTemplate.replace( QString("$(OBJINIT)"), gcsObjInit);
bool res = writeFileIfDiffrent( gcsCodePath.absolutePath() + "/uavobjectsinit.cpp", gcsInitTemplate );
if (!res) {
cout << "Error: Could not write output files" << endl;
return false;
}
return true; // if we come here everything should be fine
}
/**
* Generate the GCS object files
*/
bool UAVObjectGeneratorGCS::process_object(ObjectInfo* info)
{
if (info == NULL)
return false;
// Prepare output strings
QString outInclude = gcsIncludeTemplate;
QString outCode = gcsCodeTemplate;
// Replace common tags
replaceCommonTags(outInclude, info);
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString type;
QString fields;
for (int n = 0; n < info->fields.length(); ++n)
{
// Determine type
type = fieldTypeStrCPP[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
{
fields.append( QString(" %1 %2[%3];\n").arg(type).arg(info->fields[n]->name)
.arg(info->fields[n]->numElements) );
}
else
{
fields.append( QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name) );
}
}
outInclude.replace(QString("$(DATAFIELDS)"), fields);
// Replace the $(FIELDSINIT) tag
QString finit;
for (int n = 0; n < info->fields.length(); ++n)
{
// Setup element names
QString varElemName = info->fields[n]->name + "ElemNames";
finit.append( QString(" QStringList %1;\n").arg(varElemName) );
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
finit.append( QString(" %1.append(\"%2\");\n")
.arg(varElemName)
.arg(elemNames[m]) );
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM) {
QString varOptionName = info->fields[n]->name + "EnumOptions";
finit.append( QString(" QStringList %1;\n").arg(varOptionName) );
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m)
{
finit.append( QString(" %1.append(\"%2\");\n")
.arg(varOptionName)
.arg(options[m]) );
}
finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::ENUM, %3, %4) );\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->units)
.arg(varElemName)
.arg(varOptionName) );
}
// For all other types
else {
finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::%3, %4, QStringList()) );\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->units)
.arg(fieldTypeStrCPPClass[info->fields[n]->type])
.arg(varElemName) );
}
}
outCode.replace(QString("$(FIELDSINIT)"), finit);
// Replace the $(DATAFIELDINFO) tag
QString name;
QString enums;
for (int n = 0; n < info->fields.length(); ++n)
{
enums.append(QString(" // Field %1 information\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
enums.append(QString(" /* Enumeration options for field %1 */\n").arg(info->fields[n]->name));
enums.append(" typedef enum { ");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString s = (m != (options.length()-1)) ? "%1_%2=%3, " : "%1_%2=%3";
enums.append( s.arg( info->fields[n]->name.toUpper() )
.arg( options[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1Options;\n")
.arg( info->fields[n]->name ) );
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) {
enums.append(QString(" /* Array element names for field %1 */\n").arg(info->fields[n]->name));
enums.append(" typedef enum { ");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m) {
QString s = (m != (elemNames.length()-1)) ? "%1_%2=%3, " : "%1_%2=%3";
enums.append( s.arg( info->fields[n]->name.toUpper() )
.arg( elemNames[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1Elem;\n")
.arg( info->fields[n]->name ) );
}
// Generate array information
if (info->fields[n]->numElements > 1) {
enums.append(QString(" /* Number of elements for field %1 */\n").arg(info->fields[n]->name));
enums.append( QString(" static const quint32 %1_NUMELEM = %2;\n")
.arg( info->fields[n]->name.toUpper() )
.arg( info->fields[n]->numElements ) );
}
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
// Replace the $(INITFIELDS) tag
QString initfields;
for (int n = 0; n < info->fields.length(); ++n)
{
if (!info->fields[n]->defaultValues.isEmpty() )
{
// For non-array fields
if ( info->fields[n]->numElements == 1)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toFloat() ) );
}
else
{
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toInt() ) );
}
}
else
{
// Initialize all fields in the array
for (int idx = 0; idx < info->fields[n]->numElements; ++idx)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM ) {
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 ) {
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toFloat() ) );
}
else {
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toInt() ) );
}
}
}
}
}
outCode.replace(QString("$(INITFIELDS)"), initfields);
// Write the GCS code
bool res = writeFileIfDiffrent( gcsCodePath.absolutePath() + "/" + info->namelc + ".cpp", outCode );
if (!res) {
cout << "Error: Could not write gcs output files" << endl;
return false;
}
res = writeFileIfDiffrent( gcsCodePath.absolutePath() + "/" + info->namelc + ".h", outInclude );
if (!res) {
cout << "Error: Could not write gcs output files" << endl;
return false;
}
return true;
}

View File

@ -0,0 +1,47 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorgcs.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce gcs code for uavobjects
*
* @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
*/
#ifndef UAVOBJECTGENERATORGCS_H
#define UAVOBJECTGENERATORGCS_H
#define GCS_CODE_DIR "ground/src/plugins/uavobjects"
#include "../generator_common.h"
class UAVObjectGeneratorGCS
{
public:
bool generate(UAVObjectParser* gen,QString basepath);
private:
bool process_object(ObjectInfo* info);
QString gcsCodeTemplate,gcsIncludeTemplate;
QStringList fieldTypeStrCPP,fieldTypeStrCPPClass;
QDir gcsCodePath;
};
#endif

View File

@ -0,0 +1,122 @@
/**
******************************************************************************
*
* @file generator_common.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief common functions for generating uavobjects code
*
* @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
*/
#include "generator_common.h"
void replaceCommonTags(QString& out)
{
// Replace $(GENERATEDWARNING) tag
out.replace(QString("$(GENERATEDWARNING)"), "This is a autogenerated file!! Do not modify and expect a result.");
}
/**
* Replace all the common tags from the template file with actual object information.
*/
void replaceCommonTags(QString& out, ObjectInfo* info)
{
QStringList updateModeStr,accessModeStr;
updateModeStr << "UPDATEMODE_PERIODIC" << "UPDATEMODE_ONCHANGE"
<< "UPDATEMODE_MANUAL" << "UPDATEMODE_NEVER";
accessModeStr << "ACCESS_READWRITE" << "ACCESS_READONLY";
QString value;
// replace the tags which don't need info
replaceCommonTags(out);
// Replace $(XMLFILE) tag
out.replace(QString("$(XMLFILE)"), info->filename);
// Replace $(NAME) tag
out.replace(QString("$(NAME)"), info->name);
// Replace $(NAMELC) tag
out.replace(QString("$(NAMELC)"), info->namelc);
// Replace $(DESCRIPTION) tag
out.replace(QString("$(DESCRIPTION)"), info->description);
// Replace $(NAMEUC) tag
out.replace(QString("$(NAMEUC)"), info->name.toUpper());
// Replace $(OBJID) tag
out.replace(QString("$(OBJID)"), QString().setNum(info->id));
// Replace $(OBJIDHEX) tag
out.replace(QString("$(OBJIDHEX)"),QString("0x")+ QString().setNum(info->id,16).toUpper());
// Replace $(ISSINGLEINST) tag
out.replace(QString("$(ISSINGLEINST)"), boolTo01String( info->isSingleInst ));
out.replace(QString("$(ISSINGLEINSTTF)"), boolToTRUEFALSEString( info->isSingleInst ));
// Replace $(ISSETTINGS) tag
out.replace(QString("$(ISSETTINGS)"), boolTo01String( info->isSettings ));
out.replace(QString("$(ISSETTINGSTF)"), boolToTRUEFALSEString( info->isSettings ));
// Replace $(GCSACCESS) tag
value = accessModeStr[info->gcsAccess];
out.replace(QString("$(GCSACCESS)"), value);
// Replace $(FLIGHTACCESS) tag
value = accessModeStr[info->flightAccess];
out.replace(QString("$(FLIGHTACCESS)"), value);
// Replace $(FLIGHTTELEM_ACKED) tag
out.replace(QString("$(FLIGHTTELEM_ACKED)"), boolTo01String( info->flightTelemetryAcked ));
out.replace(QString("$(FLIGHTTELEM_ACKEDTF)"), boolToTRUEFALSEString( info->flightTelemetryAcked ));
// Replace $(FLIGHTTELEM_UPDATEMODE) tag
value =updateModeStr[info->flightTelemetryUpdateMode];
out.replace(QString("$(FLIGHTTELEM_UPDATEMODE)"), value);
// Replace $(FLIGHTTELEM_UPDATEPERIOD) tag
out.replace(QString("$(FLIGHTTELEM_UPDATEPERIOD)"), QString().setNum(info->flightTelemetryUpdatePeriod));
// Replace $(GCSTELEM_ACKED) tag
out.replace(QString("$(GCSTELEM_ACKED)"), boolTo01String( info->gcsTelemetryAcked ));
out.replace(QString("$(GCSTELEM_ACKEDTF)"), boolToTRUEFALSEString( info->gcsTelemetryAcked ));
// Replace $(GCSTELEM_UPDATEMODE) tag
value = updateModeStr[info->gcsTelemetryUpdateMode];
out.replace(QString("$(GCSTELEM_UPDATEMODE)"), value);
// Replace $(GCSTELEM_UPDATEPERIOD) tag
out.replace(QString("$(GCSTELEM_UPDATEPERIOD)"), QString().setNum(info->gcsTelemetryUpdatePeriod));
// Replace $(LOGGING_UPDATEMODE) tag
value = updateModeStr[info->loggingUpdateMode];
out.replace(QString("$(LOGGING_UPDATEMODE)"), value);
// Replace $(LOGGING_UPDATEPERIOD) tag
out.replace(QString("$(LOGGING_UPDATEPERIOD)"), QString().setNum(info->loggingUpdatePeriod));
}
/**
* Convert a boolean to string "0" or "1"
*/
QString boolTo01String(bool value)
{
if ( value )
return QString("1");
return QString("0");
}
/**
* Convert a boolean to string "TRUE" or "FALSE"
*/
QString boolToTRUEFALSEString(bool value)
{
if ( value )
return QString("TRUE");
return QString("FALSE");
}

View File

@ -0,0 +1,38 @@
/**
******************************************************************************
*
* @file generator_common.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief common functions for generating uavobjects code
*
* @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
*/
#ifndef UAVOBJECTGENERATORCOMMON_H
#define UAVOBJECTGENERATORCOMMON_H
#include "../uavobjectparser.h"
#include "generator_io.h"
void replaceCommonTags(QString& out, ObjectInfo* info);
void replaceCommonTags(QString& out);
QString boolTo01String(bool value);
QString boolToTRUEFALSEString(bool value);
#endif

View File

@ -0,0 +1,79 @@
/**
******************************************************************************
*
* @file generator_io.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief I/O Code for the generator
*
* @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
*/
#include "generator_io.h"
using namespace std;
/**
* Read a file and return its contents as a string
*/
QString readFile(QString name,bool do_warn)
{
QFile file(name);
if (!file.open(QFile::ReadOnly)) {
if (do_warn)
std::cout << "Warning: Could not open " << name.toStdString() << endl;
return QString();
}
QTextStream fileStr(&file);
QString str = fileStr.readAll();
file.close();
return str;
}
/**
* Read a file and return its contents as a string
*/
QString readFile(QString name)
{
return readFile(name,true);
}
/**
* Write contents of string to file
*/
bool writeFile(QString name, QString& str)
{
QFile file(name);
if (!file.open(QFile::WriteOnly))
return false;
QTextStream fileStr(&file);
fileStr << str;
file.close();
return true;
}
/**
* Write contents of string to file if the content changes
*/
bool writeFileIfDiffrent(QString name, QString& str)
{
if (str==readFile(name,false))
return true;
return writeFile(name,str);
}

View File

@ -1,62 +1,42 @@
/**
******************************************************************************
*
* @file uavobjectgenerator.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief UAVObjectGenerator, generates UAVObjects from XML files.
*
* @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
*/
#ifndef UAVOBJECTGENERATOR_H
#define UAVOBJECTGENERATOR_H
#include <QTextStream>
#include <QString>
#include <QDir>
#include <QFile>
#include "uavobjectparser.h"
class UAVObjectGenerator
{
public:
UAVObjectGenerator(QString& basepath, FILE* out = stdout);
bool processAll();
private:
QDir basepath;
QTextStream sout;
QDir xmlPath;
QDir flightCodePath;
QDir gcsCodePath;
QDir pythonTemplatePath;
QDir matlabTemplatePath;
QDir pythonCodePath;
QString objectTemplateFilename;
QString objectsInitTemplateFilename;
QString objectsInitFilename;
QString matlabOutFilename;
QString readFile(QString name);
bool writeFile(QString name, QString& str);
bool writeFileIfDiffrent(QString name, QString& str);
};
#endif // UAVOBJECTGENERATOR_H
/**
******************************************************************************
*
* @file generator_io.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief I/O Code for the generator
*
* @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
*/
#ifndef GENERATORIO
#define GENERATORIO
#include <QString>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <iostream>
QString readFile(QString name);
QString readFile(QString name);
bool writeFile(QString name, QString& str);
bool writeFileIfDiffrent(QString name, QString& str);
#endif

View File

@ -0,0 +1,337 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorjava.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce java code for uavobjects
*
* @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
*/
#include "uavobjectgeneratorjava.h"
using namespace std;
bool UAVObjectGeneratorJava::generate(UAVObjectParser* parser,QString basepath) {
QDir javaTemplatePath = QDir( basepath + QString(JAVA_TEMPLATE_DIR));
javaCodePath = QDir ( basepath + QString(JAVA_GENERATED_DIR));
javaCodeTemplate = readFile( javaTemplatePath.absoluteFilePath("uavobjecttemplate.java") );
QString javaInitCodeTemplate = readFile( javaTemplatePath.absoluteFilePath("uavobjectsinittemplate.java") );
if (javaCodeTemplate.isEmpty() || javaInitCodeTemplate.isEmpty()) {
std::cerr << "Problem reading java templates" << endl;
return false;
}
QString javaObjInit,javaObjGetter;
javaCodePath.mkpath(javaCodePath.absolutePath() + "/uavobjects");
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo* info=parser->getObjectByIndex(objidx);
process_object(info);
if (!javaObjInit.isNull())
javaObjInit.append(",\n");
javaObjInit.append(" new " + info->name + "()");
javaObjGetter.append(QString(" public static %1 get%1() { return (%1)uavobjects[%2];}\n").arg( info->name).arg(objidx));
}
javaInitCodeTemplate.replace("$(OBJINIT)",javaObjInit);
javaInitCodeTemplate.replace("$(OBJGETTER)",javaObjGetter);
replaceCommonTags(javaInitCodeTemplate);
// Write the java object inialization files
bool res = writeFileIfDiffrent(javaCodePath.absolutePath() + "/UAVObjects.java", javaInitCodeTemplate );
if (!res) {
cerr << "Error: Could not write java init output files" << endl;
return false;
}
return true; // if we come here everything should be fine
}
QString UAVObjectGeneratorJava::getFieldTypeStr(int type,bool as_obj) {
switch(type) {
case FIELDTYPE_INT8:
return (QString(as_obj?"Byte":"byte"));
case FIELDTYPE_INT16:
case FIELDTYPE_INT32:
case FIELDTYPE_UINT8:
case FIELDTYPE_UINT16:
return (QString(as_obj?"Integer":"int"));
case FIELDTYPE_UINT32:
return (QString(as_obj?"Long":"long"));
case FIELDTYPE_FLOAT32:
return (QString(as_obj?"Float":"float"));
case FIELDTYPE_ENUM:
return (QString(as_obj?"Byte":"byte"));
default:
return QString("error: unknown type");
}
}
/**
*
* format a value from FieldInfo with a given index (idx) to a java code snippet
*
*/
QString UAVObjectGeneratorJava::formatJavaValue(FieldInfo* info,int idx) {
switch(info->type) {
case FIELDTYPE_ENUM:
return (info->name.toUpper() + QString("_") + info->defaultValues[idx].toUpper());
case FIELDTYPE_FLOAT32:
return QString("%1f").arg( info->defaultValues[idx].toFloat() );
default:
return QString("%1").arg( info->defaultValues[idx].toInt() );
}
}
QString UAVObjectGeneratorJava::QStringList2JavaArray(QStringList strl) {
QString csv=QString();
for (int i = 0; i < strl.length(); i++){
if (i!=0)
csv.append(QString(","));
csv.append(QString("\"%1\"").arg(strl[i]));
}
return QString("new String[] { %1 }").arg(csv);
}
QString UAVObjectGeneratorJava::serializeJavaValue(int type,QString name)
{
QString res;
switch(type) {
case FIELDTYPE_ENUM: // OK
case FIELDTYPE_INT8:
res=name;
break;
case FIELDTYPE_UINT8:
res=QString("(byte)(%1&0xFF)").arg(name);
break;
case FIELDTYPE_INT16:
case FIELDTYPE_UINT16:
res=QString("(byte)(("+name+">>0)&0xFF) , (byte)(("+name+">>8)&0xFF)");
break;
case FIELDTYPE_UINT32:
case FIELDTYPE_INT32:
res=QString("(byte)(("+name+">>0)&0xFF) , (byte)(("+name+">>8)&0xFF) , (byte)(("+name+">>16)&0xFF) , (byte)(("+name+">>24)&0xFF)");
break;
case FIELDTYPE_FLOAT32:
res=QString("(byte)((Float.floatToIntBits("+name+")>>0)&0xFF) , (byte)((Float.floatToIntBits("+name+")>>8)&0xFF) , (byte)((Float.floatToIntBits("+name+")>>16)&0xFF) , (byte)((Float.floatToIntBits("+name+")>>24)&0xFF) "); // OK
break;
default:
res=QString("unresolved type");
break;
}
return res;
}
/**
* this function is used to build the deserializing code
*/
QString UAVObjectGeneratorJava::deSerializeJavaValue(int type,QString name)
{
switch(type) {
case FIELDTYPE_ENUM: // OK
case FIELDTYPE_INT8:
return (name.append("=arr[pos++];\n"));
case FIELDTYPE_UINT8:
return (name.append("=arr[pos++];\n")); /*todo implement & check */
case FIELDTYPE_INT16:
case FIELDTYPE_UINT16:
return (QString(" pos+=2;\n")); /*todo implement & check */
case FIELDTYPE_UINT32:
case FIELDTYPE_INT32:
return (QString(" pos+=4;\n")); /*todo implement & test */
case FIELDTYPE_FLOAT32:
return (QString(" pos+=4;\n")); /*todo implement & test */
default:
cout << "Warning: unresolved type " << type << " for " << name.toStdString() << endl;
return(QString("unresolved type")); // will throw an arr when compiling then
}
}
/**
* Generate the java object files
*/
bool UAVObjectGeneratorJava::process_object(ObjectInfo* info)
{
if (info == NULL) return false;
// Prepare output strings
QString outCode = javaCodeTemplate;
// Replace common tags
replaceCommonTags(outCode, info);
QString type,fieldsinit,serialize_code,serialize_code_inner,deserialize_code,gettersetter;
QString fielddesc=QString(" public final UAVObjectFieldDescription[] getFieldDescriptions() { return new UAVObjectFieldDescription[] {");
QString fieldgetter=QString(" public Object getField(byte fieldid,byte arr_pos) { switch(fieldid) {\n");
QString fieldsetter=QString(" public void setField(byte fieldid,byte arr_pos,Object obj) { switch(fieldid) {\n");
for (int n = 0; n < info->fields.length(); ++n) {
FieldInfo* act_field_info=info->fields[n];
bool is_array = info->fields[n]->numElements > 1;
type = getFieldTypeStr(act_field_info->type,false); // Determine type
for (int enum_n = 0; enum_n < act_field_info->options.length(); ++enum_n)
fieldsinit.append(QString(" public final static byte %1 = %2;\n").arg(act_field_info->name.toUpper() + QString("_") + act_field_info->options[enum_n].toUpper()).arg(enum_n) );
fieldsinit.append(QString(" private ") + type);
if ( is_array )
fieldsinit.append(QString("[]"));
fieldsinit.append(QString(" %1").arg(act_field_info->name));
if (!info->fields[n]->defaultValues.isEmpty()) { // if we have default vals
fieldsinit.append(QString("="));
if ( is_array ) {
fieldsinit.append(QString("{"));
for (int val_n = 0; val_n < act_field_info->defaultValues.length(); ++val_n)
fieldsinit.append( ((val_n>0)?QString(","):QString() ) + formatJavaValue(act_field_info,val_n) );
fieldsinit.append(QString("}"));
}
else
fieldsinit.append(formatJavaValue(act_field_info,0));
}
else {
if ( is_array ) // when it is an array
fieldsinit.append(QString("= new ") + type + QString("[%1]").arg(info->fields[n]->numElements));
}
fieldsinit.append(QString(";"));
if (n!=0)
serialize_code_inner.append(QString(","));
if ( is_array ) {
for (int el=0;el<info->fields[n]->numElements;el++) {
if (el!=0)
serialize_code_inner.append(QString(","));
serialize_code_inner.append(serializeJavaValue(info->fields[n]->type,info->fields[n]->name+ QString("[%1]").arg(el)));
deserialize_code.append(deSerializeJavaValue(info->fields[n]->type,info->fields[n]->name+ QString("[%1]").arg(el)));
}
}
else { // no array
serialize_code_inner.append(serializeJavaValue(info->fields[n]->type,info->fields[n]->name));
deserialize_code.append(deSerializeJavaValue(info->fields[n]->type,info->fields[n]->name));
}
serialize_code_inner.append(QString("//%1\n" ).arg(info->fields[n]->name));
// Determine type
type = getFieldTypeStr(act_field_info->type,false);
QString typespec=type;
if ( is_array ) {
typespec.append(QString("[]"));
fieldgetter.append(QString("case %1: return (Object)%2[arr_pos];\n").arg(n).arg(act_field_info->name));
fieldsetter.append(QString("case %1: %2[arr_pos]=(%3)obj;break;\n").arg(n).arg(act_field_info->name).arg( getFieldTypeStr(act_field_info->type,true)));
}
else { // no array
fieldgetter.append(QString("case %1: return (Object)%2;\n").arg(n).arg(act_field_info->name));
fieldsetter.append(QString("case %1: %2=(%3)obj;break;\n").arg(n).arg(act_field_info->name).arg(getFieldTypeStr(act_field_info->type,true)));
}
if (!act_field_info->units.isEmpty()) // when we have unit info
gettersetter.append(QString("\n /**\n * unit: %1\n */\n").arg(act_field_info->units));
gettersetter.append(QString(" public void set%1( %2 _%1 ) { %1=_%1; }\n").arg(act_field_info->name).arg(typespec));
if (n!=0)
fielddesc.append(QString("\t,"));
fielddesc.append(QString("new UAVObjectFieldDescription(\"%1\",this.getObjID(),(byte)%2,(byte)%3,\"%4\",%5,%6)\n").arg(act_field_info->name).arg(n).arg(act_field_info->type).arg(act_field_info->units).arg(QStringList2JavaArray( act_field_info->options)).arg(QStringList2JavaArray( act_field_info->elementNames)) );
if (!act_field_info->units.isEmpty())
gettersetter.append(QString("\n /**\n * unit: %1\n */\n").arg(act_field_info->units));
gettersetter.append(QString(" public ") + typespec);
gettersetter.append(QString(" get%1() { return %1; }\n").arg(act_field_info->name));
if ( act_field_info->options.length()!=0) {
QString enumOptionsGetter=QString(" public final static String[] get%1EnumOptions() { return new String[] {").arg(act_field_info->name);
// gettersetter.append(QString(" get%1s() { return %1; }\n").arg(act_field_info->name));
for (int enum_n = 0; enum_n < act_field_info->options.length(); ++enum_n) {
if (enum_n!=0)
enumOptionsGetter.append(QString(","));
enumOptionsGetter.append(QString("\"")+act_field_info->options[enum_n] +QString("\""));
}
gettersetter.append(enumOptionsGetter+QString("};}\n"));
}
if ( is_array ) { // when it is an array create getter for the element names
QString elementListGetter=QString(" public final static String[] get%1ElementNames() { return new String[] {").arg(act_field_info->name);
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m) {
gettersetter.append(QString(" public ") + type);
gettersetter.append(QString(" get%1%2() { return %1[%3]; }\n").arg(act_field_info->name).arg(elemNames[m]).arg(m));
if (m!=0)
elementListGetter.append(QString(","));
elementListGetter.append(QString("\"") + elemNames[m]+QString("\""));
}
gettersetter.append(elementListGetter+QString("};}\n"));
}
}
serialize_code.append(QString(" public byte[] serialize() { return new byte[]{%1 } ;}; \n ").arg(serialize_code_inner));
serialize_code.append(QString(" public void deserialize(byte[] arr,int offset) {\nsuper.deserialize(arr,offset);\n int pos=offset;\n%1 };\n").arg(deserialize_code));
outCode.replace(QString("$(FIELDSINIT)"), fieldsinit);
fielddesc.append(QString("};}"));
fieldgetter.append(QString("};\n return null;\n}\n"));
fieldsetter.append(QString("};\n}\n"));
outCode.replace(QString("$(GETTERSETTER)"), gettersetter + serialize_code+ fielddesc + fieldgetter + fieldsetter);
bool res = writeFileIfDiffrent(javaCodePath.absolutePath() + "/uavobjects/" + info->name + ".java", outCode );
if (!res) {
cerr << "Error: Could not write java init output file " << info->name.toStdString()<< endl;
return false;
}
return true;
}

View File

@ -0,0 +1,51 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorjava.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce java code for uavobjects
*
* @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
*/
#ifndef UAVOBJECTGENERATORJAVA_H
#define UAVOBJECTGENERATORJAVA_H
#define JAVA_TEMPLATE_DIR "ground/src/libs/juavobjects/templates/"
#define JAVA_GENERATED_DIR "build/juavobjects/src/org/openpilot/uavtalk"
#include "../generator_common.h"
class UAVObjectGeneratorJava
{
public:
bool generate(UAVObjectParser* gen,QString basepath);
private:
QString javaCodeTemplate;
QDir javaCodePath;
bool process_object(ObjectInfo* info);
QString formatJavaValue(FieldInfo* info,int idx);
QString QStringList2JavaArray(QStringList strl);
QString serializeJavaValue(int type,QString name);
QString deSerializeJavaValue(int type,QString name);
QString getFieldTypeStr(int type,bool as_obj);
};
#endif

View File

@ -0,0 +1,135 @@
/**
******************************************************************************
*
* @file uavobjectgeneratormatlab.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce matlab code for uavobjects
*
* @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
*/
#include "uavobjectgeneratormatlab.h"
using namespace std;
bool UAVObjectGeneratorMatlab::generate(UAVObjectParser* parser,QString basepath) {
fieldTypeStrMatlab << "int8" << "int16" << "int32"
<< "uint8" << "uint16" << "uint32" << "float32" << "uint8";
QDir matlabTemplatePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
QString matlabCodeTemplate = readFile( matlabTemplatePath.absoluteFilePath( "uavobjecttemplate.m") );
if (matlabCodeTemplate.isEmpty() ) {
std::cerr << "Problem reading matlab templates" << endl;
return false;
}
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
ObjectInfo* info=parser->getObjectByIndex(objidx);
process_object(info);
}
matlabCodeTemplate.replace( QString("$(ALLOCATIONCODE)"), matlabAllocationCode);
matlabCodeTemplate.replace( QString("$(SWITCHCODE)"), matlabSwithCode);
matlabCodeTemplate.replace( QString("$(SAVEOBJECTSCODE)"), matlabSaveObjectsCode);
matlabCodeTemplate.replace( QString("$(FUNCTIONSCODE)"), matlabFunctionsCode);
bool res = writeFile( matlabTemplatePath.absolutePath() + "/OPLogConvert.m", matlabCodeTemplate );
if (!res) {
cout << "Error: Could not write output files" << endl;
return false;
}
return true; // if we come here everything should be fine
}
/**
* Generate the matlab object files
*/
bool UAVObjectGeneratorMatlab::process_object(ObjectInfo* info)
{
if (info == NULL)
return false;
QString objectName(info->name);
// QString objectTableName(objectName + "Objects");
QString objectTableName(objectName);
QString tableIdxName(objectName.toLower() + "Idx");
QString functionName("Read" + info->name + "Object");
QString functionCall(functionName + "(fid, timestamp)");
QString objectID(QString().setNum(info->id));
QString isSingleInst = boolTo01String( info->isSingleInst );
// Generate allocation code (will replace the $(ALLOCATIONCODE) tag)
matlabAllocationCode.append("\n " + tableIdxName + " = 1;\n");
matlabAllocationCode.append(" " + objectTableName + ".timestamp = 0;\n");
QString type;
QString allocfields;
for (int n = 0; n < info->fields.length(); ++n) {
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
allocfields.append(" " + objectTableName + "(1)." + info->fields[n]->name + " = zeros(1," + QString::number(info->fields[n]->numElements, 10) + ");\n");
else
allocfields.append(" " + objectTableName + "(1)." + info->fields[n]->name + " = 0;\n");
}
matlabAllocationCode.append(allocfields);
// Generate 'swith:' code (will replace the $(SWITCHCODE) tag)
matlabSwithCode.append(" case " + objectID + "\n");
matlabSwithCode.append(" " + objectTableName + "(" + tableIdxName +") = " + functionCall + ";\n");
matlabSwithCode.append(" " + tableIdxName + " = " + tableIdxName +" + 1;\n");
// Generate objects saving code code (will replace the $(SAVEOBJECTSCODE) tag)
matlabSaveObjectsCode.append(",'"+objectTableName+"'");
// Generate functions code (will replace the $(FUNCTIONSCODE) tag)
matlabFunctionsCode.append("function [" + objectName + "] = " + functionCall + "\n");
matlabFunctionsCode.append(" if " + isSingleInst + "\n");
matlabFunctionsCode.append(" headerSize = 8;\n");
matlabFunctionsCode.append(" else\n");
matlabFunctionsCode.append(" " + objectName + ".instanceID = fread(fid, 1, 'uint16');\n");
matlabFunctionsCode.append(" headerSize = 10;\n");
matlabFunctionsCode.append(" end\n\n");
matlabFunctionsCode.append(" " + objectName + ".timestamp = timestamp;\n");
// Generate functions code, actual fields of the object
QString funcfields;
for (int n = 0; n < info->fields.length(); ++n) {
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
funcfields.append(" " + objectName + "." + info->fields[n]->name + " = double(fread(fid, " + QString::number(info->fields[n]->numElements, 10) + ", '" + type + "'));\n");
else
funcfields.append(" " + objectName + "." + info->fields[n]->name + " = double(fread(fid, 1, '" + type + "'));\n");
}
matlabFunctionsCode.append(funcfields);
matlabFunctionsCode.append(" % read CRC\n");
matlabFunctionsCode.append(" fread(fid, 1, 'uint8');\n");
matlabFunctionsCode.append("end\n\n");
return true;
}

View File

@ -0,0 +1,47 @@
/**
******************************************************************************
*
* @file uavobjectgeneratormatlab.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce matlab code for uavobjects
*
* @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
*/
#ifndef UAVOBJECTGENERATORMATLAB_H
#define UAVOBJECTGENERATORMATLAB_H
#include "../generator_common.h"
class UAVObjectGeneratorMatlab
{
public:
bool generate(UAVObjectParser* gen,QString basepath);
private:
bool process_object(ObjectInfo* info);
QString matlabAllocationCode;
QString matlabSwithCode;
QString matlabSaveObjectsCode;
QString matlabFunctionsCode;
QStringList fieldTypeStrMatlab;
};
#endif

View File

@ -0,0 +1,117 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorpython.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce python code for uavobjects
*
* @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
*/
#include "uavobjectgeneratorpython.h"
using namespace std;
bool UAVObjectGeneratorPython::generate(UAVObjectParser* parser,QString basepath) {
fieldTypeStrPython << "b" << "h" << "i" << "B" << "H" << "I" << "f" << "b";
pythonCodePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
pythonCodeTemplate = readFile( pythonCodePath.absoluteFilePath("uavobjecttemplate.py") );
QString pythonImport,pythonObjInit;
if (pythonCodeTemplate.isEmpty()) {
std::cerr << "Problem reading python templates" << endl;
return false;
}
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
}
/**
* Generate the python object files
*/
bool UAVObjectGeneratorPython::process_object(ObjectInfo* info)
{
if (info == NULL)
return false;
// Prepare output strings
QString outCode = pythonCodeTemplate;
// Replace common tags
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString fields;
fields.append(QString("[ \\\n"));
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"));
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
// 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] ) );
}
}
fields.append(QString("\t\t}\n"));
fields.append(QString("\t),\n"));
}
fields.append(QString("]\n"));
outCode.replace(QString("$(DATAFIELDS)"), fields);
// Write the Python code
bool res = writeFileIfDiffrent( pythonCodePath.absolutePath() + "/" + info->namelc + ".py", outCode );
if (!res) {
cout << "Error: Could not write Python output files" << endl;
return false;
}
return true;
}

View File

@ -0,0 +1,45 @@
/**
******************************************************************************
*
* @file uavobjectgeneratorpython.h
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief produce python code for uavobjects
*
* @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
*/
#ifndef UAVOBJECTGENERATORPYTHON_H
#define UAVOBJECTGENERATORPYTHON_H
#include "../generator_common.h"
class UAVObjectGeneratorPython
{
public:
bool generate(UAVObjectParser* gen,QString basepath);
private:
bool process_object(ObjectInfo* info);
QString pythonCodeTemplate;
QDir pythonCodePath;
QStringList fieldTypeStrPython;
};
#endif

View File

@ -1,57 +1,172 @@
/**
******************************************************************************
*
* @file main.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief UAVObjectGenerator main.
*
* @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
*/
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QString>
#include <iostream>
#include "uavobjectgenerator.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString basepath;
// Get arguments
if (argc == 1)
{
basepath = QString("../../../../../");
}
else if (argc == 2)
{
basepath = QString(argv[1]);
}
else
{
std::cout << "Invalid arguments: uavobjectgenerator [base path to gcs and flight directories (as in svn)]" << std::endl;
}
// Start application
UAVObjectGenerator gen(basepath);
gen.processAll();
return 0;
}
/**
******************************************************************************
*
* @file main.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief UAVObjectGenerator main.
*
* @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
*/
#include <QtCore/QCoreApplication>
#include <QFile>
#include <QString>
#include <QStringList>
#include <iostream>
#include "generators/java/uavobjectgeneratorjava.h"
#include "generators/flight/uavobjectgeneratorflight.h"
#include "generators/gcs/uavobjectgeneratorgcs.h"
#include "generators/matlab/uavobjectgeneratormatlab.h"
#include "generators/python/uavobjectgeneratorpython.h"
#define ERR_USAGE 1
#define ERR_XML 2
using namespace std;
/**
* print usage info
*/
void usage() {
cout << "Usage: uavobjectgenerator [-gcs] [-flight] [-java] [-python] [-mathlab] [base_path]" << endl;
cout << " If no language is specified - all are build." << endl;
cout << " base_path - base path to gcs and flight directories (as in svn)." << endl;
}
/**
* inform user of invalid usage
*/
int usage_err() {
cout << "Invalid usage!" << endl;
usage();
return ERR_USAGE;
}
/**
* entrance
*/
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cout << "- OpenPilot UAVObject Generator -" << endl;
QString basepath;
QStringList arguments_stringlist;
// process arguments
for (int argi=1;argi<argc;argi++)
arguments_stringlist << argv[argi];
bool do_gcs=(arguments_stringlist.removeAll("-gcs")>0);
bool do_flight=(arguments_stringlist.removeAll("-flight")>0);
bool do_java=(arguments_stringlist.removeAll("-java")>0);
bool do_python=(arguments_stringlist.removeAll("-python")>0);
bool do_matlab=(arguments_stringlist.removeAll("-mathlab")>0);
bool do_all=((do_gcs||do_flight||do_java||do_python||do_matlab)==false);
if (arguments_stringlist.length() == 0) // if we have no param left - make up a basepath
basepath =QString("../../../../../");
else if (arguments_stringlist.length() == 1) // if we have one param left it is the basepath
basepath = arguments_stringlist.at(0);
else // too many arguments
return usage_err();
if (!basepath.endsWith("/"))
basepath.append("/"); // append a slash if it is not there
QDir xmlPath = QDir( basepath + QString("ground/src/shared/uavobjectdefinition"));
UAVObjectParser* parser = new UAVObjectParser();
QStringList filters=QStringList("*.xml");
xmlPath.setNameFilters(filters);
QFileInfoList xmlList = xmlPath.entryInfoList();
// Read in each XML file and parse object(s) in them
for (int n = 0; n < xmlList.length(); ++n) {
QFileInfo fileinfo = xmlList[n];
std::cout << "Parsing XML file: " << fileinfo.fileName().toStdString() << std::endl;
QString filename = fileinfo.fileName();
QString xmlstr = readFile(fileinfo.absoluteFilePath());
QString res = parser->parseXML(xmlstr, filename);
if (!res.isNull()) {
std::cout << "Error parsing " << res.toStdString() << endl;
return ERR_XML;
}
}
// check for duplicate object ID's
QList<quint32> objIDList;
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) {
quint32 id = parser->getObjectID(objidx);
if ( objIDList.contains(id) || id == 0 ) {
cout << "Error: Object ID collision found in object " << parser->getObjectName(objidx).toStdString() << ", modify object name" << endl;
return ERR_XML;
}
objIDList.append(id);
}
// done parsing and checking
cout << "Done: processed " << xmlList.length() << " XML files and generated "
<< objIDList.length() << " objects with no ID collisions." << endl;
// generate flight code if wanted
if (do_flight|do_all) {
std::cout << "generating flight code" << endl ;
UAVObjectGeneratorFlight flightgen;
flightgen.generate(parser,basepath);
}
// generate gcs code if wanted
if (do_gcs|do_all) {
std::cout << "generating gcs code" << endl ;
UAVObjectGeneratorGCS gcsgen;
gcsgen.generate(parser,basepath);
}
// generate java code if wanted
if (do_java|do_all) {
std::cout << "generating java code" << endl ;
UAVObjectGeneratorJava javagen;
javagen.generate(parser,basepath);
}
// generate python code if wanted
if (do_python|do_all) {
std::cout << "generating python code" << endl ;
UAVObjectGeneratorPython pygen;
pygen.generate(parser,basepath);
}
// generate matlab code if wanted
if (do_matlab|do_all) {
std::cout << "generating matlab code" << endl ;
UAVObjectGeneratorMatlab matlabgen;
matlabgen.generate(parser,basepath);
}
return 0;
}

View File

@ -1,305 +0,0 @@
/**
******************************************************************************
*
* @file uavobjectgenerator.cpp
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
* @brief UAVObjectGenerator, generates UAVObjects from XML files.
*
* @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
*/
/*
* The following is done by the object generator:
* - Read all XML files in the XML source directory
* - Process each XML and extract the information for all defined objects
* - Generate the unique objects IDs and check for collisions
* - Generate the GCS and Flight UAVObject code based on the supplied template source files
* - Update the object initialization source files for both the GCS and Flight code
*/
#include "uavobjectgenerator.h"
/**
* Constructor
* @param basepath The base directory where the 'flight' and 'gcs' folders are located (the SVN structure is expected)
* @param out The stdout file
*/
UAVObjectGenerator::UAVObjectGenerator(QString& basepath, FILE* out) :
basepath(basepath),
sout(out)
{
xmlPath = QDir( basepath + QString("ground/src/shared/uavobjectdefinition"));
flightCodePath = QDir( basepath + QString("flight/OpenPilot/UAVObjects"));
gcsCodePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
pythonTemplatePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
matlabTemplatePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
// synthetic output files should go into the build directory once the various GUI build systems
// learn how to find these output files in the build directory.
//pythonCodePath = QDir( basepath + QString("build/uavobjects"));
pythonCodePath = QDir( basepath + QString("ground/src/plugins/uavobjects"));
objectTemplateFilename = QString("uavobjecttemplate");
objectsInitTemplateFilename = QString("uavobjectsinittemplate");
objectsInitFilename = QString("uavobjectsinit");
matlabOutFilename = QString("OPLogConvert");
sout << "- OpenPilot UAVObject Generator -" << endl;
}
/**
* Process all XML files and generate object code.
*/
bool UAVObjectGenerator::processAll()
{
// Read the template files
QString flightCodeTemplate = readFile( flightCodePath.absoluteFilePath(objectTemplateFilename + ".c") );
QString flightIncludeTemplate = readFile( flightCodePath.absoluteFilePath("inc/" + objectTemplateFilename + ".h") );
QString flightInitTemplate = readFile( flightCodePath.absoluteFilePath(objectsInitTemplateFilename + ".c") );
QString gcsCodeTemplate = readFile( gcsCodePath.absoluteFilePath(objectTemplateFilename + ".cpp") );
QString gcsIncludeTemplate = readFile( gcsCodePath.absoluteFilePath(objectTemplateFilename + ".h") );
QString gcsInitTemplate = readFile( gcsCodePath.absoluteFilePath(objectsInitTemplateFilename + ".cpp") );
QString pythonCodeTemplate = readFile( pythonTemplatePath.absoluteFilePath(objectTemplateFilename + ".py") );
QString matlabCodeTemplate = readFile( matlabTemplatePath.absoluteFilePath(objectTemplateFilename + ".m") );
if ( flightCodeTemplate.isNull() || flightIncludeTemplate.isNull() ||
gcsCodeTemplate.isNull() || gcsIncludeTemplate.isNull() ||
pythonCodeTemplate.isNull() ||
flightInitTemplate.isNull() || gcsInitTemplate.isNull() )
{
sout << "Error: Could not open template files." << endl;
return false;
}
// Get all XML files
QStringList filters;
filters.append("*.xml");
xmlPath.setNameFilters(filters);
QFileInfoList xmlList = xmlPath.entryInfoList();
// Read in each XML file and parse it
QList<UAVObjectParser*> parsers;
for (int n = 0; n < xmlList.length(); ++n)
{
QFileInfo fileinfo = xmlList[n];
QString filename = fileinfo.fileName();
QString xmlstr = readFile(fileinfo.absoluteFilePath());
UAVObjectParser* parser = new UAVObjectParser();
sout << "Parsing XML file: " << fileinfo.fileName() << endl;
QString res = parser->parseXML(xmlstr, filename);
if (!res.isNull())
{
sout << "Error: " << res << endl;
return false;
}
parsers.append(parser);
}
// Generate the code for each object and write it to the destination directory
QList<quint32> objIDList;
QString objInc;
QString pythonImport;
QString flightObjInit;
QString gcsObjInit;
QString pythonObjInit;
int numBytesTotal = 0;
QString matlabAllocationCode;
QString matlabSwithCode;
QString matlabSaveObjectsCode;
QString matlabFunctionsCode;
bool res;
for (int parseridx = 0; parseridx < parsers.length(); ++ parseridx)
{
UAVObjectParser* parser = parsers[parseridx];
for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx)
{
QString name = parser->getObjectName(objidx);
QString namelc = name.toLower();
int numBytes = parser->getNumBytes(objidx);
numBytesTotal += numBytes;
sout << "Generating code for object: " << name << " (" << numBytes << " bytes)" << endl;
// Check for object ID conflicts
quint32 id = parser->getObjectID(objidx);
if ( objIDList.contains(id) || id == 0 )
{
sout << "Error: Object ID collision found in object " << name << ", modify object name" << endl;
return false;
}
else
{
objIDList.append(id);
}
// Generate the flight code
QString flightCode;
QString flightInclude;
res = parser->generateFlightObject(objidx, flightIncludeTemplate, flightCodeTemplate,
flightInclude, flightCode);
if (!res)
{
sout << "Error: Improperly formatted flight object template file" << endl;
return false;
}
// Generate the GCS code
QString gcsCode;
QString gcsInclude;
res = parser->generateGCSObject(objidx, gcsIncludeTemplate, gcsCodeTemplate,
gcsInclude, gcsCode);
if (!res)
{
sout << "Error: Improperly formatted GCS object template file" << endl;
return false;
}
// Generate the Python code
QString pythonCode;
res = parser->generatePythonObject(objidx, pythonCodeTemplate, pythonCode);
if (!res)
{
sout << "Error: Improperly formatted Python object template file" << endl;
return false;
}
// Generate the Matlab code
res = parser->generateMatlabFile(objidx, matlabAllocationCode, matlabSwithCode, matlabSaveObjectsCode, matlabFunctionsCode);
// Write the flight code
res = writeFileIfDiffrent( flightCodePath.absolutePath() + "/" + namelc + ".c", flightCode );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
res = writeFileIfDiffrent( flightCodePath.absolutePath() + "/inc/" + namelc + ".h", flightInclude );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Write the GCS code
res = writeFileIfDiffrent( gcsCodePath.absolutePath() + "/" + namelc + ".cpp", gcsCode );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
res = writeFileIfDiffrent( gcsCodePath.absolutePath() + "/" + namelc + ".h", gcsInclude );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Write the Python code
res = writeFileIfDiffrent( pythonCodePath.absolutePath() + "/" + namelc + ".py", pythonCode );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Update strings for the object initialization
objInc.append("#include \"" + namelc + ".h\"\n");
pythonImport.append("import " + namelc + "\n");
flightObjInit.append(" " + name + "Initialize();\n");
gcsObjInit.append(" objMngr->registerObject( new " + name + "() );\n");
pythonObjInit.append("\tuavobjectsinit.uavobjects.append(" + name + "." + name + "())\n");
}
}
// Write the flight object inialization files
sout << "Updating object initialization files" << endl;
flightInitTemplate.replace( QString("$(OBJINC)"), objInc);
flightInitTemplate.replace( QString("$(OBJINIT)"), flightObjInit);
res = writeFileIfDiffrent( flightCodePath.absolutePath() + "/" + objectsInitFilename + ".c",
flightInitTemplate );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Write the gcs object inialization files
gcsInitTemplate.replace( QString("$(OBJINC)"), objInc);
gcsInitTemplate.replace( QString("$(OBJINIT)"), gcsObjInit);
res = writeFileIfDiffrent( gcsCodePath.absolutePath() + "/" + objectsInitFilename + ".cpp",
gcsInitTemplate );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
matlabCodeTemplate.replace( QString("$(ALLOCATIONCODE)"), matlabAllocationCode);
matlabCodeTemplate.replace( QString("$(SWITCHCODE)"), matlabSwithCode);
matlabCodeTemplate.replace( QString("$(SAVEOBJECTSCODE)"), matlabSaveObjectsCode);
matlabCodeTemplate.replace( QString("$(FUNCTIONSCODE)"), matlabFunctionsCode);
res = writeFile( gcsCodePath.absolutePath() + "/" + matlabOutFilename + ".m", matlabCodeTemplate );
if (!res)
{
sout << "Error: Could not write output files" << endl;
return false;
}
// Done
sout << "Done: processed " << xmlList.length() << " XML files and generated "
<< objIDList.length() << " objects with no ID collisions. Total size of the data fields is " << numBytesTotal << " bytes." << endl;
return true;
}
/**
* Read a file and return its contents as a string
*/
QString UAVObjectGenerator::readFile(QString name)
{
QFile file(name);
if (!file.open(QFile::ReadOnly))
{
sout << "Warning: Could not open " << name << endl;
return QString();
}
QTextStream fileStr(&file);
QString str = fileStr.readAll();
file.close();
return str;
}
/**
* Write contents of string to file
*/
bool UAVObjectGenerator::writeFile(QString name, QString& str)
{
QFile file(name);
if (!file.open(QFile::WriteOnly)) return false;
QTextStream fileStr(&file);
fileStr << str;
file.close();
return true;
}
/**
* Write contents of string to file if the content changes
*/
bool UAVObjectGenerator::writeFileIfDiffrent(QString name, QString& str)
{
if (readFile(name)==str) return true;
return writeFile(name,str);
}

View File

@ -25,51 +25,25 @@
*/
#include "uavobjectparser.h"
#include <QByteArray>
/**
* Constructor
*/
UAVObjectParser::UAVObjectParser()
{
fieldTypeStrC << QString("int8_t") << QString("int16_t") << QString("int32_t") <<
QString("uint8_t") << QString("uint16_t") << QString("uint32_t") <<
QString("float") << QString("uint8_t");
fieldTypeStrXML << "int8" << "int16" << "int32" << "uint8"
<< "uint16" << "uint32" <<"float" << "enum";
fieldTypeStrCPP << QString("qint8") << QString("qint16") << QString("qint32") <<
QString( "quint8") << QString("quint16") << QString("quint32") <<
QString("float") << QString("quint8");
updateModeStrXML << "periodic" << "onchange" << "manual" << "never";
fieldTypeStrPython << QString("b") << QString("h") << QString("i") <<
QString( "B") << QString("H") << QString("I") <<
QString("f") << QString("b");
fieldTypeStrCPPClass << QString("INT8") << QString("INT16") << QString("INT32") <<
QString( "UINT8") << QString("UINT16") << QString("UINT32") <<
QString("FLOAT32") << QString("ENUM");
fieldTypeStrMatlab << QString("int8") << QString("int16") << QString("int32") <<
QString( "uint8") << QString("uint16") << QString("uint32") <<
QString("float32") << QString("uint8");
fieldTypeStrXML << QString("int8") << QString("int16") << QString("int32") <<
QString("uint8") << QString("uint16") << QString("uint32") <<
QString("float") << QString("enum");
accessModeStr << "ACCESS_READWRITE" << "ACCESS_READONLY";
fieldTypeNumBytes << int(1) << int(2) << int(4) <<
int(1) << int(2) << int(4) <<
int(4) << int(1);
updateModeStr << QString("UPDATEMODE_PERIODIC") << QString("UPDATEMODE_ONCHANGE") <<
QString("UPDATEMODE_MANUAL") << QString("UPDATEMODE_NEVER");
updateModeStrXML << QString("periodic") << QString("onchange") <<
QString("manual") << QString("never");
accessModeStr << QString("ACCESS_READWRITE") << QString("ACCESS_READONLY");
accessModeStrXML << QString("readwrite") << QString("readonly");
accessModeStrXML << "readwrite" << "readonly";
}
/**
@ -83,11 +57,16 @@ int UAVObjectParser::getNumObjects()
/**
* Get the detailed object information
*/
QList<UAVObjectParser::ObjectInfo*> UAVObjectParser::getObjectInfo()
QList<ObjectInfo*> UAVObjectParser::getObjectInfo()
{
return objInfo;
}
ObjectInfo* UAVObjectParser::getObjectByIndex(int objIndex)
{
return objInfo[objIndex];
}
/**
* Get the name of the object
*/
@ -95,13 +74,9 @@ QString UAVObjectParser::getObjectName(int objIndex)
{
ObjectInfo* info = objInfo[objIndex];
if (info == NULL)
{
return QString();
}
else
{
return info->name;
}
return info->name;
}
/**
@ -111,13 +86,8 @@ quint32 UAVObjectParser::getObjectID(int objIndex)
{
ObjectInfo* info = objInfo[objIndex];
if (info == NULL)
{
return 0;
}
else
{
return info->id;
}
return info->id;
}
/**
@ -149,7 +119,6 @@ int UAVObjectParser::getNumBytes(int objIndex)
*/
QString UAVObjectParser::parseXML(QString& xml, QString& filename)
{
this->filename = filename;
// Create DOM document and parse it
QDomDocument doc("UAVObjects");
bool parsed = doc.setContent(xml);
@ -158,16 +127,15 @@ QString UAVObjectParser::parseXML(QString& xml, QString& filename)
// Read all objects contained in the XML file, creating an new ObjectInfo for each
QDomElement docElement = doc.documentElement();
QDomNode node = docElement.firstChild();
while ( !node.isNull() )
{
while ( !node.isNull() ) {
// Create new object entry
ObjectInfo* info = new ObjectInfo;
info->filename=filename;
// Process object attributes
QString status = processObjectAttributes(node, info);
if (!status.isNull())
{
return status;
}
// Process child elements (fields and metadata)
QDomNode childNode = node.firstChild();
@ -177,97 +145,78 @@ QString UAVObjectParser::parseXML(QString& xml, QString& filename)
bool telFlightFound = false;
bool logFound = false;
bool descriptionFound = false;
while ( !childNode.isNull() )
{
while ( !childNode.isNull() ) {
// Process element depending on its type
if ( childNode.nodeName().compare(QString("field")) == 0 )
{
if ( childNode.nodeName().compare(QString("field")) == 0 ) {
QString status = processObjectFields(childNode, info);
if (!status.isNull())
{
return status;
}
fieldFound = true;
}
else if ( childNode.nodeName().compare(QString("access")) == 0 )
{
else if ( childNode.nodeName().compare(QString("access")) == 0 ) {
QString status = processObjectAccess(childNode, info);
if (!status.isNull())
{
return status;
}
accessFound = true;
}
else if ( childNode.nodeName().compare(QString("telemetrygcs")) == 0 )
{
else if ( childNode.nodeName().compare(QString("telemetrygcs")) == 0 ) {
QString status = processObjectMetadata(childNode, &info->gcsTelemetryUpdateMode,
&info->gcsTelemetryUpdatePeriod, &info->gcsTelemetryAcked);
if (!status.isNull())
{
return status;
}
telGCSFound = true;
}
else if ( childNode.nodeName().compare(QString("telemetryflight")) == 0 )
{
else if ( childNode.nodeName().compare(QString("telemetryflight")) == 0 ) {
QString status = processObjectMetadata(childNode, &info->flightTelemetryUpdateMode,
&info->flightTelemetryUpdatePeriod, &info->flightTelemetryAcked);
if (!status.isNull())
{
return status;
}
telFlightFound = true;
}
else if ( childNode.nodeName().compare(QString("logging")) == 0 )
{
else if ( childNode.nodeName().compare(QString("logging")) == 0 ) {
QString status = processObjectMetadata(childNode, &info->loggingUpdateMode,
&info->loggingUpdatePeriod, NULL);
if (!status.isNull())
{
return status;
}
logFound = true;
}
else if ( childNode.nodeName().compare(QString("description")) == 0 )
{
else if ( childNode.nodeName().compare(QString("description")) == 0 ) {
QString status = processObjectDescription(childNode, &info->description);
if (!status.isNull())
{
return status;
}
descriptionFound = true;
}
else
{
else {
return QString("Unknown object element");
}
// Get next element
childNode = childNode.nextSibling();
}
// Make sure that required elements were found
if ( !accessFound )
{
return QString("Object::access element is missing");
}
else if ( !telGCSFound )
{
if ( !telGCSFound )
return QString("Object::telemetrygcs element is missing");
}
else if ( !telFlightFound )
{
if ( !telFlightFound )
return QString("Object::telemetryflight element is missing");
}
else if ( !logFound )
{
if ( !logFound )
return QString("Object::logging element is missing");
}
// TODO: Make into error once all objects updated
if ( !descriptionFound )
{
return QString("Object::description element is missing");
}
// Calculate ID
calculateID(info);
@ -296,8 +245,7 @@ void UAVObjectParser::calculateID(ObjectInfo* info)
hash = updateHash(info->isSettings, hash);
hash = updateHash(info->isSingleInst, hash);
// Hash field information
for (int n = 0; n < info->fields.length(); ++n)
{
for (int n = 0; n < info->fields.length(); ++n) {
hash = updateHash(info->fields[n]->name, hash);
hash = updateHash(info->fields[n]->numElements, hash);
hash = updateHash(info->fields[n]->type, hash);
@ -325,9 +273,8 @@ quint32 UAVObjectParser::updateHash(QString& value, quint32 hash)
QByteArray bytes = value.toAscii();
quint32 hashout = hash;
for (int n = 0; n < bytes.length(); ++n)
{
hashout = updateHash(bytes[n], hashout);
}
return hashout;
}
@ -340,54 +287,35 @@ QString UAVObjectParser::processObjectMetadata(QDomNode& childNode, UpdateMode*
QDomNamedNodeMap elemAttributes = childNode.attributes();
QDomNode elemAttr = elemAttributes.namedItem("updatemode");
if ( elemAttr.isNull() )
{
return QString("Object:telemetrygcs:updatemode attribute is missing");
}
else
{
int index = updateModeStrXML.indexOf( elemAttr.nodeValue() );
if (index >= 0)
{
*mode = (UpdateMode)index;
}
else
{
return QString("Object:telemetrygcs:updatemode attribute value is invalid");
}
}
int index = updateModeStrXML.indexOf( elemAttr.nodeValue() );
if (index<0)
return QString("Object:telemetrygcs:updatemode attribute value is invalid");
*mode = (UpdateMode)index;
// Get period attribute
elemAttr = elemAttributes.namedItem("period");
if ( elemAttr.isNull() )
{
return QString("Object:telemetrygcs:period attribute is missing");
}
else
{
*period = elemAttr.nodeValue().toInt();
}
*period = elemAttr.nodeValue().toInt();
// Get acked attribute (only if acked parameter is not null, not applicable for logging metadata)
if ( acked != NULL)
{
if ( acked != NULL) {
elemAttr = elemAttributes.namedItem("acked");
if ( elemAttr.isNull())
{
return QString("Object:telemetrygcs:acked attribute is missing");
}
if ( elemAttr.nodeValue().compare(QString("true")) == 0 )
*acked = true;
else if ( elemAttr.nodeValue().compare(QString("false")) == 0 )
*acked = false;
else
{
if ( elemAttr.nodeValue().compare(QString("true")) == 0 )
{
*acked = true;
}
else if ( elemAttr.nodeValue().compare(QString("false")) == 0 )
{
*acked = false;
}
else
{
return QString("Object:telemetrygcs:acked attribute value is invalid");
}
}
return QString("Object:telemetrygcs:acked attribute value is invalid");
}
// Done
return QString();
@ -402,39 +330,25 @@ QString UAVObjectParser::processObjectAccess(QDomNode& childNode, ObjectInfo* in
QDomNamedNodeMap elemAttributes = childNode.attributes();
QDomNode elemAttr = elemAttributes.namedItem("gcs");
if ( elemAttr.isNull() )
{
return QString("Object:access:gcs attribute is missing");
}
int index = accessModeStrXML.indexOf( elemAttr.nodeValue() );
if (index >= 0)
info->gcsAccess = (AccessMode)index;
else
{
int index = accessModeStrXML.indexOf( elemAttr.nodeValue() );
if (index >= 0)
{
info->gcsAccess = (AccessMode)index;
}
else
{
return QString("Object:access:gcs attribute value is invalid");
}
}
return QString("Object:access:gcs attribute value is invalid");
// Get flight attribute
elemAttr = elemAttributes.namedItem("flight");
if ( elemAttr.isNull() )
{
return QString("Object:access:flight attribute is missing");
}
index = accessModeStrXML.indexOf( elemAttr.nodeValue() );
if (index >= 0)
info->flightAccess = (AccessMode)index;
else
{
int index = accessModeStrXML.indexOf( elemAttr.nodeValue() );
if (index >= 0)
{
info->flightAccess = (AccessMode)index;
}
else
{
return QString("Object:access:flight attribute value is invalid");
}
}
return QString("Object:access:flight attribute value is invalid");
// Done
return QString();
}
@ -450,123 +364,92 @@ QString UAVObjectParser::processObjectFields(QDomNode& childNode, ObjectInfo* in
QDomNamedNodeMap elemAttributes = childNode.attributes();
QDomNode elemAttr = elemAttributes.namedItem("name");
if ( elemAttr.isNull() )
{
return QString("Object:field:name attribute is missing");
}
else
{
field->name = elemAttr.nodeValue();
}
field->name = elemAttr.nodeValue();
// Get units attribute
elemAttr = elemAttributes.namedItem("units");
if ( elemAttr.isNull() )
{
return QString("Object:field:units attribute is missing");
}
else
{
field->units = elemAttr.nodeValue();
}
field->units = elemAttr.nodeValue();
// Get type attribute
elemAttr = elemAttributes.namedItem("type");
if ( elemAttr.isNull() )
{
return QString("Object:field:type attribute is missing");
}
else
{
int index = fieldTypeStrXML.indexOf(elemAttr.nodeValue());
if (index >= 0)
{
field->type = (FieldType)index;
field->numBytes = fieldTypeNumBytes[index];
}
else
{
return QString("Object:field:type attribute value is invalid");
}
}
int index = fieldTypeStrXML.indexOf(elemAttr.nodeValue());
if (index >= 0) {
field->type = (FieldType)index;
field->numBytes = fieldTypeNumBytes[index];
}
else {
return QString("Object:field:type attribute value is invalid");
}
// Get numelements or elementnames attribute
elemAttr = elemAttributes.namedItem("elementnames");
if ( !elemAttr.isNull() )
{
if ( !elemAttr.isNull() ) {
// Get element names
QStringList names = elemAttr.nodeValue().split(",", QString::SkipEmptyParts);
for (int n = 0; n < names.length(); ++n)
{
names[n] = names[n].trimmed();
}
field->elementNames = names;
field->numElements = names.length();
field->defaultElementNames = false;
}
else
{
else {
elemAttr = elemAttributes.namedItem("elements");
if ( elemAttr.isNull() )
{
if ( elemAttr.isNull() ) {
return QString("Object:field:elements and Object:field:elementnames attribute is missing");
}
else
{
else {
field->numElements = elemAttr.nodeValue().toInt();
for (int n = 0; n < field->numElements; ++n)
{
field->elementNames.append(QString("%1").arg(n));
}
field->defaultElementNames = true;
}
}
// Get options attribute (only if an enum type)
if (field->type == FIELDTYPE_ENUM)
{
if (field->type == FIELDTYPE_ENUM) {
// Get options attribute
elemAttr = elemAttributes.namedItem("options");
if ( elemAttr.isNull() )
{
return QString("Object:field:options attribute is missing");
}
else
{
QStringList options = elemAttr.nodeValue().split(",", QString::SkipEmptyParts);
for (int n = 0; n < options.length(); ++n)
{
options[n] = options[n].trimmed();
}
field->options = options;
}
QStringList options = elemAttr.nodeValue().split(",", QString::SkipEmptyParts);
for (int n = 0; n < options.length(); ++n)
options[n] = options[n].trimmed();
field->options = options;
}
// Get the default value attribute (required for settings objects, optional for the rest)
elemAttr = elemAttributes.namedItem("defaultvalue");
if ( elemAttr.isNull() )
{
if ( elemAttr.isNull() ) {
if ( info->isSettings )
{
return QString("Object:field:defaultvalue attribute is missing (required for settings objects)");
}else
{
field->defaultValues = QStringList();
}
field->defaultValues = QStringList();
}
else
{
else {
QStringList defaults = elemAttr.nodeValue().split(",", QString::SkipEmptyParts);
for (int n = 0; n < defaults.length(); ++n)
{
defaults[n] = defaults[n].trimmed();
}
if(defaults.length() != field->numElements)
{
if(defaults.length() != field->numElements) {
if(defaults.length() != 1)
{
return QString("Object:field:incorrect number of default values");
}
/*support legacy single default for multiple elements
We sould really issue a warning*/
for(int ct=1; ct< field->numElements; ct++)
{
defaults.append(defaults[0]);
}
}
field->defaultValues = defaults;
}
@ -585,60 +468,40 @@ QString UAVObjectParser::processObjectAttributes(QDomNode& node, ObjectInfo* inf
QDomNamedNodeMap attributes = node.attributes();
QDomNode attr = attributes.namedItem("name");
if ( attr.isNull() )
{
return QString("Object:name attribute is missing");
}
else
{
info->name = attr.nodeValue();
}
info->name = attr.nodeValue();
info->namelc = attr.nodeValue().toLower();
// Get singleinstance attribute
attr = attributes.namedItem("singleinstance");
if ( attr.isNull() )
{
return QString("Object:singleinstance attribute is missing");
}
if ( attr.nodeValue().compare(QString("true")) == 0 )
info->isSingleInst = true;
else if ( attr.nodeValue().compare(QString("false")) == 0 )
info->isSingleInst = false;
else
{
if ( attr.nodeValue().compare(QString("true")) == 0 )
{
info->isSingleInst = true;
}
else if ( attr.nodeValue().compare(QString("false")) == 0 )
{
info->isSingleInst = false;
}
else
{
return QString("Object:singleinstance attribute value is invalid");
}
}
return QString("Object:singleinstance attribute value is invalid");
// Get settings attribute
attr = attributes.namedItem("settings");
if ( attr.isNull() )
{
return QString("Object:settings attribute is missing");
}
else
{
if ( attr.nodeValue().compare(QString("true")) == 0 )
{
if ( attr.nodeValue().compare(QString("true")) == 0 )
info->isSettings = true;
}
else if ( attr.nodeValue().compare(QString("false")) == 0 )
{
info->isSettings = false;
}
else
{
return QString("Object:settings attribute value is invalid");
}
}
else if ( attr.nodeValue().compare(QString("false")) == 0 )
info->isSettings = false;
else
return QString("Object:settings attribute value is invalid");
// Settings objects can only have a single instance
if ( info->isSettings && !info->isSingleInst )
{
return QString("Object: Settings objects can not have multiple instances");
}
// Done
return QString();
}
@ -651,579 +514,3 @@ QString UAVObjectParser::processObjectDescription(QDomNode& childNode, QString *
description->append(childNode.firstChild().nodeValue());
return QString();
}
/**
* Replace all the common tags from the template file with actual object
* information.
*/
void UAVObjectParser::replaceCommonTags(QString& out, ObjectInfo* info)
{
QString value;
// Replace $(XMLFILE) tag
out.replace(QString("$(XMLFILE)"), filename);
// Replace $(NAME) tag
out.replace(QString("$(NAME)"), info->name);
// Replace $(NAMELC) tag
out.replace(QString("$(NAMELC)"), info->name.toLower());
// Replace $(DESCRIPTION) tag
out.replace(QString("$(DESCRIPTION)"), info->description);
// Replace $(NAMEUC) tag
out.replace(QString("$(NAMEUC)"), info->name.toUpper());
// Replace $(OBJID) tag
out.replace(QString("$(OBJID)"), QString().setNum(info->id));
// Replace $(ISSINGLEINST) tag
value = boolToString( info->isSingleInst );
out.replace(QString("$(ISSINGLEINST)"), value);
// Replace $(ISSETTINGS) tag
value = boolToString( info->isSettings );
out.replace(QString("$(ISSETTINGS)"), value);
// Replace $(GCSACCESS) tag
value = accessModeStr[info->gcsAccess];
out.replace(QString("$(GCSACCESS)"), value);
// Replace $(FLIGHTACCESS) tag
value = accessModeStr[info->flightAccess];
out.replace(QString("$(FLIGHTACCESS)"), value);
// Replace $(FLIGHTTELEM_ACKED) tag
value = boolToString( info->flightTelemetryAcked );
out.replace(QString("$(FLIGHTTELEM_ACKED)"), value);
// Replace $(FLIGHTTELEM_UPDATEMODE) tag
value = updateModeStr[info->flightTelemetryUpdateMode];
out.replace(QString("$(FLIGHTTELEM_UPDATEMODE)"), value);
// Replace $(FLIGHTTELEM_UPDATEPERIOD) tag
out.replace(QString("$(FLIGHTTELEM_UPDATEPERIOD)"), QString().setNum(info->flightTelemetryUpdatePeriod));
// Replace $(GCSTELEM_ACKED) tag
value = boolToString( info->gcsTelemetryAcked );
out.replace(QString("$(GCSTELEM_ACKED)"), value);
// Replace $(GCSTELEM_UPDATEMODE) tag
value = updateModeStr[info->gcsTelemetryUpdateMode];
out.replace(QString("$(GCSTELEM_UPDATEMODE)"), value);
// Replace $(GCSTELEM_UPDATEPERIOD) tag
out.replace(QString("$(GCSTELEM_UPDATEPERIOD)"), QString().setNum(info->gcsTelemetryUpdatePeriod));
// Replace $(LOGGING_UPDATEMODE) tag
value = updateModeStr[info->loggingUpdateMode];
out.replace(QString("$(LOGGING_UPDATEMODE)"), value);
// Replace $(LOGGING_UPDATEPERIOD) tag
out.replace(QString("$(LOGGING_UPDATEPERIOD)"), QString().setNum(info->loggingUpdatePeriod));
}
/**
* Convert a boolean to string
*/
QString UAVObjectParser::boolToString(bool value)
{
if ( value )
{
return QString("1");
}
else
{
return QString("0");
}
}
/**
* Generate the flight object files
*/
bool UAVObjectParser::generateFlightObject(int objIndex, const QString& templateInclude, const QString& templateCode,
QString& outInclude, QString& outCode)
{
// Get object
ObjectInfo* info = objInfo[objIndex];
if (info == NULL) return false;
// Prepare output strings
outInclude = templateInclude;
outCode = templateCode;
// Replace common tags
replaceCommonTags(outInclude, info);
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString type;
QString fields;
for (int n = 0; n < info->fields.length(); ++n)
{
// Determine type
type = fieldTypeStrC[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
{
fields.append( QString(" %1 %2[%3];\n").arg(type)
.arg(info->fields[n]->name).arg(info->fields[n]->numElements) );
}
else
{
fields.append( QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name) );
}
}
outInclude.replace(QString("$(DATAFIELDS)"), fields);
// Replace the $(DATAFIELDINFO) tag
QString enums;
for (int n = 0; n < info->fields.length(); ++n)
{
enums.append(QString("// Field %1 information\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
enums.append(QString("/* Enumeration options for field %1 */\n").arg(info->fields[n]->name));
enums.append("typedef enum { ");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m)
{
QString s = (m == (options.length()-1)) ? "%1_%2_%3=%4" : "%1_%2_%3=%4, ";
enums.append( s
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( options[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1%2Options;\n")
.arg( info->name )
.arg( info->fields[n]->name ) );
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames)
{
enums.append(QString("/* Array element names for field %1 */\n").arg(info->fields[n]->name));
enums.append("typedef enum { ");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
{
QString s = (m != (elemNames.length()-1)) ? "%1_%2_%3=%4, " : "%1_%2_%3=%4";
enums.append( s
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( elemNames[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1%2Elem;\n")
.arg( info->name )
.arg( info->fields[n]->name ) );
}
// Generate array information
if (info->fields[n]->numElements > 1)
{
enums.append(QString("/* Number of elements for field %1 */\n").arg(info->fields[n]->name));
enums.append( QString("#define %1_%2_NUMELEM %3\n")
.arg( info->name.toUpper() )
.arg( info->fields[n]->name.toUpper() )
.arg( info->fields[n]->numElements ) );
}
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
// Replace the $(INITFIELDS) tag
QString initfields;
for (int n = 0; n < info->fields.length(); ++n)
{
if (!info->fields[n]->defaultValues.isEmpty() )
{
// For non-array fields
if ( info->fields[n]->numElements == 1)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString("\tdata.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString("\tdata.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toFloat() ) );
}
else
{
initfields.append( QString("\tdata.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toInt() ) );
}
}
else
{
// Initialize all fields in the array
for (int idx = 0; idx < info->fields[n]->numElements; ++idx)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString("\tdata.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString("\tdata.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toFloat() ) );
}
else
{
initfields.append( QString("\tdata.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toInt() ) );
}
}
}
}
}
outCode.replace(QString("$(INITFIELDS)"), initfields);
// Done
return true;
}
/**
* Generate the GCS object files
*/
bool UAVObjectParser::generateGCSObject(int objIndex, const QString& templateInclude, const QString& templateCode,
QString& outInclude, QString& outCode)
{
// Get object
ObjectInfo* info = objInfo[objIndex];
if (info == NULL) return false;
// Prepare output strings
outInclude = templateInclude;
outCode = templateCode;
// Replace common tags
replaceCommonTags(outInclude, info);
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString type;
QString fields;
for (int n = 0; n < info->fields.length(); ++n)
{
// Determine type
type = fieldTypeStrCPP[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
{
fields.append( QString(" %1 %2[%3];\n").arg(type).arg(info->fields[n]->name)
.arg(info->fields[n]->numElements) );
}
else
{
fields.append( QString(" %1 %2;\n").arg(type).arg(info->fields[n]->name) );
}
}
outInclude.replace(QString("$(DATAFIELDS)"), fields);
// Replace the $(FIELDSINIT) tag
QString finit;
for (int n = 0; n < info->fields.length(); ++n)
{
// Setup element names
QString varElemName = info->fields[n]->name + "ElemNames";
finit.append( QString(" QStringList %1;\n").arg(varElemName) );
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
{
finit.append( QString(" %1.append(\"%2\");\n")
.arg(varElemName)
.arg(elemNames[m]) );
}
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
QString varOptionName = info->fields[n]->name + "EnumOptions";
finit.append( QString(" QStringList %1;\n").arg(varOptionName) );
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m)
{
finit.append( QString(" %1.append(\"%2\");\n")
.arg(varOptionName)
.arg(options[m]) );
}
finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::ENUM, %3, %4) );\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->units)
.arg(varElemName)
.arg(varOptionName) );
}
// For all other types
else
{
finit.append( QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::%3, %4, QStringList()) );\n")
.arg(info->fields[n]->name)
.arg(info->fields[n]->units)
.arg(fieldTypeStrCPPClass[info->fields[n]->type])
.arg(varElemName) );
}
}
outCode.replace(QString("$(FIELDSINIT)"), finit);
// Replace the $(DATAFIELDINFO) tag
QString name;
QString enums;
for (int n = 0; n < info->fields.length(); ++n)
{
enums.append(QString(" // Field %1 information\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
enums.append(QString(" /* Enumeration options for field %1 */\n").arg(info->fields[n]->name));
enums.append(" typedef enum { ");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m)
{
QString s = (m != (options.length()-1)) ? "%1_%2=%3, " : "%1_%2=%3";
enums.append( s
.arg( info->fields[n]->name.toUpper() )
.arg( options[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1Options;\n")
.arg( info->fields[n]->name ) );
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames)
{
enums.append(QString(" /* Array element names for field %1 */\n").arg(info->fields[n]->name));
enums.append(" typedef enum { ");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m)
{
QString s = (m != (elemNames.length()-1)) ? "%1_%2=%3, " : "%1_%2=%3";
enums.append( s
.arg( info->fields[n]->name.toUpper() )
.arg( elemNames[m].toUpper() )
.arg(m) );
}
enums.append( QString(" } %1Elem;\n")
.arg( info->fields[n]->name ) );
}
// Generate array information
if (info->fields[n]->numElements > 1)
{
enums.append(QString(" /* Number of elements for field %1 */\n").arg(info->fields[n]->name));
enums.append( QString(" static const quint32 %1_NUMELEM = %2;\n")
.arg( info->fields[n]->name.toUpper() )
.arg( info->fields[n]->numElements ) );
}
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
// Replace the $(INITFIELDS) tag
QString initfields;
for (int n = 0; n < info->fields.length(); ++n)
{
if (!info->fields[n]->defaultValues.isEmpty() )
{
// For non-array fields
if ( info->fields[n]->numElements == 1)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[0] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toFloat() ) );
}
else
{
initfields.append( QString(" data.%1 = %2;\n")
.arg( info->fields[n]->name )
.arg( info->fields[n]->defaultValues[0].toInt() ) );
}
}
else
{
// Initialize all fields in the array
for (int idx = 0; idx < info->fields[n]->numElements; ++idx)
{
if ( info->fields[n]->type == FIELDTYPE_ENUM )
{
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->options.indexOf( info->fields[n]->defaultValues[idx] ) ) );
}
else if ( info->fields[n]->type == FIELDTYPE_FLOAT32 )
{
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toFloat() ) );
}
else
{
initfields.append( QString(" data.%1[%2] = %3;\n")
.arg( info->fields[n]->name )
.arg( idx )
.arg( info->fields[n]->defaultValues[idx].toInt() ) );
}
}
}
}
}
outCode.replace(QString("$(INITFIELDS)"), initfields);
// Done
return true;
}
/**
* Generate the Python object files
*/
bool UAVObjectParser::generatePythonObject(int objIndex, const QString& templateCode, QString& outCode)
{
// Get object
ObjectInfo* info = objInfo[objIndex];
if (info == NULL) return false;
// Prepare output strings
outCode = templateCode;
// Replace common tags
replaceCommonTags(outCode, info);
// Replace the $(DATAFIELDS) tag
QString fields;
fields.append(QString("[ \\\n"));
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"));
if (info->fields[n]->type == FIELDTYPE_ENUM)
{
// 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] ) );
}
}
fields.append(QString("\t\t}\n"));
fields.append(QString("\t),\n"));
}
fields.append(QString("]\n"));
outCode.replace(QString("$(DATAFIELDS)"), fields);
// Done
return true;
}
/**
* Generate Matlab OPLogConvert.m file
*/
bool UAVObjectParser::generateMatlabFile(int objIndex, QString& matlabAllocationCode, QString& matlabSwithCode, QString& matlabSaveObjectsCode, QString& matlabFunctionsCode){
// Get object
ObjectInfo* info = objInfo[objIndex];
if (info == NULL) return false;
QString objectName(info->name);
// QString objectTableName(objectName + "Objects");
QString objectTableName(objectName);
QString tableIdxName(objectName.toLower() + "Idx");
QString functionName("Read" + info->name + "Object");
QString functionCall(functionName + "(fid, timestamp)");
QString objectID(QString().setNum(info->id));
QString isSingleInst = boolToString( info->isSingleInst );
// Generate allocation code (will replace the $(ALLOCATIONCODE) tag)
matlabAllocationCode.append("\n " + tableIdxName + " = 1;\n");
matlabAllocationCode.append(" " + objectTableName + ".timestamp = 0;\n");
QString type;
QString allocfields;
for (int n = 0; n < info->fields.length(); ++n)
{
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
{
allocfields.append(" " + objectTableName + "(1)." + info->fields[n]->name + " = zeros(1," + QString::number(info->fields[n]->numElements, 10) + ");\n");
}
else
{
allocfields.append(" " + objectTableName + "(1)." + info->fields[n]->name + " = 0;\n");
}
}
matlabAllocationCode.append(allocfields);
// Generate 'swith:' code (will replace the $(SWITCHCODE) tag)
matlabSwithCode.append(" case " + objectID + "\n");
matlabSwithCode.append(" " + objectTableName + "(" + tableIdxName +") = " + functionCall + ";\n");
matlabSwithCode.append(" " + tableIdxName + " = " + tableIdxName +" + 1;\n");
// Generate objects saving code code (will replace the $(SAVEOBJECTSCODE) tag)
matlabSaveObjectsCode.append(",'"+objectTableName+"'");
// Generate functions code (will replace the $(FUNCTIONSCODE) tag)
matlabFunctionsCode.append("function [" + objectName + "] = " + functionCall + "\n");
matlabFunctionsCode.append(" if " + isSingleInst + "\n");
matlabFunctionsCode.append(" headerSize = 8;\n");
matlabFunctionsCode.append(" else\n");
matlabFunctionsCode.append(" " + objectName + ".instanceID = fread(fid, 1, 'uint16');\n");
matlabFunctionsCode.append(" headerSize = 10;\n");
matlabFunctionsCode.append(" end\n\n");
matlabFunctionsCode.append(" " + objectName + ".timestamp = timestamp;\n");
// Genrate functions code, actual fields of the object
QString funcfields;
for (int n = 0; n < info->fields.length(); ++n)
{
// Determine type
type = fieldTypeStrMatlab[info->fields[n]->type];
// Append field
if ( info->fields[n]->numElements > 1 )
{
funcfields.append(" " + objectName + "." + info->fields[n]->name + " = double(fread(fid, " + QString::number(info->fields[n]->numElements, 10) + ", '" + type + "'));\n");
}
else
{
funcfields.append(" " + objectName + "." + info->fields[n]->name + " = double(fread(fid, 1, '" + type + "'));\n");
}
}
matlabFunctionsCode.append(funcfields);
matlabFunctionsCode.append(" % read CRC\n");
matlabFunctionsCode.append(" fread(fid, 1, 'uint8');\n");
matlabFunctionsCode.append("end\n\n");
// Done
return true;
}

View File

@ -33,67 +33,73 @@
#include <QDomDocument>
#include <QDomElement>
#include <QDomNode>
#include <QByteArray>
// Types
typedef enum {
FIELDTYPE_INT8 = 0,
FIELDTYPE_INT16,
FIELDTYPE_INT32,
FIELDTYPE_UINT8,
FIELDTYPE_UINT16,
FIELDTYPE_UINT32,
FIELDTYPE_FLOAT32,
FIELDTYPE_ENUM
} FieldType;
typedef struct {
QString name;
QString units;
FieldType type;
int numElements;
int numBytes;
QStringList elementNames;
QStringList options; // for enums only
bool defaultElementNames;
QStringList defaultValues;
} FieldInfo;
/**
* 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;
typedef enum {
ACCESS_READWRITE = 0,
ACCESS_READONLY = 1
} AccessMode;
typedef struct {
QString name;
QString namelc; /** name in lowercase */
QString filename;
quint32 id;
bool isSingleInst;
bool isSettings;
AccessMode gcsAccess;
AccessMode flightAccess;
bool flightTelemetryAcked;
UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */
int flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */
bool gcsTelemetryAcked;
UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */
int gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
UpdateMode loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */
int loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
QList<FieldInfo*> fields; /** The data fields for the object **/
QString description; /** Description used for Doxygen **/
} ObjectInfo;
class UAVObjectParser
{
public:
// Types
typedef enum {
FIELDTYPE_INT8 = 0,
FIELDTYPE_INT16,
FIELDTYPE_INT32,
FIELDTYPE_UINT8,
FIELDTYPE_UINT16,
FIELDTYPE_UINT32,
FIELDTYPE_FLOAT32,
FIELDTYPE_ENUM
} FieldType;
/**
* 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;
typedef enum {
ACCESS_READWRITE = 0,
ACCESS_READONLY = 1
} AccessMode;
typedef struct {
QString name;
QString units;
FieldType type;
int numElements;
int numBytes;
QStringList elementNames;
QStringList options; // for enums only
bool defaultElementNames;
QStringList defaultValues;
} FieldInfo;
typedef struct {
QString name;
quint32 id;
bool isSingleInst;
bool isSettings;
AccessMode gcsAccess;
AccessMode flightAccess;
bool flightTelemetryAcked;
UpdateMode flightTelemetryUpdateMode; /** Update mode used by the autopilot (UpdateMode) */
int flightTelemetryUpdatePeriod; /** Update period used by the autopilot (only if telemetry mode is PERIODIC) */
bool gcsTelemetryAcked;
UpdateMode gcsTelemetryUpdateMode; /** Update mode used by the GCS (UpdateMode) */
int gcsTelemetryUpdatePeriod; /** Update period used by the GCS (only if telemetry mode is PERIODIC) */
UpdateMode loggingUpdateMode; /** Update mode used by the logging module (UpdateMode) */
int loggingUpdatePeriod; /** Update period used by the logging module (only if logging mode is PERIODIC) */
QList<FieldInfo*> fields; /** The data fields for the object **/
QString description; /** Description used for Doxygen **/
} ObjectInfo;
// Functions
UAVObjectParser();
@ -102,24 +108,12 @@ public:
QList<ObjectInfo*> getObjectInfo();
QString getObjectName(int objIndex);
quint32 getObjectID(int objIndex);
int getNumBytes(int objIndex);
bool generateFlightObject(int objIndex, const QString& templateInclude, const QString& templateCode,
QString& outInclude, QString& outCode);
bool generateGCSObject(int objIndex, const QString& templateInclude, const QString& templateCode,
QString& outInclude, QString& outCode);
bool generatePythonObject(int objIndex, const QString& templateCode, QString& outCode);
bool generateMatlabFile(int objIndex, QString& matlabAllocationCode, QString& matlabSwithCode, QString& matlabSaveObjectsCode, QString& matlabFunctionsCode);
ObjectInfo* getObjectByIndex(int objIndex);
int getNumBytes(int objIndex);
private:
QList<ObjectInfo*> objInfo;
QString filename;
QStringList fieldTypeStrC;
QStringList fieldTypeStrCPP;
QStringList fieldTypeStrPython;
QStringList fieldTypeStrCPPClass;
QStringList fieldTypeStrMatlab;
QStringList fieldTypeStrXML;
QList<int> fieldTypeNumBytes;
QStringList updateModeStr;
@ -135,10 +129,6 @@ private:
void calculateID(ObjectInfo* info);
quint32 updateHash(quint32 value, quint32 hash);
quint32 updateHash(QString& value, quint32 hash);
QString boolToString(bool value);
QString updateModeToString(UpdateMode mode);
void replaceCommonTags(QString& out, ObjectInfo* info);
};
#endif // UAVOBJECTPARSER_H

View File

@ -9,6 +9,17 @@ CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
uavobjectparser.cpp \
uavobjectgenerator.cpp
generators/generator_io.cpp \
generators/java/uavobjectgeneratorjava.cpp \
generators/flight/uavobjectgeneratorflight.cpp \
generators/gcs/uavobjectgeneratorgcs.cpp \
generators/matlab/uavobjectgeneratormatlab.cpp \
generators/python/uavobjectgeneratorpython.cpp \
generators/generator_common.cpp
HEADERS += uavobjectparser.h \
uavobjectgenerator.h
generators/generator_io.h \
generators/java/uavobjectgeneratorjava.h \
generators/gcs/uavobjectgeneratorgcs.h \
generators/matlab/uavobjectgeneratormatlab.h \
generators/python/uavobjectgeneratorpython.h \
generators/generator_common.h