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:
parent
cb2aa1d389
commit
dbc5d26605
25
Makefile
25
Makefile
@ -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 $*
|
||||
|
2
ground/src/libs/juavobjects/README
Normal file
2
ground/src/libs/juavobjects/README
Normal file
@ -0,0 +1,2 @@
|
||||
compile with ant
|
||||
depends on juavtalk and the generated java code from uavobjgenerator in the build dir
|
42
ground/src/libs/juavobjects/build.xml
Normal file
42
ground/src/libs/juavobjects/build.xml
Normal 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>
|
||||
|
@ -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)
|
||||
}
|
73
ground/src/libs/juavobjects/templates/uavobjecttemplate.java
Normal file
73
ground/src/libs/juavobjects/templates/uavobjecttemplate.java
Normal 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)
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
122
ground/src/libs/uavobjgenerator/generators/generator_common.cpp
Normal file
122
ground/src/libs/uavobjgenerator/generators/generator_common.cpp
Normal 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");
|
||||
}
|
||||
|
@ -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
|
79
ground/src/libs/uavobjgenerator/generators/generator_io.cpp
Normal file
79
ground/src/libs/uavobjgenerator/generators/generator_io.cpp
Normal 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);
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user