Commit 1cad7af3 authored by Bryant Mairs's avatar Bryant Mairs

Removed mavlinkgen application as it has been unused and deprecated for many months.

parent 08a35cfb
......@@ -21,7 +21,6 @@ tmp
debug
release
/qgroundcontrol
mavlinkgen-build-desktop
qgroundcontrol.xcodeproj/**
doc/html
doc/doxy.log
......
......@@ -123,34 +123,6 @@ INCLUDEPATH += $$MAVLINKPATH
INCLUDEPATH += $$MAVLINKPATH/common
}
#
# [DEPRECATED] MAVLink generator UI. Provides a GUI interface for generating MAVLink dialects.
# Replaced by mavgenerator.py within the MAVLink project.
#
contains(DEFINES, ENABLE_MAVGEN) {
warning("Including support for MAVLink generator GUI (manual override from command line, CAUTION: deprecated)")
} else:infile(user_config.pri, DEFINES, ENABLE_MAVGEN) {
DEFINES += ENABLE_MAVGEN # infile doesn't automatically include everything in the specified file
warning("Including support for MAVLink generator GUI (manual override from user_config.pri, CAUTION: deprecated)")
}
contains(DEFINES, ENABLE_MAVGEN) {
# Rename the macro to be consistent with other QGC feature existance macros.
DEFINES -= ENABLE_MAVGEN
DEFINES += QGC_MAVGEN_ENABLED
DEPENDPATH += \
src/apps/mavlinkgen
INCLUDEPATH += \
src/apps/mavlinkgen \
src/apps/mavlinkgen/ui \
src/apps/mavlinkgen/generator
include(src/apps/mavlinkgen/mavlinkgen.pri)
} else {
message("Skipping support for MAVLink generator GUI (deprecated, see README)")
}
#
# [OPTIONAL] OpenSceneGraph
# Allow the user to override OpenSceneGraph compilation through a DISABLE_OPEN_SCENE_GRAPH
......
......@@ -37,9 +37,6 @@ The QUpgrade module relies on `libudev` on Linux platforms, so be sure to instal
### Specifying MAVLink dialects
The MAVLink dialect compiled by default by QGC is for the ardupilotmega. This will happen if no other dialects are specified. Setting the `MAVLINK_CONF` variable sets the dialects, with more than one specified in a space-separated list. Note that doing this may result in compilation errors as certain dialects may conflict with each other!
### MAVLink dialect generator
An add-on is available for QGC that provides a UI for generating MAVLink dialects from within QGC. This feature has been deprecated since identical functionality now exists within the MAVLink project itself. Enable this functionality by specifying the `DEFINES` variable `ENABLE_MAVGEN`.
### Opal-RT's RT-LAB simulator
Integration with Opal-RT's RT-LAB simulator can be enabled on Windows by installing RT-LAB 7.2.4. This allows vehicles to be simulated in RT-LAB and communicate directly with QGC on the same computer as if the UAS was actually deployed. This support is enabled by default once the requisite RT-LAB software is installed. Disabling this can be done by adding `DISABLE_RTLAB` to the `DEFINES` variable.
......
/*=====================================================================
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("MAVLink Consortium"));
this->setOrganizationDomain("http://qgroundcontrol.org/mavlink");
QSettings::setDefaultFormat(QSettings::IniFormat);
// Exit main application when last window is closed
connect(this, SIGNAL(lastWindowClosed()), this, SLOT(quit()));
// Create main window
window = new QMainWindow();
window->setCentralWidget(new XMLCommProtocolWidget(window));
window->setWindowTitle(applicationName() + " " + applicationVersion());
window->resize(qMax(950, static_cast<int>(QApplication::desktop()->width()*0.7f)), qMax(600, static_cast<int>(QApplication::desktop()->height()*0.8f)));
window->show();
}
/**
* @brief Destructor
*
**/
MAVLinkGen::~MAVLinkGen()
{
window->hide();
delete window;
}
/*=====================================================================
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>
#include <QMainWindow>
/**
* @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:
QMainWindow* window;
private:
};
#endif /* MAVLINKGEN_H */
Code Generator for the MAVLink Micro Air Vehicle Message Marshalling Library
This is a code generator for the library for lightweight communication between
Micro Air Vehicles and/or ground control stations.
It serializes C-structs for serial channels and can be used with
any type of radio modem.
**********
* NEWS *
**********
MAVLink has been ported to Python and Java. MAVLinkGen will soon support the output of Python and Java code as well.
For help, please visit the mailing list: http://groups.google.com/group/mavlink
MAVLink is licensed under the terms of the Lesser General Public License of the Free Software Foundation (LGPL).
MAVLink's reference implementation is done in the QGroundControl operator control unit. MAVLink is however not tied in any way to QGroundControl nor does it depend on it. Many other groundstations (APM Planner, HK GCS, Copter-GCS) support it and might be better suited for your application than QGC - check them out.
Project:
http://qgroundcontrol.org/mavlink
Files:
http://github.com/pixhawk/mavlinkgen
http://github.com/pixhawk/mavlink
(c) 2009-2011 Lorenz Meier <mail@qgroundcontrol.org>
\ No newline at end of file
#!/bin/sh
cp -r ../../mavlinkgen-build-desktop/mavlinkgen.app .
echo -e '\n\nStarting to create disk image. This may take a while..\n'
macdeployqt mavlinkgen.app -dmg
rm -rf mavlinkgen.app
echo -e '\n\n MAVLinkGen .DMG file is now ready for publishing\n'
Name "MAVLink Generator"
OutFile "mavlinkgen-installer-win32.exe"
InstallDir $PROGRAMFILES\mavlinkgen
Page license
Page directory
Page components
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
LicenseData ..\license.txt
Section ""
SetOutPath $INSTDIR
File ..\release\*.*
WriteUninstaller $INSTDIR\mavlinkgen_uninstall.exe
SectionEnd
Section "Uninstall"
Delete $INSTDIR\mavlinkgen_uninstall.exe
Delete $INSTDIR\*.*
RMDir $INSTDIR
Delete "$SMPROGRAMS\mavlinkgen\*.*"
RMDir "$SMPROGRAMS\mavlinkgen\"
SectionEnd
Section "create Start Menu Shortcuts"
CreateDirectory "$SMPROGRAMS\MAVLink"
CreateShortCut "$SMPROGRAMS\MAVLink\Uninstall.lnk" "$INSTDIR\mavlinkgen_uninstall.exe" "" "$INSTDIR\mavlinkgen_uninstall.exe" 0
CreateShortCut "$SMPROGRAMS\MAVLink\MAVLinkGen.lnk" "$INSTDIR\mavlinkgen.exe" "" "$INSTDIR\mavlinkgen.exe" 0
SectionEnd
\ No newline at end of file
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2011 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 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://qgroundcontrol.org/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;
}
/*=====================================================================
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
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2011 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 Implementation of class MAVLinkXMLParserV10
* @author Lorenz Meier <mail@qgroundcontrol.org>
*/
#include <QFile>
#include <QDir>
#include <QPair>
#include <QList>
#include <QMap>
#include <QDateTime>
#include <QLocale>
#include <QApplication>
#include "MAVLinkXMLParserV10.h"
#include <QDebug>
MAVLinkXMLParserV10::MAVLinkXMLParserV10(QDomDocument* document, QString outputDirectory, QObject* parent) : QObject(parent),
doc(document),
outputDirName(outputDirectory),
fileName("")
{
}
MAVLinkXMLParserV10::MAVLinkXMLParserV10(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;
}
MAVLinkXMLParserV10::~MAVLinkXMLParserV10()
{
}
void MAVLinkXMLParserV10::processError(QProcess::ProcessError err)
{
switch(err)
{
case QProcess::FailedToStart:
emit parseState(tr("Generator failed to start. Please check if the path and command is correct."));
break;
case QProcess::Crashed:
emit parseState("Generator crashed, This is a generator-related problem. Please upgrade MAVLink generator.");
break;
case QProcess::Timedout:
emit parseState(tr("Generator start timed out, please check if the path and command are correct"));
break;
case QProcess::WriteError:
emit parseState(tr("Could not communicate with generator. Please check if the path and command are correct"));
break;
case QProcess::ReadError:
emit parseState(tr("Could not communicate with generator. Please check if the path and command are correct"));
break;
case QProcess::UnknownError:
default:
emit parseState(tr("Generator error. Please check if the path and command is correct."));
break;
}
}
/**
* Generate C-code (C-89 compliant) out of the XML protocol specs.
*/
bool MAVLinkXMLParserV10::generate()
{
emit parseState(tr("Generator ready."));
#ifdef Q_OS_WIN
QString generatorCall("files/mavgen.exe");
#endif
#if (defined Q_OS_MAC) || (defined Q_OS_LINUX)
QString generatorCall("python");
#endif
QString lang("C");
QString version("1.0");
QStringList arguments;
#if (defined Q_OS_MAC) || (defined Q_OS_LINUX)
// Script is only needed as argument if Python is used, the Py2Exe implicitely knows the script
arguments << QString("%1/libs/mavlink/share/pyshared/pymavlink/generator/mavgen.py").arg(QApplication::applicationDirPath());
#endif
arguments << QString("--lang=%1").arg(lang);
arguments << QString("--output=%2").arg(outputDirName);
arguments << QString("%3").arg(fileName);
arguments << QString("--wire-protocol=%4").arg(version);
qDebug() << "Attempted to start" << generatorCall << arguments;
process = new QProcess(this);
process->setProcessChannelMode(QProcess::SeparateChannels);
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdOut()));
connect(process, SIGNAL(readyReadStandardError()), this, SLOT(readStdErr()));
process->start(generatorCall, arguments, QIODevice::ReadWrite);
QString output = QString(process->readAll());
emit parseState(output);
// Print process status
emit parseState(QString("<font color=\"red\">%1</font>").arg(QString(process->readAllStandardError())));
emit parseState(QString(process->readAllStandardOutput()));
process->waitForFinished(20000);
process->terminate();
process->kill();
return true;//result;
}
void MAVLinkXMLParserV10::readStdOut()
{
QString out(process->readAllStandardOutput());
emit parseState(out);
}
void MAVLinkXMLParserV10::readStdErr()
{
QString out = QString("<font color=\"red\">%1</font>").arg(QString(process->readAllStandardError()));
emit parseState(out);
}
/*=====================================================================
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 MAVLinkXMLParserV10
* @author Lorenz Meier <mail@qgroundcontrol.org>
*/
#ifndef MAVLINKXMLPARSERV10_H
#define MAVLINKXMLPARSERV10_H
#include <QObject>
#include <QDomDocument>
#include <QString>
#include <QProcess>
#include <inttypes.h>
/**
* @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 MAVLinkXMLParserV10 : public QObject
{
Q_OBJECT
public:
MAVLinkXMLParserV10(QDomDocument* document, QString outputDirectory, QObject* parent=0);
MAVLinkXMLParserV10(QString document, QString outputDirectory, QObject* parent=0);
~MAVLinkXMLParserV10();
public slots:
/** @brief Parse XML and generate C files */
bool generate();
/** @brief Handle process errors */
void processError(QProcess::ProcessError err);
/** @brief Redirect standard output */
void readStdOut();
/** @brief Redirect standard error output */
void readStdErr();
signals:
/** @brief Status message on the parsing */
void parseState(QString message);
protected:
// /** @brief Accumulate the X.25 CRC by adding one char at a time. */
// void crcAccumulate(uint8_t data, uint16_t *crcAccum);
// /** @brief Initialize the buffer for the X.25 CRC */
// void crcInit(uint16_t* crcAccum);
QDomDocument* doc;
QString outputDirName;
QString fileName;
QProcess* process;
};
#endif // MAVLINKXMLPARSERV10_H
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48.000000px"
height="48.000000px"
id="svg53383"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/categories"
sodipodi:docname="applications-system.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 24 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="48 : 24 : 1"
inkscape:persp3d-origin="24 : 16 : 1"
id="perspective31" />
<linearGradient
id="linearGradient3264">
<stop
style="stop-color:#c9c9c9;stop-opacity:1;"
offset="0"
id="stop3266" />
<stop
id="stop3276"
offset="0.25"
style="stop-color:#f8f8f8;stop-opacity:1;" />
<stop
id="stop3272"
offset="0.5"
style="stop-color:#e2e2e2;stop-opacity:1;" />
<stop
style="stop-color:#b0b0b0;stop-opacity:1;"
offset="0.75"
id="stop3274" />
<stop
style="stop-color:#c9c9c9;stop-opacity:1;"
offset="1"
id="stop3268" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3264"
id="linearGradient3281"
gradientUnits="userSpaceOnUse"
x1="14.462892"
y1="12.284524"
x2="34.534348"
y2="39.684914"
gradientTransform="matrix(1.241935,0,0,1.241935,-5.027508,-7.208988)" />
<linearGradient
id="linearGradient2300">
<stop
id="stop2302"
offset="0.0000000"
style="stop-color:#000000;stop-opacity:0.32673267;" />
<stop
id="stop2304"
offset="1"
style="stop-color:#000000;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="aigrd1"
gradientUnits="userSpaceOnUse"
x1="99.7773"
y1="15.4238"
x2="153.0005"
y2="248.6311">
<stop
offset="0"
style="stop-color:#184375"
id="stop53300" />
<stop
offset="1"
style="stop-color:#C8BDDC"
id="stop53302" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#aigrd1"
id="linearGradient53551"
gradientUnits="userSpaceOnUse"
x1="99.7773"
y1="15.4238"
x2="153.0005"
y2="248.6311"
gradientTransform="matrix(0.200685,0.000000,0.000000,0.200685,-0.585758,-1.050787)" />
<radialGradient
gradientUnits="userSpaceOnUse"
r="11.689870"
fy="72.568001"
fx="14.287618"
cy="68.872971"
cx="14.287618"
gradientTransform="matrix(1.399258,-2.234445e-7,8.196178e-8,0.513264,4.365074,4.839285)"
id="radialGradient2308"
xlink:href="#linearGradient2300"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3264"
id="linearGradient3760"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.241935,0,0,1.241935,-5.027508,-7.208988)"
x1="14.462892"
y1="12.284524"
x2="34.534348"
y2="39.684914" />
<linearGradient
inkscape:collect="always"
xlink:href="#aigrd1"
id="linearGradient3773"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.200685,0,0,0.200685,-54.33576,-1.050787)"
x1="99.7773"
y1="15.4238"
x2="153.0005"
y2="248.6311" />
</defs>
<sodipodi:namedview
inkscape:showpageshadow="false"
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="0.11764706"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="43.652227"
inkscape:cy="21.164787"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="872"
inkscape:window-height="697"
inkscape:window-x="562"
inkscape:window-y="151" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>System Applications</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:source>http://jimmac.musichall.cz/</dc:source>
<dc:subject>
<rdf:Bag>
<rdf:li>system</rdf:li>
<rdf:li>applications</rdf:li>
<rdf:li>group</rdf:li>
<rdf:li>category</rdf:li>
<rdf:li>admin</rdf:li>
<rdf:li>root</rdf:li>
</rdf:Bag>
</dc:subject>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g
inkscape:label="shadow"
id="layer2"
inkscape:groupmode="layer">
<path
transform="matrix(1.186380,0.000000,0.000000,1.186380,-4.539687,-7.794678)"
d="M 44.285715 38.714287 A 19.928572 9.8372450 0 1 1 4.4285717,38.714287 A 19.928572 9.8372450 0 1 1 44.285715 38.714287 z"
sodipodi:ry="9.8372450"
sodipodi:rx="19.928572"
sodipodi:cy="38.714287"
sodipodi:cx="24.357143"
id="path1538"
style="color:#000000;fill:url(#radialGradient2308);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.50000042;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
sodipodi:type="arc" />
</g>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<path
inkscape:r_cy="true"
inkscape:r_cx="true"
style="opacity:1;color:#000000;fill:url(#linearGradient3773);fill-opacity:1;fill-rule:nonzero;stroke:#3f4561;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 22.699525,0.94746963 C 22.22635,0.97984519 21.766437,1.0531317 21.301673,1.1063165 L 21.269903,1.1063165 L 20.157975,7.1742671 C 18.345621,7.5870046 16.640562,8.2874574 15.106644,9.2392765 L 10.118853,5.6493371 C 8.770521,6.6961412 7.543552,7.9170049 6.465374,9.2392765 L 9.928236,14.290607 C 8.876814,15.89739 8.086153,17.732094 7.640841,19.659632 C 7.640765,19.668743 7.640779,19.689813 7.640841,19.691401 L 1.60466,20.644482 C 1.494303,21.545851 1.445813,22.477386 1.445813,23.408418 C 1.445813,24.170171 1.466846,24.921747 1.541121,25.664043 L 7.577303,26.744202 C 8.0066,28.840363 8.822112,30.797987 9.960006,32.526228 L 6.370066,37.450482 C 7.398201,38.726866 8.585171,39.888962 9.864698,40.913343 L 14.947798,37.418712 C 16.724273,38.551956 18.707343,39.346604 20.856901,39.737877 L 21.809983,45.742288 C 22.487237,45.803935 23.181758,45.805827 23.874992,45.805827 C 24.853677,45.805826 25.788512,45.768738 26.734236,45.64698 L 27.877933,39.515491 C 29.91886,39.007587 31.836112,38.126493 33.501113,36.942172 L 38.393596,40.500342 C 39.662366,39.420897 40.822583,38.180154 41.824689,36.846863 L 38.266519,31.700225 C 39.230125,30.036028 39.897817,28.199859 40.23622,26.235892 L 46.240632,25.282811 C 46.29329,24.656221 46.30417,24.048546 46.30417,23.408418 C 46.30417,22.296018 46.174875,21.205317 46.018246,20.136172 L 39.918526,19.024244 C 39.440518,17.259164 38.656214,15.612364 37.662901,14.13176 L 41.25284,9.2075071 C 40.140075,7.8466524 38.870718,6.5895264 37.472284,5.5222596 L 32.293876,9.0804296 C 30.805549,8.200202 29.203897,7.5248159 27.464931,7.1424978 L 26.51185,1.1063165 C 25.644369,1.0042729 24.769749,0.94746963 23.874992,0.94746963 C 23.633166,0.94746964 23.384286,0.93986063 23.144296,0.94746963 C 23.027301,0.95117908 22.911525,0.94066346 22.794833,0.94746963 C 22.763228,0.94931296 22.73107,0.94531125 22.699525,0.94746963 z M 23.525529,16.387386 C 23.641592,16.381497 23.757473,16.387386 23.874992,16.387386 C 27.635598,16.387386 30.705408,19.457196 30.705408,23.217802 C 30.705409,26.978407 27.635597,30.016448 23.874992,30.016448 C 20.114387,30.016449 17.076346,26.978407 17.076346,23.217802 C 17.076347,19.574716 19.927558,16.569963 23.525529,16.387386 z "
id="path3243" />
<path
inkscape:r_cy="true"
inkscape:r_cx="true"
sodipodi:type="arc"
style="opacity:0.64772728;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.62180054;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path3283"
sodipodi:cx="23.511301"
sodipodi:cy="23.781593"
sodipodi:rx="12.727922"
sodipodi:ry="12.727922"
d="M 36.239223 23.781593 A 12.727922 12.727922 0 1 1 10.783379,23.781593 A 12.727922 12.727922 0 1 1 36.239223 23.781593 z"
transform="matrix(0.616598,0,0,0.616598,9.38202,8.539674)" />
<path
inkscape:r_cy="true"
inkscape:r_cx="true"
id="path3285"
d="M 21.995808,2.1484671 L 21.103024,8.0235243 C 19.404254,8.4103946 16.279442,9.5936035 14.841657,10.485771 L 10.091975,6.9406268 C 8.828145,7.9218257 8.741474,7.9883656 7.730867,9.2277688 L 11.165063,14.320988 C 10.179537,15.827071 8.995796,18.510982 8.570778,20.42893 C 8.570778,20.42893 2.552988,21.443355 2.552988,21.443355 C 2.449547,22.288234 2.49926,24.096528 2.56888,24.792303 L 8.317097,25.82782 C 8.71949,27.79261 10.225324,30.955232 11.291904,32.575161 L 7.656902,37.377719 C 8.620601,38.57411 8.813474,38.683589 10.01281,39.64377 L 14.873441,36.082733 C 16.538581,37.144954 19.84373,38.437109 21.858571,38.80386 L 22.656299,44.604952 C 23.291109,44.662736 25.044829,44.824827 25.931283,44.710701 L 26.824066,38.671821 C 28.737084,38.195749 32.042539,36.838896 33.603191,35.728798 L 38.458624,39.236958 C 39.647878,38.225166 39.658533,38.072709 40.597835,36.822978 L 36.999815,31.708667 C 37.90303,30.148767 39.070902,27.098068 39.388097,25.257187 L 45.279046,24.279744 C 45.328399,23.692424 45.330802,22.054578 45.18399,21.052439 L 39.182092,20.016922 C 38.73404,18.362463 37.196418,15.381153 36.265359,13.993342 L 40.080075,9.1907857 C 39.037052,7.915218 38.64924,7.7402002 37.338448,6.7398212 L 32.313994,10.337839 C 30.918941,9.5127782 28.137095,8.2550417 26.507114,7.8966842 L 25.619528,2.1484671 C 24.806414,2.0528187 22.460488,2.0952921 21.995808,2.1484671 z "
style="opacity:0.34659089;color:#000000;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.99999923;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
sodipodi:nodetypes="ccccccccccccccccccccccccccccccccc" />
<path
style="opacity:0.5;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 10.102903,6.2970655 C 8.7545689,7.3438694 8.1656464,7.9719226 7.0874684,9.2941942 L 10.489927,14.259153 C 9.4385072,15.857755 8.3316275,18.426114 8.1423859,19.987706 C 8.1423859,19.987706 2.0798859,21.0319 2.0798859,21.0319 C 2.0109129,21.595256 1.90625,22.884803 1.90625,22.884803 L 2.0830267,24.447303 C 2.5107567,24.535638 2.9231817,24.617818 3.3642767,24.666053 L 3.8642767,23.134803 C 4.2083177,23.163279 4.5439297,23.197303 4.8955267,23.197303 C 5.2467347,23.197303 5.6139847,23.163473 5.9580267,23.134803 L 6.4267767,24.666053 C 6.8680647,24.617818 7.3115487,24.535638 7.7392767,24.447303 L 7.7392767,22.884803 C 8.4250337,22.72518 9.0712777,22.497045 9.7080267,22.228553 L 10.645527,23.509803 C 11.047878,23.327709 11.421123,23.133984 11.801777,22.916053 L 11.301777,21.416053 C 11.89901,21.053803 12.463529,20.620706 12.989277,20.166053 L 14.270527,21.103553 C 14.596162,20.806973 14.91164,20.491691 15.208027,20.166053 L 14.270527,18.916053 C 14.725373,18.390305 15.127027,17.826171 15.489277,17.228553 L 16.989277,17.697303 C 17.207208,17.316456 17.432571,16.943209 17.614277,16.541053 L 16.333027,15.603553 C 16.601517,14.966804 16.798016,14.320561 16.958027,13.634803 L 18.551777,13.634803 C 18.640112,13.207076 18.691236,12.763591 18.739277,12.322303 L 17.239277,11.853553 C 17.268139,11.509705 17.301777,11.142456 17.301777,10.791053 C 17.301776,10.43965 17.267753,10.104039 17.239277,9.7598034 L 18.739277,9.2910534 C 18.69373,8.8711662 18.633686,8.4490548 18.551777,8.0410534 C 17.404349,8.4403544 15.999117,9.1941729 14.983265,9.8245243 L 10.102903,6.2970655 z "
id="path3767"
inkscape:r_cx="true"
inkscape:r_cy="true"
sodipodi:nodetypes="cccccccccsccccccccccccccccccccsccccc" />
<path
style="opacity:0.5;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 37.236641,17.217754 C 36.85286,17.39913 36.490003,17.603509 36.123236,17.813295 L 36.692886,19.548136 C 35.995792,19.970436 35.338156,20.467825 34.725008,20.998151 L 33.249099,19.910639 C 32.869013,20.256538 32.507327,20.618223 32.161588,20.998151 L 33.249099,22.474059 C 32.718773,23.087371 32.221547,23.745002 31.799084,24.441937 L 31.255328,24.260685 C 31.207646,24.960968 31.018949,25.62217 30.737466,26.228563 L 30.841038,26.306242 C 30.527881,27.048922 30.27649,27.83664 30.090137,28.636624 L 28.614229,28.636624 C 28.477946,28.722076 28.343676,28.821684 28.199938,28.895555 C 28.121568,29.310822 28.065026,29.712881 28.018687,30.138426 L 29.77942,30.708074 C 29.746033,31.10935 29.727633,31.515269 29.727633,31.925052 C 29.727631,32.334993 29.746034,32.740753 29.77942,33.142029 L 28.018687,33.711677 C 28.074705,34.226432 28.148678,34.740347 28.251725,35.239372 L 30.090137,35.213479 C 30.218255,35.763466 30.393202,36.320918 30.582107,36.844746 C 31.327023,36.557466 32.05594,36.214561 32.731236,35.809021 C 32.319649,34.59298 32.083908,33.279913 32.083908,31.925052 C 32.083909,26.727119 35.376289,22.288397 39.981313,20.583861 L 38.893802,20.402608 C 38.671014,19.579946 38.382478,18.774017 38.013435,18.020441 C 38.002581,17.998277 37.99851,17.96486 37.987542,17.942761 L 37.935756,17.890975 L 37.236641,17.217754 z "
id="path3770"
inkscape:r_cx="true"
inkscape:r_cy="true" />
</g>
</svg>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48.000000px"
height="48.000000px"
id="svg97"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/status"
sodipodi:docname="folder-open.svg"
inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/snowdunes/gnome-fs-directory-accept.png"
inkscape:export-xdpi="90.000000"
inkscape:export-ydpi="90.000000"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 24 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="48 : 24 : 1"
inkscape:persp3d-origin="24 : 16 : 1"
id="perspective75" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5060"
id="radialGradient6719"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<linearGradient
inkscape:collect="always"
id="linearGradient5060">
<stop
style="stop-color:black;stop-opacity:1;"
offset="0"
id="stop5062" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5064" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient5060"
id="radialGradient6717"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
cx="605.71429"
cy="486.64789"
fx="605.71429"
fy="486.64789"
r="117.14286" />
<linearGradient
id="linearGradient5048">
<stop
style="stop-color:black;stop-opacity:0;"
offset="0"
id="stop5050" />
<stop
id="stop5056"
offset="0.5"
style="stop-color:black;stop-opacity:1;" />
<stop
style="stop-color:black;stop-opacity:0;"
offset="1"
id="stop5052" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient5048"
id="linearGradient6715"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
x1="302.85715"
y1="366.64789"
x2="302.85715"
y2="609.50507" />
<linearGradient
inkscape:collect="always"
id="linearGradient13842">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop13844" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop13846" />
</linearGradient>
<linearGradient
id="linearGradient9766">
<stop
style="stop-color:#6194cb;stop-opacity:1;"
offset="0"
id="stop9768" />
<stop
style="stop-color:#729fcf;stop-opacity:1;"
offset="1"
id="stop9770" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient9806">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop9808" />
<stop
style="stop-color:#000000;stop-opacity:0;"
offset="1"
id="stop9810" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient9806"
id="radialGradient9812"
cx="24.35099"
cy="41.591846"
fx="24.35099"
fy="41.591846"
r="19.136078"
gradientTransform="matrix(1.000000,0.000000,0.000000,0.242494,1.565588e-16,31.50606)"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient148">
<stop
style="stop-color:#ffffff;stop-opacity:0.13402061;"
offset="0.0000000"
id="stop149" />
<stop
style="stop-color:#ffffff;stop-opacity:0.051546391;"
offset="1.0000000"
id="stop150" />
</linearGradient>
<linearGradient
id="linearGradient335">
<stop
style="stop-color:#ffffff;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop336" />
<stop
style="stop-color:#ffffff;stop-opacity:0.0000000;"
offset="1.0000000"
id="stop337" />
</linearGradient>
<linearGradient
id="linearGradient1789">
<stop
style="stop-color:#a0a0a0;stop-opacity:1;"
offset="0"
id="stop1790" />
<stop
style="stop-color:#a8a8a8;stop-opacity:1;"
offset="1"
id="stop1791" />
</linearGradient>
<linearGradient
id="linearGradient137">
<stop
style="stop-color:#ffffff;stop-opacity:0.70059878;"
offset="0.0000000"
id="stop138" />
<stop
style="stop-color:#ffffff;stop-opacity:0.0000000;"
offset="1.0000000"
id="stop139" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient335"
id="linearGradient155"
gradientUnits="userSpaceOnUse"
gradientTransform="scale(1.421537,0.703464)"
x1="19.116116"
y1="28.946041"
x2="19.426924"
y2="51.912693" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient148"
id="linearGradient156"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.535299,0,0,0.651339,3.451418,2.448)"
x1="14.899379"
y1="27.059643"
x2="22.715446"
y2="41.836895" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient137"
id="linearGradient158"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.462696,0,6.907908e-2,0.683669,-8.7075e-19,0)"
x1="5.2657914"
y1="18.725863"
x2="8.2122240"
y2="52.625851" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient1789"
id="radialGradient159"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.015635,0,0.103105,1.000512,-6.73857e-18,-8.369458e-2)"
cx="26.106777"
cy="38.195114"
fx="26.106777"
fy="38.195114"
r="32.259769" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient9766"
id="linearGradient13162"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,1.022118,52.05694,-1.323026)"
x1="22.175976"
y1="36.987999"
x2="22.065331"
y2="32.050499" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient13842"
id="linearGradient13848"
x1="22.25"
y1="37.625"
x2="19.75"
y2="14.875"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="10.54135"
inkscape:cx="8.8898314"
inkscape:cy="26.16018"
inkscape:current-layer="layer3"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1027"
inkscape:window-height="818"
inkscape:window-x="271"
inkscape:window-y="30"
inkscape:showpageshadow="false" />
<metadata
id="metadata4">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Folder Icon Accept</dc:title>
<dc:date>2005-01-31</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
<dc:source>http://jimmac.musichall.cz</dc:source>
<dc:description>Active state - when files are being dragged to.</dc:description>
<dc:publisher>
<cc:Agent>
<dc:title>Novell, Inc.</dc:title>
</cc:Agent>
</dc:publisher>
<dc:contributor>
<cc:Agent>
<dc:title>Garrett LeSage</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Folder"
inkscape:groupmode="layer" />
<g
inkscape:label="Open"
id="layer3"
inkscape:groupmode="layer">
<g
style="display:inline"
transform="matrix(2.262383e-2,0,0,2.086758e-2,43.38343,36.36962)"
id="g6707">
<rect
style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="rect6709"
width="1339.6335"
height="478.35718"
x="-1559.2523"
y="-150.69685" />
<path
style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
id="path6711"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
id="path6713"
d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
</g>
<path
sodipodi:nodetypes="ccccccssssccc"
style="color:#000000;fill:url(#radialGradient159);fill-opacity:1;fill-rule:nonzero;stroke:#5a5a5a;stroke-width:0.99487108;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
id="path2375"
d="M 4.6200285,38.651015 C 4.6618365,39.07147 5.1174141,39.491924 5.5311838,39.491924 L 36.667346,39.491924 C 37.081116,39.491924 37.453078,39.07147 37.41127,38.651015 L 34.714653,11.531728 C 34.672845,11.111274 34.217267,10.69082 33.803498,10.69082 L 21.080082,10.69082 C 20.489536,10.69082 19.870999,10.311268 19.677221,9.7304849 L 18.574219,6.4246085 C 18.404967,5.9173308 18.027069,5.6888138 17.259746,5.6888138 L 2.3224188,5.6888138 C 1.9086492,5.6888138 1.5366876,6.109268 1.5784956,6.529722 L 4.6200285,38.651015 z "
transform="matrix(1.004486,0,0,1.005825,-8.234449e-2,-0.221964)"
inkscape:r_cx="true"
inkscape:r_cy="true" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 5.3301525,37.533487 L 35.317907,37.533487"
id="path13160"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13139"
d="M 5.3301525,35.533487 L 35.317907,35.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
sodipodi:nodetypes="ccccccsscsscccc"
id="path2380"
d="M 6.1717518,38.418674 C 6.2031078,38.729001 6.017127,38.935886 5.6963478,38.832443 L 5.6963478,38.832443 C 5.3755686,38.729001 5.1477798,38.522116 5.1164238,38.211789 L 2.0868572,6.8445942 C 2.0555012,6.534267 2.2434512,6.3468711 2.5537784,6.3468711 L 17.303531,6.2554251 C 17.834815,6.2521313 18.04296,6.308731 18.18333,6.7726371 C 18.18333,6.7726371 19.268704,9.885435 19.429564,10.470742 L 17.873968,7.5537061 C 17.608788,7.0564434 17.275224,7.1399365 16.901178,7.1399365 L 3.7717775,7.1399365 C 3.4614503,7.1399365 3.2754695,7.3468213 3.3068255,7.6571485 L 6.2856462,38.522116 L 6.1717518,38.418674 z "
style="color:#000000;fill:url(#linearGradient158);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.17341149;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
transform="matrix(1.008872,0,0,1.012144,-0.101943,-0.33126)"
inkscape:r_cx="true"
inkscape:r_cy="true" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 3.3386019,17.533487 L 34.488461,17.533487"
id="path13113"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13115"
d="M 2.7573333,11.533487 L 33.496214,11.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<g
inkscape:export-ydpi="74.800003"
inkscape:export-xdpi="74.800003"
inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
transform="matrix(1.034503,0,0.104528,1.035221,-9.922058,2.395183)"
id="g2381"
style="fill:#ffffff;fill-opacity:0.5803109;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4;display:block"
inkscape:r_cx="true"
inkscape:r_cy="true">
<path
sodipodi:nodetypes="cscscs"
id="path2382"
d="M 41.785743,9.0363862 C 41.795369,8.5618034 41.800932,8.3118806 41.36235,8.312183 L 28.80653,8.3208402 C 28.50653,8.3208402 28.481916,8.1776341 28.80653,8.3208402 C 29.131144,8.4640463 30.053628,8.9791114 30.989227,9.0218349 C 30.989227,9.0218349 41.785704,9.0382983 41.785743,9.0363862 z "
style="stroke:none"
inkscape:r_cx="true"
inkscape:r_cy="true" />
</g>
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 5.1594716,33.533487 L 35.147226,33.533487"
id="path13121"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13119"
d="M 4.8658086,31.533487 L 34.974533,31.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 4.6336367,29.533487 L 34.802847,29.533487"
id="path13135"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13137"
d="M 4.4629557,27.533487 L 34.632166,27.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 4.2556718,25.533487 L 34.460793,25.533487"
id="path13143"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13133"
d="M 4.0235198,23.533487 L 34.289101,23.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 3.8528389,21.533487 L 34.11842,21.533487"
id="path13117"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13125"
d="M 3.6514189,19.533487 L 33.947215,19.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.39204545;color:#000000;fill:url(#linearGradient13848);fill-opacity:1.0;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
d="M 34.375,14.125 L 37,38.75 L 6,38.875 C 6,38.875 4.125,14.125 4.125,14.125 C 4.125,14.125 34.5,14.125 34.375,14.125 z "
id="path13840"
sodipodi:nodetypes="cccsc" />
<path
inkscape:export-ydpi="74.800003"
inkscape:export-xdpi="74.800003"
inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
sodipodi:nodetypes="cccsscccscc"
id="path2401"
d="M 5.7785654,39.065997 C 5.8820074,39.277466 6.0888914,39.488925 6.3992173,39.488925 L 39.70767,39.488925 C 39.914562,39.488925 40.228834,39.36262 40.415844,39.224574 C 40.946246,38.833039 41.070704,38.612189 41.308626,38.251107 C 43.756752,34.535647 47.113767,18.974214 47.113767,18.974214 C 47.217209,18.762754 47.010326,18.551294 46.7,18.551294 L 11.776358,18.551294 C 11.466032,18.551294 10.120393,34.658624 6.9133592,37.838317 L 5.6751235,39.065997 L 5.7785654,39.065997 z "
style="opacity:1;color:#000000;fill:url(#linearGradient13162);fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:1.00416672;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
transform="matrix(0.988773,0,0,1.002979,-0.111407,-0.106563)"
inkscape:r_cx="true"
inkscape:r_cy="true" />
<path
id="path323"
d="M 13.134476,20.138641 C 12.361729,25.129398 11.633175,29.147884 10.418486,33.652505 C 12.804971,32.945398 17.534602,30.448 27.534602,30.448 C 37.534602,30.448 44.258175,21.199301 45.186253,20.094447 L 13.134476,20.138641 z "
style="fill:url(#linearGradient156);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
sodipodi:nodetypes="ccccc"
transform="matrix(0.988773,0,0,1.002979,-0.111407,-0.106563)"
inkscape:r_cx="true"
inkscape:r_cy="true" />
<path
style="opacity:0.52272728;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient155);stroke-width:1.00416696px;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 45.820083,19.6875 L 12.661612,19.6875 C 12.661612,19.6875 10.513864,35.707107 7.9393398,37.928078 C 16.060417,37.928078 39.510511,37.879442 39.53033,37.879442 C 41.281989,37.879442 44.437971,25.243248 45.820083,19.6875 z "
id="path324"
sodipodi:nodetypes="cccsc"
transform="matrix(0.988773,0,0,1.002979,-0.111407,-0.106563)"
inkscape:r_cx="true"
inkscape:r_cy="true" />
<path
sodipodi:nodetypes="cc"
id="path13123"
d="M 3.1628954,15.533487 L 33.993452,15.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 2.9642313,13.533487 L 33.990735,13.533487"
id="path13127"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path13145"
d="M 2.3052333,7.533487 L 17.088967,7.533487"
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.99999982;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
<path
style="opacity:0.11363633;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.00000024;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 2.5242572,9.5334871 L 17.805073,9.5334871"
id="path13147"
sodipodi:nodetypes="cc" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="pattern" />
</svg>
This software is published under GNU GENERAL PUBLIC LICENSE 3
TERMS AND CONDITIONS
0. Definitions.
“This License” refers to version 3 of the GNU General Public License.
“Copyright” also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
“The Program” refers to any copyrightable work licensed under this License. Each licensee is addressed as “you”. “Licensees” and “recipients” may be individuals or organizations.
To “modify” a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version” of the earlier work or a work “based on” the earlier work.
A “covered work” means either the unmodified Program or a work based on the Program.
To “propagate” a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To “convey” a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays “Appropriate Legal Notices” to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
1. Source Code.
The “source code” for a work means the preferred form of the work for making modifications to it. “Object code” means any non-source form of a work.
A “Standard Interface” means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The “System Libraries” of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Component”, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The “Corresponding Source” for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
* a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
* b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all notices”.
* c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
* d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate” if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
* a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
* b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
* c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
* d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
* e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A “User Product” is either (1) a “consumer product”, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used” refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
“Installation Information” for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
“Additional permissions” are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
* a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
* b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
* c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
* d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
* e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
* f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered “further restrictions” within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An “entity transaction” is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A “contributor” is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor version”.
A contributor's “essential patent claims” are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control” includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a “patent license” is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant” such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying” means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is “discriminatory” if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
/*=====================================================================
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();
}
# Third-party includes.
# if you include this file with the commands below into
# your Qt project, you can enable your application
# to generate MAVLink code easily.
###### EXAMPLE BEGIN
## Include MAVLink generator
#DEPENDPATH += \
# src/apps/mavlinkgen
#
#INCLUDEPATH += \
# src/apps/mavlinkgen
# src/apps/mavlinkgen/ui \
# src/apps/mavlinkgen/generator
#
#include(src/apps/mavlinkgen/mavlinkgen.pri)
###### EXAMPLE END
INCLUDEPATH += .\
ui \
generator
FORMS += ui/XMLCommProtocolWidget.ui
HEADERS += \
ui/XMLCommProtocolWidget.h \
generator/MAVLinkXMLParser.h \
generator/MAVLinkXMLParserV10.h \
ui/DomItem.h \
ui/DomModel.h \
ui/QGCMAVLinkTextEdit.h
SOURCES += \
ui/XMLCommProtocolWidget.cc \
ui/DomItem.cc \
ui/DomModel.cc \
generator/MAVLinkXMLParser.cc \
generator/MAVLinkXMLParserV10.cc \
ui/QGCMAVLinkTextEdit.cc
RESOURCES += mavlinkgen.qrc
# MAVLink code generator
# generates code in several languages for MAVLink encoding/decoding
QT += svg xml
TEMPLATE = app
TARGET = mavlinkgen
LANGUAGE = C++
# Widget files (can be included in third-party Qt applications)
include(mavlinkgen.pri)
# Standalone files
HEADERS += MAVLinkGen.h
win32-msvc2008|win32-msvc2010 {
HEADERS += msinttypes/inttypes.h \
msinttypes/stdint.h
INCLUDEPATH += msinttypes
}
SOURCES += main.cc \
MAVLinkGen.cc
<RCC>
<qresource prefix="/">
<file>images/categories/applications-system.svg</file>
<file>images/status/folder-open.svg</file>
</qresource>
</RCC>
// ISO C9x compliant inttypes.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_INTTYPES_H_ // [
#define _MSC_INTTYPES_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include "stdint.h"
// 7.8 Format conversion of integer types
typedef struct {
intmax_t quot;
intmax_t rem;
} imaxdiv_t;
// 7.8.1 Macros for format specifiers
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
// The fprintf macros for signed integers are:
#define PRId8 "d"
#define PRIi8 "i"
#define PRIdLEAST8 "d"
#define PRIiLEAST8 "i"
#define PRIdFAST8 "d"
#define PRIiFAST8 "i"
#define PRId16 "hd"
#define PRIi16 "hi"
#define PRIdLEAST16 "hd"
#define PRIiLEAST16 "hi"
#define PRIdFAST16 "hd"
#define PRIiFAST16 "hi"
#define PRId32 "I32d"
#define PRIi32 "I32i"
#define PRIdLEAST32 "I32d"
#define PRIiLEAST32 "I32i"
#define PRIdFAST32 "I32d"
#define PRIiFAST32 "I32i"
#define PRId64 "I64d"
#define PRIi64 "I64i"
#define PRIdLEAST64 "I64d"
#define PRIiLEAST64 "I64i"
#define PRIdFAST64 "I64d"
#define PRIiFAST64 "I64i"
#define PRIdMAX "I64d"
#define PRIiMAX "I64i"
#define PRIdPTR "Id"
#define PRIiPTR "Ii"
// The fprintf macros for unsigned integers are:
#define PRIo8 "o"
#define PRIu8 "u"
#define PRIx8 "x"
#define PRIX8 "X"
#define PRIoLEAST8 "o"
#define PRIuLEAST8 "u"
#define PRIxLEAST8 "x"
#define PRIXLEAST8 "X"
#define PRIoFAST8 "o"
#define PRIuFAST8 "u"
#define PRIxFAST8 "x"
#define PRIXFAST8 "X"
#define PRIo16 "ho"
#define PRIu16 "hu"
#define PRIx16 "hx"
#define PRIX16 "hX"
#define PRIoLEAST16 "ho"
#define PRIuLEAST16 "hu"
#define PRIxLEAST16 "hx"
#define PRIXLEAST16 "hX"
#define PRIoFAST16 "ho"
#define PRIuFAST16 "hu"
#define PRIxFAST16 "hx"
#define PRIXFAST16 "hX"
#define PRIo32 "I32o"
#define PRIu32 "I32u"
#define PRIx32 "I32x"
#define PRIX32 "I32X"
#define PRIoLEAST32 "I32o"
#define PRIuLEAST32 "I32u"
#define PRIxLEAST32 "I32x"
#define PRIXLEAST32 "I32X"
#define PRIoFAST32 "I32o"
#define PRIuFAST32 "I32u"
#define PRIxFAST32 "I32x"
#define PRIXFAST32 "I32X"
#define PRIo64 "I64o"
#define PRIu64 "I64u"
#define PRIx64 "I64x"
#define PRIX64 "I64X"
#define PRIoLEAST64 "I64o"
#define PRIuLEAST64 "I64u"
#define PRIxLEAST64 "I64x"
#define PRIXLEAST64 "I64X"
#define PRIoFAST64 "I64o"
#define PRIuFAST64 "I64u"
#define PRIxFAST64 "I64x"
#define PRIXFAST64 "I64X"
#define PRIoMAX "I64o"
#define PRIuMAX "I64u"
#define PRIxMAX "I64x"
#define PRIXMAX "I64X"
#define PRIoPTR "Io"
#define PRIuPTR "Iu"
#define PRIxPTR "Ix"
#define PRIXPTR "IX"
// The fscanf macros for signed integers are:
#define SCNd8 "d"
#define SCNi8 "i"
#define SCNdLEAST8 "d"
#define SCNiLEAST8 "i"
#define SCNdFAST8 "d"
#define SCNiFAST8 "i"
#define SCNd16 "hd"
#define SCNi16 "hi"
#define SCNdLEAST16 "hd"
#define SCNiLEAST16 "hi"
#define SCNdFAST16 "hd"
#define SCNiFAST16 "hi"
#define SCNd32 "ld"
#define SCNi32 "li"
#define SCNdLEAST32 "ld"
#define SCNiLEAST32 "li"
#define SCNdFAST32 "ld"
#define SCNiFAST32 "li"
#define SCNd64 "I64d"
#define SCNi64 "I64i"
#define SCNdLEAST64 "I64d"
#define SCNiLEAST64 "I64i"
#define SCNdFAST64 "I64d"
#define SCNiFAST64 "I64i"
#define SCNdMAX "I64d"
#define SCNiMAX "I64i"
#ifdef _WIN64 // [
# define SCNdPTR "I64d"
# define SCNiPTR "I64i"
#else // _WIN64 ][
# define SCNdPTR "ld"
# define SCNiPTR "li"
#endif // _WIN64 ]
// The fscanf macros for unsigned integers are:
#define SCNo8 "o"
#define SCNu8 "u"
#define SCNx8 "x"
#define SCNX8 "X"
#define SCNoLEAST8 "o"
#define SCNuLEAST8 "u"
#define SCNxLEAST8 "x"
#define SCNXLEAST8 "X"
#define SCNoFAST8 "o"
#define SCNuFAST8 "u"
#define SCNxFAST8 "x"
#define SCNXFAST8 "X"
#define SCNo16 "ho"
#define SCNu16 "hu"
#define SCNx16 "hx"
#define SCNX16 "hX"
#define SCNoLEAST16 "ho"
#define SCNuLEAST16 "hu"
#define SCNxLEAST16 "hx"
#define SCNXLEAST16 "hX"
#define SCNoFAST16 "ho"
#define SCNuFAST16 "hu"
#define SCNxFAST16 "hx"
#define SCNXFAST16 "hX"
#define SCNo32 "lo"
#define SCNu32 "lu"
#define SCNx32 "lx"
#define SCNX32 "lX"
#define SCNoLEAST32 "lo"
#define SCNuLEAST32 "lu"
#define SCNxLEAST32 "lx"
#define SCNXLEAST32 "lX"
#define SCNoFAST32 "lo"
#define SCNuFAST32 "lu"
#define SCNxFAST32 "lx"
#define SCNXFAST32 "lX"
#define SCNo64 "I64o"
#define SCNu64 "I64u"
#define SCNx64 "I64x"
#define SCNX64 "I64X"
#define SCNoLEAST64 "I64o"
#define SCNuLEAST64 "I64u"
#define SCNxLEAST64 "I64x"
#define SCNXLEAST64 "I64X"
#define SCNoFAST64 "I64o"
#define SCNuFAST64 "I64u"
#define SCNxFAST64 "I64x"
#define SCNXFAST64 "I64X"
#define SCNoMAX "I64o"
#define SCNuMAX "I64u"
#define SCNxMAX "I64x"
#define SCNXMAX "I64X"
#ifdef _WIN64 // [
# define SCNoPTR "I64o"
# define SCNuPTR "I64u"
# define SCNxPTR "I64x"
# define SCNXPTR "I64X"
#else // _WIN64 ][
# define SCNoPTR "lo"
# define SCNuPTR "lu"
# define SCNxPTR "lx"
# define SCNXPTR "lX"
#endif // _WIN64 ]
#endif // __STDC_FORMAT_MACROS ]
// 7.8.2 Functions for greatest-width integer types
// 7.8.2.1 The imaxabs function
#define imaxabs _abs64
// 7.8.2.2 The imaxdiv function
// This is modified version of div() function from Microsoft's div.c found
// in %MSVC.NET%\crt\src\div.c
#ifdef STATIC_IMAXDIV // [
static
#else // STATIC_IMAXDIV ][
_inline
#endif // STATIC_IMAXDIV ]
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
{
imaxdiv_t result;
result.quot = numer / denom;
result.rem = numer % denom;
if (numer < 0 && result.rem > 0) {
// did division wrong; must fix up
++result.quot;
result.rem -= denom;
}
return result;
}
// 7.8.2.3 The strtoimax and strtoumax functions
#define strtoimax _strtoi64
#define strtoumax _strtoui64
// 7.8.2.4 The wcstoimax and wcstoumax functions
#define wcstoimax _wcstoi64
#define wcstoumax _wcstoui64
#endif // _MSC_INTTYPES_H_ ]
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN ((int8_t)_I8_MIN)
#define INT8_MAX _I8_MAX
#define INT16_MIN ((int16_t)_I16_MIN)
#define INT16_MAX _I16_MAX
#define INT32_MIN ((int32_t)_I32_MIN)
#define INT32_MAX _I32_MAX
#define INT64_MIN ((int64_t)_I64_MIN)
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _CHECKSUM_H_
#define _CHECKSUM_H_
#include "inttypes.h"
/**
*
* CALCULATE THE CHECKSUM
*
*/
#define X25_INIT_CRC 0xffff
#define X25_VALIDATE_CRC 0xf0b8
/**
* @brief Accumulate the X.25 CRC by adding one char at a time.
*
* The checksum function adds the hash of one char at a time to the
* 16 bit checksum (uint16_t).
*
* @param data new char to hash
* @param crcAccum the already accumulated checksum
**/
static inline void crc_accumulate(uint8_t data, uint16_t *crcAccum)
{
/*Accumulate one byte of data into the CRC*/
uint8_t tmp;
tmp=data ^ (uint8_t)(*crcAccum &0xff);
tmp^= (tmp<<4);
*crcAccum = (*crcAccum>>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4);
// *crcAccum += data; // super simple to test
}
/**
* @brief Initiliaze the buffer for the X.25 CRC
*
* @param crcAccum the 16 bit X.25 CRC
*/
static inline void crc_init(uint16_t* crcAccum)
{
*crcAccum = X25_INIT_CRC;
}
/**
* @brief Calculates the X.25 checksum on a byte buffer
*
* @param pBuffer buffer containing the byte array to hash
* @param length length of the byte array
* @return the checksum over the buffer bytes
**/
static inline uint16_t crc_calculate(uint8_t* pBuffer, int length)
{
// For a "message" of length bytes contained in the unsigned char array
// pointed to by pBuffer, calculate the CRC
// crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed
uint16_t crcTmp;
//uint16_t tmp;
uint8_t* pTmp;
int i;
pTmp=pBuffer;
/* init crcTmp */
crc_init(&crcTmp);
for (i = 0; i < length; i++){
crc_accumulate(*pTmp++, &crcTmp);
}
/* This is currently not needed, as only the checksum over payload should be computed
tmp = crcTmp;
crcAccumulate((unsigned char)(~crcTmp & 0xff),&tmp);
crcAccumulate((unsigned char)((~crcTmp>>8)&0xff),&tmp);
*checkConst = tmp;
*/
return(crcTmp);
}
/**
* @brief Calculates the X.25 checksum on a msg buffer
*
* @param pMSG buffer containing the msg to hash
* @param length number of bytes to hash
* @return the checksum over the buffer bytes
**/
static inline uint16_t crc_calculate_msg(mavlink_message_t* pMSG, int length)
{
// For a "message" of length bytes contained in the unsigned char array
// pointed to by pBuffer, calculate the CRC
// crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed
uint16_t crcTmp;
//uint16_t tmp;
uint8_t* pTmp;
int i;
pTmp=&pMSG->len;
/* init crcTmp */
crc_init(&crcTmp);
for (i = 0; i < 5; i++){
crc_accumulate(*pTmp++, &crcTmp);
}
pTmp=&pMSG->payload[0];
for (; i < length; i++){
crc_accumulate(*pTmp++, &crcTmp);
}
/* This is currently not needed, as only the checksum over payload should be computed
tmp = crcTmp;
crcAccumulate((unsigned char)(~crcTmp & 0xff),&tmp);
crcAccumulate((unsigned char)((~crcTmp>>8)&0xff),&tmp);
*checkConst = tmp;
*/
return(crcTmp);
}
#endif /* _CHECKSUM_H_ */
#ifdef __cplusplus
}
#endif
/**
* @file
* @brief MAVLink communication protocol
*
* @author Lorenz Meier <mavteam@student.ethz.ch>
*
*/
/**
* @mainpage MAVLink API Documentation
*
* @section intro_sec Introduction
*
* This <a href="http://en.wikipedia.org/wiki/API" target="_blank">API</a> documentation covers the MAVLink
* protocol developed <a href="http://pixhawk.ethz.ch" target="_blank">PIXHAWK</a> project.
* In case you have generated this documentation locally, the most recent version (generated on every commit)
* is also publicly available on the internet.
*
* @sa http://pixhawk.ethz.ch/api/qgroundcontrol/ - Groundstation code base
* @sa http://pixhawk.ethz.ch/api/mavlink - (this) MAVLink communication protocol
* @sa http://pixhawk.ethz.ch/api/imu_autopilot/ - Flight board (ARM MCU) code base
* @sa http://pixhawk.ethz.ch/api/ai_vision - Computer Vision / AI API docs
*
* @section further_sec Further Information
*
* How to run our software and a general overview of the software architecture is documented in the project
* wiki pages.
*
* @sa http://pixhawk.ethz.ch/software/mavlink/ - MAVLink main documentation
*
* See the <a href="http://pixhawk.ethz.ch" target="_blank">PIXHAWK website</a> for more information.
*
* @section usage_sec Doxygen Usage
*
* You can exclude files from being parsed into this Doxygen documentation
* by adding them to the EXCLUDE list in the file in embedded/cmake/doc/api/doxy.config.in.
*
*
*
**/
/** @file
* @brief MAVLink comm protocol checksum routines.
* @see http://qgroundcontrol.org/mavlink/
* Edited on Monday, August 8 2011
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _CHECKSUM_H_
#define _CHECKSUM_H_
#include "inttypes.h"
/**
*
* CALCULATE THE CHECKSUM
*
*/
#define X25_INIT_CRC 0xffff
#define X25_VALIDATE_CRC 0xf0b8
/**
* @brief Accumulate the X.25 CRC by adding one char at a time.
*
* The checksum function adds the hash of one char at a time to the
* 16 bit checksum (uint16_t).
*
* @param data new char to hash
* @param crcAccum the already accumulated checksum
**/
static inline void crc_accumulate(uint8_t data, uint16_t *crcAccum)
{
/*Accumulate one byte of data into the CRC*/
uint8_t tmp;
tmp=data ^ (uint8_t)(*crcAccum &0xff);
tmp^= (tmp<<4);
*crcAccum = (*crcAccum>>8) ^ (tmp<<8) ^ (tmp <<3) ^ (tmp>>4);
// *crcAccum += data; // super simple to test
}
/**
* @brief Initiliaze the buffer for the X.25 CRC
*
* @param crcAccum the 16 bit X.25 CRC
*/
static inline void crc_init(uint16_t* crcAccum)
{
*crcAccum = X25_INIT_CRC;
}
/**
* @brief Initiliaze the buffer for the X.25 CRC to a specified value
*
* @param crcAccum the 16 bit X.25 CRC
*/
static inline void crc_init2(uint16_t* crcAccum, uint16_t crcValue)
{
*crcAccum = crcValue;
}
/**
* @brief Calculates the X.25 checksum on a byte buffer
*
* @param pBuffer buffer containing the byte array to hash
* @param length length of the byte array
* @return the checksum over the buffer bytes
**/
static inline uint16_t crc_calculate(uint8_t* pBuffer, int length)
{
// For a "message" of length bytes contained in the unsigned char array
// pointed to by pBuffer, calculate the CRC
// crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed
uint16_t crcTmp;
//uint16_t tmp;
uint8_t* pTmp;
int i;
pTmp=pBuffer;
/* init crcTmp */
crc_init(&crcTmp);
for (i = 0; i < length; i++){
crc_accumulate(*pTmp++, &crcTmp);
}
/* This is currently not needed, as only the checksum over payload should be computed
tmp = crcTmp;
crcAccumulate((unsigned char)(~crcTmp & 0xff),&tmp);
crcAccumulate((unsigned char)((~crcTmp>>8)&0xff),&tmp);
*checkConst = tmp;
*/
return(crcTmp);
}
/**
* @brief Calculates the X.25 checksum on a byte buffer
*
* @param pBuffer buffer containing the byte array to hash
* @param length length of the byte array
* @return the checksum over the buffer bytes
**/
static inline uint16_t crc_calculate_mem(uint8_t *pBuffer, uint16_t *crcTmp, int length)
{
// For a "message" of length bytes contained in the unsigned char array
// pointed to by pBuffer, calculate the CRC
// crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed
//uint16_t tmp;
//uint8_t* pTmp;
int i;
// pTmp=pBuffer;
for (i = 0; i < length; i++){
crc_accumulate(*pBuffer++, crcTmp);
}
return(*crcTmp);
}
/**
* @brief Calculates the X.25 checksum on a msg buffer
*
* @param pMSG buffer containing the msg to hash
* @param length number of bytes to hash
* @return the checksum over the buffer bytes
**/
static inline uint16_t crc_calculate_msg(mavlink_message_t* pMSG, int length)
{
// For a "message" of length bytes contained in the unsigned char array
// pointed to by pBuffer, calculate the CRC
// crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed
uint16_t crcTmp;
//uint16_t tmp;
uint8_t* pTmp;
int i;
pTmp=&pMSG->len;
/* init crcTmp */
crc_init(&crcTmp);
for (i = 0; i < 5; i++){
crc_accumulate(*pTmp++, &crcTmp);
}
pTmp=&pMSG->payload[0];
for (; i < length; i++){
crc_accumulate(*pTmp++, &crcTmp);
}
/* This is currently not needed, as only the checksum over payload should be computed
tmp = crcTmp;
crcAccumulate((unsigned char)(~crcTmp & 0xff),&tmp);
crcAccumulate((unsigned char)((~crcTmp>>8)&0xff),&tmp);
*checkConst = tmp;
*/
return(crcTmp);
}
#endif /* _CHECKSUM_H_ */
#ifdef __cplusplus
}
#endif
/** @file
* @brief Main MAVLink comm protocol data.
* @see http://qgroundcontrol.org/mavlink/
* Edited on Monday, August 8 2011
*/
#ifndef _ML_DATA_H_
#define _ML_DATA_H_
#include "mavlink_types.h"
#ifdef MAVLINK_CHECK_LENGTH
const uint8_t MAVLINK_CONST mavlink_msg_lengths[256] = MAVLINK_MESSAGE_LENGTHS;
#endif
const uint8_t MAVLINK_CONST mavlink_msg_keys[256] = MAVLINK_MESSAGE_KEYS;
mavlink_status_t m_mavlink_status[MAVLINK_COMM_NB];
mavlink_message_t m_mavlink_message[MAVLINK_COMM_NB];
mavlink_system_t mavlink_system;
#endif
\ No newline at end of file
/** @file
* @brief MAVLink comm protocol option constants.
* @see http://qgroundcontrol.org/mavlink/
* Edited on Monday, August 8 2011
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ML_OPTIONS_H_
#define _ML_OPTIONS_H_
/**
*
* Receive message length check option. On receive verify the length field
* as soon as the message ID field is received. Requires a 256 byte const
* table. Comment out the define to leave out the table and code to check it.
*
*/
//#define MAVLINK_CHECK_LENGTH
/**
*
* Receive message buffer option. This option should be used only when the
* side effects are understood but allows the underlying program access to
* the internal recieve buffer - eliminating the usual double buffering. It
* also REQUIRES changes in the return type of mavlink_parse_char so only
* enable if you make the changes required. Default DISABLED.
*
*/
//#define MAVLINK_STATIC_BUFFER
/**
*
* Receive message buffers option. This option defines how many msg buffers
* mavlink will define, and thereby how many links it can support. A default
* will be supplied if the symbol is not pre-defined, dependant on the make
* envionment. The default is 16 for a recognised OS envionment and 1
* otherwise.
*
*/
#if !((defined MAVLINK_COMM_NB) | (MAVLINK_COMM_NB < 1))
#undef MAVLINK_COMM_NB
#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32) | (defined __APPLE__)
#define MAVLINK_COMM_NB 16
#else
#define MAVLINK_COMM_NB 1
#endif
#endif
/**
*
* Data relization option. This option controls inclusion of the file
* mavlink_data.h in the current compile unit - thus defining mavlink's
* variables. Default is ON (not defined) because typically mavlink.h is only
* included once in a system but if it was used in two files there would
* be duplicate variables at link time. Normal practice would be to define
* this symbol outside of this file as defining it here will cause missing
* symbols at link time. In other words in the first file to include mavlink.h
* do not define this sybol, then define this symbol in all other files before
* including mavlink.h
*
*/
//#define MAVLINK_NO_DATA
#ifdef MAVLINK_NO_DATA
#undef MAVLINK_DATA
#else
#define MAVLINK_DATA
#endif
/**
*
* Custom data const data relization and access options.
* This define is placed in the form
* const uint8_t MAVLINK_CONST name[] = { ... };
* for the keys table and (if applicable) lengths table to tell the compiler
* were to put the data. The access option is placed in the form
* variable = MAVLINK_CONST_READ( name[i] );
* in order to allow custom read function's or accessors.
* By default MAVLINK_CONST is defined as nothing and MAVLINK_CONST_READ as
* MAVLINK_CONST_READ( a ) a
* These symbols are only defined if not already defined allowing this file
* to remain unchanged while the actual definitions are maintained in external
* files.
*
*/
#ifndef MAVLINK_CONST
#define MAVLINK_CONST
#endif
#ifndef MAVLINK_CONST_READ
#define MAVLINK_CONST_READ( a ) a
#endif
/**
*
* Convience functions. These are all in one send functions that are very
* easy to use. Just define the symbol MAVLINK_USE_CONVENIENCE_FUNCTIONS.
* These functions also support a buffer check, to ensure there is enough
* space in your comm buffer that the function would not block - it could
* also be used as the basis of a MUTEX. This is implemented in the send
* function as a macro with two arguments, first the comm chan number and
* the message length in the form
* MAVLINK_BUFFER_CHECK_START( chan, MAVLINK_MSG_ID_LEN )
* followed by the function code and then
* MAVLINK_BUFFER_CHECK_START
* Note that there are no terminators on these statements to allow for
* code nesting or other constructs. Default value for both is empty.
* A sugested implementation is shown below and the symbols will be defined
* only if they are not allready.
*
* if ( serial_space( chan ) > len ) { // serial_space returns available space
* ..... code that creates message
* }
*
* #define MAVLINK_BUFFER_CHECK_START( c, l ) if ( serial_space( c ) > l ) {
* #define MAVLINK_BUFFER_CHECK_END }
*
*/
//#define MAVLINK_USE_CONVENIENCE_FUNCTIONS
#ifndef MAVLINK_BUFFER_CHECK_START
#define MAVLINK_BUFFER_CHECK_START( c, l ) ;
#endif
#ifndef MAVLINK_BUFFER_CHECK_END
#define MAVLINK_BUFFER_CHECK_END ;
#endif
#endif /* _ML_OPTIONS_H_ */
#ifdef __cplusplus
}
#endif
/** @file
* @brief Main MAVLink comm protocol routines.
* @see http://qgroundcontrol.org/mavlink/
* Edited on Monday, August 8 2011
*/
#ifndef _MAVLINK_PROTOCOL_H_
#define _MAVLINK_PROTOCOL_H_
#include "mavlink_types.h"
#include "mavlink_checksum.h"
#ifdef MAVLINK_CHECK_LENGTH
extern const uint8_t MAVLINK_CONST mavlink_msg_lengths[256];
#endif
extern const uint8_t MAVLINK_CONST mavlink_msg_keys[256];
extern mavlink_status_t m_mavlink_status[MAVLINK_COMM_NB];
extern mavlink_message_t m_mavlink_message[MAVLINK_COMM_NB];
extern mavlink_system_t mavlink_system;
/**
* @brief Initialize the communication stack
*
* This function has to be called before using commParseBuffer() to initialize the different status registers.
*
* @return Will initialize the different buffers and status registers.
*/
static void mavlink_parse_state_initialize(mavlink_status_t* initStatus)
{
if ((initStatus->parse_state <= MAVLINK_PARSE_STATE_UNINIT) || (initStatus->parse_state > MAVLINK_PARSE_STATE_GOT_CRC1))
{
initStatus->ck_a = 0;
initStatus->ck_b = 0;
initStatus->msg_received = 0;
initStatus->buffer_overrun = 0;
initStatus->parse_error = 0;
initStatus->parse_state = MAVLINK_PARSE_STATE_UNINIT;
initStatus->packet_idx = 0;
initStatus->packet_rx_drop_count = 0;
initStatus->packet_rx_success_count = 0;
initStatus->current_rx_seq = 0;
initStatus->current_tx_seq = 0;
}
}
static inline mavlink_status_t* mavlink_get_channel_status(uint8_t chan)
{
return &m_mavlink_status[chan];
}
/**
* @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel
*
* This function calculates the checksum and sets length and aircraft id correctly.
* It assumes that the message id and the payload are already correctly set.
*
* @warning This function implicitely assumes the message is sent over channel zero.
* if the message is sent over a different channel it will reach the receiver
* without error, BUT the sequence number might be wrong due to the wrong
* channel sequence counter. This will result is wrongly reported excessive
* packet loss. Please use @see mavlink_{pack|encode}_headerless and then
* @see mavlink_finalize_message_chan before sending for a correct channel
* assignment. Please note that the mavlink_msg_xxx_pack and encode functions
* assign channel zero as default and thus induce possible loss counter errors.\
* They have been left to ensure code compatibility.
*
* @see mavlink_finalize_message_chan
* @param msg Message to finalize
* @param system_id Id of the sending (this) system, 1-127
* @param length Message length, usually just the counter incremented while packing the message
*/
static inline uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, uint16_t length)
{
// This code part is the same for all messages;
uint8_t key;
msg->len = length;
msg->sysid = system_id;
msg->compid = component_id;
// One sequence number per component
msg->seq = mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq;
mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq = mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq+1;
msg->ck = crc_calculate_msg(msg, length + MAVLINK_CORE_HEADER_LEN);
key = MAVLINK_CONST_READ( mavlink_msg_keys[msg->msgid] );
crc_accumulate( key, &msg->ck ); /// include key in X25 checksum
return length + MAVLINK_NUM_NON_STX_PAYLOAD_BYTES;
}
/**
* @brief Finalize a MAVLink message with channel assignment
*
* This function calculates the checksum and sets length and aircraft id correctly.
* It assumes that the message id and the payload are already correctly set. This function
* can also be used if the message header has already been written before (as in mavlink_msg_xxx_pack
* instead of mavlink_msg_xxx_pack_headerless), it just introduces little extra overhead.
*
* @param msg Message to finalize
* @param system_id Id of the sending (this) system, 1-127
* @param length Message length, usually just the counter incremented while packing the message
*/
static inline uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, uint8_t chan, uint16_t length)
{
// This code part is the same for all messages;
uint8_t key;
msg->len = length;
msg->sysid = system_id;
msg->compid = component_id;
// One sequence number per component
msg->seq = mavlink_get_channel_status(chan)->current_tx_seq;
mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1;
msg->ck = crc_calculate_msg(msg, length + MAVLINK_CORE_HEADER_LEN);
key = MAVLINK_CONST_READ( mavlink_msg_keys[msg->msgid] );
crc_accumulate( key, &msg->ck ); /// include key in X25 checksum
return length + MAVLINK_NUM_NON_STX_PAYLOAD_BYTES;
}
/**
* @brief Pack a message to send it over a serial byte stream
*/
static inline uint16_t mavlink_msg_to_send_buffer(uint8_t* buffer, const mavlink_message_t* msg)
{
*(buffer+0) = MAVLINK_STX; ///< Start transmit
// memcpy((buffer+1), msg, msg->len + MAVLINK_CORE_HEADER_LEN); ///< Core header plus payload
memcpy((buffer+1), &msg->len, MAVLINK_CORE_HEADER_LEN); ///< Core header
memcpy((buffer+1+MAVLINK_CORE_HEADER_LEN), &msg->payload[0], msg->len); ///< payload
*(buffer + msg->len + MAVLINK_CORE_HEADER_LEN + 1) = msg->ck_a;
*(buffer + msg->len + MAVLINK_CORE_HEADER_LEN + 2) = msg->ck_b;
return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES;
// return 0;
}
/**
* @brief Get the required buffer size for this message
*/
static inline uint16_t mavlink_msg_get_send_buffer_length(const mavlink_message_t* msg)
{
return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES;
}
union checksum_ {
uint16_t s;
uint8_t c[2];
};
static inline void mavlink_start_checksum(mavlink_message_t* msg)
{
crc_init(&msg->ck);
}
static inline void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c)
{
crc_accumulate(c, &msg->ck);
}
/**
* This is a convenience function which handles the complete MAVLink parsing.
* the function will parse one byte at a time and return the complete packet once
* it could be successfully decoded. Checksum and other failures will be silently
* ignored.
*
* @param chan ID of the current channel. This allows to parse different channels with this function.
* a channel is not a physical message channel like a serial port, but a logic partition of
* the communication streams in this case. COMM_NB is the limit for the number of channels
* on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows
* @param c The char to barse
*
* @param returnMsg NULL if no message could be decoded, the message data else
* @return 0 if no message could be decoded, 1 else
*
* A typical use scenario of this function call is:
*
* @code
* #include <inttypes.h> // For fixed-width uint8_t type
*
* mavlink_message_t msg;
* int chan = 0;
*
*
* while(serial.bytesAvailable > 0)
* {
* uint8_t byte = serial.getNextByte();
* if (mavlink_parse_char(chan, byte, &msg))
* {
* printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid);
* }
* }
*
*
* @endcode
*/
#ifdef MAVLINK_STATIC_BUFFER
static inline mavlink_message_t* mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status)
#else
static inline int16_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status)
#endif
{
// Initializes only once, values keep unchanged after first initialization
mavlink_parse_state_initialize(mavlink_get_channel_status(chan));
mavlink_message_t* rxmsg = &m_mavlink_message[chan]; ///< The currently decoded message
mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status
int bufferIndex = 0;
status->msg_received = 0;
switch (status->parse_state)
{
case MAVLINK_PARSE_STATE_UNINIT:
case MAVLINK_PARSE_STATE_IDLE:
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
mavlink_start_checksum(rxmsg);
}
break;
case MAVLINK_PARSE_STATE_GOT_STX:
if (status->msg_received)
{
status->buffer_overrun++;
status->parse_error++;
status->msg_received = 0;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
}
else
{
// NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2
rxmsg->len = c;
status->packet_idx = 0;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH;
}
break;
case MAVLINK_PARSE_STATE_GOT_LENGTH:
rxmsg->seq = c;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ;
break;
case MAVLINK_PARSE_STATE_GOT_SEQ:
rxmsg->sysid = c;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID;
break;
case MAVLINK_PARSE_STATE_GOT_SYSID:
rxmsg->compid = c;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID;
break;
case MAVLINK_PARSE_STATE_GOT_COMPID:
rxmsg->msgid = c;
mavlink_update_checksum(rxmsg, c);
#ifdef MAVLINK_CHECK_LENGTH
if (rxmsg->len != MAVLINK_CONST_READ( mavlink_msg_lengths[c] ) )
{
status->parse_state = MAVLINK_PARSE_STATE_IDLE; // abort, not going to understand it anyway
break;
} else ;
#endif
if (rxmsg->len == 0)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD;
}
else
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID;
}
break;
case MAVLINK_PARSE_STATE_GOT_MSGID:
rxmsg->payload[status->packet_idx++] = c;
mavlink_update_checksum(rxmsg, c);
if (status->packet_idx == rxmsg->len)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD;
mavlink_update_checksum(rxmsg,
MAVLINK_CONST_READ( mavlink_msg_keys[rxmsg->msgid] ));
}
break;
case MAVLINK_PARSE_STATE_GOT_PAYLOAD:
if (c != rxmsg->ck_a)
{
// Check first checksum byte
status->parse_error++;
status->msg_received = 0;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
mavlink_start_checksum(rxmsg);
}
}
else
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1;
}
break;
case MAVLINK_PARSE_STATE_GOT_CRC1:
if (c != rxmsg->ck_b)
{// Check second checksum byte
status->parse_error++;
status->msg_received = 0;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
mavlink_start_checksum(rxmsg);
}
}
else
{
// Successfully got message
status->msg_received = 1;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
if ( r_message != NULL )
memcpy(r_message, rxmsg, sizeof(mavlink_message_t));
else ;
}
break;
}
bufferIndex++;
// If a message has been sucessfully decoded, check index
if (status->msg_received == 1)
{
//while(status->current_seq != rxmsg->seq)
//{
// status->packet_rx_drop_count++;
// status->current_seq++;
//}
status->current_rx_seq = rxmsg->seq;
// Initial condition: If no packet has been received so far, drop count is undefined
if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0;
// Count this packet as received
status->packet_rx_success_count++;
}
r_mavlink_status->current_rx_seq = status->current_rx_seq+1;
r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count;
r_mavlink_status->packet_rx_drop_count = status->parse_error;
status->parse_error = 0;
#ifdef MAVLINK_STATIC_BUFFER
if (status->msg_received == 1)
{
if ( r_message != NULL )
return r_message;
else return rxmsg;
} else return NULL;
#else
if (status->msg_received == 1)
return 1;
else return 0;
#endif
}
#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS
// To make MAVLink work on your MCU, define a similar function
/*
#include "mavlink_types.h"
void comm_send_ch(mavlink_channel_t chan, uint8_t ch)
{
if (chan == MAVLINK_COMM_0)
{
uart0_transmit(ch);
}
if (chan == MAVLINK_COMM_1)
{
uart1_transmit(ch);
}
}
static inline void mavlink_send_msg(mavlink_channel_t chan, mavlink_message_t* msg)
{
// ARM7 MCU board implementation
// Create pointer on message struct
// Send STX
comm_send_ch(chan, MAVLINK_STX);
comm_send_ch(chan, msg->len);
comm_send_ch(chan, msg->seq);
comm_send_ch(chan, msg->sysid);
comm_send_ch(chan, msg->compid);
comm_send_ch(chan, msg->msgid);
for(uint16_t i = 0; i < msg->len; i++)
{
comm_send_ch(chan, msg->payload[i]);
}
comm_send_ch(chan, msg->ck_a);
comm_send_ch(chan, msg->ck_b);
}
static inline void mavlink_send_mem(mavlink_channel_t chan, (uint8_t *)mem, uint8_t num)
{
// ARM7 MCU board implementation
// Create pointer on message struct
// Send STX
for(uint16_t i = 0; i < num; i++)
{
comm_send_ch( chan, mem[i] );
}
}
*/
static inline void mavlink_send_uart(mavlink_channel_t chan, mavlink_message_t* msg);
static inline void mavlink_send_mem(mavlink_channel_t chan, uint8_t *mem, uint16_t num);
#define mavlink_send_msg( a, b ) mavlink_send_uart( a, b )
#endif
#endif /* _MAVLINK_PROTOCOL_H_ */
/** @file
* @brief MAVLink comm protocol enumerations / structures / constants.
* @see http://qgroundcontrol.org/mavlink/
* Edited on Monday, August 8 2011
*/
#ifndef MAVLINK_TYPES_H_
#define MAVLINK_TYPES_H_
#include "inttypes.h"
#define MAVLINK_STX 0xD5 ///< Packet start sign
#define MAVLINK_STX_LEN 1 ///< Length of start sign
#define MAVLINK_MAX_PAYLOAD_LEN 255 ///< Maximum payload length
#define MAVLINK_CORE_HEADER_LEN 5 ///< Length of core header (of the comm. layer): message length (1 byte) + message sequence (1 byte) + message system id (1 byte) + message component id (1 byte) + message type id (1 byte)
#define MAVLINK_NUM_HEADER_BYTES (MAVLINK_CORE_HEADER_LEN + MAVLINK_STX_LEN) ///< Length of all header bytes, including core and checksum
#define MAVLINK_NUM_CHECKSUM_BYTES 2
#define MAVLINK_NUM_NON_PAYLOAD_BYTES (MAVLINK_NUM_HEADER_BYTES + MAVLINK_NUM_CHECKSUM_BYTES)
#define MAVLINK_NUM_NON_STX_PAYLOAD_BYTES (MAVLINK_NUM_NON_PAYLOAD_BYTES - MAVLINK_STX_LEN)
#define MAVLINK_MAX_PACKET_LEN (MAVLINK_MAX_PAYLOAD_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES) ///< Maximum packet length
//#define MAVLINK_MAX_DATA_LEN MAVLINK_MAX_PACKET_LEN - MAVLINK_STX_LEN
typedef struct __mavlink_system
{
uint8_t sysid; ///< Used by the MAVLink message_xx_send() convenience function
uint8_t compid; ///< Used by the MAVLink message_xx_send() convenience function
uint8_t type; ///< Unused, can be used by user to store the system's type
uint8_t state; ///< Unused, can be used by user to store the system's state
uint8_t mode; ///< Unused, can be used by user to store the system's mode
uint8_t nav_mode; ///< Unused, can be used by user to store the system's navigation mode
} mavlink_system_t;
typedef struct __mavlink_message
{
union
{
uint16_t ck; ///< Checksum word
struct
{
uint8_t ck_a; ///< Checksum low byte
uint8_t ck_b; ///< Checksum high byte
};
};
uint8_t STX; ///< start of packet marker
uint8_t len; ///< Length of payload
uint8_t seq; ///< Sequence of packet
uint8_t sysid; ///< ID of message sender system/aircraft
uint8_t compid; ///< ID of the message sender component
uint8_t msgid; ///< ID of message in payload
uint8_t payload[MAVLINK_MAX_PAYLOAD_LEN]; ///< Payload data, ALIGNMENT IMPORTANT ON MCU
} mavlink_message_t;
typedef struct __mavlink_header
{
union
{
uint16_t ck; ///< Checksum word
struct
{
uint8_t ck_a; ///< Checksum low byte
uint8_t ck_b; ///< Checksum high byte
};
};
uint8_t STX; ///< start of packet marker
uint8_t len; ///< Length of payload
uint8_t seq; ///< Sequence of packet
uint8_t sysid; ///< ID of message sender system/aircraft
uint8_t compid; ///< ID of the message sender component
uint8_t msgid; ///< ID of message in payload
} mavlink_header_t;
typedef enum
{
MAVLINK_COMM_0,
MAVLINK_COMM_1,
MAVLINK_COMM_2,
MAVLINK_COMM_3,
MAVLINK_COMM_NB,
MAVLINK_COMM_NB_HIGH = 16
} mavlink_channel_t;
typedef enum
{
MAVLINK_PARSE_STATE_UNINIT=0,
MAVLINK_PARSE_STATE_IDLE,
MAVLINK_PARSE_STATE_GOT_STX,
MAVLINK_PARSE_STATE_GOT_SEQ,
MAVLINK_PARSE_STATE_GOT_LENGTH,
MAVLINK_PARSE_STATE_GOT_SYSID,
MAVLINK_PARSE_STATE_GOT_COMPID,
MAVLINK_PARSE_STATE_GOT_MSGID,
MAVLINK_PARSE_STATE_GOT_PAYLOAD,
MAVLINK_PARSE_STATE_GOT_CRC1
} mavlink_parse_state_t; ///< The state machine for the comm parser
typedef struct __mavlink_status
{
union
{
uint16_t ck; ///< Checksum word
struct
{
uint8_t ck_a; ///< Checksum low byte
uint8_t ck_b; ///< Checksum high byte
};
};
uint8_t msg_received; ///< Number of received messages
uint8_t buffer_overrun; ///< Number of buffer overruns
uint8_t parse_error; ///< Number of parse errors
mavlink_parse_state_t parse_state; ///< Parsing state machine
uint8_t packet_idx; ///< Index in current packet
uint8_t current_rx_seq; ///< Sequence number of last packet received
uint8_t current_tx_seq; ///< Sequence number of last packet sent
uint16_t packet_rx_success_count; ///< Received packets
uint16_t packet_rx_drop_count; ///< Number of packet drops
} mavlink_status_t;
#endif /* MAVLINK_TYPES_H_ */
#ifndef _MAVLINK_PROTOCOL_H_
#define _MAVLINK_PROTOCOL_H_
#include "string.h"
#include "mavlink_types.h"
#include "checksum.h"
/**
* @brief Initialize the communication stack
*
* This function has to be called before using commParseBuffer() to initialize the different status registers.
*
* @return Will initialize the different buffers and status registers.
*/
static void mavlink_parse_state_initialize(mavlink_status_t* initStatus)
{
if ((initStatus->parse_state <= MAVLINK_PARSE_STATE_UNINIT) || (initStatus->parse_state > MAVLINK_PARSE_STATE_GOT_CRC1))
{
initStatus->ck_a = 0;
initStatus->ck_b = 0;
initStatus->msg_received = 0;
initStatus->buffer_overrun = 0;
initStatus->parse_error = 0;
initStatus->parse_state = MAVLINK_PARSE_STATE_UNINIT;
initStatus->packet_idx = 0;
initStatus->packet_rx_drop_count = 0;
initStatus->packet_rx_success_count = 0;
initStatus->current_rx_seq = 0;
initStatus->current_tx_seq = 0;
}
}
static inline mavlink_status_t* mavlink_get_channel_status(uint8_t chan)
{
#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32)
static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NB_HIGH];
#else
static mavlink_status_t m_mavlink_status[MAVLINK_COMM_NB];
#endif
return &m_mavlink_status[chan];
}
/**
* @brief Finalize a MAVLink message with MAVLINK_COMM_0 as default channel
*
* This function calculates the checksum and sets length and aircraft id correctly.
* It assumes that the message id and the payload are already correctly set.
*
* @warning This function implicitely assumes the message is sent over channel zero.
* if the message is sent over a different channel it will reach the receiver
* without error, BUT the sequence number might be wrong due to the wrong
* channel sequence counter. This will result is wrongly reported excessive
* packet loss. Please use @see mavlink_{pack|encode}_headerless and then
* @see mavlink_finalize_message_chan before sending for a correct channel
* assignment. Please note that the mavlink_msg_xxx_pack and encode functions
* assign channel zero as default and thus induce possible loss counter errors.\
* They have been left to ensure code compatibility.
*
* @see mavlink_finalize_message_chan
* @param msg Message to finalize
* @param system_id Id of the sending (this) system, 1-127
* @param length Message length, usually just the counter incremented while packing the message
*/
static inline uint16_t mavlink_finalize_message(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, uint16_t length)
{
// This code part is the same for all messages;
uint16_t checksum;
msg->len = length;
msg->sysid = system_id;
msg->compid = component_id;
// One sequence number per component
msg->seq = mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq;
mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq = mavlink_get_channel_status(MAVLINK_COMM_0)->current_tx_seq+1;
// checksum = crc_calculate((uint8_t*)((void*)msg), length + MAVLINK_CORE_HEADER_LEN);
checksum = crc_calculate_msg(msg, length + MAVLINK_CORE_HEADER_LEN);
msg->ck_a = (uint8_t)(checksum & 0xFF); ///< High byte
msg->ck_b = (uint8_t)(checksum >> 8); ///< Low byte
return length + MAVLINK_NUM_NON_STX_PAYLOAD_BYTES;
}
/**
* @brief Finalize a MAVLink message with channel assignment
*
* This function calculates the checksum and sets length and aircraft id correctly.
* It assumes that the message id and the payload are already correctly set. This function
* can also be used if the message header has already been written before (as in mavlink_msg_xxx_pack
* instead of mavlink_msg_xxx_pack_headerless), it just introduces little extra overhead.
*
* @param msg Message to finalize
* @param system_id Id of the sending (this) system, 1-127
* @param length Message length, usually just the counter incremented while packing the message
*/
static inline uint16_t mavlink_finalize_message_chan(mavlink_message_t* msg, uint8_t system_id, uint8_t component_id, uint8_t chan, uint16_t length)
{
// This code part is the same for all messages;
uint16_t checksum;
msg->len = length;
msg->sysid = system_id;
msg->compid = component_id;
// One sequence number per component
msg->seq = mavlink_get_channel_status(chan)->current_tx_seq;
mavlink_get_channel_status(chan)->current_tx_seq = mavlink_get_channel_status(chan)->current_tx_seq+1;
// checksum = crc_calculate((uint8_t*)((void*)msg), length + MAVLINK_CORE_HEADER_LEN);
checksum = crc_calculate_msg(msg, length + MAVLINK_CORE_HEADER_LEN);
msg->ck_a = (uint8_t)(checksum & 0xFF); ///< High byte
msg->ck_b = (uint8_t)(checksum >> 8); ///< Low byte
return length + MAVLINK_NUM_NON_STX_PAYLOAD_BYTES;
}
/**
* @brief Pack a message to send it over a serial byte stream
*/
static inline uint16_t mavlink_msg_to_send_buffer(uint8_t* buffer, const mavlink_message_t* msg)
{
*(buffer+0) = MAVLINK_STX; ///< Start transmit
// memcpy((buffer+1), msg, msg->len + MAVLINK_CORE_HEADER_LEN); ///< Core header plus payload
memcpy((buffer+1), &msg->len, MAVLINK_CORE_HEADER_LEN); ///< Core header
memcpy((buffer+1+MAVLINK_CORE_HEADER_LEN), &msg->payload[0], msg->len); ///< payload
*(buffer + msg->len + MAVLINK_CORE_HEADER_LEN + 1) = msg->ck_a;
*(buffer + msg->len + MAVLINK_CORE_HEADER_LEN + 2) = msg->ck_b;
return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES;
// return 0;
}
/**
* @brief Get the required buffer size for this message
*/
static inline uint16_t mavlink_msg_get_send_buffer_length(const mavlink_message_t* msg)
{
return msg->len + MAVLINK_NUM_NON_PAYLOAD_BYTES;
}
union checksum_ {
uint16_t s;
uint8_t c[2];
};
union __mavlink_bitfield {
uint8_t uint8;
int8_t int8;
uint16_t uint16;
int16_t int16;
uint32_t uint32;
int32_t int32;
};
static inline void mavlink_start_checksum(mavlink_message_t* msg)
{
union checksum_ ck;
crc_init(&(ck.s));
msg->ck_a = ck.c[0];
msg->ck_b = ck.c[1];
}
static inline void mavlink_update_checksum(mavlink_message_t* msg, uint8_t c)
{
union checksum_ ck;
ck.c[0] = msg->ck_a;
ck.c[1] = msg->ck_b;
crc_accumulate(c, &(ck.s));
msg->ck_a = ck.c[0];
msg->ck_b = ck.c[1];
}
/**
* This is a convenience function which handles the complete MAVLink parsing.
* the function will parse one byte at a time and return the complete packet once
* it could be successfully decoded. Checksum and other failures will be silently
* ignored.
*
* @param chan ID of the current channel. This allows to parse different channels with this function.
* a channel is not a physical message channel like a serial port, but a logic partition of
* the communication streams in this case. COMM_NB is the limit for the number of channels
* on MCU (e.g. ARM7), while COMM_NB_HIGH is the limit for the number of channels in Linux/Windows
* @param c The char to barse
*
* @param returnMsg NULL if no message could be decoded, the message data else
* @return 0 if no message could be decoded, 1 else
*
* A typical use scenario of this function call is:
*
* @code
* #include <inttypes.h> // For fixed-width uint8_t type
*
* mavlink_message_t msg;
* int chan = 0;
*
*
* while(serial.bytesAvailable > 0)
* {
* uint8_t byte = serial.getNextByte();
* if (mavlink_parse_char(chan, byte, &msg))
* {
* printf("Received message with ID %d, sequence: %d from component %d of system %d", msg.msgid, msg.seq, msg.compid, msg.sysid);
* }
* }
*
*
* @endcode
*/
static inline uint8_t mavlink_parse_char(uint8_t chan, uint8_t c, mavlink_message_t* r_message, mavlink_status_t* r_mavlink_status)
{
#if (defined linux) | (defined __linux) | (defined __MACH__) | (defined _WIN32)
static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NB_HIGH];
#elif defined(NB_MAVLINK_COMM)
static mavlink_message_t m_mavlink_message[NB_MAVLINK_COMM];
#else
static mavlink_message_t m_mavlink_message[MAVLINK_COMM_NB];
#endif
// Initializes only once, values keep unchanged after first initialization
mavlink_parse_state_initialize(mavlink_get_channel_status(chan));
mavlink_message_t* rxmsg = &m_mavlink_message[chan]; ///< The currently decoded message
mavlink_status_t* status = mavlink_get_channel_status(chan); ///< The current decode status
int bufferIndex = 0;
status->msg_received = 0;
switch (status->parse_state)
{
case MAVLINK_PARSE_STATE_UNINIT:
case MAVLINK_PARSE_STATE_IDLE:
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
mavlink_start_checksum(rxmsg);
}
break;
case MAVLINK_PARSE_STATE_GOT_STX:
if (status->msg_received)
{
status->buffer_overrun++;
status->parse_error++;
status->msg_received = 0;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
}
else
{
// NOT counting STX, LENGTH, SEQ, SYSID, COMPID, MSGID, CRC1 and CRC2
rxmsg->len = c;
status->packet_idx = 0;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_LENGTH;
}
break;
case MAVLINK_PARSE_STATE_GOT_LENGTH:
rxmsg->seq = c;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_SEQ;
break;
case MAVLINK_PARSE_STATE_GOT_SEQ:
rxmsg->sysid = c;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_SYSID;
break;
case MAVLINK_PARSE_STATE_GOT_SYSID:
rxmsg->compid = c;
mavlink_update_checksum(rxmsg, c);
status->parse_state = MAVLINK_PARSE_STATE_GOT_COMPID;
break;
case MAVLINK_PARSE_STATE_GOT_COMPID:
rxmsg->msgid = c;
mavlink_update_checksum(rxmsg, c);
#ifdef MAVLINK_CHECK_LENGTH
if (rxmsg->len != mavlink_msg_lengths[c] )
status->parse_state = MAVLINK_PARSE_STATE_IDLE; // abort, not going to understand it anyway
else ;
#endif
if (rxmsg->len == 0)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD;
}
else
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_MSGID;
}
break;
case MAVLINK_PARSE_STATE_GOT_MSGID:
rxmsg->payload[status->packet_idx++] = c;
mavlink_update_checksum(rxmsg, c);
if (status->packet_idx == rxmsg->len)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_PAYLOAD;
}
break;
case MAVLINK_PARSE_STATE_GOT_PAYLOAD:
if (c != rxmsg->ck_a)
{
// Check first checksum byte
status->parse_error++;
status->msg_received = 0;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
mavlink_start_checksum(rxmsg);
}
}
else
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_CRC1;
}
break;
case MAVLINK_PARSE_STATE_GOT_CRC1:
if (c != rxmsg->ck_b)
{// Check second checksum byte
status->parse_error++;
status->msg_received = 0;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
if (c == MAVLINK_STX)
{
status->parse_state = MAVLINK_PARSE_STATE_GOT_STX;
mavlink_start_checksum(rxmsg);
}
}
else
{
// Successfully got message
status->msg_received = 1;
status->parse_state = MAVLINK_PARSE_STATE_IDLE;
if ( r_message != NULL )
{
memcpy(r_message, rxmsg, sizeof(mavlink_message_t));
}
}
break;
}
bufferIndex++;
// If a message has been sucessfully decoded, check index
if (status->msg_received == 1)
{
//while(status->current_seq != rxmsg->seq)
//{
// status->packet_rx_drop_count++;
// status->current_seq++;
//}
status->current_rx_seq = rxmsg->seq;
// Initial condition: If no packet has been received so far, drop count is undefined
if (status->packet_rx_success_count == 0) status->packet_rx_drop_count = 0;
// Count this packet as received
status->packet_rx_success_count++;
}
r_mavlink_status->current_rx_seq = status->current_rx_seq+1;
r_mavlink_status->packet_rx_success_count = status->packet_rx_success_count;
r_mavlink_status->packet_rx_drop_count = status->parse_error;
status->parse_error = 0;
// For future use
// if (status->msg_received == 1)
// {
// if ( r_message != NULL )
// {
// return r_message;
// }
// else
// {
// return rxmsg;
// }
// }
// else
// {
// return NULL;
// }
return status->msg_received;
}
#ifdef MAVLINK_USE_CONVENIENCE_FUNCTIONS
// To make MAVLink work on your MCU, define a similar function
/*
#include "mavlink_types.h"
void comm_send_ch(mavlink_channel_t chan, uint8_t ch)
{
if (chan == MAVLINK_COMM_0)
{
uart0_transmit(ch);
}
if (chan == MAVLINK_COMM_1)
{
uart1_transmit(ch);
}
}
static inline void mavlink_send_msg(mavlink_channel_t chan, mavlink_message_t* msg)
{
// ARM7 MCU board implementation
// Create pointer on message struct
// Send STX
comm_send_ch(chan, MAVLINK_STX);
comm_send_ch(chan, msg->len);
comm_send_ch(chan, msg->seq);
comm_send_ch(chan, msg->sysid);
comm_send_ch(chan, msg->compid);
comm_send_ch(chan, msg->msgid);
for(uint16_t i = 0; i < msg->len; i++)
{
comm_send_ch(chan, msg->payload[i]);
}
comm_send_ch(chan, msg->ck_a);
comm_send_ch(chan, msg->ck_b);
}
static inline void mavlink_send_mem(mavlink_channel_t chan, (uint8_t *)mem, uint8_t num)
{
// ARM7 MCU board implementation
// Create pointer on message struct
// Send STX
for(uint16_t i = 0; i < num; i++)
{
comm_send_ch( chan, mem[i] );
}
}
*/
static inline void mavlink_send_uart(mavlink_channel_t chan, mavlink_message_t* msg);
static inline void mavlink_send_mem(mavlink_channel_t chan, (uint8_t *)mem, uint8_t num);
#define mavlink_send_msg( a, b ) mavlink_send_uart( a, b )
#endif
#endif /* _MAVLINK_PROTOCOL_H_ */
#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;
}
#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
#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;
}
// Return empty variant if no case applied
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();
}
#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
#include "QGCMAVLinkTextEdit.h"
#include <QMessageBox>
#include <QMenu>
#include <QEvent>
#include <QPainter>
#include <QScrollBar>
#include <QTextLayout>
QGCMAVLinkTextEdit::QGCMAVLinkTextEdit(QWidget *parent)
: QTextEdit(parent)
{
setViewportMargins(50, 0, 0, 0);
highlight = new XmlHighlighter(document());
setLineWrapMode ( QTextEdit::NoWrap );
setAcceptRichText ( false );
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(update()));
connect(this, SIGNAL(textChanged()), this, SLOT(update()));
}
bool QGCMAVLinkTextEdit::Conform()
{
QString errorStr;
int errorLine, errorColumn;
QDomDocument doc;
return doc.setContent(text(),false, &errorStr, &errorLine, &errorColumn);
}
QDomDocument QGCMAVLinkTextEdit::xml_document()
{
QString errorStr;
int errorLine, errorColumn;
QDomDocument doc;
doc.setContent(text(),false, &errorStr, &errorLine, &errorColumn);
return doc;
}
void QGCMAVLinkTextEdit::setPlainText( const QString txt )
{
QString errorStr;
int errorLine, errorColumn;
QDomDocument doc;
if (!doc.setContent(txt,false, &errorStr, &errorLine, &errorColumn)) {
QTextEdit::setPlainText(txt);
} else {
QTextEdit::setPlainText(doc.toString(5));
}
}
bool QGCMAVLinkTextEdit::syntaxcheck()
{
bool noError = true;
if (text().size() > 0 ) {
QString errorStr;
int errorLine, errorColumn;
QDomDocument doc;
if (!doc.setContent(text(),false, &errorStr, &errorLine, &errorColumn)) {
//////return doc.toString(5);
QMessageBox::critical(0, tr("Found xml error"),tr("Check line %1 column %2 on string \"%3\"!")
.arg(errorLine - 1)
.arg(errorColumn - 1)
.arg(errorStr));
noError = false;
// FIXME Mark line
if (errorLine >= 0 ) {
}
} else {
QMessageBox::information(0, tr("XML valid."),tr("All tags are valid. Document size is %1 characters.").arg(text().size()));
setPlainText(doc.toString(5));
}
} else {
QMessageBox::information(0, tr("XML not found!"),tr("Null size xml document!"));
noError = false;
}
return noError;
}
void QGCMAVLinkTextEdit::contextMenuEvent ( QContextMenuEvent * e )
{
Q_UNUSED(e);
QMenu *RContext = createOwnStandardContextMenu();
RContext->exec(QCursor::pos());
delete RContext;
}
QMenu *QGCMAVLinkTextEdit::createOwnStandardContextMenu()
{
QMenu *TContext = createStandardContextMenu();
TContext->addAction(QIcon(QString::fromUtf8(":/img/zoomin.png")),tr( "Zoom In" ), this , SLOT( zoomIn() ) );
TContext->addAction(QIcon(QString::fromUtf8(":/img/zoomout.png")),tr( "Zoom Out" ), this , SLOT( zoomOut() ) );
TContext->addAction(tr("Check xml syntax" ), this , SLOT( syntaxcheck() ) );
return TContext;
}
bool QGCMAVLinkTextEdit::event( QEvent *event )
{
if (event->type()==QEvent::Paint) {
QPainter p(this);
p.fillRect(0, 0, 50, height(), QColor("#636363"));
QFont workfont(font());
QPen pen(QColor("#ffffff"),1);
p.setPen(pen);
p.setFont (workfont);
int contentsY = verticalScrollBar()->value();
qreal pageBottom = contentsY+viewport()->height();
int m_lineNumber(1);
const QFontMetrics fm=fontMetrics();
const int ascent = fontMetrics().ascent() +1;
for (QTextBlock block=document()->begin(); block.isValid(); block=block.next(), m_lineNumber++) {
QTextLayout *layout = block.layout();
const QRectF boundingRect = layout->boundingRect();
QPointF position = layout->position();
if ( position.y() +boundingRect.height() < contentsY ) {
continue;
}
if ( position.y() > pageBottom ) {
break;
}
const QString txt = QString::number(m_lineNumber);
p.drawText(50-fm.width(txt)-2, qRound(position.y())-contentsY+ascent, txt);
}
p.setPen(QPen(Qt::NoPen));
} else if ( event->type() == QEvent::KeyPress ) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if ((ke->modifiers() & Qt::ControlModifier) && ke->key() == Qt::Key_Minus) {
QTextEdit::zoomOut();
return true;
}
if ((ke->modifiers() & Qt::ControlModifier) && ke->key() == Qt::Key_Plus) {
QTextEdit::zoomIn();
return true;
}
}
return QTextEdit::event(event);
}
static const QColor DEFAULT_SYNTAX_CHAR = Qt::blue;
static const QColor DEFAULT_ELEMENT_NAME = Qt::darkRed;
static const QColor DEFAULT_COMMENT = Qt::darkGreen;
static const QColor DEFAULT_ATTRIBUTE_NAME = Qt::red;
static const QColor DEFAULT_ATTRIBUTE_VALUE = Qt::darkGreen;
static const QColor DEFAULT_ERROR = Qt::darkMagenta;
static const QColor DEFAULT_OTHER = Qt::black;
// Regular expressions for parsing XML borrowed from:
// http://www.cs.sfu.ca/~cameron/REX.html
static const QString EXPR_COMMENT = "<!--[^-]*-([^-][^-]*-)*->";
static const QString EXPR_COMMENT_BEGIN = "<!--";
static const QString EXPR_COMMENT_END = "[^-]*-([^-][^-]*-)*->";
static const QString EXPR_ATTRIBUTE_VALUE = "\"[^<\"]*\"|'[^<']*'";
static const QString EXPR_NAME = "([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*";
XmlHighlighter::XmlHighlighter(QObject* parent)
: QSyntaxHighlighter(parent)
{
init();
}
XmlHighlighter::XmlHighlighter(QTextDocument* parent)
: QSyntaxHighlighter(parent)
{
init();
}
XmlHighlighter::XmlHighlighter(QTextEdit* parent)
: QSyntaxHighlighter(parent)
{
init();
}
XmlHighlighter::~XmlHighlighter()
{
}
void XmlHighlighter::init()
{
fmtSyntaxChar.setForeground(DEFAULT_SYNTAX_CHAR);
fmtElementName.setForeground(DEFAULT_ELEMENT_NAME);
fmtComment.setForeground(DEFAULT_COMMENT);
fmtAttributeName.setForeground(DEFAULT_ATTRIBUTE_NAME);
fmtAttributeValue.setForeground(DEFAULT_ATTRIBUTE_VALUE);
fmtError.setForeground(DEFAULT_ERROR);
fmtOther.setForeground(DEFAULT_OTHER);
}
void XmlHighlighter::setHighlightColor(HighlightType type, QColor color, bool foreground)
{
QTextCharFormat format;
if (foreground)
format.setForeground(color);
else
format.setBackground(color);
setHighlightFormat(type, format);
}
void XmlHighlighter::setHighlightFormat(HighlightType type, QTextCharFormat format)
{
switch (type)
{
case SyntaxChar:
fmtSyntaxChar = format;
break;
case ElementName:
fmtElementName = format;
break;
case Comment:
fmtComment = format;
break;
case AttributeName:
fmtAttributeName = format;
break;
case AttributeValue:
fmtAttributeValue = format;
break;
case Error:
fmtError = format;
break;
case Other:
fmtOther = format;
break;
}
rehighlight();
}
void XmlHighlighter::highlightBlock(const QString& text)
{
int i = 0;
int pos = 0;
int brackets = 0;
state = (previousBlockState() == InElement ? ExpectAttributeOrEndOfElement : NoState);
if (previousBlockState() == InComment)
{
// search for the end of the comment
QRegExp expression(EXPR_COMMENT_END);
pos = expression.indexIn(text, i);
if (pos >= 0)
{
// end comment found
const int iLength = expression.matchedLength();
setFormat(0, iLength - 3, fmtComment);
setFormat(iLength - 3, 3, fmtSyntaxChar);
i += iLength; // skip comment
}
else
{
// in comment
setFormat(0, text.length(), fmtComment);
setCurrentBlockState(InComment);
return;
}
}
for (; i < text.length(); i++)
{
switch (text.at(i).toAscii())
{
case '<':
brackets++;
if (brackets == 1)
{
setFormat(i, 1, fmtSyntaxChar);
state = ExpectElementNameOrSlash;
}
else
{
// wrong bracket nesting
setFormat(i, 1, fmtError);
}
break;
case '>':
brackets--;
if (brackets == 0)
{
setFormat(i, 1, fmtSyntaxChar);
}
else
{
// wrong bracket nesting
setFormat( i, 1, fmtError);
}
state = NoState;
break;
case '/':
if (state == ExpectElementNameOrSlash)
{
state = ExpectElementName;
setFormat(i, 1, fmtSyntaxChar);
}
else
{
if (state == ExpectAttributeOrEndOfElement)
{
setFormat(i, 1, fmtSyntaxChar);
}
else
{
processDefaultText(i, text);
}
}
break;
case '=':
if (state == ExpectEqual)
{
state = ExpectAttributeValue;
setFormat(i, 1, fmtOther);
}
else
{
processDefaultText(i, text);
}
break;
case '\'':
case '\"':
if (state == ExpectAttributeValue)
{
// search attribute value
QRegExp expression(EXPR_ATTRIBUTE_VALUE);
pos = expression.indexIn(text, i);
if (pos == i) // attribute value found ?
{
const int iLength = expression.matchedLength();
setFormat(i, 1, fmtOther);
setFormat(i + 1, iLength - 2, fmtAttributeValue);
setFormat(i + iLength - 1, 1, fmtOther);
i += iLength - 1; // skip attribute value
state = ExpectAttributeOrEndOfElement;
}
else
{
processDefaultText(i, text);
}
}
else
{
processDefaultText(i, text);
}
break;
case '!':
if (state == ExpectElementNameOrSlash)
{
// search comment
QRegExp expression(EXPR_COMMENT);
pos = expression.indexIn(text, i - 1);
if (pos == i - 1) // comment found ?
{
const int iLength = expression.matchedLength();
setFormat(pos, 4, fmtSyntaxChar);
setFormat(pos + 4, iLength - 7, fmtComment);
setFormat(iLength - 3, 3, fmtSyntaxChar);
i += iLength - 2; // skip comment
state = NoState;
brackets--;
}
else
{
// Try find multiline comment
QRegExp expression(EXPR_COMMENT_BEGIN); // search comment start
pos = expression.indexIn(text, i - 1);
//if (pos == i - 1) // comment found ?
if (pos >= i - 1)
{
setFormat(i, 3, fmtSyntaxChar);
setFormat(i + 3, text.length() - i - 3, fmtComment);
setCurrentBlockState(InComment);
return;
}
else
{
processDefaultText(i, text);
}
}
}
else
{
processDefaultText(i, text);
}
break;
default:
const int iLength = processDefaultText(i, text);
if (iLength > 0)
i += iLength - 1;
break;
}
}
if (state == ExpectAttributeOrEndOfElement)
{
setCurrentBlockState(InElement);
}
}
int XmlHighlighter::processDefaultText(int i, const QString& text)
{
// length of matched text
int iLength = 0;
switch(state)
{
case ExpectElementNameOrSlash:
case ExpectElementName:
{
// search element name
QRegExp expression(EXPR_NAME);
const int pos = expression.indexIn(text, i);
if (pos == i) // found ?
{
iLength = expression.matchedLength();
setFormat(pos, iLength, fmtElementName);
state = ExpectAttributeOrEndOfElement;
}
else
{
setFormat(i, 1, fmtOther);
}
}
break;
case ExpectAttributeOrEndOfElement:
{
// search attribute name
QRegExp expression(EXPR_NAME);
const int pos = expression.indexIn(text, i);
if (pos == i) // found ?
{
iLength = expression.matchedLength();
setFormat(pos, iLength, fmtAttributeName);
state = ExpectEqual;
}
else
{
setFormat(i, 1, fmtOther);
}
}
break;
default:
setFormat(i, 1, fmtOther);
break;
}
return iLength;
}
// Based on: Syntax highlighting from:
// http://code.google.com/p/fop-miniscribus/
// (GPL v2) thanks!
#ifndef QGCMAVLINKTEXTEDIT_H
#define QGCMAVLINKTEXTEDIT_H
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QColor>
#include <QDomDocument>
#include <QTextEdit>
//class QGCMAVLinkTextEdit : public QTextEdit
//{
//public:
// QGCMAVLinkTextEdit();
//};
class XmlHighlighter : public QSyntaxHighlighter
{
public:
XmlHighlighter(QObject* parent);
XmlHighlighter(QTextDocument* parent);
XmlHighlighter(QTextEdit* parent);
~XmlHighlighter();
enum HighlightType
{
SyntaxChar,
ElementName,
Comment,
AttributeName,
AttributeValue,
Error,
Other
};
void setHighlightColor(HighlightType type, QColor color, bool foreground = true);
void setHighlightFormat(HighlightType type, QTextCharFormat format);
protected:
void highlightBlock(const QString& rstrText);
int processDefaultText(int i, const QString& rstrText);
private:
void init();
QTextCharFormat fmtSyntaxChar;
QTextCharFormat fmtElementName;
QTextCharFormat fmtComment;
QTextCharFormat fmtAttributeName;
QTextCharFormat fmtAttributeValue;
QTextCharFormat fmtError;
QTextCharFormat fmtOther;
enum ParsingState
{
NoState = 0,
ExpectElementNameOrSlash,
ExpectElementName,
ExpectAttributeOrEndOfElement,
ExpectEqual,
ExpectAttributeValue
};
enum BlockState
{
NoBlock = -1,
InComment,
InElement
};
ParsingState state;
};
class QGCMAVLinkTextEdit : public QTextEdit
{
Q_OBJECT
//
public:
QGCMAVLinkTextEdit( QWidget * parent = 0 );
bool Conform();
QDomDocument xml_document();
inline QString text() const
{
return QTextEdit::toPlainText();
}
QMenu *createOwnStandardContextMenu();
protected:
void contextMenuEvent ( QContextMenuEvent * e );
bool event( QEvent *event );
private:
XmlHighlighter *highlight;
signals:
public slots:
bool syntaxcheck();
void setPlainText( const QString txt );
};
#endif // QGCMAVLINKTEXTEDIT_H
#include <QFileDialog>
#include <QTextBrowser>
#include <QMessageBox>
#include <QSettings>
#include <QDesktopServices>
#include "XMLCommProtocolWidget.h"
#include "ui_XMLCommProtocolWidget.h"
#include "MAVLinkXMLParser.h"
#include "MAVLinkXMLParserV10.h"
#include <QDebug>
#include <iostream>
XMLCommProtocolWidget::XMLCommProtocolWidget(QWidget *parent) :
QWidget(parent),
model(NULL),
m_ui(new Ui::XMLCommProtocolWidget)
{
m_ui->setupUi(this);
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()));
// Make sure text background is white
m_ui->xmlTextView->setStyleSheet("QGCMAVLinkTextEdit { background-color: #FFFFFF; }");
}
void XMLCommProtocolWidget::selectXMLFile()
{
QSettings settings("MAVLink Consortium", "MAVLink Generator");
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)
{
QFile file(fileNames.first());
m_ui->fileNameLabel->setText(file.fileName());
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>"));
}
}
void XMLCommProtocolWidget::selectOutputDirectory()
{
QSettings settings("MAVLink Consortium", "MAVLink Generator");
const QString mavlinkOutputDir = "MAVLINK_OUTPUT_DIR";
QString dirPath = settings.value(mavlinkOutputDir, QDesktopServices::DesktopLocation).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())
{
// Syntax check already gives output
return;
}
MAVLinkXMLParser* parser = NULL;
MAVLinkXMLParserV10* parserV10 = NULL;
bool result = false;
if (m_ui->versionComboBox->currentIndex() == 1)
{
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)));
result = parser->generate();
}
else if (m_ui->versionComboBox->currentIndex() == 0)
{
MAVLinkXMLParserV10* parserV10 = new MAVLinkXMLParserV10(m_ui->fileNameLabel->text().trimmed(), m_ui->outputDirNameLabel->text().trimmed());
connect(parserV10, SIGNAL(parseState(QString)), m_ui->compileLog, SLOT(appendHtml(QString)));
result = parserV10->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);
}
if (parser) delete parser;
if (parserV10) delete parserV10;
}
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()
{
if (model) 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;
}
}
/*=====================================================================
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"
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:
DomModel* model;
void changeEvent(QEvent *e);
signals:
void visibilityChanged(bool visible);
protected:
void showEvent(QShowEvent* event)
{
QWidget::showEvent(event);
emit visibilityChanged(true);
}
void hideEvent(QHideEvent* event)
{
QWidget::hideEvent(event);
emit visibilityChanged(false);
}
private:
Ui::XMLCommProtocolWidget *m_ui;
};
#endif // XMLCOMMPROTOCOLWIDGET_H
<?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" columnstretch="1,1,1,100">
<property name="horizontalSpacing">
<number>8</number>
</property>
<property name="verticalSpacing">
<number>12</number>
</property>
<property name="margin">
<number>8</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>
</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="../../../../qgroundcontrol.qrc">
<normaloff>:/files/images/status/folder-open.svg</normaloff>:/files/images/status/folder-open.svg</iconset>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="7">
<widget class="QGCMAVLinkTextEdit" name="xmlTextView">
<property name="minimumSize">
<size>
<width>200</width>
<height>100</height>
</size>
</property>
<property name="baseSize">
<size>
<width>800</width>
<height>600</height>
</size>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<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="../../../../qgroundcontrol.qrc">
<normaloff>:/files/images/status/folder-open.svg</normaloff>:/files/images/status/folder-open.svg</iconset>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Compile Output</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QPlainTextEdit" name="compileLog">
<property name="tabStopWidth">
<number>40</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="validXMLLabel">
<property name="text">
<string>No file loaded</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Save file</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="generateButton">
<property name="text">
<string>Save and generate</string>
</property>
<property name="icon">
<iconset resource="../../../../qgroundcontrol.qrc">
<normaloff>:/files/images/categories/applications-system.svg</normaloff>:/files/images/categories/applications-system.svg</iconset>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Select MAVLink Version</string>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="versionComboBox">
<item>
<property name="text">
<string>MAVLink v1.0 (Sept'10+)</string>
</property>
</item>
<item>
<property name="text">
<string>MAVLink v0.9 (-Aug'10)</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QGCMAVLinkTextEdit</class>
<extends>QTextEdit</extends>
<header location="global">QGCMAVLinkTextEdit.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../../qgroundcontrol.qrc"/>
</resources>
<connections/>
</ui>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment