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 "QGCApplication.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 (!qgcApp()->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 qgcApp()
#define QGC_LOGGING_CATEGORY(name, categoryStr)
static void insert(QString &group, QString &image, QString &name, int id)
static QMap< QString, AirframeComponentAirframes::AirframeType_t * > & get()
Collection of Parameter Facts for PX4 AutoPilot.
static void loadAirframeMetaData(void)
static QString aiframeMetaDataFile(void)