QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
PX4AirframeLoader.cc
Go to the documentation of this file.
1#include "PX4AirframeLoader.h"
2#include "AppMessages.h"
5#include "AutoPilotPlugin.h"
6
7#include <QFile>
8#include <QFileInfo>
9#include <QDir>
10#include <QDebug>
11#include <QtCore/QXmlStreamReader>
12#include <QtCore/QSettings>
13
14QGC_LOGGING_CATEGORY(PX4AirframeLoaderLog, "AutoPilotPlugins.PX4AirframeLoader")
15
16bool PX4AirframeLoader::_airframeMetaDataLoaded = false;
17
19{
20 Q_UNUSED(autopilot);
21 Q_UNUSED(parent);
22}
23
25{
26 QSettings settings;
27 QDir parameterDir = QFileInfo(settings.fileName()).dir();
28 return parameterDir.filePath("PX4AirframeFactMetaData.xml");
29}
30
35{
36 if (_airframeMetaDataLoaded) {
37 return;
38 }
39
40 qCDebug(PX4AirframeLoaderLog) << "Loading PX4 airframe fact meta data";
41
42 if (AirframeComponentAirframes::get().count() != 0) {
43 qCWarning(PX4AirframeLoaderLog) << "Internal error";
44 return;
45 }
46
47 QString airframeFilename;
48
49 // We want unit test builds to always use the resource based meta data to provide repeatable results
50 if (!QGC::runningUnitTests()) {
51 // First look for meta data that comes from a firmware download. Fall back to resource if not there.
52 airframeFilename = aiframeMetaDataFile();
53 }
54 if (airframeFilename.isEmpty() || !QFile(airframeFilename).exists()) {
55 airframeFilename = ":/AutoPilotPlugins/PX4/AirframeFactMetaData.xml";
56 }
57
58 qCDebug(PX4AirframeLoaderLog) << "Loading meta data file:" << airframeFilename;
59
60 QFile xmlFile(airframeFilename);
61 if (!xmlFile.exists()) {
62 qCWarning(PX4AirframeLoaderLog) << "Internal error";
63 return;
64 }
65
66 bool success = xmlFile.open(QIODevice::ReadOnly);
67
68 if (!success) {
69 qCWarning(PX4AirframeLoaderLog) << "Failed opening airframe XML";
70 return;
71 }
72
73 QXmlStreamReader xml(xmlFile.readAll());
74 xmlFile.close();
75 if (xml.hasError()) {
76 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML" << xml.errorString();
77 return;
78 }
79
80 QString airframeGroup;
81 QString image;
82 int xmlState = XmlStateNone;
83
84 while (!xml.atEnd()) {
85 if (xml.isStartElement()) {
86 QString elementName = xml.name().toString();
87
88 if (elementName == "airframes") {
89 if (xmlState != XmlStateNone) {
90 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
91 return;
92 }
93 xmlState = XmlStateFoundAirframes;
94
95 } else if (elementName == "version") {
96 if (xmlState != XmlStateFoundAirframes) {
97 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
98 return;
99 }
100 xmlState = XmlStateFoundVersion;
101
102 bool convertOk;
103 QString strVersion = xml.readElementText();
104 int intVersion = strVersion.toInt(&convertOk);
105 if (!convertOk) {
106 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
107 return;
108 }
109 if (intVersion < 1) {
110 // We can't read these old files
111 qDebug() << "Airframe version stamp too old, skipping load. Found:" << intVersion << "Want: 3 File:" << airframeFilename;
112 return;
113 }
114
115 } else if (elementName == "airframe_version_major") {
116 // Just skip over for now
117 } else if (elementName == "airframe_version_minor") {
118 // Just skip over for now
119
120 } else if (elementName == "airframe_group") {
121 if (xmlState != XmlStateFoundVersion) {
122 // We didn't get a version stamp, assume older version we can't read
123 qDebug() << "Parameter version stamp not found, skipping load" << airframeFilename;
124 return;
125 }
126 xmlState = XmlStateFoundGroup;
127
128 if (!xml.attributes().hasAttribute("name") || !xml.attributes().hasAttribute("image")) {
129 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
130 return;
131 }
132 airframeGroup = xml.attributes().value("name").toString();
133 image = xml.attributes().value("image").toString();
134 qCDebug(PX4AirframeLoaderLog) << "Found group: " << airframeGroup << " image:" << image;
135
136 } else if (elementName == "airframe") {
137 if (xmlState != XmlStateFoundGroup) {
138 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
139 return;
140 }
141 xmlState = XmlStateFoundAirframe;
142
143 if (!xml.attributes().hasAttribute("name") || !xml.attributes().hasAttribute("id")) {
144 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
145 return;
146 }
147
148 QString name = xml.attributes().value("name").toString();
149 QString id = xml.attributes().value("id").toString();
150
151 qCDebug(PX4AirframeLoaderLog) << "Found airframe name:" << name << " type:" << airframeGroup << " id:" << id;
152
153 // Now that we know type we can airframe meta data object and add it to the system
154 AirframeComponentAirframes::insert(airframeGroup, image, name, id.toInt());
155
156 } else {
157 // We should be getting meta data now
158 if (xmlState != XmlStateFoundAirframe) {
159 qCWarning(PX4AirframeLoaderLog) << "Badly formed XML";
160 return;
161 }
162 }
163 } else if (xml.isEndElement()) {
164 QString elementName = xml.name().toString();
165
166 if (elementName == "airframe") {
167 // Reset for next airframe
168 xmlState = XmlStateFoundGroup;
169 } else if (elementName == "airframe_group") {
170 xmlState = XmlStateFoundVersion;
171 } else if (elementName == "airframes") {
172 xmlState = XmlStateFoundAirframes;
173 }
174 }
175 xml.readNext();
176 }
177
178 _airframeMetaDataLoaded = true;
179}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
static void insert(QString &group, QString &image, QString &name, int id)
static QMap< QString, AirframeComponentAirframes::AirframeType_t * > & get()
The AutoPilotPlugin class is an abstract base class which represents the methods and objects which ar...
Collection of Parameter Facts for PX4 AutoPilot.
static void loadAirframeMetaData(void)
static QString aiframeMetaDataFile(void)
bool runningUnitTests()