Browse Source

Removed MAVLinkGen from main QGC codebase-readding it now as standalone app

QGC4.4
lm 14 years ago
parent
commit
f338b5ef70
  1. 48
      mavlinkgen.pro
  2. 7
      qgroundcontrol.pro
  3. 46
      src/comm/MAVLinkSyntaxHighlighter.cc
  4. 19
      src/comm/MAVLinkSyntaxHighlighter.h
  5. 651
      src/comm/MAVLinkXMLParser.cc
  6. 66
      src/comm/MAVLinkXMLParser.h
  7. 94
      src/standalone/mavlinkgen/MAVLinkGen.cc
  8. 58
      src/standalone/mavlinkgen/MAVLinkGen.h
  9. 46
      src/standalone/mavlinkgen/main.cc
  10. 2
      src/ui/JoystickWidget.cc
  11. 15
      src/ui/JoystickWidget.ui
  12. 170
      src/ui/XMLCommProtocolWidget.cc
  13. 75
      src/ui/XMLCommProtocolWidget.h
  14. 144
      src/ui/XMLCommProtocolWidget.ui
  15. 47
      src/ui/mavlink/DomItem.cc
  16. 24
      src/ui/mavlink/DomItem.h
  17. 197
      src/ui/mavlink/DomModel.cc
  18. 34
      src/ui/mavlink/DomModel.h
  19. 28
      standalone/qgroundcontrol-server/qgroundcontrol-server.pro
  20. 93
      standalone/qgroundcontrol-server/src/QGroundControlServer.cc
  21. 58
      standalone/qgroundcontrol-server/src/QGroundControlServer.h
  22. 46
      standalone/qgroundcontrol-server/src/main.cc

48
mavlinkgen.pro

@ -1,48 +0,0 @@ @@ -1,48 +0,0 @@
# }
# Include general settings for MAVGround
# necessary as last include to override any non-acceptable settings
# done by the plugins above
QT += svg xml
TEMPLATE = app
TARGET = mavlinkgen
BASEDIR = .
BUILDDIR = build/mavlinkgen
LANGUAGE = C++
CONFIG += release
CONFIG -= debug
OBJECTS_DIR = $$BUILDDIR/obj
MOC_DIR = $$BUILDDIR/moc
UI_HEADERS_DIR = src/ui/generated
macx:DESTDIR = $$BASEDIR/bin/mac
INCLUDEPATH += . \
src \
src/ui \
src/comm \
include/ui \
src/ui/mavlink \
src/standalone/mavlinkgen
# Input
FORMS += src/ui/XMLCommProtocolWidget.ui
HEADERS += src/standalone/mavlinkgen/MAVLinkGen.h \
src/ui/XMLCommProtocolWidget.h \
src/comm/MAVLinkXMLParser.h \
src/ui/mavlink/DomItem.h \
src/ui/mavlink/DomModel.h \
src/ui/mavlink/QGCMAVLinkTextEdit.h
SOURCES += src/standalone/mavlinkgen/main.cc \
src/standalone/mavlinkgen/MAVLinkGen.cc \
src/ui/XMLCommProtocolWidget.cc \
src/ui/mavlink/DomItem.cc \
src/ui/mavlink/DomModel.cc \
src/comm/MAVLinkXMLParser.cc \
src/ui/mavlink/QGCMAVLinkTextEdit.cc
RESOURCES = mavground.qrc

7
qgroundcontrol.pro

