Commit 57d0292d authored by DonLakeFlyer's avatar DonLakeFlyer

parent a32d84f8
......@@ -6,6 +6,7 @@ Note: This file only contains high level features or important fixes.
### 3.6.0 - Daily Build
* ArduPilot: Rework Airframe setup ui
* Plan/Pattern: Support named presets to simplify commonly used settings setup. Currently only supported by Survey.
* ArduCopter: Handle 3.7 parameter name change from CH#_OPT to RC#_OPTION.
* Improved support for flashing/connecting to ChibiOS bootloaders boards.
......
......@@ -984,9 +984,7 @@ APMFirmwarePlugin {
HEADERS += \
src/AutoPilotPlugins/APM/APMAirframeComponent.h \
src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h \
src/AutoPilotPlugins/APM/APMAirframeComponentController.h \
src/AutoPilotPlugins/APM/APMAirframeLoader.h \
src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h \
src/AutoPilotPlugins/APM/APMCameraComponent.h \
src/AutoPilotPlugins/APM/APMCompassCal.h \
......@@ -1011,9 +1009,7 @@ APMFirmwarePlugin {
SOURCES += \
src/AutoPilotPlugins/APM/APMAirframeComponent.cc \
src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc \
src/AutoPilotPlugins/APM/APMAirframeComponentController.cc \
src/AutoPilotPlugins/APM/APMAirframeLoader.cc \
src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc \
src/AutoPilotPlugins/APM/APMCameraComponent.cc \
src/AutoPilotPlugins/APM/APMCompassCal.cc \
......
......@@ -22,90 +22,155 @@ import QGroundControl.ScreenTools 1.0
SetupPage {
id: airframePage
pageComponent: _useOldFrameParam ? oldFramePageComponent: newFramePageComponent
property real _margins: ScreenTools.defaultFontPixelWidth
property bool _useOldFrameParam: controller.parameterExists(-1, "FRAME")
property Fact _oldFrameParam: controller.getParameterFact(-1, "FRAME", false)
property Fact _newFrameParam: controller.getParameterFact(-1, "FRAME_CLASS", false)
property Fact _frameTypeParam: controller.getParameterFact(-1, "FRAME_TYPE", false)
APMAirframeComponentController {
id: controller
factPanel: airframePage.viewPanel
}
ExclusiveGroup {
id: airframeTypeExclusive
}
pageComponent: pageComponent
Component {
id: oldFramePageComponent
Column {
width: availableWidth
height: 1000
spacing: _margins
RowLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margins
QGCLabel {
font.pointSize: ScreenTools.mediumFontPointSize
wrapMode: Text.WordWrap
text: qsTr("Please select your airframe type")
Layout.fillWidth: true
id: pageComponent
ColumnLayout {
id: mainColumn
width: availableWidth
property real _minW: ScreenTools.defaultFontPixelWidth * 20
property real _boxWidth: _minW
property real _boxSpace: ScreenTools.defaultFontPixelWidth
property real _margins: ScreenTools.defaultFontPixelWidth
property Fact _frameClass: controller.getParameterFact(-1, "FRAME_CLASS")
property Fact _frameType: controller.getParameterFact(-1, "FRAME_TYPE")
readonly property real spacerHeight: ScreenTools.defaultFontPixelHeight
onWidthChanged: computeDimensions()
Component.onCompleted: computeDimensions()
function computeDimensions() {
var sw = 0
var rw = 0
var idx = Math.floor(mainColumn.width / (_minW + ScreenTools.defaultFontPixelWidth))
if(idx < 1) {
_boxWidth = mainColumn.width
_boxSpace = 0
} else {
_boxSpace = 0
if(idx > 1) {
_boxSpace = ScreenTools.defaultFontPixelWidth
sw = _boxSpace * (idx - 1)
}
rw = mainColumn.width - sw
_boxWidth = rw / idx
}
}
Repeater {
model: controller.airframeTypesModel
APMAirframeComponentController {
id: controller
factPanel: airframePage.viewPanel
}
QGCRadioButton {
text: object.name
checked: controller.currentAirframeType == object
exclusiveGroup: airframeTypeExclusive
QGCLabel {
id: helpText
Layout.fillWidth: true
text: (_frameClass.rawValue === 0 ?
qsTr("Airframe is currently not set.") :
qsTr("Currently set to frame class '%1' and frame type '%2'.").arg(_frameClass.enumStringValue).arg(_frameType.enumStringValue)) +
qsTr(" To change this configuration, select the desired frame class below and frame type.")
font.family: ScreenTools.demiboldFontFamily
wrapMode: Text.WordWrap
}
onCheckedChanged: {
if (checked) {
controller.currentAirframeType = object
}
}
}
Item {
id: lastSpacer
height: parent.spacerHeight
width: 10
}
} // Column
} // Component - oldFramePageComponent
Component {
id: newFramePageComponent
Flow {
id: flowView
Layout.fillWidth: true
spacing: _boxSpace
Grid {
width: availableWidth
spacing: _margins
columns: 2
ExclusiveGroup {
id: airframeTypeExclusive
}
QGCLabel {
text: qsTr("Frame Class:")
}
Repeater {
model: controller.frameClassModel
FactComboBox {
fact: _newFrameParam
indexModel: false
width: ScreenTools.defaultFontPixelWidth * 15
}
// Outer summary item rectangle
Rectangle {
id: outerRect
width: _boxWidth
height: ScreenTools.defaultFontPixelHeight * 14
color: qgcPal.window
QGCLabel {
text: qsTr("Frame Type:")
}
readonly property real titleHeight: ScreenTools.defaultFontPixelHeight * 1.75
readonly property real innerMargin: ScreenTools.defaultFontPixelWidth
FactComboBox {
fact: _frameTypeParam
indexModel: false
width: ScreenTools.defaultFontPixelWidth * 15
}
}
}
MouseArea {
anchors.fill: parent
onClicked: airframeCheckBox.checked = true
}
QGCLabel {
id: title
text: object.name
}
Rectangle {
anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2
anchors.top: title.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
color: airframeCheckBox.checked ? qgcPal.buttonHighlight : qgcPal.windowShade
ColumnLayout {
anchors.margins: innerMargin
anchors.fill: parent
spacing: innerMargin
Image {
id: image
Layout.fillWidth: true
Layout.fillHeight: true
fillMode: Image.PreserveAspectFit
smooth: true
mipmap: true
source: object.imageResource
}
QGCCheckBox {
// Although this item is invisible we still use it to manage state
id: airframeCheckBox
checked: object.frameClass === _frameClass.rawValue
exclusiveGroup: airframeTypeExclusive
visible: false
onCheckedChanged: {
if (checked) {
_frameClass.rawValue = object.frameClass
}
}
}
QGCLabel {
text: qsTr("Frame Type")
font.pointSize: ScreenTools.smallFontPointSize
color: qgcPal.buttonHighlightText
visible: airframeCheckBox.checked && object.frameTypeSupported
}
FactComboBox {
id: combo
Layout.fillWidth: true
fact: _frameType
indexModel: false
visible: airframeCheckBox.checked && object.frameTypeSupported
}
}
}
}
} // Repeater - summary boxes
} // Flow - summary boxes
} // Column
} // Component
} // SetupPage
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMAirframeComponentAirframes.h"
#include "APMAirframeComponentController.h"
QMap<QString, APMAirframeComponentAirframes::AirframeType_t*> APMAirframeComponentAirframes::rgAirframeTypes;
QMap<QString, APMAirframeComponentAirframes::AirframeType_t*>& APMAirframeComponentAirframes::get() {
return rgAirframeTypes;
}
void APMAirframeComponentAirframes::insert(const QString& group, int groupId, const QString& image,const QString& name, const QString& file)
{
AirframeType_t *g;
if (!rgAirframeTypes.contains(group)) {
g = new AirframeType_t;
g->name = group;
g->type = groupId;
g->imageResource = image.isEmpty() ? QString() : QStringLiteral("qrc:/qmlimages/") + image;
rgAirframeTypes.insert(group, g);
} else {
g = rgAirframeTypes.value(group);
}
if (!name.isEmpty() && !file.isEmpty())
g->rgAirframeInfo.append(new APMAirframe(name, file, g->type));
}
void APMAirframeComponentAirframes::clear() {
QList<AirframeType_t*> valueList = get().values();
foreach(AirframeType_t *pType, valueList) {
qDeleteAll(pType->rgAirframeInfo);
delete pType;
}
rgAirframeTypes.clear();
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef APMAirframeComponentAirframes_H
#define APMAirframeComponentAirframes_H
#include <QObject>
#include <QQuickItem>
#include <QList>
#include <QMap>
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
class APMAirframe;
/// MVC Controller for AirframeComponent.qml.
class APMAirframeComponentAirframes
{
public:
typedef struct {
QString name;
QString imageResource;
int type;
QList<APMAirframe*> rgAirframeInfo;
} AirframeType_t;
typedef QMap<QString, AirframeType_t*> AirframeTypeMap;
static AirframeTypeMap& get();
static void clear();
static void insert(const QString& group, int groupId, const QString& image,const QString& name = QString(), const QString& file = QString());
protected:
static AirframeTypeMap rgAirframeTypes;
private:
};
#endif
......@@ -7,12 +7,7 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMAirframeComponentController.h"
#include "APMAirframeComponentAirframes.h"
#include "QGCMAVLink.h"
#include "MultiVehicleManager.h"
#include "QGCApplication.h"
......@@ -26,71 +21,113 @@
#include <QJsonParseError>
#include <QJsonObject>
bool APMAirframeComponentController::_typesRegistered = false;
const char* APMAirframeComponentController::_oldFrameParam = "FRAME";
const char* APMAirframeComponentController::_newFrameParam = "FRAME_CLASS";
APMAirframeComponentController::APMAirframeComponentController(void) :
_airframeTypesModel(new QmlObjectListModel(this))
{
if (!_typesRegistered) {
_typesRegistered = true;
qmlRegisterUncreatableType<APMAirframeType>("QGroundControl.Controllers", 1, 0, "APMAirframeType", QStringLiteral("Can only reference APMAirframeType"));
}
_fillAirFrames();
Fact* frame = NULL;
if (parameterExists(FactSystem::defaultComponentId, _oldFrameParam)) {
frame = getParameterFact(FactSystem::defaultComponentId, _oldFrameParam);
} else if (parameterExists(FactSystem::defaultComponentId, _newFrameParam)){
frame = getParameterFact(FactSystem::defaultComponentId, _newFrameParam);
// These should match the FRAME_CLASS parameter enum meta data
#define FRAME_CLASS_UNDEFINED 0
#define FRAME_CLASS_QUAD 1
#define FRAME_CLASS_HEX 2
#define FRAME_CLASS_OCTA 3
#define FRAME_CLASS_OCTAQUAD 4
#define FRAME_CLASS_Y6 5
#define FRAME_CLASS_HELI 6
#define FRAME_CLASS_TRI 7
#define FRAME_CLASS_SINGLECOPTER 8
#define FRAME_CLASS_COAXCOPTER 9
#define FRAME_CLASS_BICOPTER 10
#define FRAME_CLASS_HELI_DUAL 11
#define FRAME_CLASS_DODECAHEXA 12
#define FRAME_CLASS_HELIQUAD 13
// These should match the FRAME_TYPE parameter enum meta data
#define FRAME_TYPE_PLUS 0
#define FRAME_TYPE_X 1
#define FRAME_TYPE_V 2
#define FRAME_TYPE_H 3
#define FRAME_TYPE_V_TAIL 4
#define FRAME_TYPE_A_TAIL 5
#define FRAME_TYPE_Y6B 10
#define FRAME_TYPE_Y6F 11
#define FRAME_TYPE_BETAFLIGHTX 12
#define FRAME_TYPE_DJIX 13
#define FRAME_TYPE_CLOCKWISEX 14
typedef struct {
int frameClass;
int frameType;
const char* imageResource;
} FrameToImageInfo_t;
static const FrameToImageInfo_t s_rgFrameToImage[] = {
{ FRAME_CLASS_QUAD, FRAME_TYPE_PLUS, "QuadRotorPlus" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_X, "QuadRotorX" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_V, "QuadRotorWide" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_H, "QuadRotorH" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_V_TAIL, "QuadRotorVTail" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_A_TAIL, "QuadRotorATail" },
{ FRAME_CLASS_HEX, FRAME_TYPE_PLUS, "HexaRotorPlus" },
{ FRAME_CLASS_HEX, FRAME_TYPE_X, "HexaRotorX" },
{ FRAME_CLASS_OCTA, FRAME_TYPE_PLUS, "OctoRotorPlus" },
{ FRAME_CLASS_OCTA, FRAME_TYPE_X, "OctoRotorX" },
{ FRAME_CLASS_OCTAQUAD, FRAME_TYPE_PLUS, "OctoRotorPlusCoaxial" },
{ FRAME_CLASS_OCTAQUAD, FRAME_TYPE_X, "OctoRotorXCoaxial" },
{ FRAME_CLASS_Y6, FRAME_TYPE_Y6B, "Y6B" },
{ FRAME_CLASS_Y6, FRAME_TYPE_Y6F, "AirframeUnknown" },
{ FRAME_CLASS_Y6, -1, "Y6A" },
{ FRAME_CLASS_HELI, -1, "Helicopter" },
{ FRAME_CLASS_TRI, -1, "YPlus" },
};
static QString s_findImageResource(int frameClass, int frameType)
{
for (size_t i=0; i<sizeof(s_rgFrameToImage)/sizeof(s_rgFrameToImage[0]); i++) {
const FrameToImageInfo_t* pFrameToImageInfo = &s_rgFrameToImage[i];
if (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == frameType) {
return pFrameToImageInfo->imageResource;
} else if (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == -1) {
return pFrameToImageInfo->imageResource;
}
}
if (frame) {
connect(frame, &Fact::rawValueChanged, this, &APMAirframeComponentController::_factFrameChanged);
_factFrameChanged(frame->rawValue());
}
return QStringLiteral("AirframeUnknown");
}
APMAirframeComponentController::~APMAirframeComponentController()
APMAirframeComponentController::APMAirframeComponentController(void)
: _frameClassFact (getParameterFact(FactSystem::defaultComponentId, QStringLiteral("FRAME_CLASS")))
, _frameTypeFact (getParameterFact(FactSystem::defaultComponentId, QStringLiteral("FRAME_TYPE")))
, _frameClassModel (new QmlObjectListModel(this))
{
_fillFrameClasses();
}
void APMAirframeComponentController::_factFrameChanged(QVariant value)
APMAirframeComponentController::~APMAirframeComponentController()
{
FrameId v = (FrameId) value.toInt();
for(int i = 0, size = _airframeTypesModel->count(); i < size; i++ ) {
APMAirframeType *airframeType = qobject_cast<APMAirframeType*>(_airframeTypesModel->get(i));
Q_ASSERT(airframeType);
if (airframeType->type() == v) {
_currentAirframeType = airframeType;
break;
}
}
emit currentAirframeTypeChanged(_currentAirframeType);
}
void APMAirframeComponentController::_fillAirFrames()
void APMAirframeComponentController::_fillFrameClasses()
{
for (int tindex = 0; tindex < APMAirframeComponentAirframes::get().count(); tindex++) {
const APMAirframeComponentAirframes::AirframeType_t* pType = APMAirframeComponentAirframes::get().values().at(tindex);
QList<int> frameTypeNotSupported;
APMAirframeType* airframeType = new APMAirframeType(pType->name, pType->imageResource, pType->type, this);
Q_CHECK_PTR(airframeType);
frameTypeNotSupported << FRAME_CLASS_HELI
<< FRAME_CLASS_SINGLECOPTER
<< FRAME_CLASS_COAXCOPTER
<< FRAME_CLASS_BICOPTER
<< FRAME_CLASS_HELI_DUAL
<< FRAME_CLASS_HELIQUAD;
for (int index = 0; index < pType->rgAirframeInfo.count(); index++) {
const APMAirframe* pInfo = pType->rgAirframeInfo.at(index);
Q_CHECK_PTR(pInfo);
for (int i=1; i<_frameClassFact->enumStrings().count(); i++) {
QString frameClassName = _frameClassFact->enumStrings()[i];
int frameClass = _frameClassFact->enumValues()[i].toInt();
int defaultFrameType;
airframeType->addAirframe(pInfo->name(), pInfo->params(), pInfo->type());
if (frameTypeNotSupported.contains(frameClass)) {
defaultFrameType = -1;
} else {
defaultFrameType = FRAME_TYPE_X;
}
_airframeTypesModel->append(airframeType);
_frameClassModel->append(new APMFrameClass(frameClassName, frameClass, _frameTypeFact, defaultFrameType, _frameClassModel));
}
emit loadAirframesCompleted();
}
void APMAirframeComponentController::_loadParametersFromDownloadFile(const QString& downloadedParamFile)
......@@ -120,86 +157,6 @@ void APMAirframeComponentController::_loadParametersFromDownloadFile(const QStri
_vehicle->parameterManager()->refreshAllParameters();
}
APMAirframeType::APMAirframeType(const QString& name, const QString& imageResource, int type, QObject* parent) :
QObject(parent),
_name(name),
_imageResource(imageResource),
_type(type),
_dirty(false)
{
}
APMAirframeType::~APMAirframeType()
{
}
void APMAirframeType::addAirframe(const QString& name, const QString& file, int type)
{
APMAirframe* airframe = new APMAirframe(name, file, type);
Q_CHECK_PTR(airframe);
_airframes.append(QVariant::fromValue(airframe));
}
APMAirframe::APMAirframe(const QString& name, const QString& paramsFile, int type, QObject* parent) :
QObject(parent),
_name(name),
_paramsFile(paramsFile),
_type(type)
{
}
QString APMAirframe::name() const
{
return _name;
}
QString APMAirframe::params() const
{
return _paramsFile;
}
int APMAirframe::type() const
{
return _type;
}
APMAirframe::~APMAirframe()
{
}
QString APMAirframeType::imageResource() const
{
return _imageResource;
}
QString APMAirframeType::name() const
{
return _name;
}
int APMAirframeType::type() const
{
return _type;
}
APMAirframeType *APMAirframeComponentController::currentAirframeType() const
{
return _currentAirframeType;
}
QString APMAirframeComponentController::currentAirframeTypeName() const
{
return _vehicle->vehicleTypeName();
}
void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t)
{
Fact *param = getParameterFact(-1, QStringLiteral("FRAME"));
Q_ASSERT(param);
param->setRawValue(t->type());
}
void APMAirframeComponentController::loadParameters(const QString& paramFile)
{
qgcApp()->setOverrideCursor(Qt::WaitCursor);
......@@ -258,3 +215,25 @@ void APMAirframeComponentController::_paramFileDownloadError(QString errorMsg)
qgcApp()->showMessage(tr("Param file download failed: %1").arg(errorMsg));
qgcApp()->restoreOverrideCursor();
}
APMFrameClass::APMFrameClass(const QString& name, int frameClass, Fact* frameTypeFact, int defaultFrameType, QObject* parent)
: QObject (parent)
, _name (name)
, _frameClass (frameClass)
, _defaultFrameType (defaultFrameType)
, _frameTypeSupported (defaultFrameType != -1)
, _frameTypeFact (frameTypeFact)
{
connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::imageResourceChanged);
connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::frameTypeChanged);
}
APMFrameClass::~APMFrameClass()
{
}
QString APMFrameClass::imageResource(void)
{
return QStringLiteral("/qmlimages/Airframe/%1").arg(s_findImageResource(_frameClass, _frameTypeFact->rawValue().toInt()));
}
......@@ -7,12 +7,7 @@
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef APMAirframeComponentController_H
#define APMAirframeComponentController_H
#pragma once
#include <QObject>
#include <QQuickItem>
......@@ -22,7 +17,6 @@
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
#include "FactPanelController.h"
#include "APMAirframeComponentAirframes.h"
class APMAirframeModel;
class APMAirframeType;
......@@ -33,98 +27,56 @@ class APMAirframeComponentController : public FactPanelController
Q_OBJECT
public:
enum FrameId{FRAME_TYPE_PLUS = 0,
FRAME_TYPE_X = 1,
FRAME_TYPE_V = 2,
FRAME_TYPE_H = 3,
FRAME_TYPE_NEWY6 = 10};
Q_ENUM(FrameId)
APMAirframeComponentController(void);
~APMAirframeComponentController();
Q_PROPERTY(QmlObjectListModel* airframeTypesModel MEMBER _airframeTypesModel CONSTANT)
Q_PROPERTY(APMAirframeType* currentAirframeType READ currentAirframeType WRITE setCurrentAirframeType NOTIFY currentAirframeTypeChanged)
Q_PROPERTY(QmlObjectListModel* frameClassModel MEMBER _frameClassModel CONSTANT)
Q_INVOKABLE void loadParameters(const QString& paramFile);
int currentAirframeIndex(void);
void setCurrentAirframeIndex(int newIndex);
signals:
void loadAirframesCompleted();
void currentAirframeTypeChanged(APMAirframeType* airframeType);
public slots:
APMAirframeType *currentAirframeType() const;
Q_INVOKABLE QString currentAirframeTypeName() const;
void setCurrentAirframeType(APMAirframeType *t);
private slots:
void _fillAirFrames(void);
void _factFrameChanged(QVariant v);
void _githubJsonDownloadFinished(QString remoteFile, QString localFile);
void _githubJsonDownloadError(QString errorMsg);
void _paramFileDownloadFinished(QString remoteFile, QString localFile);
void _paramFileDownloadError(QString errorMsg);
private:
void _fillFrameClasses(void);
void _loadParametersFromDownloadFile(const QString& downloadedParamFile);
APMAirframeType *_currentAirframeType;
QmlObjectListModel *_airframeTypesModel;
static bool _typesRegistered;
static const char* _oldFrameParam;
static const char* _newFrameParam;
Fact* _frameClassFact;
Fact* _frameTypeFact;
QmlObjectListModel* _frameClassModel;
};
class APMAirframe : public QObject
class APMFrameClass : public QObject
{
Q_OBJECT
public:
APMAirframe(const QString& name, const QString& paramsFile, int type, QObject* parent = NULL);
~APMAirframe();
APMFrameClass(const QString& name, int frameClass, Fact* frameTypeFact, int defaultFrameType, QObject* parent = nullptr);
~APMFrameClass();
Q_PROPERTY(QString name MEMBER _name CONSTANT)
Q_PROPERTY(int type MEMBER _type CONSTANT)
Q_PROPERTY(QString params MEMBER _paramsFile CONSTANT)
QString name() const;
QString params() const;
int type() const;
Q_PROPERTY(QString name MEMBER _name CONSTANT)
Q_PROPERTY(int frameClass MEMBER _frameClass CONSTANT)
Q_PROPERTY(int frameType READ frameType NOTIFY frameTypeChanged)
Q_PROPERTY(int defaultFrameType MEMBER _defaultFrameType CONSTANT)
Q_PROPERTY(QString imageResource READ imageResource NOTIFY imageResourceChanged)
Q_PROPERTY(bool frameTypeSupported MEMBER _frameTypeSupported CONSTANT)
int frameType (void) { return _frameTypeFact->rawValue().toInt(); };
QString imageResource (void);
private:
QString _name;
QString _paramsFile;
int _type;
};
QString _imageResource;
int _frameClass;
int _defaultFrameType;
bool _frameTypeSupported;
class APMAirframeType : public QObject
{
Q_OBJECT
public:
APMAirframeType(const QString& name, const QString& imageResource, int type, QObject* parent = NULL);
~APMAirframeType();
Q_PROPERTY(QString name MEMBER _name CONSTANT)
Q_PROPERTY(QString imageResource MEMBER _imageResource CONSTANT)
Q_PROPERTY(QVariantList airframes MEMBER _airframes CONSTANT)
Q_PROPERTY(int type MEMBER _type CONSTANT)
Q_PROPERTY(bool dirty MEMBER _dirty CONSTANT)
void addAirframe(const QString& name, const QString& paramsFile, int type);
signals:
void imageResourceChanged(void);
void frameTypeChanged();
QString name() const;
QString imageResource() const;
int type() const;
private:
QString _name;
QString _imageResource;
QVariantList _airframes;
int _type;
bool _dirty;
Fact* _frameTypeFact;
};
#endif
<?xml version='1.0' encoding='UTF-8'?>
<airframes>
<version>1</version>
<airframe_group image="AirframeQuadRotorPlus.png" name="Plus Style: Quad, Hexa, Octo, Heli" id="0">
<airframe name="3DR Aero M" file="3DR_AERO_M.param"/>
<airframe name="3DR Aero RTF" file="3DR_Aero_RTF.param"/>
<airframe name="3DR Rover" file="3DR_Rover.param"/>
<airframe name="3DR Tarot" file="3DR_Tarot.bgsc"/>
<airframe name="Parrot Bebop" file="Parrot_Bebop.param"/>
<airframe name="Storm32" file="SToRM32-MAVLink.param"/>
</airframe_group>
<airframe_group image="AirframeQuadRotorX.png" name="X Style, Y6A Style: Quad, Hexa, Octo, X8, Tri, Y6A" id="1">
<airframe name="3DR X8-M RTF" file="3DR_X8-M_RTF.param"/>
<airframe name="3DR Y6A" file="3DR_Y6A_RTF.param"/>
<airframe name="3DR X8+ RTF" file="3DR_X8+_RTF.param"/>
<airframe name="3DR QUAD X4 RTF" file="3DR_QUAD_X4_RTF.param"/>
<airframe name="3DR X8" file="3DR_X8_RTF.param"/>
</airframe_group>
<airframe_group image="AirframeQuadRotorH.png" name="V (3DR Iris)" id="2">
<airframe name="Iris with GoPro" file="Iris with Front Mount Go Pro.param"/>
<airframe name="Iris with Tarot" file="Iris with Tarot Gimbal.param"/>
<airframe name="3DR Iris+" file="3DR_Iris+.param"/>
<airframe name="Iris" file="Iris.param"/>
</airframe_group>
<airframe_group image="AirframeQuadRotorH.png" name="V Tail" id="4">
</airframe_group>
<airframe_group image="AirframeQuadRotorH.png" name="A Tail" id="5">
</airframe_group>
<airframe_group name="H: X and H differ in prop rotation" id="3">
</airframe_group>
<airframe_group name="Y6B Frame (3DR TriCopter): Y6B and Y6A differ in prop rotation" id="10">
<airframe name="3DR Y6B" file="3DR_Y6B_RTF.param"/>
</airframe_group>
<airframes>
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMAirframeLoader.h"
#include "QGCApplication.h"
#include "QGCLoggingCategory.h"
#include "APMAirframeComponentAirframes.h"
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
QGC_LOGGING_CATEGORY(APMAirframeLoaderLog, "APMAirframeLoaderLog")
bool APMAirframeLoader::_airframeMetaDataLoaded = false;
APMAirframeLoader::APMAirframeLoader(AutoPilotPlugin* autopilot, UASInterface* uas, QObject* parent)
{
Q_UNUSED(autopilot);
Q_UNUSED(uas);
Q_UNUSED(parent);
Q_ASSERT(uas);
}
/// Load Airframe Fact meta data
void APMAirframeLoader::loadAirframeFactMetaData(void)
{
if (_airframeMetaDataLoaded) {
return;
}
qCDebug(APMAirframeLoaderLog) << "Loading APM airframe fact meta data";
Q_ASSERT(APMAirframeComponentAirframes::get().count() == 0);
QString airframeFilename(QStringLiteral(":/AutoPilotPlugins/APM/APMAirframeFactMetaData.xml"));
qCDebug(APMAirframeLoaderLog) << "Loading meta data file:" << airframeFilename;
QFile xmlFile(airframeFilename);
Q_ASSERT(xmlFile.exists());
bool success = xmlFile.open(QIODevice::ReadOnly);
Q_UNUSED(success);
Q_ASSERT(success);
QXmlStreamReader xml(xmlFile.readAll());
xmlFile.close();
if (xml.hasError()) {
qCWarning(APMAirframeLoaderLog) << "Badly formed XML" << xml.errorString();
return;
}
QString airframeGroup;
QString image;
int groupId = 0;
while (!xml.atEnd()) {
if (xml.isStartElement()) {
QString elementName = xml.name().toString();
QXmlStreamAttributes attr = xml.attributes();
if (elementName == QLatin1Literal("airframe_group")) {
airframeGroup = attr.value(QStringLiteral("name")).toString();
image = attr.value(QStringLiteral("image")).toString();
groupId = attr.value(QStringLiteral("id")).toInt();
APMAirframeComponentAirframes::insert(airframeGroup, groupId, image);
} else if (elementName == QLatin1Literal("airframe")) {
QString name = attr.value(QStringLiteral("name")).toString();
QString file = attr.value(QStringLiteral("file")).toString();
APMAirframeComponentAirframes::insert(airframeGroup, groupId, image, name, file);
}
}
xml.readNext();
}
_airframeMetaDataLoaded = true;
}
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#ifndef APMAirframeLoader_H
#define APMAirframeLoader_H
#include <QObject>
#include <QMap>
#include <QXmlStreamReader>
#include <QLoggingCategory>
#include "ParameterManager.h"
#include "FactSystem.h"
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
/// @file APMAirframeLoader.h
/// @author Lorenz Meier <lm@qgroundcontrol.org>
Q_DECLARE_LOGGING_CATEGORY(APMAirframeLoaderLog)
/// Collection of Parameter Facts for PX4 AutoPilot
class APMAirframeLoader : QObject
{
Q_OBJECT
public:
/// @param uas Uas which this set of facts is associated with
APMAirframeLoader(AutoPilotPlugin* autpilot,UASInterface* uas, QObject* parent = NULL);
static void loadAirframeFactMetaData(void);
private:
static bool _airframeMetaDataLoaded; ///< true: parameter meta data already loaded
static QMap<QString, FactMetaData*> _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData
};
#endif // APMAirframeLoader_H
......@@ -15,8 +15,6 @@
#include "FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h"
#include "VehicleComponent.h"
#include "APMAirframeComponent.h"
#include "APMAirframeComponentAirframes.h"
#include "APMAirframeLoader.h"
#include "APMFlightModesComponent.h"
#include "APMRadioComponent.h"
#include "APMSafetyComponent.h"
......@@ -30,6 +28,7 @@
#include "ESP8266Component.h"
#include "APMHeliComponent.h"
#include "QGCApplication.h"
#include "ParameterManager.h"
#if !defined(NO_SERIAL_LINK) && !defined(__android__)
#include <QSerialPortInfo>
......@@ -50,12 +49,9 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent)
, _safetyComponent (NULL)
, _sensorsComponent (NULL)
, _tuningComponent (NULL)
, _airframeFacts (new APMAirframeLoader(this, vehicle->uas(), this))
, _esp8266Component (NULL)
, _heliComponent (NULL)
{
APMAirframeLoader::loadAirframeFactMetaData();
#if !defined(NO_SERIAL_LINK) && !defined(__android__)
connect(vehicle->parameterManager(), &ParameterManager::parametersReadyChanged, this, &APMAutoPilotPlugin::_checkForBadCubeBlack);
#endif
......
......@@ -15,7 +15,6 @@
#include "Vehicle.h"
class APMAirframeComponent;
class APMAirframeLoader;
class APMFlightModesComponent;
class APMRadioComponent;
class APMTuningComponent;
......@@ -55,7 +54,6 @@ protected:
APMSafetyComponent* _safetyComponent;
APMSensorsComponent* _sensorsComponent;
APMTuningComponent* _tuningComponent;
APMAirframeLoader* _airframeFacts;
ESP8266Component* _esp8266Component;
APMHeliComponent* _heliComponent;
......
......@@ -37,9 +37,6 @@
<file alias="APM/MavCmdInfoSub.json">MavCmdInfoSub.json</file>
<file alias="APM/MavCmdInfoVTOL.json">MavCmdInfoVTOL.json</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/APM">
<file alias="APMAirframeFactMetaData.xml">../../AutoPilotPlugins/APM/APMAirframeFactMetaData.xml</file>
</qresource>
<qresource prefix="/FirmwarePlugin/APM">
<file alias="APMParameterFactMetaData.Plane.3.3.xml">APMParameterFactMetaData.Plane.3.3.xml</file>
<file alias="APMParameterFactMetaData.Plane.3.5.xml">APMParameterFactMetaData.Plane.3.5.xml</file>
......
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