Commit 8113009a authored by Lorenz Meier's avatar Lorenz Meier

Merge pull request #1750 from mavlink/airframe_meta

Airframe meta information
parents 9daac0a2 c6e64bcd
......@@ -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 += \
......
......@@ -137,9 +137,6 @@
<file alias="QGroundControl/FlightControls/qmldir">src/ui/qmlcommon/qmldir</file>
<file alias="QGroundControl/FlightControls/QGCWaypoint.qml">src/ui/qmlcommon/QGCWaypoint.qml</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/PX4">
<file alias="ParameterFactMetaData.xml">src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml</file>
</qresource>
<qresource prefix="/res">
<file alias="LeftArrow">resources/LeftArrow.svg</file>
<file alias="RightArrow">resources/RightArrow.svg</file>
......@@ -247,4 +244,8 @@
<qresource prefix="/res/audio">
<file alias="Alert">resources/audio/alert.wav</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/PX4">
<file alias="AirframeFactMetaData.xml">src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml</file>
<file alias="ParameterFactMetaData.xml">src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml</file>
</qresource>
</RCC>
......@@ -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<QString, AirframeComponentAirframes::AirframeType_t*> AirframeComponentAirframes::rgAirframeTypes;
QMap<QString, AirframeComponentAirframes::AirframeType_t*>& 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();
}
......@@ -30,6 +30,7 @@
#include <QObject>
#include <QQuickItem>
#include <QList>
#include <QMap>
#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<AirframeInfo_t*> rgAirframeInfo;
} AirframeType_t;
static QMap<QString, AirframeComponentAirframes::AirframeType_t*>& get();
static void clear();
static void insert(QString& group, QString& image, QString& name, int id);
public:
static const AirframeType_t rgAirframeTypes[];
protected:
static QMap<QString, AirframeType_t*> 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
......@@ -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));
......
<?xml version='1.0' encoding='UTF-8'?>
<airframes>
<version>1</version>
<airframe_group image="AirframeFlyingWing.png" name="Flying Wing">
<airframe id="3030" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="IO Camflyer">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/bormatec_camflyer_q</url>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
</airframe>
<airframe id="3031" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Phantom FPV Flying Wing">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/z-84_wing_wing</url>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
</airframe>
<airframe id="3032" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;, Julian Oes &lt;julian@px4.io&gt;" name="Skywalker X5 Flying Wing">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;, Julian Oes &lt;julian@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/skywalker_x5</url>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
</airframe>
<airframe id="3033" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Wing Wing (aka Z-84) Flying Wing">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
<url>https://pixhawk.org/platforms/planes/z-84_wing_wing</url>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">left aileron</output>
<output name="MAIN2">right aileron</output>
<output name="MAIN4">throttle</output>
</airframe>
<airframe id="3034" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="FX-79 Buffalo Flying Wing">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
<airframe id="3035" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Viper">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
<airframe id="3100" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="TBS Caipirinha">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Flying Wing</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeHexaRotorPlus.png" name="Hexarotor +">
<airframe id="7001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Hexarotor + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Hexarotor +</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
</airframe_group>
<airframe_group image="" name="Hexarotor Coaxial">
<airframe id="11001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Hexa coaxial geometry">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Hexarotor Coaxial</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeHexaRotorX.png" name="Hexarotor x">
<airframe id="6001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Hexarotor x geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Hexarotor x</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
</airframe_group>
<airframe_group image="AirframeOctoRotorPlus.png" name="Octorotor +">
<airframe id="9001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Octocopter + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Octorotor +</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
</airframe_group>
<airframe_group image="" name="Octorotor Coaxial">
<airframe id="12001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic 10&quot; Octo coaxial geometry">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Octorotor Coaxial</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeOctoRotorX.png" name="Octorotor x">
<airframe id="8001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic Octocopter X geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Octorotor x</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
</airframe_group>
<airframe_group image="AirframeQuadRotorPlus.png" name="Quadrotor +">
<airframe id="5001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="Generic 10&quot; Quad + geometry">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Quadrotor +</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeQuadRotorH.png" name="Quadrotor Wide">
<airframe id="10015" maintainer="Anton Babushkin &lt;anton@px4.io&gt;, Simon Wilks &lt;simon@px4.io&gt;" name="Team Blacksheep Discovery">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;, Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type>
</airframe>
<airframe id="10016" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="3DR Iris Quadrotor">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type>
</airframe>
<airframe id="10017" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;" name="Steadidrone QU4D">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type>
</airframe>
<airframe id="10018" maintainer="Simon Wilks &lt;simon@px4.io&gt;" name="Team Blacksheep Discovery Endurance">
<maintainer>Simon Wilks &lt;simon@px4.io&gt;</maintainer>
<type>Quadrotor Wide</type>
</airframe>
<airframe id="10019" maintainer="Anton Matosov &lt;anton.matosov@gmail.com&gt;" name="HobbyKing SK450 DeadCat modification">
<maintainer>Anton Matosov &lt;anton.matosov@gmail.com&gt;</maintainer>
<type>Quadrotor Wide</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeQuadRotorX.png" name="Quadrotor x">
<airframe id="4001" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Generic Quadrotor X config">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="4008" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="AR.Drone Frame">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
</airframe>
<airframe id="4010" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="DJI Flame Wheel F330">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="4011" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="DJI Flame Wheel F450">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
</airframe>
<airframe id="4012" maintainer="Pavel Kirienko &lt;pavel@px4.io&gt;" name="F450-sized quadrotor with CAN">
<maintainer>Pavel Kirienko &lt;pavel@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
</airframe>
<airframe id="4020" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;" name="Hobbyking Micro PCB">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;</maintainer>
<type>Quadrotor x</type>
</airframe>
</airframe_group>
<airframe_group image="" name="Rover">
<airframe id="50001" maintainer="John Doe &lt;john@example.com&gt;" name="Axial Racing AX10">
<type>Rover</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeSimulation.png" name="Simulation">
<airframe id="1000" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="HILStar (XPlane)">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Simulation</type>
<output name="MAIN1">aileron</output>
<output name="MAIN2">elevator</output>
<output name="MAIN3">rudder</output>
<output name="MAIN4">throttle</output>
</airframe>
<airframe id="1001" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="HIL Quadcopter X">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Simulation</type>
</airframe>
<airframe id="1003" maintainer="Anton Babushkin &lt;anton@px4.io&gt;" name="HIL Quadcopter +">
<maintainer>Anton Babushkin &lt;anton@px4.io&gt;</maintainer>
<type>Simulation</type>
</airframe>
<airframe id="1004" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;" name="HIL Rascal 110 (Flightgear)">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;</maintainer>
<type>Simulation</type>
</airframe>
<airframe id="1005" maintainer="Thomas Gubler &lt;thomas@px4.io&gt;" name="HIL Malolo 1 (Flightgear)">
<maintainer>Thomas Gubler &lt;thomas@px4.io&gt;</maintainer>
<type>Simulation</type>
</airframe>
</airframe_group>
<airframe_group image="AirframeStandardPlane.png" name="Standard Plane">
<airframe id="2100" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Multiplex Easystar">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type>
</airframe>
<airframe id="2101" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Standard AERT Plane">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">aileron</output>
<output name="MAIN2">elevator</output>
<output name="MAIN3">throttle</output>
<output name="MAIN4">rudder</output>
<output name="MAIN5">flaps</output>
</airframe>
<airframe id="2102" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Skywalker (3DR Aero)">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">aileron</output>
<output name="MAIN2">elevator</output>
<output name="MAIN3">throttle</output>
<output name="MAIN4">rudder</output>
<output name="MAIN5">flaps</output>
</airframe>
<airframe id="2103" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Skyhunter 1800">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">aileron</output>
<output name="MAIN2">elevator</output>
<output name="MAIN4">throttle</output>
</airframe>
<airframe id="2104" maintainer="Lorenz Meier &lt;lorenz@px4.io&gt;" name="Standard AETR Plane">
<maintainer>Lorenz Meier &lt;lorenz@px4.io&gt;</maintainer>
<type>Standard Plane</type>
<output name="AUX1">feed-through of RC AUX1 channel</output>
<output name="AUX2">feed-through of RC AUX2 channel</output>
<output name="AUX3">feed-through of RC AUX3 channel</output>
<output name="MAIN1">aileron</output>
<output name="MAIN2">elevator</output>
<output name="MAIN3">throttle</output>
<output name="MAIN4">rudder</output>
<output name="MAIN5">flaps</output>
</airframe>
</airframe_group>
<airframe_group image="" name="Tricopter Y+">
<airframe id="14001" maintainer="Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;" name="Generic Tricopter Y+ Geometry">
<maintainer>Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;</maintainer>
<type>Tricopter Y+</type>
</airframe>
</airframe_group>
<airframe_group image="" name="Tricopter Y-">
<airframe id="14002" maintainer="Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;" name="Generic Tricopter Y- Geometry">
<maintainer>Trent Lukaczyk &lt;aerialhedgehog@gmail.com&gt;</maintainer>
<type>Tricopter Y-</type>
</airframe>
</airframe_group>
<airframe_group image="" name="VTOL Tailsitter">
<airframe id="13001" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Duorotor Tailsitter">
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Tailsitter</type>
</airframe>
<airframe id="13003" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Quadrotor X Tailsitter">
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Tailsitter</type>
</airframe>
<airframe id="13004" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="Quadrotor + Tailsitter">
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Tailsitter</type>
</airframe>
</airframe_group>
<airframe_group image="" name="VTOL Tiltrotor">
<airframe id="13002" maintainer="Roman Bapst &lt;roman@px4.io&gt;" name="BirdsEyeView Aerobotics FireFly6">
<maintainer>Roman Bapst &lt;roman@px4.io&gt;</maintainer>
<type>VTOL Tiltrotor</type>
</airframe>
</airframe_group>
</airframes>
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 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
/// @author Don Gagne <don@thegagnes.com>
#include "PX4AirframeLoader.h"
#include "QGCApplication.h"
#include "QGCLoggingCategory.h"
#include "AirframeComponentAirframes.h"
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
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;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 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/>.
======================================================================*/
#ifndef PX4AIRFRAMELOADER_H
#define PX4AIRFRAMELOADER_H
#include <QObject>
#include <QMap>
#include <QXmlStreamReader>
#include <QLoggingCategory>
#include "ParameterLoader.h"
#include "FactSystem.h"
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
/// @file PX4AirframeLoader.h
/// @author Lorenz Meier <lm@qgroundcontrol.org>
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<QString, FactMetaData*> _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData
};
#endif // PX4AIRFRAMELOADER_H
......@@ -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<AutoPilotPluginManager::FullMode_t> 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)
......
......@@ -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;
......
......@@ -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();
......
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