@ -32,8 +32,13 @@ include(lib/nmea/nmea.pri) @@ -32,8 +32,13 @@ include(lib/nmea/nmea.pri)
# of open-source software!
# (We're not reusing any part of the OP GCS, just the map library)
# Include MAVLink generator
include(src/apps/mavlinkgen.pri)
# Try to get it from OP mainline, if this fails fall back to internal copies
exists(../openpilot/ground/openpilotgcs/src/libs) {
exists(../openpilot-xxxxxxx/ground/openpilotgcs/src/libs) {
include(../openpilot/ground/openpilotgcs/src/libs/utils/utils_external.pri)
include(../openpilot/ground/openpilotgcs/src/libs/opmapcontrol/opmapcontrol_external.pri)
DEPENDPATH += \

46
src/comm/MAVLinkSyntaxHighlighter.cc

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "MAVLinkSyntaxHighlighter.h"
MAVLinkSyntaxHighlighter::MAVLinkSyntaxHighlighter(QObject *parent) :
QSyntaxHighlighter(parent)
{
}
void MAVLinkSyntaxHighlighter::highlightBlock(const QString &text)
{
QTextCharFormat myClassFormat;
myClassFormat.setFontWeight(QFont::Bold);
myClassFormat.setForeground(Qt::darkMagenta);
QString pattern = "\"[A-Za-z0-9]+\"";
QRegExp expression(pattern);
int index = text.indexOf(expression);
while (index >= 0) {
int length = expression.matchedLength();
setFormat(index, length, myClassFormat);
index = text.indexOf(expression, index + length);
}
}

19
src/comm/MAVLinkSyntaxHighlighter.h

@ -1,19 +0,0 @@ @@ -1,19 +0,0 @@
#ifndef MAVLINKSYNTAXHIGHLIGHTER_H
#define MAVLINKSYNTAXHIGHLIGHTER_H
#include <QSyntaxHighlighter>
class MAVLinkSyntaxHighlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
explicit MAVLinkSyntaxHighlighter(QObject *parent = 0);
signals:
public slots:
void highlightBlock(const QString &text);
};
#endif // MAVLINKSYNTAXHIGHLIGHTER_H

651
src/comm/MAVLinkXMLParser.cc

@ -1,651 +0,0 @@ @@ -1,651 +0,0 @@
/*=====================================================================
======================================================================*/
/**
* @file
* @brief Implementation of class MAVLinkXMLParser
* @author Lorenz Meier <mail@qgroundcontrol.org>
*/
#include <QFile>
#include <QDir>
#include <QPair>
#include <QList>
#include <QMap>
#include <QDateTime>
#include <QLocale>
#include "MAVLinkXMLParser.h"
#include <QDebug>
MAVLinkXMLParser::MAVLinkXMLParser(QDomDocument* document, QString outputDirectory, QObject* parent) : QObject(parent),
doc(document),
outputDirName(outputDirectory),
fileName("")
{
}
MAVLinkXMLParser::MAVLinkXMLParser(QString document, QString outputDirectory, QObject* parent) : QObject(parent)
{
doc = new QDomDocument();
QFile file(document);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
const QString instanceText(QString::fromUtf8(file.readAll()));
doc->setContent(instanceText);
}
fileName = document;
outputDirName = outputDirectory;
}
MAVLinkXMLParser::~MAVLinkXMLParser()
{
}
/**
* Generate C-code (C-89 compliant) out of the XML protocol specs.
*/
bool MAVLinkXMLParser::generate()
{
// Process result
bool success = true;
// Only generate if output dir is correctly set
if (outputDirName == "") {
emit parseState(tr("<font color=\"red\">ERROR: No output directory given.\nAbort.</font>"));
return false;
}
QString topLevelOutputDirName = outputDirName;
// print out the element names of all elements that are direct children
// of the outermost element.
QDomElement docElem = doc->documentElement();
QDomNode n = docElem;//.firstChild();
QDomNode p = docElem;
// Sanity check variables
QList<int>* usedMessageIDs = new QList<int>();
QMap<QString, QString>* usedMessageNames = new QMap<QString, QString>();
QMap<QString, QString>* usedEnumNames = new QMap<QString, QString>();
QList< QPair<QString, QString> > cFiles;
QString lcmStructDefs = "";
QString pureFileName;
QString pureIncludeFileName;
QFileInfo fInfo(this->fileName);
pureFileName = fInfo.baseName().split(".", QString::SkipEmptyParts).first();
// XML parsed and converted to C code. Now generating the files
outputDirName += QDir::separator() + pureFileName;
QDateTime now = QDateTime::currentDateTime().toUTC();
QLocale loc(QLocale::English);
QString dateFormat = "dddd, MMMM d yyyy, hh:mm UTC";
QString date = loc.toString(now, dateFormat);
QString includeLine = "#include \"%1\"\n";
QString mainHeaderName = pureFileName + ".h";
QString messagesDirName = ".";//"generated";
QDir dir(outputDirName + "/" + messagesDirName);
int mavlinkVersion = 0;
// we need to gather the message lengths across multiple includes,
// which we can do via detecting recursion
static unsigned message_lengths[256];
static int highest_message_id;
static int recursion_level;
if (recursion_level == 0) {
highest_message_id = 0;
memset(message_lengths, 0, sizeof(message_lengths));
}
// Start main header
QString mainHeader = QString("/** @file\n *\t@brief MAVLink comm protocol.\n *\t@see http://pixhawk.ethz.ch/software/mavlink\n *\t Generated on %1\n */\n#ifndef " + pureFileName.toUpper() + "_H\n#define " + pureFileName.toUpper() + "_H\n\n").arg(date); // The main header includes all messages
// Mark all code as C code
mainHeader += "#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
mainHeader += "\n#include \"../protocol.h\"\n";
mainHeader += "\n#define MAVLINK_ENABLED_" + pureFileName.toUpper() + "\n\n";
QString enums;
// Run through root children
while(!n.isNull()) {
// Each child is a message
QDomElement e = n.toElement(); // try to convert the node to an element.
if(!e.isNull()) {
if (e.tagName() == "mavlink") {
p = n;
n = n.firstChild();
while (!n.isNull()) {
e = n.toElement();
if (!e.isNull()) {
// Handle all include tags
if (e.tagName() == "include") {
QString incFileName = e.text();
// Load file
//QDomDocument includeDoc = QDomDocument();
// Prepend file path if it is a relative path and
// make it relative to opened file
QFileInfo fInfo(incFileName);
QString incFilePath;
if (fInfo.isRelative()) {
QFileInfo rInfo(this->fileName);
incFilePath = rInfo.absoluteDir().canonicalPath() + "/" + incFileName;
pureIncludeFileName = fInfo.baseName().split(".", QString::SkipEmptyParts).first();
}
QFile file(incFilePath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
emit parseState(QString("<font color=\"green\">Included messages from file: %1</font>").arg(incFileName));
// NEW MODE: CREATE INDIVIDUAL FOLDERS
// Create new output directory, parse included XML and generate C-code
MAVLinkXMLParser includeParser(incFilePath, topLevelOutputDirName, this);
connect(&includeParser, SIGNAL(parseState(QString)), this, SIGNAL(parseState(QString)));
// Generate and write
recursion_level++;
// Abort if inclusion fails
if (!includeParser.generate()) return false;
recursion_level--;
mainHeader += "\n#include \"../" + pureIncludeFileName + "/" + pureIncludeFileName + ".h\"\n";
// OLD MODE: MERGE BOTH FILES
// const QString instanceText(QString::fromUtf8(file.readAll()));
// includeDoc.setContent(instanceText);
// // Get all messages
// QDomNode in = includeDoc.documentElement().firstChild();
// QDomElement ie = in.toElement();
// if (!ie.isNull())
// {
// if (ie.tagName() == "messages" || ie.tagName() == "include")
// {
// QDomNode ref = n.parentNode().insertAfter(in, n);
// if (ref.isNull())
// {
// emit parseState(QString("<font color=\"red\">ERROR: Inclusion failed: XML syntax error in file %1. Wrong/misspelled XML?\nAbort.</font>").arg(fileName));
// return false;
// }
// }
// }
emit parseState(QString("<font color=\"green\">End of inclusion from file: %1</font>").arg(incFileName));
} else {
// Include file could not be opened
emit parseState(QString("<font color=\"red\">ERROR: Failed including file: %1, file is not readable. Wrong/misspelled filename?\nAbort.</font>").arg(fileName));
return false;
}
}
// Handle all enum tags
else if (e.tagName() == "version") {
//QString fieldType = e.attribute("type", "");
//QString fieldName = e.attribute("name", "");
QString fieldText = e.text();
// Check if version has been previously set
if (mavlinkVersion != 0) {
emit parseState(QString("<font color=\"red\">ERROR: Protocol version tag set twice, please use it only once. First version was %1, second version is %2.\nAbort.</font>").arg(mavlinkVersion).arg(fieldText));
return false;
}
bool ok;
int version = fieldText.toInt(&ok);
if (ok && (version > 0) && (version < 256)) {
// Set MAVLink version
mavlinkVersion = version;
} else {
emit parseState(QString("<font color=\"red\">ERROR: Reading version string failed: %1, string is not an integer number between 1 and 255.\nAbort.</font>").arg(fieldText));
return false;
}
}
// Handle all enum tags
else if (e.tagName() == "enums") {
// One down into the enums list
p = n;
n = n.firstChild();
while (!n.isNull()) {
e = n.toElement();
QString currEnum;
QString currEnumEnd;
// Comment
QString comment;
if(!e.isNull() && e.tagName() == "enum") {
// Get enum name
QString enumName = e.attribute("name", "").toLower();
if (enumName.size() == 0) {
emit parseState(tr("<font color=\"red\">ERROR: Missing required name=\"\" attribute for tag %2 near line %1\nAbort.</font>").arg(QString::number(e.lineNumber()), e.tagName()));
return false;
} else {
// Sanity check: Accept only enum names not used previously
if (usedEnumNames->contains(enumName)) {
emit parseState(tr("<font color=\"red\">ERROR: Enum name %1 used twice, second occurence near line %2 of file %3\nAbort.</font>").arg(enumName, QString::number(e.lineNumber()), fileName));
return false;
} else {
usedEnumNames->insert(enumName, QString::number(e.lineNumber()));
}
// Everything sane, starting with enum content
currEnum = "enum " + enumName.toUpper() + "\n{\n";
currEnumEnd = QString("\t%1_ENUM_END\n};\n\n").arg(enumName.toUpper());
int nextEnumValue = 0;
// Get the enum fields
QDomNode f = e.firstChild();
while (!f.isNull()) {
QDomElement e2 = f.toElement();
if (!e2.isNull() && e2.tagName() == "entry") {
QString fieldValue = e2.attribute("value", "");
// If value was given, use it, if not, use the enum iterator
// value. The iterator value gets reset by manual values
QString fieldName = e2.attribute("name", "");
if (fieldValue.length() == 0) {
fieldValue = QString::number(nextEnumValue);
nextEnumValue++;
} else {
bool ok;
nextEnumValue = fieldValue.toInt(&ok) + 1;
if (!ok) {
emit parseState(tr("<font color=\"red\">ERROR: Enum entry %1 has not a valid number (%2) in the value field.\nAbort.</font>").arg(fieldName, fieldValue));
return false;
}
}
// Add comment of field if there is one
QString fieldComment;
if (e2.text().length() > 0)
{
QString sep(" | ");
QDomNode pp = e2.firstChild();
while (!pp.isNull()) {
QDomElement pp2 = pp.toElement();
if (pp2.isText() || pp2.isCDATASection())
{
fieldComment += pp2.nodeValue() + sep;
}
else if (pp2.isElement())
{
fieldComment += pp2.text() + sep;
pp = pp.nextSibling();
}
}
fieldComment = fieldComment.replace("\n", " ");
fieldComment = " /* " + fieldComment.simplified() + " */";
}
currEnum += "\t" + fieldName.toUpper() + "=" + fieldValue + "," + fieldComment + "\n";
}
else if(!e2.isNull() && e2.tagName() == "description")
{
comment = " " + e2.text().replace("\n", " ") + comment;
}
f = f.nextSibling();
}
}
// Add the last parsed enum
// Remove the last comma, as the last value has none
// ENUM END MARKER IS LAST ENTRY, COMMA REMOVAL NOT NEEDED
//int commaPosition = currEnum.lastIndexOf(",");
//currEnum.remove(commaPosition, 1);
enums += "/** @brief " + comment + " */\n" + currEnum + currEnumEnd;
} // Element is non-zero and element name is <enum>
n = n.nextSibling();
} // While through <enums>
// One up, back into the <mavlink> structure
n = p;
}
// Handle all message tags
else if (e.tagName() == "messages") {
p = n;
n = n.firstChild();
while (!n.isNull()) {
e = n.toElement();
if(!e.isNull()) {
//if (e.isNull()) continue;
// Get message name
QString messageName = e.attribute("name", "").toLower();
if (messageName.size() == 0) {
emit parseState(tr("<font color=\"red\">ERROR: Missing required name=\"\" attribute for tag %2 near line %1\nAbort.</font>").arg(QString::number(e.lineNumber()), e.tagName()));
return false;
} else {
// Get message id
bool ok;
int messageId = e.attribute("id", "-1").toInt(&ok, 10);
emit parseState(tr("Compiling message <strong>%1 \t(#%3)</strong> \tnear line %2").arg(messageName, QString::number(n.lineNumber()), QString::number(messageId)));
// Sanity check: Accept only message IDs not used previously
if (usedMessageIDs->contains(messageId)) {
emit parseState(tr("<font color=\"red\">ERROR: Message ID %1 used twice, second occurence near line %2 of file %3\nAbort.</font>").arg(QString::number(messageId), QString::number(e.lineNumber()), fileName));
return false;
} else {
usedMessageIDs->append(messageId);
}
// Sanity check: Accept only message names not used previously
if (usedMessageNames->contains(messageName)) {
emit parseState(tr("<font color=\"red\">ERROR: Message name %1 used twice, second occurence near line %2 of file %3\nAbort.</font>").arg(messageName, QString::number(e.lineNumber()), fileName));
return false;
} else {
usedMessageNames->insert(messageName, QString::number(e.lineNumber()));
}
QString channelType("mavlink_channel_t");
QString messageType("mavlink_message_t");
// Build up function call
QString commentContainer("/**\n * @brief Pack a %1 message\n * @param system_id ID of this system\n * @param component_id ID of this component (e.g. 200 for IMU)\n * @param msg The MAVLink message to compress the data into\n *\n%2 * @return length of the message in bytes (excluding serial stream start sign)\n */\n");
QString commentPackChanContainer("/**\n * @brief Pack a %1 message\n * @param system_id ID of this system\n * @param component_id ID of this component (e.g. 200 for IMU)\n * @param chan The MAVLink channel this message was sent over\n * @param msg The MAVLink message to compress the data into\n%2 * @return length of the message in bytes (excluding serial stream start sign)\n */\n");
QString commentSendContainer("/**\n * @brief Send a %1 message\n * @param chan MAVLink channel to send the message\n *\n%2 */\n");
QString commentEncodeContainer("/**\n * @brief Encode a %1 struct into a message\n *\n * @param system_id ID of this system\n * @param component_id ID of this component (e.g. 200 for IMU)\n * @param msg The MAVLink message to compress the data into\n * @param %1 C-struct to read the message contents from\n */\n");
QString commentDecodeContainer("/**\n * @brief Decode a %1 message into a struct\n *\n * @param msg The message to decode\n * @param %1 C-struct to decode the message contents into\n */\n");
QString commentEntry(" * @param %1 %2\n");
QString idDefine = QString("#define MAVLINK_MSG_ID_%1 %2").arg(messageName.toUpper(), QString::number(messageId));
QString arrayDefines;
QString cStructName = QString("mavlink_%1_t").arg(messageName);
QString cStruct("typedef struct __%1 \n{\n%2\n} %1;");
QString cStructLines;
QString encode("static inline uint16_t mavlink_msg_%1_encode(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg, const %2* %1)\n{\n\treturn mavlink_msg_%1_pack(%3);\n}\n");
QString decode("static inline void mavlink_msg_%1_decode(const mavlink_message_t* msg, %2* %1)\n{\n%3}\n");
QString pack("static inline uint16_t mavlink_msg_%1_pack(uint8_t system_id, uint8_t component_id, mavlink_message_t* msg%2)\n{\n\tuint16_t i = 0;\n\tmsg->msgid = MAVLINK_MSG_ID_%3;\n\n%4\n\treturn mavlink_finalize_message(msg, system_id, component_id, i);\n}\n\n");
QString packChan("static inline uint16_t mavlink_msg_%1_pack_chan(uint8_t system_id, uint8_t component_id, uint8_t chan, mavlink_message_t* msg%2)\n{\n\tuint16_t i = 0;\n\tmsg->msgid = MAVLINK_MSG_ID_%3;\n\n%4\n\treturn mavlink_finalize_message_chan(msg, system_id, component_id, chan, i);\n}\n\n");
QString compactSend("#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS\n\nstatic inline void mavlink_msg_%3_send(%1 chan%5)\n{\n\t%2 msg;\n\tmavlink_msg_%3_pack_chan(mavlink_system.sysid, mavlink_system.compid, chan, &msg%4);\n\tmavlink_send_uart(chan, &msg);\n}\n\n#endif");
//QString compactStructSend = "#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS\n\nstatic inline void mavlink_msg_%3_struct_send(%1 chan%5)\n{\n\t%2 msg;\n\tmavlink_msg_%3_encode(mavlink_system.sysid, mavlink_system.compid, &msg%4);\n\tmavlink_send_uart(chan, &msg);\n}\n\n#endif";
QString unpacking;
QString prepends;
QString packParameters;
QString packArguments("system_id, component_id, msg");
QString packLines;
QString decodeLines;
QString sendArguments;
QString commentLines;
unsigned message_length = 0;
// Get the message fields
QDomNode f = e.firstChild();
while (!f.isNull()) {
QDomElement e2 = f.toElement();
if (!e2.isNull() && e2.tagName() == "field") {
QString fieldType = e2.attribute("type", "");
QString fieldName = e2.attribute("name", "");
QString fieldText = e2.text();
QString unpackingCode;
QString unpackingComment = QString("/**\n * @brief Get field %1 from %2 message\n *\n * @return %3\n */\n").arg(fieldName, messageName, fieldText);
// Send arguments do not work for the version field
if (!fieldType.contains("uint8_t_mavlink_version")) {
// Send arguments are the same for integral types and arrays
sendArguments += ", " + fieldName;
commentLines += commentEntry.arg(fieldName, fieldText.replace("\n", " "));
}
// MAVLink version field
// this is a special field always containing the version define
if (fieldType.contains("uint8_t_mavlink_version")) {
// Add field to C structure
cStructLines += QString("\t%1 %2; ///< %3\n").arg("uint8_t", fieldName, fieldText);
// Add pack line to message_xx_pack function
packLines += QString("\ti += put_uint8_t_by_index(%1, i, msg->payload); // %2\n").arg(mavlinkVersion).arg(fieldText);
// Add decode function for this type
decodeLines += QString("\t%1->%2 = mavlink_msg_%1_get_%2(msg);\n").arg(messageName, fieldName);
}
// Array handling is different from simple types
else if (fieldType.startsWith("array")) {
int arrayLength = QString(fieldType.split("[").at(1).split("]").first()).toInt();
QString arrayType = fieldType.split("[").first();
packParameters += QString(", const ") + QString("int8_t*") + " " + fieldName;
packArguments += ", " + messageName + "->" + fieldName;
// Add field to C structure
cStructLines += QString("\t%1 %2[%3]; ///< %4\n").arg("int8_t", fieldName, QString::number(arrayLength), fieldText);
// Add pack line to message_xx_pack function
packLines += QString("\ti += put_%1_by_index(%2, %3, i, msg->payload); // %4\n").arg(arrayType, fieldName, QString::number(arrayLength), fieldText);
// Add decode function for this type
decodeLines += QString("\tmavlink_msg_%1_get_%2(msg, %1->%2);\n").arg(messageName, fieldName);
arrayDefines += QString("#define MAVLINK_MSG_%1_FIELD_%2_LEN %3\n").arg(messageName.toUpper(), fieldName.toUpper(), QString::number(arrayLength));
} else if (fieldType.startsWith("string")) {
int arrayLength = QString(fieldType.split("[").at(1).split("]").first()).toInt();
QString arrayType = fieldType.split("[").first();
packParameters += QString(", const ") + QString("char*") + " " + fieldName;
packArguments += ", " + messageName + "->" + fieldName;
// Add field to C structure
cStructLines += QString("\t%1 %2[%3]; ///< %4\n").arg("char", fieldName, QString::number(arrayLength), fieldText);
// Add pack line to message_xx_pack function
packLines += QString("\ti += put_%1_by_index(%2, %3, i, msg->payload); // %4\n").arg(arrayType, fieldName, QString::number(arrayLength), e2.text());
// Add decode function for this type
decodeLines += QString("\tmavlink_msg_%1_get_%2(msg, %1->%2);\n").arg(messageName, fieldName);
arrayDefines += QString("#define MAVLINK_MSG_%1_FIELD_%2_LEN %3\n").arg(messageName.toUpper(), fieldName.toUpper(), QString::number(arrayLength));
}
// Expand array handling to all valid mavlink data types
else if(fieldType.contains('[') && fieldType.contains(']')) {
int arrayLength = QString(fieldType.split("[").at(1).split("]").first()).toInt();
QString arrayType = fieldType.split("[").first();
packParameters += QString(", const ") + arrayType + "* " + fieldName;
packArguments += ", " + messageName + "->" + fieldName;
// Add field to C structure
cStructLines += QString("\t%1 %2[%3]; ///< %4\n").arg(arrayType, fieldName, QString::number(arrayLength), fieldText);
// Add pack line to message_xx_pack function
packLines += QString("\ti += put_array_by_index((const int8_t*)%1, sizeof(%2)*%3, i, msg->payload); // %4\n").arg(fieldName, arrayType, QString::number(arrayLength), fieldText);
// Add decode function for this type
decodeLines += QString("\tmavlink_msg_%1_get_%2(msg, %1->%2);\n").arg(messageName, fieldName);
arrayDefines += QString("#define MAVLINK_MSG_%1_FIELD_%2_LEN %3\n").arg(messageName.toUpper(), fieldName.toUpper(), QString::number(arrayLength));
unpackingCode = QString("\n\tmemcpy(r_data, msg->payload%1, sizeof(%2)*%3);\n\treturn sizeof(%2)*%3;").arg(prepends, arrayType, QString::number(arrayLength));
unpacking += unpackingComment + QString("static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, %3* r_data)\n{\n%4\n}\n\n").arg(messageName, fieldName, arrayType, unpackingCode);
// decodeLines += "";
prepends += QString("+sizeof(%1)*%2").arg(arrayType, QString::number(arrayLength));
} else
// Handle simple types like integers and floats
{
packParameters += ", " + fieldType + " " + fieldName;
packArguments += ", " + messageName + "->" + fieldName;
// Add field to C structure
cStructLines += QString("\t%1 %2; ///< %3\n").arg(fieldType, fieldName, fieldText);
// Add pack line to message_xx_pack function
packLines += QString("\ti += put_%1_by_index(%2, i, msg->payload); // %3\n").arg(fieldType, fieldName, e2.text());
// Add decode function for this type
decodeLines += QString("\t%1->%2 = mavlink_msg_%1_get_%2(msg);\n").arg(messageName, fieldName);
}
// message length calculation
unsigned element_multiplier = 1;
unsigned element_length = 0;
const struct {
const char *prefix;
unsigned length;
} length_map[] = {
{ "array", 1 },
{ "char", 1 },
{ "uint8", 1 },
{ "int8", 1 },
{ "uint16", 2 },
{ "int16", 2 },
{ "uint32", 4 },
{ "int32", 4 },
{ "uint64", 8 },
{ "int64", 8 },
{ "float", 4 },
{ "double", 8 },
};
if (fieldType.contains("[")) {
element_multiplier = fieldType.split("[").at(1).split("]").first().toInt();
}
for (unsigned i=0; i<sizeof(length_map)/sizeof(length_map[0]); i++) {
if (fieldType.startsWith(length_map[i].prefix)) {
element_length = length_map[i].length * element_multiplier;
break;
}
}
if (element_length == 0) {
emit parseState(tr("<font color=\"red\">ERROR: Unable to calculate length for %2 near line %1\nAbort.</font>").arg(QString::number(e.lineNumber()), fieldType));
}
message_length += element_length;
//
// QString unpackingCode;
if (fieldType == "uint8_t_mavlink_version") {
unpackingCode = QString("\treturn (%1)(msg->payload%2)[0];").arg("uint8_t", prepends);
} else if (fieldType == "uint8_t" || fieldType == "int8_t") {
unpackingCode = QString("\treturn (%1)(msg->payload%2)[0];").arg(fieldType, prepends);
} else if (fieldType == "uint16_t" || fieldType == "int16_t") {
unpackingCode = QString("\tgeneric_16bit r;\n\tr.b[1] = (msg->payload%1)[0];\n\tr.b[0] = (msg->payload%1)[1];\n\treturn (%2)r.s;").arg(prepends).arg(fieldType);
} else if (fieldType == "uint32_t" || fieldType == "int32_t") {
unpackingCode = QString("\tgeneric_32bit r;\n\tr.b[3] = (msg->payload%1)[0];\n\tr.b[2] = (msg->payload%1)[1];\n\tr.b[1] = (msg->payload%1)[2];\n\tr.b[0] = (msg->payload%1)[3];\n\treturn (%2)r.i;").arg(prepends).arg(fieldType);
} else if (fieldType == "float") {
unpackingCode = QString("\tgeneric_32bit r;\n\tr.b[3] = (msg->payload%1)[0];\n\tr.b[2] = (msg->payload%1)[1];\n\tr.b[1] = (msg->payload%1)[2];\n\tr.b[0] = (msg->payload%1)[3];\n\treturn (%2)r.f;").arg(prepends).arg(fieldType);
} else if (fieldType == "uint64_t" || fieldType == "int64_t") {
unpackingCode = QString("\tgeneric_64bit r;\n\tr.b[7] = (msg->payload%1)[0];\n\tr.b[6] = (msg->payload%1)[1];\n\tr.b[5] = (msg->payload%1)[2];\n\tr.b[4] = (msg->payload%1)[3];\n\tr.b[3] = (msg->payload%1)[4];\n\tr.b[2] = (msg->payload%1)[5];\n\tr.b[1] = (msg->payload%1)[6];\n\tr.b[0] = (msg->payload%1)[7];\n\treturn (%2)r.ll;").arg(prepends).arg(fieldType);
} else if (fieldType.startsWith("array")) {
// fieldtype formatis string[n] where n is the number of bytes, extract n from field type string
unpackingCode = QString("\n\tmemcpy(r_data, msg->payload%1, %2);\n\treturn %2;").arg(prepends, fieldType.split("[").at(1).split("]").first());
} else if (fieldType.startsWith("string")) {
// fieldtype formatis string[n] where n is the number of bytes, extract n from field type string
unpackingCode = QString("\n\tstrcpy(r_data, msg->payload%1, %2);\n\treturn %2;").arg(prepends, fieldType.split("[").at(1).split("]").first());
}
// Generate the message decoding function
if (fieldType.contains("uint8_t_mavlink_version")) {
unpacking += unpackingComment + QString("static inline %1 mavlink_msg_%2_get_%3(const mavlink_message_t* msg)\n{\n%4\n}\n\n").arg("uint8_t", messageName, fieldName, unpackingCode);
decodeLines += "";
prepends += "+sizeof(uint8_t)";
}
// Array handling is different from simple types
else if (fieldType.startsWith("array")) {
unpacking += unpackingComment + QString("static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, int8_t* r_data)\n{\n%4\n}\n\n").arg(messageName, fieldName, unpackingCode);
decodeLines += "";
QString arrayLength = QString(fieldType.split("[").at(1).split("]").first());
prepends += "+" + arrayLength;
} else if (fieldType.startsWith("string")) {
unpacking += unpackingComment + QString("static inline uint16_t mavlink_msg_%1_get_%2(const mavlink_message_t* msg, char* r_data)\n{\n%4\n}\n\n").arg(messageName, fieldName, unpackingCode);
decodeLines += "";
QString arrayLength = QString(fieldType.split("[").at(1).split("]").first());
prepends += "+" + arrayLength;
} else if(fieldType.contains('[') && fieldType.contains(']')) {
// prevent this case from being caught in the following else
} else {
unpacking += unpackingComment + QString("static inline %1 mavlink_msg_%2_get_%3(const mavlink_message_t* msg)\n{\n%4\n}\n\n").arg(fieldType, messageName, fieldName, unpackingCode);
decodeLines += "";
prepends += "+sizeof(" + e2.attribute("type", "void") + ")";
}
}
f = f.nextSibling();
}
if (messageId > highest_message_id) {
highest_message_id = messageId;
}
message_lengths[messageId] = message_length;
cStruct = cStruct.arg(cStructName, cStructLines);
lcmStructDefs.append("\n").append(cStruct).append("\n");
pack = pack.arg(messageName, packParameters, messageName.toUpper(), packLines);
packChan = packChan.arg(messageName, packParameters, messageName.toUpper(), packLines);
encode = encode.arg(messageName).arg(cStructName).arg(packArguments);
decode = decode.arg(messageName).arg(cStructName).arg(decodeLines);
compactSend = compactSend.arg(channelType, messageType, messageName, sendArguments, packParameters);
QString cFile = "// MESSAGE " + messageName.toUpper() + " PACKING\n\n" + idDefine + "\n\n" + cStruct + "\n\n" + arrayDefines + "\n\n" + commentContainer.arg(messageName.toLower(), commentLines) + pack + commentPackChanContainer.arg(messageName.toLower(), commentLines) + packChan + commentEncodeContainer.arg(messageName.toLower()) + encode + "\n" + commentSendContainer.arg(messageName.toLower(), commentLines) + compactSend + "\n" + "// MESSAGE " + messageName.toUpper() + " UNPACKING\n\n" + unpacking + commentDecodeContainer.arg(messageName.toLower()) + decode;
cFiles.append(qMakePair(QString("mavlink_msg_%1.h").arg(messageName), cFile));
} // Check if tag = message
} // Check if e = NULL
n = n.nextSibling();
} // While through <message>
n = p;
} // Check if tag = messages
} // Check if e = NULL
n = n.nextSibling();
} // While through include and messages
// One up - current node = parent
n = p;
} // Check if tag = mavlink
} // Check if e = NULL
n = n.nextSibling();
} // While through root children
// Add version to main header
mainHeader += "// MAVLINK VERSION\n\n";
mainHeader += QString("#ifndef MAVLINK_VERSION\n#define MAVLINK_VERSION %1\n#endif\n\n").arg(mavlinkVersion);
mainHeader += QString("#if (MAVLINK_VERSION == 0)\n#undef MAVLINK_VERSION\n#define MAVLINK_VERSION %1\n#endif\n\n").arg(mavlinkVersion);
// Add enums to main header
mainHeader += "// ENUM DEFINITIONS\n\n";
mainHeader += enums;
mainHeader += "\n";
mainHeader += "// MESSAGE DEFINITIONS\n\n";
// Create directory if it doesn't exist, report result in success
if (!dir.exists()) success = success && dir.mkpath(outputDirName + "/" + messagesDirName);
for (int i = 0; i < cFiles.size(); i++) {
QFile rawFile(dir.filePath(cFiles.at(i).first));
bool ok = rawFile.open(QIODevice::WriteOnly | QIODevice::Text);
success = success && ok;
rawFile.write(cFiles.at(i).second.toLatin1());
rawFile.close();
mainHeader += includeLine.arg(messagesDirName + "/" + cFiles.at(i).first);
}
mainHeader += "\n\n// MESSAGE LENGTHS\n\n";
mainHeader += "#undef MAVLINK_MESSAGE_LENGTHS\n";
mainHeader += "#define MAVLINK_MESSAGE_LENGTHS { ";
for (int i=0; i<highest_message_id; i++) {
mainHeader += QString::number(message_lengths[i]);
if (i < highest_message_id-1) mainHeader += ", ";
}
mainHeader += " }\n\n";
mainHeader += "#ifdef __cplusplus\n}\n#endif\n";
mainHeader += "#endif";
// Newline to make compiler happy
mainHeader += "\n";
// Write main header
QFile rawHeader(outputDirName + "/" + mainHeaderName);
bool ok = rawHeader.open(QIODevice::WriteOnly | QIODevice::Text);
success = success && ok;
rawHeader.write(mainHeader.toLatin1());
rawHeader.close();
// Write alias mavlink header
QFile mavlinkHeader(outputDirName + "/mavlink.h");
ok = mavlinkHeader.open(QIODevice::WriteOnly | QIODevice::Text);
success = success && ok;
QString mHeader = QString("/** @file\n *\t@brief MAVLink comm protocol.\n *\t@see http://pixhawk.ethz.ch/software/mavlink\n *\t Generated on %1\n */\n#ifndef MAVLINK_H\n#define MAVLINK_H\n\n").arg(date); // The main header includes all messages
// Mark all code as C code
mHeader += "#include \"" + mainHeaderName + "\"\n\n";
mHeader += "#endif\n";
mavlinkHeader.write(mHeader.toLatin1());
mavlinkHeader.close();
// Write C structs / lcm definitions
// QFile lcmStructs(outputDirName + "/mavlink.lcm");
// ok = lcmStructs.open(QIODevice::WriteOnly | QIODevice::Text);
// success = success && ok;
// lcmStructs.write(lcmStructDefs.toLatin1());
return success;
}

