/** ****************************************************************************** * * @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 templatepath, QString outputpath) { // Load template and setup output directory pythonCodePath = QDir(templatepath + QString("flight/modules/FlightPlan/lib")); pythonOutputPath = QDir(outputpath + QString("python")); pythonOutputPath.mkpath(pythonOutputPath.absolutePath()); pythonCodeTemplate = readFile(pythonCodePath.absoluteFilePath("uavobject.pyt.template")); if (pythonCodeTemplate.isEmpty()) { std::cerr << "Problem reading python templates" << endl; return false; } // Process each object for (int objidx = 0; objidx < parser->getNumObjects(); ++objidx) { ObjectInfo *info = parser->getObjectByIndex(objidx); process_object(info); } 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 datafields; for (int n = 0; n < info->fields.length(); ++n) { // Class header datafields.append(QString("# Field %1 definition\n").arg(info->fields[n]->name)); datafields.append(QString("class %1Field(UAVObjectField):\n").arg(info->fields[n]->name)); // Only for enum types if (info->fields[n]->type == FIELDTYPE_ENUM) { datafields.append(QString(" # Enumeration options\n")); // Go through each option QStringList options = info->fields[n]->options; for (int m = 0; m < options.length(); ++m) { QString name = options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""); if (name[0].isDigit()) { name = QString("N%1").arg(name); } datafields.append(QString(" %1 = %2\n").arg(name).arg(m)); } } // Generate element names (only if field has more than one element) if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) { datafields.append(QString(" # Array element names\n")); // Go through the element names QStringList elemNames = info->fields[n]->elementNames; for (int m = 0; m < elemNames.length(); ++m) { QString name = elemNames[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""); if (name[0].isDigit()) { name = QString("N%1").arg(name); } datafields.append(QString(" %1 = %2\n").arg(name).arg(m)); } } // Constructor datafields.append(QString(" def __init__(self):\n")); datafields.append(QString(" UAVObjectField.__init__(self, %1, %2)\n\n").arg(info->fields[n]->type).arg(info->fields[n]->numElements)); } outCode.replace(QString("$(DATAFIELDS)"), datafields); // Replace the $(DATAFIELDINIT) tag QString fields; for (int n = 0; n < info->fields.length(); ++n) { fields.append(QString(" self.%1 = %1Field()\n").arg(info->fields[n]->name)); fields.append(QString(" self.addField(self.%1)\n").arg(info->fields[n]->name)); } outCode.replace(QString("$(DATAFIELDINIT)"), fields); // Write the Python code bool res = writeFileIfDifferent(pythonOutputPath.absolutePath() + "/" + info->namelc + ".py", outCode); if (!res) { cout << "Error: Could not write Python output files" << endl; return false; } return true; }