Unverified Commit f726b74a authored by Don Gagne's avatar Don Gagne Committed by GitHub

Merge pull request #7849 from DonLakeFlyer/APMAirframe

ArduPilot: Airframe Setup
parents 0cf4b6ee 6b6aa978
...@@ -106,8 +106,15 @@ SetupPage { ...@@ -106,8 +106,15 @@ SetupPage {
readonly property real innerMargin: ScreenTools.defaultFontPixelWidth readonly property real innerMargin: ScreenTools.defaultFontPixelWidth
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: airframeCheckBox.checked = true onClicked: {
if (!airframeCheckBox.checked || !combo.valid) {
if (_frameTypeAvailable && object.defaultFrameType != -1) {
_frameType.rawValue = object.defaultFrameType
}
airframeCheckBox.checked = true
}
}
} }
QGCLabel { QGCLabel {
...@@ -116,12 +123,14 @@ SetupPage { ...@@ -116,12 +123,14 @@ SetupPage {
} }
Rectangle { Rectangle {
id: imageComboRect
anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2 anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2
anchors.top: title.bottom anchors.top: title.bottom
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
color: airframeCheckBox.checked ? qgcPal.buttonHighlight : qgcPal.windowShade color: airframeCheckBox.checked ? qgcPal.buttonHighlight : qgcPal.windowShade
opacity: combo.valid ? 1.0 : 0.5
ColumnLayout { ColumnLayout {
anchors.margins: innerMargin anchors.margins: innerMargin
...@@ -136,7 +145,7 @@ SetupPage { ...@@ -136,7 +145,7 @@ SetupPage {
smooth: true smooth: true
antialiasing: true antialiasing: true
sourceSize.width: width sourceSize.width: width
source: object.imageResource source: airframeCheckBox.checked ? object.imageResource : object.imageResourceDefault
} }
QGCCheckBox { QGCCheckBox {
...@@ -160,15 +169,47 @@ SetupPage { ...@@ -160,15 +169,47 @@ SetupPage {
visible: airframeCheckBox.checked && object.frameTypeSupported visible: airframeCheckBox.checked && object.frameTypeSupported
} }
FactComboBox { QGCComboBox {
id: combo id: combo
Layout.fillWidth: true Layout.fillWidth: true
fact: _frameType model: object.frameTypeEnumStrings
indexModel: false
visible: airframeCheckBox.checked && object.frameTypeSupported visible: airframeCheckBox.checked && object.frameTypeSupported
onActivated: _frameType.rawValue = object.frameTypeEnumValues[index]
property bool valid: true
function checkFrameType(value) {
return value == _frameType.rawValue
}
function selectFrameType() {
var index = object.frameTypeEnumValues.findIndex(checkFrameType)
if (index == -1 && combo.visible) {
// Frame Class/Type is set to an invalid combination
combo.valid = false
} else {
combo.currentIndex = index
combo.valid = true
}
}
Component.onCompleted: selectFrameType()
Connections {
target: _frameTypeAvailable ? _frameType : null
ignoreUnknownSignals: true
onRawValueChanged: combo.selectFrameType()
}
} }
} }
} }
QGCLabel {
anchors.fill: imageComboRect
text: qsTr("Invalid setting for FRAME_TYPE. Click to Reset.")
wrapMode: Text.WordWrap
visible: !combo.valid
}
} }
} // Repeater - summary boxes } // Repeater - summary boxes
} // Flow - summary boxes } // Flow - summary boxes
......
...@@ -70,23 +70,35 @@ typedef struct { ...@@ -70,23 +70,35 @@ typedef struct {
} FrameToImageInfo_t; } FrameToImageInfo_t;
static const FrameToImageInfo_t s_rgFrameToImageCopter[] = { static const FrameToImageInfo_t s_rgFrameToImageCopter[] = {
{ FRAME_CLASS_QUAD, FRAME_TYPE_PLUS, "QuadRotorPlus" }, { FRAME_CLASS_QUAD, FRAME_TYPE_X, "QuadRotorX" }, // Default
{ FRAME_CLASS_QUAD, FRAME_TYPE_X, "QuadRotorX" }, { FRAME_CLASS_QUAD, FRAME_TYPE_PLUS, "QuadRotorPlus" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_V, "QuadRotorWide" }, { FRAME_CLASS_QUAD, FRAME_TYPE_V, "QuadRotorWide" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_H, "QuadRotorH" }, { FRAME_CLASS_QUAD, FRAME_TYPE_H, "QuadRotorH" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_V_TAIL, "QuadRotorVTail" }, { FRAME_CLASS_QUAD, FRAME_TYPE_V_TAIL, "QuadRotorVTail" },
{ FRAME_CLASS_QUAD, FRAME_TYPE_A_TAIL, "QuadRotorATail" }, { FRAME_CLASS_QUAD, FRAME_TYPE_A_TAIL, "QuadRotorATail" },
{ FRAME_CLASS_HEX, FRAME_TYPE_PLUS, "HexaRotorPlus" },
{ FRAME_CLASS_HEX, FRAME_TYPE_X, "HexaRotorX" }, { FRAME_CLASS_HEX, FRAME_TYPE_X, "HexaRotorX" }, // Default
{ FRAME_CLASS_OCTA, FRAME_TYPE_PLUS, "OctoRotorPlus" }, { FRAME_CLASS_HEX, FRAME_TYPE_PLUS, "HexaRotorPlus" },
{ FRAME_CLASS_OCTA, FRAME_TYPE_X, "OctoRotorX" },
{ FRAME_CLASS_OCTAQUAD, FRAME_TYPE_PLUS, "OctoRotorPlusCoaxial" }, { FRAME_CLASS_OCTA, FRAME_TYPE_X, "OctoRotorX" }, // Default
{ FRAME_CLASS_OCTAQUAD, FRAME_TYPE_X, "OctoRotorXCoaxial" }, { FRAME_CLASS_OCTA, FRAME_TYPE_PLUS, "OctoRotorPlus" },
{ FRAME_CLASS_Y6, FRAME_TYPE_Y6B, "Y6B" }, { FRAME_CLASS_OCTA, FRAME_TYPE_V, "AirframeUnknown" },
{ FRAME_CLASS_Y6, FRAME_TYPE_Y6F, "AirframeUnknown" }, { FRAME_CLASS_OCTA, FRAME_TYPE_H, "AirframeUnknown" },
{ FRAME_CLASS_Y6, -1, "Y6A" },
{ FRAME_CLASS_HELI, -1, "Helicopter" }, { FRAME_CLASS_OCTAQUAD, FRAME_TYPE_X, "OctoRotorXCoaxial" }, // Default
{ FRAME_CLASS_TRI, -1, "YPlus" }, { FRAME_CLASS_OCTAQUAD, FRAME_TYPE_PLUS, "OctoRotorPlusCoaxial" },
{ FRAME_CLASS_OCTAQUAD, FRAME_TYPE_V, "AirframeUnknown" },
{ FRAME_CLASS_OCTAQUAD, FRAME_TYPE_H, "AirframeUnknown" },
{ FRAME_CLASS_Y6, FRAME_TYPE_Y6B, "Y6B" }, // Default
{ FRAME_CLASS_Y6, FRAME_TYPE_Y6F, "AirframeUnknown" },
{ FRAME_CLASS_Y6, -1, "Y6A" },
{ FRAME_CLASS_DODECAHEXA, FRAME_TYPE_X, "AirframeUnknown" }, // Default
{ FRAME_CLASS_DODECAHEXA, FRAME_TYPE_PLUS, "AirframeUnknown" },
{ FRAME_CLASS_HELI, -1, "Helicopter" },
{ FRAME_CLASS_TRI, -1, "YPlus" },
}; };
static const FrameToImageInfo_t s_rgFrameToImageRover[] = { static const FrameToImageInfo_t s_rgFrameToImageRover[] = {
...@@ -94,14 +106,16 @@ static const FrameToImageInfo_t s_rgFrameToImageRover[] = { ...@@ -94,14 +106,16 @@ static const FrameToImageInfo_t s_rgFrameToImageRover[] = {
{ FRAME_CLASS_BOAT, -1, "Boat" }, { FRAME_CLASS_BOAT, -1, "Boat" },
}; };
static QString s_findImageResourceCopter(int frameClass, int frameType) /// Returns the image resource for the frameClass, frameType pair
/// @param[in,out] frameType Specified frame type, or -1 to match first item in list (frameType found will be returned)
static QString s_findImageResourceCopter(int frameClass, int& frameType)
{ {
for (size_t i=0; i<sizeof(s_rgFrameToImageCopter)/sizeof(s_rgFrameToImageCopter[0]); i++) { for (size_t i=0; i<sizeof(s_rgFrameToImageCopter)/sizeof(s_rgFrameToImageCopter[0]); i++) {
const FrameToImageInfo_t* pFrameToImageInfo = &s_rgFrameToImageCopter[i]; const FrameToImageInfo_t* pFrameToImageInfo = &s_rgFrameToImageCopter[i];
if (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == frameType) { if ((pFrameToImageInfo->frameClass == frameClass && frameType == -1) ||
return pFrameToImageInfo->imageResource; (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == frameType)) {
} else if (pFrameToImageInfo->frameClass == frameClass && pFrameToImageInfo->frameType == -1) { frameType = pFrameToImageInfo->frameType;
return pFrameToImageInfo->imageResource; return pFrameToImageInfo->imageResource;
} }
} }
...@@ -154,32 +168,19 @@ void APMAirframeComponentController::_fillFrameClasses() ...@@ -154,32 +168,19 @@ void APMAirframeComponentController::_fillFrameClasses()
for (int i=1; i<_frameClassFact->enumStrings().count(); i++) { for (int i=1; i<_frameClassFact->enumStrings().count(); i++) {
QString frameClassName = _frameClassFact->enumStrings()[i]; QString frameClassName = _frameClassFact->enumStrings()[i];
int frameClass = _frameClassFact->enumValues()[i].toInt(); int frameClass = _frameClassFact->enumValues()[i].toInt();
int defaultFrameType;
if (frameClass == FRAME_CLASS_HELI) { if (frameClass == FRAME_CLASS_HELI) {
// Heli requires it's own firmware variant. You can't switch to Heli from a Copter variant firmware. // Heli requires it's own firmware variant. You can't switch to Heli from a Copter variant firmware.
continue; continue;
} }
if (frameTypeNotSupported.contains(frameClass)) { _frameClassModel->append(new APMFrameClass(frameClassName, true /* copter */, frameClass, _frameTypeFact, _frameClassModel));
defaultFrameType = -1;
} else {
defaultFrameType = FRAME_TYPE_X;
}
_frameClassModel->append(new APMFrameClass(frameClassName, true /* copter */, frameClass, _frameTypeFact, defaultFrameType, _frameClassModel));
} }
} else if (qobject_cast<ArduRoverFirmwarePlugin*>(fwPlugin)) { } else if (qobject_cast<ArduRoverFirmwarePlugin*>(fwPlugin)) {
for (int i=1; i<_frameClassFact->enumStrings().count(); i++) { for (int i=1; i<_frameClassFact->enumStrings().count(); i++) {
QString frameClassName = _frameClassFact->enumStrings()[i]; QString frameClassName = _frameClassFact->enumStrings()[i];
int frameClass = _frameClassFact->enumValues()[i].toInt(); int frameClass = _frameClassFact->enumValues()[i].toInt();
int defaultFrameType; _frameClassModel->append(new APMFrameClass(frameClassName, false /* copter */, frameClass, _frameTypeFact, _frameClassModel));
if (_frameTypeFact) {
defaultFrameType = FRAME_TYPE_UNDEFINED;
} else {
defaultFrameType = -1;
}
_frameClassModel->append(new APMFrameClass(frameClassName, false /* copter */, frameClass, _frameTypeFact, defaultFrameType, _frameClassModel));
} }
} }
} }
...@@ -270,19 +271,55 @@ void APMAirframeComponentController::_paramFileDownloadError(QString errorMsg) ...@@ -270,19 +271,55 @@ void APMAirframeComponentController::_paramFileDownloadError(QString errorMsg)
qgcApp()->restoreOverrideCursor(); qgcApp()->restoreOverrideCursor();
} }
APMFrameClass::APMFrameClass(const QString& name, bool copter, int frameClass, Fact* frameTypeFact, int defaultFrameType, QObject* parent) APMFrameClass::APMFrameClass(const QString& name, bool copter, int frameClass, Fact* frameTypeFact, QObject* parent)
: QObject (parent) : QObject (parent)
, _name (name) , _name (name)
, _copter (copter) , _copter (copter)
, _frameClass (frameClass) , _frameClass (frameClass)
, _defaultFrameType (defaultFrameType) , _defaultFrameType (-1)
, _frameTypeSupported (defaultFrameType != -1) , _frameTypeSupported (false)
, _frameTypeFact (frameTypeFact) , _frameTypeFact (frameTypeFact)
{ {
if (frameTypeFact) { if (frameTypeFact) {
connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::imageResourceChanged); connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::imageResourceChanged);
connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::frameTypeChanged); connect(frameTypeFact, &Fact::rawValueChanged, this, &APMFrameClass::frameTypeChanged);
} }
if (copter) {
QList<int> rgSupportedFrameTypes;
for (size_t i=0; i<sizeof(s_rgFrameToImageCopter)/sizeof(s_rgFrameToImageCopter[0]); i++) {
const FrameToImageInfo_t* pFrameToImageInfo = &s_rgFrameToImageCopter[i];
if (pFrameToImageInfo->frameClass == frameClass) {
if (_defaultFrameType == -1) {
// Default frame type/icon is the first item found to match frameClass
_defaultFrameType = pFrameToImageInfo->frameType;
_imageResourceDefault = QStringLiteral("/qmlimages/Airframe/%1").arg(pFrameToImageInfo->imageResource);
}
if (pFrameToImageInfo->frameType != -1) {
// The list includes the supported frame types for the class
rgSupportedFrameTypes.append(pFrameToImageInfo->frameType);
}
}
}
if (_imageResourceDefault.isEmpty()) {
_imageResourceDefault = QStringLiteral("/qmlimages/Airframe/AirframeUnknown");
}
// Filter the enums
for (const int frameType: rgSupportedFrameTypes) {
int index = frameTypeFact->enumValues().indexOf(frameType);
if (index != -1) {
_frameTypeEnumValues.append(frameType);
_frameTypeEnumStrings.append(frameTypeFact->enumStrings()[index]);
}
}
}
// If the frameClass is not in the list then frame type is not supported
_frameTypeSupported = _defaultFrameType != -1;
} }
APMFrameClass::~APMFrameClass() APMFrameClass::~APMFrameClass()
......
...@@ -54,25 +54,31 @@ class APMFrameClass : public QObject ...@@ -54,25 +54,31 @@ class APMFrameClass : public QObject
Q_OBJECT Q_OBJECT
public: public:
APMFrameClass(const QString& name, bool copter, int frameClass, Fact* frameTypeFact, int defaultFrameType, QObject* parent = nullptr); APMFrameClass(const QString& name, bool copter, int frameClass, Fact* frameTypeFact, QObject* parent = nullptr);
~APMFrameClass(); ~APMFrameClass();
Q_PROPERTY(QString name MEMBER _name CONSTANT) Q_PROPERTY(QString name MEMBER _name CONSTANT)
Q_PROPERTY(int frameClass MEMBER _frameClass CONSTANT) Q_PROPERTY(int frameClass MEMBER _frameClass CONSTANT)
Q_PROPERTY(int frameType READ frameType NOTIFY frameTypeChanged) Q_PROPERTY(int frameType READ frameType NOTIFY frameTypeChanged)
Q_PROPERTY(int defaultFrameType MEMBER _defaultFrameType CONSTANT) Q_PROPERTY(QStringList frameTypeEnumStrings MEMBER _frameTypeEnumStrings CONSTANT)
Q_PROPERTY(QString imageResource READ imageResource NOTIFY imageResourceChanged) Q_PROPERTY(QVariantList frameTypeEnumValues MEMBER _frameTypeEnumValues CONSTANT)
Q_PROPERTY(bool frameTypeSupported MEMBER _frameTypeSupported CONSTANT) Q_PROPERTY(int defaultFrameType MEMBER _defaultFrameType CONSTANT)
Q_PROPERTY(QString imageResource READ imageResource NOTIFY imageResourceChanged)
Q_PROPERTY(QString imageResourceDefault MEMBER _imageResourceDefault CONSTANT)
Q_PROPERTY(bool frameTypeSupported MEMBER _frameTypeSupported CONSTANT)
int frameType (void) { return _frameTypeFact->rawValue().toInt(); }; int frameType (void) { return _frameTypeFact->rawValue().toInt(); }
QString imageResource (void); QString imageResource (void);
QString _name; QString _name;
bool _copter; bool _copter;
QString _imageResource; QString _imageResource;
int _frameClass; QString _imageResourceDefault;
int _defaultFrameType; int _frameClass;
bool _frameTypeSupported; QStringList _frameTypeEnumStrings;
QVariantList _frameTypeEnumValues;
int _defaultFrameType;
bool _frameTypeSupported;
signals: signals:
void imageResourceChanged(void); void imageResourceChanged(void);
......
This diff is collapsed.
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