66
src/comm/MAVLinkXMLParser.h

@ -1,66 +0,0 @@ @@ -1,66 +0,0 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class MAVLinkXMLParser
* @author Lorenz Meier <mail@qgroundcontrol.org>
*/
#ifndef MAVLINKXMLPARSER_H
#define MAVLINKXMLPARSER_H
#include <QObject>
#include <QDomDocument>
#include <QString>
/**
* @brief MAVLink micro air vehicle protocol generator
*
* MAVLink is a generic communication protocol for micro air vehicles.
* for more information, please see the official website.
* @ref http://pixhawk.ethz.ch/software/mavlink/
**/
class MAVLinkXMLParser : public QObject
{
Q_OBJECT
public:
MAVLinkXMLParser(QDomDocument* document, QString outputDirectory, QObject* parent=0);
MAVLinkXMLParser(QString document, QString outputDirectory, QObject* parent=0);
~MAVLinkXMLParser();
public slots:
/** @brief Parse XML and generate C files */
bool generate();
signals:
/** @brief Status message on the parsing */
void parseState(QString message);
protected:
QDomDocument* doc;
QString outputDirName;
QString fileName;
};
#endif // MAVLINKXMLPARSER_H

94
src/standalone/mavlinkgen/MAVLinkGen.cc

@ -1,94 +0,0 @@ @@ -1,94 +0,0 @@
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK 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.
PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Implementation of class MAVLinkGen
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QFile>
#include <QFlags>
#include <QThread>
#include <QSplashScreen>
#include <QPixmap>
#include <QDesktopWidget>
#include <QPainter>
#include <QStyleFactory>
#include <QAction>
#include <QSettings>
#include <QFontDatabase>
#include <QMainWindow>
#include "MAVLinkGen.h"
#include "XMLCommProtocolWidget.h"
/**
* @brief Constructor for the main application.
*
* This constructor initializes and starts the whole application. It takes standard
* command-line parameters
*
* @param argc The number of command-line parameters
* @param argv The string array of parameters
**/
MAVLinkGen::MAVLinkGen(int &argc, char* argv[]) : QApplication(argc, argv)
{
this->setApplicationName("MAVLink Generator");
this->setApplicationVersion("v. 1.0.0 (Beta)");
this->setOrganizationName(QLatin1String("QGroundControl"));
this->setOrganizationDomain("http://qgroundcontrol.org");
QSettings::setDefaultFormat(QSettings::IniFormat);
// Exit main application when last window is closed
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit()));
// Set application font
QFontDatabase fontDatabase = QFontDatabase();
const QString fontFileName = ":/general/vera.ttf"; ///< Font file is part of the QRC file and compiled into the app
const QString fontFamilyName = "Bitstream Vera Sans";
if(!QFile::exists(fontFileName)) printf("ERROR! font file: %s DOES NOT EXIST!\n", fontFileName.toStdString().c_str());
fontDatabase.addApplicationFont(fontFileName);
setFont(fontDatabase.font(fontFamilyName, "Roman", 12));
// Create main window
QMainWindow* window = new QMainWindow();
window->setCentralWidget(new XMLCommProtocolWidget(window));
window->setWindowTitle(applicationName() + " " + applicationVersion());
// window->setBaseSize(qMin(1024, static_cast<int>(QApplication::desktop()->width()*0.8f)), qMin(900, static_cast<int>(QApplication::desktop()->height()*0.8f)));
window->show();
}
/**
* @brief Destructor for the groundstation. It destroys all loaded instances.
*
**/
MAVLinkGen::~MAVLinkGen()
{
}

58
src/standalone/mavlinkgen/MAVLinkGen.h

@ -1,58 +0,0 @@ @@ -1,58 +0,0 @@
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK 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.
PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class MAVLinkGen
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef MAVLINKGEN_H
#define MAVLINKGEN_H
#include <QApplication>
/**
* @brief The main application and management class.
*
* This class is started by the main method and provides
* the central management unit of the groundstation application.
*
**/
class MAVLinkGen : public QApplication
{
Q_OBJECT
public:
MAVLinkGen(int &argc, char* argv[]);
~MAVLinkGen();
protected:
private:
};
#endif /* MAVLINKGEN_H */

46
src/standalone/mavlinkgen/main.cc

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK 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.
PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Main executable
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QtGui/QApplication>
#include "MAVLinkGen.h"
/**
* @brief Starts the application
*
* @param argc Number of commandline arguments
* @param argv Commandline arguments
* @return exit code, 0 for normal exit and !=0 for error cases
*/
int main(int argc, char *argv[])
{
MAVLinkGen gen(argc, argv);
return gen.exec();
}

2
src/ui/JoystickWidget.cc

@ -69,7 +69,6 @@ void JoystickWidget::setZ(float z) @@ -69,7 +69,6 @@ void JoystickWidget::setZ(float z)
void JoystickWidget::setHat(float x, float y)
{
qDebug() << __FILE__ << __LINE__ << "HAT X:" << x << "HAT Y:" << y;
updateStatus(tr("Hat position: x: %1, y: %2").arg(x, y));
}
@ -129,7 +128,6 @@ void JoystickWidget::pressKey(int key) @@ -129,7 +128,6 @@ void JoystickWidget::pressKey(int key)
break;
}
QTimer::singleShot(20, this, SLOT(clearKeys()));
qDebug() << __FILE__ << __LINE__ << "KEY" << key << " pressed on joystick";
updateStatus(tr("Key %1 pressed").arg(key));
}

15
src/ui/JoystickWidget.ui

@ -37,6 +37,9 @@ @@ -37,6 +37,9 @@
</property>
<item row="4" column="2" colspan="3">
<widget class="QSlider" name="ySlider">
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>100</number>
</property>
@ -68,7 +71,14 @@ @@ -68,7 +71,14 @@
</widget>
</item>
<item row="0" column="1" rowspan="3" colspan="5">
<widget class="QDial" name="dial"/>
<widget class="QDial" name="dial">
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>100</number>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="label_2">
@ -114,6 +124,9 @@ @@ -114,6 +124,9 @@
</item>
<item row="1" column="0" rowspan="2">
<widget class="QSlider" name="xSlider">
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>100</number>
</property>

170
src/ui/XMLCommProtocolWidget.cc

@ -1,170 +0,0 @@ @@ -1,170 +0,0 @@
#include <QFileDialog>
#include <QTextBrowser>
#include <QMessageBox>
#include <QSettings>
#include "XMLCommProtocolWidget.h"
#include "ui_XMLCommProtocolWidget.h"
#include "MAVLinkXMLParser.h"
#include "MAVLinkSyntaxHighlighter.h"
#include "QGC.h"
#include <QDebug>
#include <iostream>
XMLCommProtocolWidget::XMLCommProtocolWidget(QWidget *parent) :
QWidget(parent),
m_ui(new Ui::XMLCommProtocolWidget)
{
m_ui->setupUi(this);
// Now set syntax highlighter
//highlighter = new MAVLinkSyntaxHighlighter(m_ui->xmlTextView->document());
connect(m_ui->selectFileButton, SIGNAL(clicked()), this, SLOT(selectXMLFile()));
connect(m_ui->selectOutputButton, SIGNAL(clicked()), this, SLOT(selectOutputDirectory()));
connect(m_ui->generateButton, SIGNAL(clicked()), this, SLOT(generate()));
connect(m_ui->saveButton, SIGNAL(clicked()), this, SLOT(save()));
}
void XMLCommProtocolWidget::selectXMLFile()
{
//QString fileName = QFileDialog::getOpenFileName(this, tr("Load Protocol Definition File"), ".", "*.xml");
QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
const QString mavlinkXML = "MAVLINK_XML_FILE";
QString dirPath = settings.value(mavlinkXML, QCoreApplication::applicationDirPath() + "../").toString();
QFileInfo dir(dirPath);
QFileDialog dialog;
dialog.setDirectory(dir.absoluteDir());
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setFilter(tr("MAVLink XML (*.xml)"));
dialog.setViewMode(QFileDialog::Detail);
QStringList fileNames;
if (dialog.exec()) {
fileNames = dialog.selectedFiles();
}
if (fileNames.size() > 0) {
m_ui->fileNameLabel->setText(fileNames.first());
QFile file(fileNames.first());
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
const QString instanceText(QString::fromUtf8(file.readAll()));
setXML(instanceText);
// Store filename for next time
settings.setValue(mavlinkXML, QFileInfo(file).absoluteFilePath());
settings.sync();
} else {
QMessageBox msgBox;
msgBox.setText("Could not read XML file. Permission denied");
msgBox.exec();
}
}
}
void XMLCommProtocolWidget::setXML(const QString& xml)
{
m_ui->xmlTextView->setText(xml);
QDomDocument doc;
if (doc.setContent(xml)) {
m_ui->validXMLLabel->setText(tr("<font color=\"green\">Valid XML file</font>"));
} else {
m_ui->validXMLLabel->setText(tr("<font color=\"red\">File is NOT valid XML, please fix in editor</font>"));
}
if (model != NULL) {
m_ui->xmlTreeView->reset();
//delete model;
}
model = new DomModel(doc, this);
m_ui->xmlTreeView->setModel(model);
// Expand the tree so that message names are visible
m_ui->xmlTreeView->expandToDepth(1);
m_ui->xmlTreeView->hideColumn(2);
m_ui->xmlTreeView->repaint();
}
void XMLCommProtocolWidget::selectOutputDirectory()
{
QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
const QString mavlinkOutputDir = "MAVLINK_OUTPUT_DIR";
QString dirPath = settings.value(mavlinkOutputDir, QCoreApplication::applicationDirPath() + "../").toString();
QFileDialog dialog;
dialog.setDirectory(dirPath);
dialog.setFileMode(QFileDialog::Directory);
dialog.setViewMode(QFileDialog::Detail);
QStringList fileNames;
if (dialog.exec()) {
fileNames = dialog.selectedFiles();
}
if (fileNames.size() > 0) {
m_ui->outputDirNameLabel->setText(fileNames.first());
// Store directory for next time
settings.setValue(mavlinkOutputDir, QFileInfo(fileNames.first()).absoluteFilePath());
settings.sync();
//QFile file(fileName);
}
}
void XMLCommProtocolWidget::generate()
{
// Check if input file is present
if (!QFileInfo(m_ui->fileNameLabel->text().trimmed()).isFile()) {
QMessageBox::critical(this, tr("Please select an XML input file first"), tr("You have to select an input XML file before generating C files."), QMessageBox::Ok);
return;
}
// Check if output dir is selected
if (!QFileInfo(m_ui->outputDirNameLabel->text().trimmed()).isDir()) {
QMessageBox::critical(this, tr("Please select output directory first"), tr("You have to select an output directory before generating C files."), QMessageBox::Ok);
return;
}
// First save file
save();
// Clean log
m_ui->compileLog->clear();
// Check XML validity
if (!m_ui->xmlTextView->syntaxcheck()) return;
MAVLinkXMLParser* parser = new MAVLinkXMLParser(m_ui->fileNameLabel->text().trimmed(), m_ui->outputDirNameLabel->text().trimmed());
connect(parser, SIGNAL(parseState(QString)), m_ui->compileLog, SLOT(appendHtml(QString)));
bool result = parser->generate();
if (result) {
QMessageBox msgBox;
msgBox.setText(QString("The C code / headers have been generated in folder\n%1").arg(m_ui->outputDirNameLabel->text().trimmed()));
msgBox.exec();
} else {
QMessageBox::critical(this, tr("C code generation failed, please see the compile log for further information"), QString("The C code / headers could not be written to folder\n%1").arg(m_ui->outputDirNameLabel->text().trimmed()), QMessageBox::Ok);
}
delete parser;
}
void XMLCommProtocolWidget::save()
{
QFile file(m_ui->fileNameLabel->text().trimmed());
setXML(m_ui->xmlTextView->document()->toPlainText().toUtf8());
file.open(QIODevice::WriteOnly | QIODevice::Text);
file.write(m_ui->xmlTextView->document()->toPlainText().toUtf8());
}
XMLCommProtocolWidget::~XMLCommProtocolWidget()
{
delete model;
delete m_ui;
}
void XMLCommProtocolWidget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
}

75
src/ui/XMLCommProtocolWidget.h

@ -1,75 +0,0 @@ @@ -1,75 +0,0 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL 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.
QGROUNDCONTROL 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 QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class XMLCommProtocolWidget
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef XMLCOMMPROTOCOLWIDGET_H
#define XMLCOMMPROTOCOLWIDGET_H
#include <QtGui/QWidget>
#include "DomModel.h"
#include "MAVLinkSyntaxHighlighter.h"
namespace Ui
{
class XMLCommProtocolWidget;
}
/**
* @brief Tool to generate MAVLink code out of XML protocol definitions
* @see http://doc.trolltech.com/4.6/itemviews-simpledommodel.html for a XML view tutorial
*/
class XMLCommProtocolWidget : public QWidget
{
Q_OBJECT
public:
XMLCommProtocolWidget(QWidget *parent = 0);
~XMLCommProtocolWidget();
protected slots:
/** @brief Select input XML protocol definition */
void selectXMLFile();
/** @brief Select output directory for generated .h files */
void selectOutputDirectory();
/** @brief Set the XML this widget currently operates on */
void setXML(const QString& xml);
/** @brief Parse XML file and generate .h files */
void generate();
/** @brief Save the edited file */
void save();
protected:
MAVLinkSyntaxHighlighter* highlighter;
DomModel* model;
void changeEvent(QEvent *e);
private:
Ui::XMLCommProtocolWidget *m_ui;
};
#endif // XMLCOMMPROTOCOLWIDGET_H

