mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-01-26 11:52:10 +01:00
df573fdad5
git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@406 ebee16cc-31ac-478f-84a7-5cbb03baadba
235 lines
9.2 KiB
C++
235 lines
9.2 KiB
C++
/**
|
|
******************************************************************************
|
|
*
|
|
* @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"));
|
|
objectTemplateFilename = QString("uavobjecttemplate");
|
|
objectsInitTemplateFilename = QString("uavobjectsinittemplate");
|
|
objectsInitFilename = QString("uavobjectsinit");
|
|
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") );
|
|
if ( flightCodeTemplate.isNull() || flightIncludeTemplate.isNull() ||
|
|
gcsCodeTemplate.isNull() || gcsIncludeTemplate.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 flightObjInit;
|
|
QString gcsObjInit;
|
|
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();
|
|
sout << "Generating code for object: " << name << endl;
|
|
// Check for object ID conflicts
|
|
quint32 id = parser->getObjectID(objidx);
|
|
if ( objIDList.contains(id) )
|
|
{
|
|
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;
|
|
}
|
|
// Write the flight code
|
|
// TODO: Only write file if modified
|
|
res = writeFile( flightCodePath.absolutePath() + "/" + namelc + ".c", flightCode );
|
|
if (!res)
|
|
{
|
|
sout << "Error: Could not write output files" << endl;
|
|
return false;
|
|
}
|
|
res = writeFile( flightCodePath.absolutePath() + "/inc/" + namelc + ".h", flightInclude );
|
|
if (!res)
|
|
{
|
|
sout << "Error: Could not write output files" << endl;
|
|
return false;
|
|
}
|
|
// Write the GCS code
|
|
// TODO: Only write file if modified
|
|
res = writeFile( gcsCodePath.absolutePath() + "/" + namelc + ".cpp", gcsCode );
|
|
if (!res)
|
|
{
|
|
sout << "Error: Could not write output files" << endl;
|
|
return false;
|
|
}
|
|
res = writeFile( gcsCodePath.absolutePath() + "/" + namelc + ".h", gcsInclude );
|
|
if (!res)
|
|
{
|
|
sout << "Error: Could not write output files" << endl;
|
|
return false;
|
|
}
|
|
// Update strings for the object initialization
|
|
objInc.append("#include \"" + namelc + ".h\"\n");
|
|
flightObjInit.append(" " + name + "Initialize();\n");
|
|
gcsObjInit.append(" objMngr->registerObject( new " + 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 = writeFile( 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 = writeFile( gcsCodePath.absolutePath() + "/" + objectsInitFilename + ".cpp",
|
|
gcsInitTemplate );
|
|
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." << 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)) 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;
|
|
}
|
|
|