diff --git a/QGCApplication.pro b/QGCApplication.pro
index f1d3507..5bbb957 100644
--- a/QGCApplication.pro
+++ b/QGCApplication.pro
@@ -339,6 +339,7 @@ HEADERS += \
src/ViewWidgets/ParameterEditorWidget.h \
src/ViewWidgets/ViewWidgetController.h \
src/Waypoint.h \
+ src/AutoPilotPlugins/PX4/PX4AirframeLoader.h
!iOSBuild {
HEADERS += \
@@ -470,6 +471,7 @@ SOURCES += \
src/ViewWidgets/ParameterEditorWidget.cc \
src/ViewWidgets/ViewWidgetController.cc \
src/Waypoint.cc \
+ src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc
!iOSBuild {
SOURCES += \
diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc
index 98f3572..c9b1729 100644
--- a/qgroundcontrol.qrc
+++ b/qgroundcontrol.qrc
@@ -137,9 +137,6 @@
src/ui/qmlcommon/qmldir
src/ui/qmlcommon/QGCWaypoint.qml
-
- src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml
-
resources/LeftArrow.svg
resources/RightArrow.svg
@@ -247,4 +244,8 @@
resources/audio/alert.wav
+
+ src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml
+ src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml
+
diff --git a/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc b/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc
index b2024f8..fc34558 100644
--- a/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc
+++ b/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc
@@ -26,86 +26,69 @@
#include "AirframeComponentAirframes.h"
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoStandardPlane[] = {
- { "Multiplex Easystar 1/2", 2100 },
- { "Generic AERT", 2101 },
- { "3DR Skywalker", 2102 },
- { "Skyhunter (1800 mm)", 2103 },
- { "Generic AETR", 2104 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoSimulation[] = {
- { "Plane (HilStar, X-Plane)", 1000 },
- { "Plane (Rascal, FlightGear)", 1004 },
- { "Quad X HIL", 1001 },
- { "Quad + HIL", 1003 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoFlyingWing[] = {
- { "Z-84 Wing Wing (845 mm)", 3033 },
- { "TBS Caipirinha (850 mm)", 3100 },
- { "Bormatec Camflyer Q (800 mm)", 3030 },
- { "FX-61 Phantom FPV (1550 mm)", 3031 },
- { "FX-79 Buffalo (2000 mm)", 3034 },
- { "Skywalker X5 (1180 mm)", 3032 },
- { "Viper v2 (3000 mm)", 3035 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoQuadRotorX[] = {
- { "DJI F330 8\" Quad", 4010 },
- { "DJI F450 10\" Quad", 4011 },
- { "X frame Quad UAVCAN", 4012 },
- { "AR.Drone Frame Quad", 4008 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoQuadRotorPlus[] = {
- { "Generic 10\" Quad +", 5001 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoHexaRotorX[] = {
- { "Standard 10\" Hexa X", 6001 },
- { "Coaxial 10\" Hexa X", 11001 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoHexaRotorPlus[] = {
- { "Standard 10\" Hexa", 7001 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoOctoRotorX[] = {
- { "Standard 10\" Octo", 8001 },
- { "Coaxial 10\" Octo", 12001 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoOctoRotorPlus[] = {
- { "Standard 10\" Octo", 9001 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoQuadRotorH[] = {
- { "3DR Iris", 10016 },
- { "TBS Discovery", 10015 },
- { "SteadiDrone QU4D", 10017 },
- { NULL, 0 }
-};
-
-const AirframeComponentAirframes::AirframeType_t AirframeComponentAirframes::rgAirframeTypes[] = {
- { "Standard Airplane", "qrc:/qmlimages/AirframeStandardPlane.png", AirframeComponentAirframes::_rgAirframeInfoStandardPlane },
- { "Flying Wing", "qrc:/qmlimages/AirframeFlyingWing.png", AirframeComponentAirframes::_rgAirframeInfoFlyingWing },
- { "QuadRotor X", "qrc:/qmlimages/AirframeQuadRotorX.png", AirframeComponentAirframes::_rgAirframeInfoQuadRotorX },
- { "QuadRotor +", "qrc:/qmlimages/AirframeQuadRotorPlus.png", AirframeComponentAirframes::_rgAirframeInfoQuadRotorPlus },
- { "HexaRotor X", "qrc:/qmlimages/AirframeHexaRotorX.png", AirframeComponentAirframes::_rgAirframeInfoHexaRotorX },
- { "HexaRotor +", "qrc:/qmlimages/AirframeHexaRotorPlus.png", AirframeComponentAirframes::_rgAirframeInfoHexaRotorPlus },
- { "OctoRotor X", "qrc:/qmlimages/AirframeOctoRotorX.png", AirframeComponentAirframes::_rgAirframeInfoOctoRotorX },
- { "OctoRotor +", "qrc:/qmlimages/AirframeOctoRotorPlus.png", AirframeComponentAirframes::_rgAirframeInfoOctoRotorPlus },
- { "QuadRotor H", "qrc:/qmlimages/AirframeQuadRotorH.png", AirframeComponentAirframes::_rgAirframeInfoQuadRotorH },
- { "Simulation", "qrc:/qmlimages/AirframeSimulation.png", AirframeComponentAirframes::_rgAirframeInfoSimulation },
- { NULL, NULL, NULL }
-};
+QMap AirframeComponentAirframes::rgAirframeTypes;
+
+QMap& AirframeComponentAirframes::get() {
+
+#if 0
+ // Set a single airframe to prevent the UI from going crazy
+ if (rgAirframeTypes.count() == 0) {
+ // Standard planes
+ AirframeType_t *standardPlane = new AirframeType_t;
+ standardPlane->name = "Standard Airplane";
+ standardPlane->imageResource = "qrc:/qmlimages/AirframeStandardPlane.png";
+ AirframeInfo_t *easystar = new AirframeInfo_t;
+ easystar->name = "Multiplex Easystar 1/2";
+ easystar->autostartId = 2100;
+ standardPlane->rgAirframeInfo.append(easystar);
+ rgAirframeTypes.insert("StandardPlane", standardPlane);
+ qDebug() << "Adding plane config";
+
+ // Flying wings
+ }
+#endif
+
+ return rgAirframeTypes;
+}
+
+void AirframeComponentAirframes::insert(QString& group, QString& image, QString& name, int id)
+{
+ AirframeType_t *g;
+ if (!rgAirframeTypes.contains(group)) {
+ g = new AirframeType_t;
+ g->name = group;
+ if (image.length() > 0) {
+ g->imageResource = QString("qrc:/qmlimages/").append(image);
+ } else {
+ g->imageResource = QString("qrc:/qmlimages/AirframeStandardPlane.png");
+ }
+ qDebug() << "IMAGE:" << g->imageResource;
+ rgAirframeTypes.insert(group, g);
+ } else {
+ g = rgAirframeTypes.value(group);
+ }
+
+ AirframeInfo_t *i = new AirframeInfo_t;
+ i->name = name;
+ i->autostartId = id;
+
+ g->rgAirframeInfo.append(i);
+}
+
+void AirframeComponentAirframes::clear() {
+
+ // Run through all and delete them
+ for (int tindex = 0; tindex < AirframeComponentAirframes::get().count(); tindex++) {
+
+ const AirframeComponentAirframes::AirframeType_t* pType = AirframeComponentAirframes::get().values().at(tindex);
+
+ for (int index = 0; index < pType->rgAirframeInfo.count(); index++) {
+ const AirframeComponentAirframes::AirframeInfo_t* pInfo = pType->rgAirframeInfo.at(index);
+ delete pInfo;
+ }
+
+ delete pType;
+ }
+
+ rgAirframeTypes.clear();
+}
diff --git a/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h b/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h
index 8c20e90..0a1116e 100644
--- a/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h
+++ b/src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
@@ -39,30 +40,24 @@ class AirframeComponentAirframes
{
public:
typedef struct {
- const char* name;
+ QString name;
int autostartId;
} AirframeInfo_t;
typedef struct {
- const char* name;
- const char* imageResource;
- const AirframeInfo_t* rgAirframeInfo;
+ QString name;
+ QString imageResource;
+ QList rgAirframeInfo;
} AirframeType_t;
+
+ static QMap& get();
+ static void clear();
+ static void insert(QString& group, QString& image, QString& name, int id);
-public:
- static const AirframeType_t rgAirframeTypes[];
+protected:
+ static QMap rgAirframeTypes;
private:
- static const AirframeInfo_t _rgAirframeInfoStandardPlane[];
- static const AirframeInfo_t _rgAirframeInfoFlyingWing[];
- static const AirframeInfo_t _rgAirframeInfoQuadRotorX[];
- static const AirframeInfo_t _rgAirframeInfoQuadRotorPlus[];
- static const AirframeInfo_t _rgAirframeInfoOctoRotorX[];
- static const AirframeInfo_t _rgAirframeInfoOctoRotorPlus[];
- static const AirframeInfo_t _rgAirframeInfoHexaRotorX[];
- static const AirframeInfo_t _rgAirframeInfoHexaRotorPlus[];
- static const AirframeInfo_t _rgAirframeInfoQuadRotorH[];
- static const AirframeInfo_t _rgAirframeInfoSimulation[];
};
#endif
diff --git a/src/AutoPilotPlugins/PX4/AirframeComponentController.cc b/src/AutoPilotPlugins/PX4/AirframeComponentController.cc
index 09cf480..c4790af 100644
--- a/src/AutoPilotPlugins/PX4/AirframeComponentController.cc
+++ b/src/AutoPilotPlugins/PX4/AirframeComponentController.cc
@@ -58,13 +58,20 @@ AirframeComponentController::AirframeComponentController(void) :
bool autostartFound = false;
_autostartId = getParameterFact(FactSystem::defaultComponentId, "SYS_AUTOSTART")->value().toInt();
+
+
- for (const AirframeComponentAirframes::AirframeType_t* pType=&AirframeComponentAirframes::rgAirframeTypes[0]; pType->name != NULL; pType++) {
+ for (int tindex = 0; tindex < AirframeComponentAirframes::get().count(); tindex++) {
+
+ const AirframeComponentAirframes::AirframeType_t* pType = AirframeComponentAirframes::get().values().at(tindex);
+
AirframeType* airframeType = new AirframeType(pType->name, pType->imageResource, this);
Q_CHECK_PTR(airframeType);
-
- int index = 0;
- for (const AirframeComponentAirframes::AirframeInfo_t* pInfo=&pType->rgAirframeInfo[0]; pInfo->name != NULL; pInfo++) {
+
+ for (int index = 0; index < pType->rgAirframeInfo.count(); index++) {
+ const AirframeComponentAirframes::AirframeInfo_t* pInfo = pType->rgAirframeInfo.at(index);
+ Q_CHECK_PTR(pInfo);
+
if (_autostartId == pInfo->autostartId) {
Q_ASSERT(!autostartFound);
autostartFound = true;
@@ -73,7 +80,6 @@ AirframeComponentController::AirframeComponentController(void) :
_currentVehicleIndex = index;
}
airframeType->addAirframe(pInfo->name, pInfo->autostartId);
- index++;
}
_airframeTypes.append(QVariant::fromValue(airframeType));
diff --git a/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml b/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml
new file mode 100644
index 0000000..d257142
--- /dev/null
+++ b/src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml
@@ -0,0 +1,288 @@
+
+
+ 1
+
+
+ Simon Wilks <simon@px4.io>
+ Flying Wing
+ https://pixhawk.org/platforms/planes/bormatec_camflyer_q
+
+
+
+
+
+
+
+
+ Simon Wilks <simon@px4.io>
+ Flying Wing
+ https://pixhawk.org/platforms/planes/z-84_wing_wing
+
+
+
+
+
+
+
+
+ Thomas Gubler <thomas@px4.io>, Julian Oes <julian@px4.io>
+ Flying Wing
+ https://pixhawk.org/platforms/planes/skywalker_x5
+
+
+
+
+
+
+
+
+ Simon Wilks <simon@px4.io>
+ Flying Wing
+ https://pixhawk.org/platforms/planes/z-84_wing_wing
+
+
+
+
+
+
+
+
+ Simon Wilks <simon@px4.io>
+ Flying Wing
+
+
+ Simon Wilks <simon@px4.io>
+ Flying Wing
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Flying Wing
+
+
+
+
+ Anton Babushkin <anton@px4.io>
+ Hexarotor +
+
+
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Hexarotor Coaxial
+
+
+
+
+ Anton Babushkin <anton@px4.io>
+ Hexarotor x
+
+
+
+
+
+
+
+ Anton Babushkin <anton@px4.io>
+ Octorotor +
+
+
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Octorotor Coaxial
+
+
+
+
+ Anton Babushkin <anton@px4.io>
+ Octorotor x
+
+
+
+
+
+
+
+ Anton Babushkin <anton@px4.io>
+ Quadrotor +
+
+
+
+
+ Anton Babushkin <anton@px4.io>, Simon Wilks <simon@px4.io>
+ Quadrotor Wide
+
+
+ Anton Babushkin <anton@px4.io>
+ Quadrotor Wide
+
+
+ Thomas Gubler <thomas@px4.io>
+ Quadrotor Wide
+
+
+ Simon Wilks <simon@px4.io>
+ Quadrotor Wide
+
+
+ Anton Matosov <anton.matosov@gmail.com>
+ Quadrotor Wide
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Quadrotor x
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Quadrotor x
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Quadrotor x
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Quadrotor x
+
+
+
+
+
+ Pavel Kirienko <pavel@px4.io>
+ Quadrotor x
+
+
+ Thomas Gubler <thomas@px4.io>
+ Quadrotor x
+
+
+
+
+ Rover
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Simulation
+
+
+
+
+
+
+ Anton Babushkin <anton@px4.io>
+ Simulation
+
+
+ Anton Babushkin <anton@px4.io>
+ Simulation
+
+
+ Thomas Gubler <thomas@px4.io>
+ Simulation
+
+
+ Thomas Gubler <thomas@px4.io>
+ Simulation
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Standard Plane
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Standard Plane
+
+
+
+
+
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Standard Plane
+
+
+
+
+
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Standard Plane
+
+
+
+
+
+
+
+
+ Lorenz Meier <lorenz@px4.io>
+ Standard Plane
+
+
+
+
+
+
+
+
+
+
+
+
+ Trent Lukaczyk <aerialhedgehog@gmail.com>
+ Tricopter Y+
+
+
+
+
+ Trent Lukaczyk <aerialhedgehog@gmail.com>
+ Tricopter Y-
+
+
+
+
+ Roman Bapst <roman@px4.io>
+ VTOL Tailsitter
+
+
+ Roman Bapst <roman@px4.io>
+ VTOL Tailsitter
+
+
+ Roman Bapst <roman@px4.io>
+ VTOL Tailsitter
+
+
+
+
+ Roman Bapst <roman@px4.io>
+ VTOL Tiltrotor
+
+
+
diff --git a/src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc b/src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc
new file mode 100644
index 0000000..0f144de
--- /dev/null
+++ b/src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc
@@ -0,0 +1,255 @@
+/*=====================================================================
+
+ QGroundControl Open Source Ground Control Station
+
+ (c) 2009 - 2014 QGROUNDCONTROL PROJECT
+
+ 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 .
+
+ ======================================================================*/
+
+/// @file
+/// @author Don Gagne
+
+#include "PX4AirframeLoader.h"
+#include "QGCApplication.h"
+#include "QGCLoggingCategory.h"
+#include "AirframeComponentAirframes.h"
+
+#include
+#include
+#include
+#include
+
+QGC_LOGGING_CATEGORY(PX4AirframeLoaderLog, "PX4AirframeLoaderLog")
+
+bool PX4AirframeLoader::_airframeMetaDataLoaded = false;
+
+PX4AirframeLoader::PX4AirframeLoader(AutoPilotPlugin* autopilot, UASInterface* uas, QObject* parent)
+{
+ Q_UNUSED(autopilot);
+ Q_UNUSED(uas);
+ Q_UNUSED(parent);
+ Q_ASSERT(uas);
+}
+
+/// Load Airframe Fact meta data
+///
+/// The meta data comes from firmware airframes.xml file.
+void PX4AirframeLoader::loadAirframeFactMetaData(void)
+{
+ if (_airframeMetaDataLoaded) {
+ return;
+ }
+
+ qCDebug(PX4AirframeLoaderLog) << "Loading PX4 airframe fact meta data";
+ qDebug() << "LOADING META DATA";
+
+ Q_ASSERT(AirframeComponentAirframes::get().count() == 0);
+
+ QString airframeFilename;
+
+ // We want unit test builds to always use the resource based meta data to provide repeatable results
+ if (!qgcApp()->runningUnitTests()) {
+ // First look for meta data that comes from a firmware download. Fall back to resource if not there.
+ QSettings settings;
+ QDir parameterDir = QFileInfo(settings.fileName()).dir();
+ airframeFilename = parameterDir.filePath("PX4AirframeFactMetaData.xml");
+ }
+ if (airframeFilename.isEmpty() || !QFile(airframeFilename).exists()) {
+ airframeFilename = ":/AutoPilotPlugins/PX4/AirframeFactMetaData.xml";
+ }
+
+ qCDebug(PX4AirframeLoaderLog) << "Loading meta data file:" << airframeFilename;
+
+ QFile xmlFile(airframeFilename);
+ Q_ASSERT(xmlFile.exists());
+
+ bool success = xmlFile.open(QIODevice::ReadOnly);
+ Q_UNUSED(success);
+ Q_ASSERT(success);
+
+ if (!success) {
+ qWarning() << "Failed opening airframe XML";
+ return;
+ }
+
+ QXmlStreamReader xml(xmlFile.readAll());
+ xmlFile.close();
+ if (xml.hasError()) {
+ qWarning() << "Badly formed XML" << xml.errorString();
+ return;
+ }
+
+ QString airframeGroup;
+ QString image;
+ QString errorString;
+ int xmlState = XmlStateNone;
+ bool badMetaData = true;
+
+ while (!xml.atEnd()) {
+ if (xml.isStartElement()) {
+ QString elementName = xml.name().toString();
+
+ if (elementName == "airframes") {
+ if (xmlState != XmlStateNone) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+ xmlState = XmlStateFoundAirframes;
+
+ } else if (elementName == "version") {
+ if (xmlState != XmlStateFoundAirframes) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+ xmlState = XmlStateFoundVersion;
+
+ bool convertOk;
+ QString strVersion = xml.readElementText();
+ int intVersion = strVersion.toInt(&convertOk);
+ if (!convertOk) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+ if (intVersion < 1) {
+ // We can't read these old files
+ qDebug() << "Airframe version stamp too old, skipping load. Found:" << intVersion << "Want: 3 File:" << airframeFilename;
+ return;
+ }
+
+
+ } else if (elementName == "airframe_group") {
+ if (xmlState != XmlStateFoundVersion) {
+ // We didn't get a version stamp, assume older version we can't read
+ qDebug() << "Parameter version stamp not found, skipping load" << airframeFilename;
+ return;
+ }
+ xmlState = XmlStateFoundGroup;
+
+ if (!xml.attributes().hasAttribute("name") || !xml.attributes().hasAttribute("image")) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+ airframeGroup = xml.attributes().value("name").toString();
+ image = xml.attributes().value("image").toString();
+ qCDebug(PX4AirframeLoaderLog) << "Found group: " << airframeGroup;
+
+ } else if (elementName == "airframe") {
+ if (xmlState != XmlStateFoundGroup) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+ xmlState = XmlStateFoundAirframe;
+
+ if (!xml.attributes().hasAttribute("name") || !xml.attributes().hasAttribute("id")) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+
+ QString name = xml.attributes().value("name").toString();
+ QString id = xml.attributes().value("id").toString();
+
+ qCDebug(PX4AirframeLoaderLog) << "Found airframe name:" << name << " type:" << airframeGroup << " id:" << id;
+
+ // Now that we know type we can airframe meta data object and add it to the system
+ AirframeComponentAirframes::insert(airframeGroup, image, name, id.toInt());
+
+ } else {
+ // We should be getting meta data now
+ if (xmlState != XmlStateFoundAirframe) {
+ qWarning() << "Badly formed XML";
+ return;
+ }
+
+ if (!badMetaData) {
+
+ // We eventually want this, just not yet now
+// if (elementName == "short_desc") {
+// Q_ASSERT(metaData);
+// QString text = xml.readElementText();
+// text = text.replace("\n", " ");
+// qCDebug(PX4AirframeLoaderLog) << "Short description:" << text;
+// metaData->setShortDescription(text);
+
+// } else if (elementName == "long_desc") {
+// Q_ASSERT(metaData);
+// QString text = xml.readElementText();
+// text = text.replace("\n", " ");
+// qCDebug(PX4AirframeLoaderLog) << "Long description:" << text;
+// metaData->setLongDescription(text);
+
+// } else if (elementName == "min") {
+// Q_ASSERT(metaData);
+// QString text = xml.readElementText();
+// qCDebug(PX4AirframeLoaderLog) << "Min:" << text;
+
+// QVariant varMin;
+// if (metaData->convertAndValidate(text, true /* convertOnly */, varMin, errorString)) {
+// metaData->setMin(varMin);
+// } else {
+// qCWarning(PX4AirframeLoaderLog) << "Invalid min value, name:" << metaData->name() << " type:" << metaData->type() << " min:" << text << " error:" << errorString;
+// }
+
+// } else if (elementName == "max") {
+// Q_ASSERT(metaData);
+// QString text = xml.readElementText();
+// qCDebug(PX4AirframeLoaderLog) << "Max:" << text;
+
+// QVariant varMax;
+// if (metaData->convertAndValidate(text, true /* convertOnly */, varMax, errorString)) {
+// metaData->setMax(varMax);
+// } else {
+// qCWarning(PX4AirframeLoaderLog) << "Invalid max value, name:" << metaData->name() << " type:" << metaData->type() << " max:" << text << " error:" << errorString;
+// }
+
+// } else if (elementName == "unit") {
+// Q_ASSERT(metaData);
+// QString text = xml.readElementText();
+// qCDebug(PX4AirframeLoaderLog) << "Unit:" << text;
+// metaData->setUnits(text);
+
+// } else {
+ qDebug() << "Unknown element in XML: " << elementName;
+// }
+ }
+ }
+ } else if (xml.isEndElement()) {
+ QString elementName = xml.name().toString();
+
+ if (elementName == "airframe") {
+ // Done loading this airframe, validate
+
+ // Reset for next airframe
+ badMetaData = false;
+ xmlState = XmlStateFoundGroup;
+ } else if (elementName == "airframe_group") {
+ xmlState = XmlStateFoundVersion;
+ } else if (elementName == "airframes") {
+ xmlState = XmlStateFoundAirframes;
+ }
+ }
+ xml.readNext();
+ }
+
+ _airframeMetaDataLoaded = true;
+}
+
+void PX4AirframeLoader::clearStaticData(void)
+{
+ AirframeComponentAirframes::clear();
+ _airframeMetaDataLoaded = false;
+}
diff --git a/src/AutoPilotPlugins/PX4/PX4AirframeLoader.h b/src/AutoPilotPlugins/PX4/PX4AirframeLoader.h
new file mode 100644
index 0000000..84d6e77
--- /dev/null
+++ b/src/AutoPilotPlugins/PX4/PX4AirframeLoader.h
@@ -0,0 +1,69 @@
+/*=====================================================================
+
+ QGroundControl Open Source Ground Control Station
+
+ (c) 2009 - 2015 QGROUNDCONTROL PROJECT
+
+ 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 .
+
+ ======================================================================*/
+
+#ifndef PX4AIRFRAMELOADER_H
+#define PX4AIRFRAMELOADER_H
+
+#include
+#include
+#include
+#include
+
+#include "ParameterLoader.h"
+#include "FactSystem.h"
+#include "UASInterface.h"
+#include "AutoPilotPlugin.h"
+
+/// @file PX4AirframeLoader.h
+/// @author Lorenz Meier
+
+Q_DECLARE_LOGGING_CATEGORY(PX4AirframeLoaderLog)
+
+/// Collection of Parameter Facts for PX4 AutoPilot
+
+class PX4AirframeLoader : QObject
+{
+ Q_OBJECT
+
+public:
+ /// @param uas Uas which this set of facts is associated with
+ PX4AirframeLoader(AutoPilotPlugin* autpilot,UASInterface* uas, QObject* parent = NULL);
+
+ static void loadAirframeFactMetaData(void);
+ static void clearStaticData(void);
+
+private:
+ enum {
+ XmlStateNone,
+ XmlStateFoundAirframes,
+ XmlStateFoundVersion,
+ XmlStateFoundGroup,
+ XmlStateFoundAirframe,
+ XmlStateDone
+ };
+
+ static bool _airframeMetaDataLoaded; ///< true: parameter meta data already loaded
+ static QMap _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData
+};
+
+#endif // PX4AIRFRAMELOADER_H
diff --git a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc
index c282deb..09ef2de 100644
--- a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc
+++ b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc
@@ -25,6 +25,7 @@
#include "AutoPilotPluginManager.h"
#include "UASManager.h"
#include "PX4ParameterLoader.h"
+#include "PX4AirframeLoader.h"
#include "FlightModesComponentController.h"
#include "AirframeComponentController.h"
#include "QGCMessageBox.h"
@@ -81,13 +82,18 @@ PX4AutoPilotPlugin::PX4AutoPilotPlugin(UASInterface* uas, QObject* parent) :
connect(_parameterFacts, &PX4ParameterLoader::parametersReady, this, &PX4AutoPilotPlugin::_pluginReadyPreChecks);
connect(_parameterFacts, &PX4ParameterLoader::parameterListProgress, this, &PX4AutoPilotPlugin::parameterListProgress);
+
+ _airframeFacts = new PX4AirframeLoader(this, uas, this);
+ Q_CHECK_PTR(_airframeFacts);
PX4ParameterLoader::loadParameterFactMetaData();
+ PX4AirframeLoader::loadAirframeFactMetaData();
}
PX4AutoPilotPlugin::~PX4AutoPilotPlugin()
{
delete _parameterFacts;
+ delete _airframeFacts;
}
QList PX4AutoPilotPlugin::getModes(void)
@@ -259,6 +265,7 @@ QString PX4AutoPilotPlugin::getShortModeText(uint8_t baseMode, uint32_t customMo
void PX4AutoPilotPlugin::clearStaticData(void)
{
PX4ParameterLoader::clearStaticData();
+ PX4AirframeLoader::clearStaticData();
}
const QVariantList& PX4AutoPilotPlugin::vehicleComponents(void)
diff --git a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h
index d391e36..8f75ab0 100644
--- a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h
+++ b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h
@@ -28,6 +28,7 @@
#include "AutoPilotPluginManager.h"
#include "UASInterface.h"
#include "PX4ParameterLoader.h"
+#include "PX4AirframeLoader.h"
#include "AirframeComponent.h"
#include "RadioComponent.h"
#include "FlightModesComponent.h"
@@ -72,7 +73,8 @@ private:
// Overrides from AutoPilotPlugin
virtual ParameterLoader* _getParameterLoader(void) { return _parameterFacts; }
- PX4ParameterLoader* _parameterFacts;
+ PX4ParameterLoader* _parameterFacts;
+ PX4AirframeLoader* _airframeFacts;
QVariantList _components;
AirframeComponent* _airframeComponent;
RadioComponent* _radioComponent;
diff --git a/src/VehicleSetup/FirmwareImage.cc b/src/VehicleSetup/FirmwareImage.cc
index 1f49de6..b2ec91b 100644
--- a/src/VehicleSetup/FirmwareImage.cc
+++ b/src/VehicleSetup/FirmwareImage.cc
@@ -242,9 +242,8 @@ bool FirmwareImage::_px4Load(const QString& imageFilename)
QSettings settings;
QDir parameterDir = QFileInfo(settings.fileName()).dir();
QString parameterFilename = parameterDir.filePath("PX4ParameterFactMetaData.xml");
- qDebug() << parameterFilename;
QFile parameterFile(parameterFilename);
-
+
if (parameterFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
qint64 bytesWritten = parameterFile.write(decompressedBytes);
if (bytesWritten != decompressedBytes.count()) {
@@ -259,6 +258,35 @@ bool FirmwareImage::_px4Load(const QString& imageFilename)
emit statusMessage(QString("Unable to open parameter meta data file %1 for writing, error: %2").arg(parameterFilename).arg(parameterFile.errorString()));
}
}
+
+ // Decompress the airframe xml and save to file
+ success = _decompressJsonValue(px4Json, // JSON object
+ bytes, // Raw bytes of JSON document
+ "airframe_xml_size", // key which holds byte size
+ "airframe_xml", // key which holds compress bytes
+ decompressedBytes); // Returned decompressed bytes
+ if (success) {
+ // We cache the airframe xml in the same location as settings and parameters
+ QSettings settings;
+ QDir airframeDir = QFileInfo(settings.fileName()).dir();
+ QString airframeFilename = airframeDir.filePath("PX4AirframeFactMetaData.xml");
+ qDebug() << airframeFilename;
+ QFile airframeFile(airframeFilename);
+
+ if (airframeFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ qint64 bytesWritten = airframeFile.write(decompressedBytes);
+ if (bytesWritten != decompressedBytes.count()) {
+ // FIXME: What about these warnings?
+ emit statusMessage(QString("Write failed for airframe meta data file, error: %1").arg(airframeFile.errorString()));
+ airframeFile.close();
+ QFile::remove(airframeFilename);
+ } else {
+ airframeFile.close();
+ }
+ } else {
+ emit statusMessage(QString("Unable to open airframe meta data file %1 for writing, error: %2").arg(airframeFilename).arg(airframeFile.errorString()));
+ }
+ }
// Decompress the image and save to file
_imageSize = px4Json.value(QString("image_size")).toInt();