144
src/ui/XMLCommProtocolWidget.ui

@ -1,144 +0,0 @@ @@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>XMLCommProtocolWidget</class>
<widget class="QWidget" name="XMLCommProtocolWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>846</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,100,0,0,0" columnstretch="1,1,1,100">
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="spacing">
<number>12</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="fileNameLabel">
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Select input file</string>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="selectFileButton">
<property name="text">
<string>Select input file</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/folder-open.svg</normaloff>:/images/status/folder-open.svg</iconset>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="6">
<widget class="QGCMAVLinkTextEdit" name="xmlTextView">
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLabel" name="outputDirNameLabel">
<property name="maximumSize">
<size>
<width>400</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Select output directory</string>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="selectOutputButton">
<property name="text">
<string>Select directory</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/status/folder-open.svg</normaloff>:/images/status/folder-open.svg</iconset>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QTreeView" name="xmlTreeView"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>Compile Output</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QPlainTextEdit" name="compileLog"/>
</item>
<item row="5" column="0">
<widget class="QLabel" name="validXMLLabel">
<property name="text">
<string>No file loaded</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Save file</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="generateButton">
<property name="text">
<string>Save and generate</string>
</property>
<property name="icon">
<iconset resource="../../mavground.qrc">
<normaloff>:/images/categories/applications-system.svg</normaloff>:/images/categories/applications-system.svg</iconset>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QGCMAVLinkTextEdit</class>
<extends>QTextEdit</extends>
<header location="global">QGCMAVLinkTextEdit.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../mavground.qrc"/>
</resources>
<connections/>
</ui>

47
src/ui/mavlink/DomItem.cc

@ -1,47 +0,0 @@ @@ -1,47 +0,0 @@
#include <QtXml>
#include "DomItem.h"
DomItem::DomItem(QDomNode &node, int row, DomItem *parent)
{
domNode = node;
// Record the item's location within its parent.
rowNumber = row;
parentItem = parent;
}
DomItem::~DomItem()
{
QHash<int,DomItem*>::iterator it;
for (it = childItems.begin(); it != childItems.end(); ++it)
delete it.value();
}
QDomNode DomItem::node() const
{
return domNode;
}
DomItem *DomItem::parent()
{
return parentItem;
}
DomItem *DomItem::child(int i)
{
if (childItems.contains(i))
return childItems[i];
if (i >= 0 && i < domNode.childNodes().count()) {
QDomNode childNode = domNode.childNodes().item(i);
DomItem *childItem = new DomItem(childNode, i, this);
childItems[i] = childItem;
return childItem;
}
return 0;
}
int DomItem::row()
{
return rowNumber;
}

24
src/ui/mavlink/DomItem.h

@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
#ifndef DOMITEM_H
#define DOMITEM_H
#include <QDomNode>
#include <QHash>
class DomItem
{
public:
DomItem(QDomNode &node, int row, DomItem *parent = 0);
~DomItem();
DomItem *child(int i);
DomItem *parent();
QDomNode node() const;
int row();
private:
QDomNode domNode;
QHash<int,DomItem*> childItems;
DomItem *parentItem;
int rowNumber;
};
#endif

197
src/ui/mavlink/DomModel.cc

@ -1,197 +0,0 @@ @@ -1,197 +0,0 @@
#include <QtGui>
#include <QtXml>
#include "DomItem.h"
#include "DomModel.h"
DomModel::DomModel(QDomDocument document, QObject *parent)
: QAbstractItemModel(parent), domDocument(document)
{
rootItem = new DomItem(domDocument, 0);
}
DomModel::~DomModel()
{
delete rootItem;
}
int DomModel::columnCount(const QModelIndex &/*parent*/) const
{
return 3;
}
QVariant DomModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
DomItem *item = static_cast<DomItem*>(index.internalPointer());
QDomNode node = item->node();
QStringList attributes;
QDomNamedNodeMap attributeMap = node.attributes();
switch (index.column()) {
case 0:
{
if (node.nodeName() == "message")
{
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
if (attribute.nodeName() == "name") return attribute.nodeValue();
}
}
else if (node.nodeName() == "field")
{
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
if (attribute.nodeName() == "name") return attribute.nodeValue();
}
}
else if (node.nodeName() == "enum")
{
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
if (attribute.nodeName() == "name") return attribute.nodeValue();
}
}
else if (node.nodeName() == "entry")
{
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
if (attribute.nodeName() == "name") return attribute.nodeValue();
}
}
else if (node.nodeName() == "#text")
{
return node.nodeValue().split("\n").join(" ");
}
else
{
return node.nodeName();
}
}
break;
case 1:
if (node.nodeName() == "description")
{
return node.nodeValue().split("\n").join(" ");
}
else
{
for (int i = 0; i < attributeMap.count(); ++i) {
QDomNode attribute = attributeMap.item(i);
if (attribute.nodeName() == "id" || attribute.nodeName() == "index" || attribute.nodeName() == "value")
{
return QString("(# %1)").arg(attribute.nodeValue());
}
else if (attribute.nodeName() == "type")
{
return attribute.nodeValue();
}
}
}
break;
// case 2:
// {
//// if (node.nodeName() != "description")
//// {
//// for (int i = 0; i < attributeMap.count(); ++i) {
//// QDomNode attribute = attributeMap.item(i);
//// attributes << attribute.nodeName() + "=\""
//// +attribute.nodeValue() + "\"";
//// }
//// return attributes.join(" ");
//// }
//// else
//// {
//// return node.nodeValue().split("\n").join(" ");
//// }
// }
// break;
default:
{
return QVariant();
}
}
}
Qt::ItemFlags DomModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
QVariant DomModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case 0:
return tr("Name ");
case 1:
return tr("Value");
// case 2:
// return tr("Description");
default:
return QVariant();
}
}
return QVariant();
}
QModelIndex DomModel::index(int row, int column, const QModelIndex &parent)
const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
DomItem *parentItem;
if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<DomItem*>(parent.internalPointer());
DomItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex DomModel::parent(const QModelIndex &child) const
{
if (!child.isValid())
return QModelIndex();
DomItem *childItem = static_cast<DomItem*>(child.internalPointer());
DomItem *parentItem = childItem->parent();
if (!parentItem || parentItem == rootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
int DomModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
DomItem *parentItem;
if (!parent.isValid())
parentItem = rootItem;
else
parentItem = static_cast<DomItem*>(parent.internalPointer());
return parentItem->node().childNodes().count();
}

34
src/ui/mavlink/DomModel.h

@ -1,34 +0,0 @@ @@ -1,34 +0,0 @@
#ifndef DOMMODEL_H
#define DOMMODEL_H
#include <QAbstractItemModel>
#include <QDomDocument>
#include <QModelIndex>
#include <QVariant>
class DomItem;
class DomModel : public QAbstractItemModel
{
Q_OBJECT
public:
DomModel(QDomDocument document, QObject *parent = 0);
~DomModel();
QVariant data(const QModelIndex &index, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
private:
QDomDocument domDocument;
DomItem *rootItem;
};
#endif

28
standalone/qgroundcontrol-server/qgroundcontrol-server.pro

@ -1,28 +0,0 @@ @@ -1,28 +0,0 @@
QT += net
TEMPLATE = app
TARGET = qgroundcontrol-server
BASEDIR = ../..
BUILDDIR = $$BASEDIR/build/qgroundcontrol-server
LANGUAGE = C++
CONFIG += release
CONFIG -= debug
OBJECTS_DIR = $$BUILDDIR/qgroundcontrol-server/obj
MOC_DIR = $$BUILDDIR/qgroundcontrol-server/moc
macx:DESTDIR = $$BASEDIR/bin/mac
INCLUDEPATH += $$BASEDIR/. \
$$BASEDIR/src \
$$BASEDIR/src/comm \
$$BASEDIR/standalone/qgroundcontrol-server/src
HEADERS += src/QGroundControlServer.h \
$$BASEDIR/src/comm/MAVLinkProtocol.h
SOURCES += src/main.cc \
src/QGroundControlServer.cc \
$$BASEDIR/src/comm/MAVLinkProtocol.cc
RESOURCES = $$BASEDIR/mavground.qrc

93
standalone/qgroundcontrol-server/src/QGroundControlServer.cc

@ -1,93 +0,0 @@ @@ -1,93 +0,0 @@
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK 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.
PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Implementation of class MAVLinkGen
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QFile>
#include <QFlags>
#include <QThread>
#include <QSplashScreen>
#include <QPixmap>
#include <QDesktopWidget>
#include <QPainter>
#include <QStyleFactory>
#include <QAction>
#include <QSettings>
#include <QFontDatabase>
#include <QMainWindow>
#include "MAVLinkGen.h"
#include "XMLCommProtocolWidget.h"
/**
* @brief Constructor for the main application.
*
* This constructor initializes and starts the whole application. It takes standard
* command-line parameters
*
* @param argc The number of command-line parameters
* @param argv The string array of parameters
**/
MAVLinkGen::MAVLinkGen(int &argc, char* argv[]) : QApplication(argc, argv)
{
this->setApplicationName("MAVLink Generator");
this->setApplicationVersion("v. 0.1.0 (Beta)");
this->setOrganizationName(QLatin1String("OpenMAV Association"));
this->setOrganizationDomain("http://qgroundcontrol.org");
QSettings::setDefaultFormat(QSettings::IniFormat);
// Exit main application when last window is closed
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit()));
// Set application font
QFontDatabase fontDatabase = QFontDatabase();
const QString fontFileName = ":/general/vera.ttf"; ///< Font file is part of the QRC file and compiled into the app
const QString fontFamilyName = "Bitstream Vera Sans";
if(!QFile::exists(fontFileName)) printf("ERROR! font file: %s DOES NOT EXIST!\n", fontFileName.toStdString().c_str());
fontDatabase.addApplicationFont(fontFileName);
setFont(fontDatabase.font(fontFamilyName, "Roman", 12));
// Create main window
QMainWindow* window = new QMainWindow();
window->setCentralWidget(new XMLCommProtocolWidget(window));
window->setWindowTitle(applicationName() + " " + applicationVersion());
window->show();
}
/**
* @brief Destructor for the groundstation. It destroys all loaded instances.
*
**/
MAVLinkGen::~MAVLinkGen()
{
}

58
standalone/qgroundcontrol-server/src/QGroundControlServer.h

@ -1,58 +0,0 @@ @@ -1,58 +0,0 @@
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK 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.
PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Definition of class MAVLinkGen
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#ifndef MAVLINKGEN_H
#define MAVLINKGEN_H
#include <QApplication>
/**
* @brief The main application and management class.
*
* This class is started by the main method and provides
* the central management unit of the groundstation application.
*
**/
class MAVLinkGen : public QApplication
{
Q_OBJECT
public:
MAVLinkGen(int &argc, char* argv[]);
~MAVLinkGen();
protected:
private:
};
#endif /* MAVLINKGEN_H */

46
standalone/qgroundcontrol-server/src/main.cc

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
/*=====================================================================
PIXHAWK Micro Air Vehicle Flying Robotics Toolkit
(c) 2009, 2010 PIXHAWK PROJECT <http://pixhawk.ethz.ch>
This file is part of the PIXHAWK project
PIXHAWK 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.
PIXHAWK 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 PIXHAWK. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/**
* @file
* @brief Main executable
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
#include <QtGui/QApplication>
#include "MAVLinkGen.h"
/**
* @brief Starts the application
*
* @param argc Number of commandline arguments
* @param argv Commandline arguments
* @return exit code, 0 for normal exit and !=0 for error cases
*/
int main(int argc, char *argv[])
{
MAVLinkGen gen(argc, argv);
return gen.exec();
}
Loading…
Cancel
Save