diff --git a/qgcresources.qrc b/qgcresources.qrc index cc3b28fba4f74d078fdc496b3989fc31b6bc950f..52a88814a471f89efd37d2fcea09f71e680eb33d 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -208,6 +208,9 @@ src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml + + src/AutoPilotPlugins/APM/AirframeFactMetaData.xml + src/FirmwarePlugin/APM/apm.pdef.xml diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 4156b72224ad910db1072a6f1274c349e7fafab5..fed4ba2436e1b8dc83a761d8f48f56e78d7607c6 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -282,7 +282,9 @@ HEADERS += \ src/uas/UASMessageHandler.h \ src/ui/toolbar/MainToolBarController.h \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.h \ + src/AutoPilotPlugins/APM/APMAirframeLoader.h \ src/QmlControls/QGCImageProvider.h \ + src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h DebugBuild { HEADERS += \ @@ -398,7 +400,9 @@ SOURCES += \ src/uas/UASMessageHandler.cc \ src/ui/toolbar/MainToolBarController.cc \ src/AutoPilotPlugins/PX4/PX4AirframeLoader.cc \ + src/AutoPilotPlugins/APM/APMAirframeLoader.cc \ src/QmlControls/QGCImageProvider.cc \ + src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc DebugBuild { SOURCES += \ @@ -550,6 +554,8 @@ HEADERS+= \ src/AutoPilotPlugins/AutoPilotPluginManager.h \ src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h \ src/AutoPilotPlugins/APM/APMAirframeComponent.h \ + src/AutoPilotPlugins/APM/APMAirframeComponentController.h \ + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h \ src/AutoPilotPlugins/APM/APMComponent.h \ src/AutoPilotPlugins/APM/APMRadioComponent.h \ src/AutoPilotPlugins/APM/APMFlightModesComponent.h \ @@ -601,6 +607,7 @@ SOURCES += \ src/AutoPilotPlugins/AutoPilotPluginManager.cc \ src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc \ src/AutoPilotPlugins/APM/APMAirframeComponent.cc \ + src/AutoPilotPlugins/APM/APMAirframeComponentController.cc \ src/AutoPilotPlugins/APM/APMComponent.cc \ src/AutoPilotPlugins/APM/APMRadioComponent.cc \ src/AutoPilotPlugins/APM/APMFlightModesComponent.cc \ @@ -610,6 +617,7 @@ SOURCES += \ src/AutoPilotPlugins/APM/APMSensorsComponentController.cc \ src/AutoPilotPlugins/APM/APMTuningComponent.cc \ src/AutoPilotPlugins/Common/RadioComponentController.cc \ + src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc \ src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.cc \ src/AutoPilotPlugins/PX4/AirframeComponent.cc \ src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc \ diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc index 1c90064d80b68d4ed5de33eba714fe236adb82b8..19899f11f903a068faccf89db10feea733f76082 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.cc +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.cc @@ -57,22 +57,13 @@ bool APMAirframeComponent::requiresSetup(void) const bool APMAirframeComponent::setupComplete(void) const { - // You'll need to figure out which parameters trigger setup complete -#if 0 - return _autopilot->getParameterFact(FactSystem::defaultComponentId, "SYS_AUTOSTART")->rawValue().toInt() != 0; -#else - return true; -#endif + //: Not the correct one, but it works for the moment. + return _autopilot->getParameterFact(FactSystem::defaultComponentId, "FRAME")->rawValue().toInt() != -1; } QStringList APMAirframeComponent::setupCompleteChangedTriggerList(void) const { - // You'll need to figure out which parameters trigger setup complete -#if 0 - return QStringList("SYS_AUTOSTART"); -#else return QStringList(); -#endif } QUrl APMAirframeComponent::setupSource(void) const diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml index e03e3e95084c396b4a52459cacec680d7616463c..1a6551e51caca5f8a8358407a8fda8b5827c5094 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponent.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponent.qml @@ -21,7 +21,7 @@ ======================================================================*/ -import QtQuick 2.2 +import QtQuick 2.5 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2 import QtQuick.Dialogs 1.2 @@ -39,13 +39,214 @@ QGCView { QGCPalette { id: qgcPal; colorGroupEnabled: panel.enabled } + property real _minW: ScreenTools.defaultFontPixelWidth * 30 + property real _boxWidth: _minW + property real _boxSpace: ScreenTools.defaultFontPixelWidth + property Fact sysIdFact: controller.getParameterFact(-1, "FRAME") + + function computeDimensions() { + var sw = 0 + var rw = 0 + var idx = Math.floor(scroll.width / (_minW + ScreenTools.defaultFontPixelWidth)) + if(idx < 1) { + _boxWidth = scroll.width + _boxSpace = 0 + } else { + _boxSpace = 0 + if(idx > 1) { + _boxSpace = ScreenTools.defaultFontPixelWidth + sw = _boxSpace * (idx - 1) + } + rw = scroll.width - sw + _boxWidth = rw / idx + } + } + + APMAirframeComponentController { + id: controller + factPanel: panel + } + + Component { + id: applyRestartDialogComponent + + QGCViewDialog { + id: applyRestartDialog + + Connections { + target: controller + onCurrentAirframeTypeChanged: { + airframePicker.model = controller.currentAirframeType.airframes; + } + onCurrentAirframeChanged : { + hideDialog(); + } + } + + QGCLabel { + id: applyParamsText + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: _boxSpace + wrapMode: Text.WordWrap + text: "Select you drone to load the default parameters for it. " + } + + Flow { + anchors.top : applyParamsText.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + spacing : _boxSpace + layoutDirection: Qt.Vertical; + anchors.margins : _boxSpace + Repeater { + id : airframePicker + model : controller.currentAirframeType.airframes; + + delegate: QGCButton { + id: btnParams + width: parent.width / 2.1 + height: (ScreenTools.defaultFontPixelHeight * 14) / 5 + text: controller.currentAirframeType.airframes[index].name; + + onClicked : { + controller.currentAirframe = controller.currentAirframeType.airframes[index] + } + } + } + } + } + } + QGCViewPanel { id: panel anchors.fill: parent - QGCLabel { - text: "Work in progress"; + readonly property real spacerHeight: ScreenTools.defaultFontPixelHeight + + onWidthChanged: { + computeDimensions() + } + + Item { + id: helpApplyRow + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: Math.max(helpText.contentHeight, applyButton.height) + + QGCLabel { + id: helpText + width: parent.width - applyButton.width - 5 + text: qsTr("Please select your airframe type") + font.pixelSize: ScreenTools.mediumFontPixelSize + wrapMode: Text.WordWrap + } + + QGCButton { + id: applyButton + anchors.right: parent.right + text: qsTr("Load common parameters") + + onClicked: showDialog(applyRestartDialogComponent, qsTr("Load common parameters"), 50, StandardButton.Close) + } + } + + Item { + id: lastSpacer + anchors.top: helpApplyRow.bottom + height: parent.spacerHeight + width: 10 } + Flickable { + id: scroll + anchors.top: lastSpacer.bottom + width: parent.width; + height: parent.height; + clip: true + boundsBehavior: Flickable.StopAtBounds + flickableDirection: Flickable.VerticalFlick + + onWidthChanged: { + computeDimensions() + } + + Flow { + id: flowView + width: scroll.width + spacing: _boxSpace + + ExclusiveGroup { + id: airframeTypeExclusive + } + + Repeater { + model: controller.airframeTypesModel + + // Outer summary item rectangle + delegate : Rectangle { + id: airframeBackground + width: _boxWidth + height: ScreenTools.defaultFontPixelHeight * 14 + color: qgcPal.windowShade; + + readonly property real titleHeight: ScreenTools.defaultFontPixelHeight * 1.75 + readonly property real innerMargin: ScreenTools.defaultFontPixelWidth + + MouseArea { + anchors.fill: parent + onClicked: airframeCheckBox.checked = true; + } + + Rectangle { + id: nameRect; + width: parent.width + height: parent.titleHeight + color: qgcPal.windowShadeDark + + QGCLabel { + anchors.fill: parent + color: qgcPal.buttonText + verticalAlignment: TextEdit.AlignVCenter + horizontalAlignment: TextEdit.AlignHCenter + text: object.name + } + } + + Image { + id: imageRect + anchors.topMargin: innerMargin + anchors.top: nameRect.bottom + width: parent.width * 0.75 + height: parent.height - nameRect.height - (innerMargin * 3) + fillMode: Image.PreserveAspectFit + smooth: true + mipmap: true + source: object.imageResource + anchors.horizontalCenter: parent.horizontalCenter + } + + QGCCheckBox { + id: airframeCheckBox + checked: object.type == sysIdFact.value + exclusiveGroup: airframeTypeExclusive + anchors.bottom: imageRect.bottom + anchors.right: parent.right + anchors.rightMargin: innerMargin + + onCheckedChanged: { + if (checked) { + controller.currentAirframeType = object + } + airframeBackground.color = checked ? qgcPal.buttonHighlight : qgcPal.windowShade; + } + } + } + } + } + } // Scroll View - summary boxes } // QGCViewPanel } // QGCView diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc new file mode 100644 index 0000000000000000000000000000000000000000..ca356f2fc60427557a726918a2ba3063597433ea --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc @@ -0,0 +1,60 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009, 2015 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Don Gagne + +#include "APMAirframeComponentAirframes.h" +#include "APMAirframeComponentController.h" + +QMap APMAirframeComponentAirframes::rgAirframeTypes; + +QMap& 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 = QString("qrc:/qmlimages/") + (!image.isEmpty() ? image : QString("AirframeStandardPlane.png")); + 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 valueList = get().values(); + foreach(AirframeType_t *pType, valueList) { + qDeleteAll(pType->rgAirframeInfo); + delete pType; + } + rgAirframeTypes.clear(); +} diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h new file mode 100644 index 0000000000000000000000000000000000000000..7d33de2e20211500b2aa6d1b591c47fb6cfdb07d --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h @@ -0,0 +1,62 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009, 2015 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Don Gagne + +#ifndef APMAirframeComponentAirframes_H +#define APMAirframeComponentAirframes_H + +#include +#include +#include +#include + +#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 rgAirframeInfo; + } AirframeType_t; + typedef QMap 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 diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc new file mode 100644 index 0000000000000000000000000000000000000000..26ff996dc7c841383e086884b41ec8fb87bb04cf --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.cc @@ -0,0 +1,208 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009, 2015 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Don Gagne + +#include "APMAirframeComponentController.h" +#include "APMAirframeComponentAirframes.h" +#include "APMRemoteParamsDownloader.h" +#include "QGCMAVLink.h" +#include "MultiVehicleManager.h" +#include "AutoPilotPluginManager.h" +#include "QGCApplication.h" + +#include +#include + +bool APMAirframeComponentController::_typesRegistered = false; + +APMAirframeComponentController::APMAirframeComponentController(void) : + _airframeTypesModel(new QmlObjectListModel(this)) +{ + if (!_typesRegistered) { + _typesRegistered = true; + qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAiframeType", "Can only reference APMAirframeType"); + qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "APMAiframe", "Can only reference APMAirframe"); + } + _fillAirFrames(); + + Fact *frame = getParameterFact(FactSystem::defaultComponentId, "FRAME"); + connect(frame, &Fact::vehicleUpdated, this, &APMAirframeComponentController::_factFrameChanged); + _factFrameChanged(frame->rawValue()); +} + +APMAirframeComponentController::~APMAirframeComponentController() +{ + +} + +void APMAirframeComponentController::_factFrameChanged(QVariant value) +{ + FrameId v = (FrameId) value.toInt(); + + for(int i = 0, size = _airframeTypesModel->count(); i < size; i++ ) { + APMAirframeType *airframeType = qobject_cast(_airframeTypesModel->get(i)); + Q_ASSERT(airframeType); + if (airframeType->type() == v) { + _currentAirframeType = airframeType; + break; + } + } + emit currentAirframeTypeChanged(_currentAirframeType); +} + +void APMAirframeComponentController::_fillAirFrames() +{ + for (int tindex = 0; tindex < APMAirframeComponentAirframes::get().count(); tindex++) { + const APMAirframeComponentAirframes::AirframeType_t* pType = APMAirframeComponentAirframes::get().values().at(tindex); + + APMAirframeType* airframeType = new APMAirframeType(pType->name, pType->imageResource, pType->type, this); + Q_CHECK_PTR(airframeType); + + for (int index = 0; index < pType->rgAirframeInfo.count(); index++) { + const APMAirframe* pInfo = pType->rgAirframeInfo.at(index); + Q_CHECK_PTR(pInfo); + + airframeType->addAirframe(pInfo->name(), pInfo->params(), pInfo->type()); + } + _airframeTypesModel->append(airframeType); + } + + emit loadAirframesCompleted(); +} + +void APMAirframeComponentController::_finishVehicleSetup() { + QDir dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0) + + QDir::separator() + qApp->applicationName(); + + QFile parametersFile(dataLocation.absoluteFilePath(_currentAirframe->params())); + parametersFile.open(QIODevice::ReadOnly); + + QTextStream reader(¶metersFile); + + while (!reader.atEnd()) { + QString line = reader.readLine().trimmed(); + if (line.isEmpty() || line.at(0) == QChar('#')) { + continue; + } + + QStringList aux = line.split(','); + if (parameterExists(-1, aux.at(0))) { + Fact *param = getParameterFact(-1, aux.at(0)); + param->setRawValue(QVariant::fromValue(aux.at(1))); + } + } + qgcApp()->setOverrideCursor(Qt::ArrowCursor); + sender()->deleteLater(); + emit currentAirframeChanged(_currentAirframe); +} + +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; +} + +APMAirframe *APMAirframeComponentController::currentAirframe() const +{ + return _currentAirframe; +} + +void APMAirframeComponentController::setCurrentAirframe(APMAirframe *t) +{ + _currentAirframe = t; + qgcApp()->setOverrideCursor(Qt::WaitCursor); + APMRemoteParamsDownloader *paramDownloader = new APMRemoteParamsDownloader(_currentAirframe->params()); + connect(paramDownloader, &APMRemoteParamsDownloader::finished, this, &APMAirframeComponentController::_finishVehicleSetup); +} + +void APMAirframeComponentController::setCurrentAirframeType(APMAirframeType *t) +{ + Fact *param = getParameterFact(-1, "FRAME"); + Q_ASSERT(param); + param->setRawValue(t->type()); +} + diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentController.h b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h new file mode 100644 index 0000000000000000000000000000000000000000..ef799ab5246960d144e73658ebb296ca5ddc5e6b --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentController.h @@ -0,0 +1,138 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009, 2015 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Don Gagne + +#ifndef APMAirframeComponentController_H +#define APMAirframeComponentController_H + +#include +#include +#include +#include + +#include "UASInterface.h" +#include "AutoPilotPlugin.h" +#include "FactPanelController.h" +#include "APMAirframeComponentAirframes.h" + +class APMAirframeModel; +class APMAirframeType; + +/// MVC Controller for APMAirframeComponent.qml. +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(APMAirframe* currentAirframe READ currentAirframe WRITE setCurrentAirframe NOTIFY currentAirframeChanged) + + int currentAirframeIndex(void); + void setCurrentAirframeIndex(int newIndex); + +signals: + void loadAirframesCompleted(); + void currentAirframeTypeChanged(APMAirframeType* airframeType); + void currentAirframeChanged(APMAirframe* airframe); + +public slots: + APMAirframeType *currentAirframeType() const; + APMAirframe *currentAirframe() const; + void setCurrentAirframeType(APMAirframeType *t); + void setCurrentAirframe(APMAirframe *t); + +private slots: + void _fillAirFrames(void); + void _finishVehicleSetup(void); + void _factFrameChanged(QVariant v); + +private: + static bool _typesRegistered; + APMAirframeType *_currentAirframeType; + APMAirframe *_currentAirframe; + int _waitParamWriteSignalCount; + QmlObjectListModel *_airframeTypesModel; +}; + +class APMAirframe : public QObject +{ + Q_OBJECT + +public: + APMAirframe(const QString& name, const QString& paramsFile, int type, QObject* parent = NULL); + ~APMAirframe(); + + 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; + +private: + QString _name; + QString _paramsFile; + int _type; +}; + +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); + + QString name() const; + QString imageResource() const; + int type() const; +private: + QString _name; + QString _imageResource; + QVariantList _airframes; + int _type; + bool _dirty; +}; + +#endif diff --git a/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml b/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml index 975a6f8254bd010dddd228e40db2a3cc306d7a9c..3e697b1b1ba96cb498628e0c380fd21fbdc8d72e 100644 --- a/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml +++ b/src/AutoPilotPlugins/APM/APMAirframeComponentSummary.qml @@ -13,33 +13,27 @@ FactPanel { color: qgcPal.windowShadeDark QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + APMAirframeComponentController { + id: controller + factPanel: panel + } -/* - property Fact sysIdFact: controller.getParameterFact(-1, "MAV_SYS_ID") - property Fact sysAutoStartFact: controller.getParameterFact(-1, "SYS_AUTOSTART") + property Fact sysIdFact: controller.getParameterFact(-1, "FRAME") - property bool autoStartSet: sysAutoStartFact.value != 0 -*/ Column { anchors.fill: parent anchors.margins: 8 -/* - VehicleSummaryRow { - labelText: "System ID:" - valueText: sysIdFact.valueString - } - VehicleSummaryRow { - labelText: "Airframe type:" - valueText: autoStartSet ? controller.currentAirframeType : "Setup required" - } + id: nameRow; + labelText: "Frame Type:" + valueText: sysIdFact.valueString === "0" ? "Plus" + : sysIdFact.valueString === "1" ? "X" + : sysIdFact.valueString === "2" ? "V" + : sysIdFact.valueString == "3" ? "H" + :/* Fact.value == 10 */ "New Y6"; - VehicleSummaryRow { - labelText: "Vehicle:" - valueText: autoStartSet ? controller.currentVehicleName : "Setup required" } -*/ } } diff --git a/src/AutoPilotPlugins/APM/APMAirframeLoader.cc b/src/AutoPilotPlugins/APM/APMAirframeLoader.cc new file mode 100644 index 0000000000000000000000000000000000000000..1a189ebd2002ebf4161e1883c1c0ab30c525dc87 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeLoader.cc @@ -0,0 +1,100 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @author Don Gagne + +#include "APMAirframeLoader.h" +#include "QGCApplication.h" +#include "QGCLoggingCategory.h" +#include "APMAirframeComponentAirframes.h" + +#include +#include +#include +#include + +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 = ":/AutoPilotPlugins/APM/AirframeFactMetaData.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 == "airframe_group") { + airframeGroup = attr.value("name").toString(); + image = attr.value("image").toString(); + groupId = attr.value("id").toInt(); + APMAirframeComponentAirframes::insert(airframeGroup, groupId, image); + } else if (elementName == "airframe") { + QString name = attr.value("name").toString(); + QString file = attr.value("file").toString(); + APMAirframeComponentAirframes::insert(airframeGroup, groupId, image, name, file); + } + } + xml.readNext(); + } + + _airframeMetaDataLoaded = true; +} diff --git a/src/AutoPilotPlugins/APM/APMAirframeLoader.h b/src/AutoPilotPlugins/APM/APMAirframeLoader.h new file mode 100644 index 0000000000000000000000000000000000000000..5d8d4e6dac9132a217688ab039b7740b4d755664 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMAirframeLoader.h @@ -0,0 +1,59 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2015 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +#ifndef APMAirframeLoader_H +#define APMAirframeLoader_H + +#include +#include +#include +#include + +#include "ParameterLoader.h" +#include "FactSystem.h" +#include "UASInterface.h" +#include "AutoPilotPlugin.h" + +/// @file APMAirframeLoader.h +/// @author Lorenz Meier + +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 _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData +}; + +#endif // APMAirframeLoader_H diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc index b04d522c8c70cef108206b79007768a33921dc84..d8254a3f0790f724518cfc8ae1b392e3e3882a04 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc @@ -1,24 +1,24 @@ /*===================================================================== QGroundControl Open Source Ground Control Station - + (c) 2009 - 2015 QGROUNDCONTROL PROJECT - + 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 . - + ======================================================================*/ #include "APMAutoPilotPlugin.h" @@ -26,6 +26,18 @@ #include "UAS.h" #include "FirmwarePlugin/APM/APMParameterMetaData.h" // FIXME: Hack #include "FirmwarePlugin/APM/APMFirmwarePlugin.h" // FIXME: Hack +#include "FirmwarePlugin/APM/ArduCopterFirmwarePlugin.h" +#include "APMComponent.h" +#include "APMAirframeComponent.h" +#include "APMAirframeComponentAirframes.h" +#include "APMAirframeComponentController.h" +#include "APMAirframeLoader.h" +#include "APMRemoteParamsDownloader.h" +#include "APMFlightModesComponent.h" +#include "APMRadioComponent.h" +#include "APMSafetyComponent.h" +#include "APMTuningComponent.h" +#include "APMSensorsComponent.h" /// This is the AutoPilotPlugin implementatin for the MAV_AUTOPILOT_ARDUPILOT type. APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) @@ -37,8 +49,9 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) , _safetyComponent(NULL) , _sensorsComponent(NULL) , _tuningComponent(NULL) + , _airframeFacts(new APMAirframeLoader(this, vehicle->uas(), this)) { - Q_ASSERT(vehicle); + APMAirframeLoader::loadAirframeFactMetaData(); } APMAutoPilotPlugin::~APMAutoPilotPlugin() @@ -52,12 +65,14 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void) Q_ASSERT(_vehicle); if (parametersReady()) { - _airframeComponent = new APMAirframeComponent(_vehicle, this); - if (_airframeComponent) { - _airframeComponent->setupTriggerSignals(); - _components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent)); - } else { - qWarning() << "new APMAirframeComponent failed"; + if (dynamic_cast(_vehicle->firmwarePlugin())){ + _airframeComponent = new APMAirframeComponent(_vehicle, this); + if(_airframeComponent) { + _airframeComponent->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_airframeComponent)); + } else { + qWarning() << "new APMAirframeComponent failed"; + } } _flightModesComponent = new APMFlightModesComponent(_vehicle, this); @@ -122,9 +137,9 @@ void APMAutoPilotPlugin::_parametersReadyPreChecks(bool missingParameters) "Please perform a Firmware Upgrade if you wish to use Vehicle Setup."); } #endif - + Q_UNUSED(missingParameters); _parametersReady = true; - _missingParameters = missingParameters; + _missingParameters = false; // we apply only the parameters that do exists on the FactSystem. emit missingParametersChanged(_missingParameters); emit parametersReadyChanged(_parametersReady); } diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h index c26dee7c07cd816a5774993be547bec8f7363ad5..1102cf1e77fb9f2e7b9f60c9eae75e61d668b17b 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h @@ -26,12 +26,14 @@ #include "AutoPilotPlugin.h" #include "Vehicle.h" -#include "APMAirframeComponent.h" -#include "APMFlightModesComponent.h" -#include "APMRadioComponent.h" -#include "APMSafetyComponent.h" -#include "APMSensorsComponent.h" -#include "APMTuningComponent.h" + +class APMAirframeComponent; +class APMAirframeLoader; +class APMFlightModesComponent; +class APMRadioComponent; +class APMTuningComponent; +class APMSafetyComponent; +class APMSensorsComponent; /// This is the APM specific implementation of the AutoPilot class. class APMAutoPilotPlugin : public AutoPilotPlugin @@ -66,6 +68,7 @@ private: APMSafetyComponent* _safetyComponent; APMSensorsComponent* _sensorsComponent; APMTuningComponent* _tuningComponent; + APMAirframeLoader* _airframeFacts; }; #endif diff --git a/src/AutoPilotPlugins/APM/APMComponent.cc b/src/AutoPilotPlugins/APM/APMComponent.cc index ec3cbf9b6e91fe989b8c5c8fb445cd5698274479..e5b745b31c61477d3b33825a1ae1069f22f97f84 100644 --- a/src/AutoPilotPlugins/APM/APMComponent.cc +++ b/src/AutoPilotPlugins/APM/APMComponent.cc @@ -37,10 +37,8 @@ APMComponent::APMComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject void APMComponent::setupTriggerSignals(void) { - // Watch for changed on trigger list params - foreach (QString paramName, setupCompleteChangedTriggerList()) { + foreach (const QString& paramName, setupCompleteChangedTriggerList()) { Fact* fact = _autopilot->getParameterFact(FactSystem::defaultComponentId, paramName); - connect(fact, &Fact::valueChanged, this, &APMComponent::_triggerUpdated); } } diff --git a/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc b/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc index 77456548006c472c8bd2b01852c89527d346b81c..80b9baa6d86c44e269df27999a8ce5f184f48088 100644 --- a/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc +++ b/src/AutoPilotPlugins/APM/APMFlightModesComponent.cc @@ -23,6 +23,8 @@ #include "APMFlightModesComponent.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" +#include "APMRadioComponent.h" APMFlightModesComponent::APMFlightModesComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent), diff --git a/src/AutoPilotPlugins/APM/APMRadioComponent.cc b/src/AutoPilotPlugins/APM/APMRadioComponent.cc index c42a1d553b99be47d23e2660385e50ce96caf89a..5cbed197ae29d864427d7f3eaf67548546ef56f1 100644 --- a/src/AutoPilotPlugins/APM/APMRadioComponent.cc +++ b/src/AutoPilotPlugins/APM/APMRadioComponent.cc @@ -23,6 +23,7 @@ #include "APMRadioComponent.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" APMRadioComponent::APMRadioComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent), diff --git a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc new file mode 100644 index 0000000000000000000000000000000000000000..8b4834dbc4b3b1d909973b21020e6d2cf3df6a31 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc @@ -0,0 +1,181 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +#include "APMRemoteParamsDownloader.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "APMRemoteParamsDownloader.h" + +#define FRAME_PARAMS_LIST QUrl("https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params") +#define FRAME_PARAMS_URL "https://raw.github.com/diydrones/ardupilot/master/Tools/Frame_params/" + +static QString dataLocation; + +APMRemoteParamsDownloader::APMRemoteParamsDownloader(const QString& file) : + m_fileToDownload(file), + m_networkReply(NULL), + m_downloadedParamFile(NULL) +{ + dataLocation = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).at(0) + + QDir::separator() + qApp->applicationName(); + refreshParamList(); +} + +QString APMRemoteParamsDownloader::statusText() const +{ + return m_statusText; +} +void APMRemoteParamsDownloader::setStatusText(const QString& text) +{ + m_statusText = text; +} + +void APMRemoteParamsDownloader::refreshParamList() +{ + setStatusText(tr("Refresh Param file list")); + + QUrl url = FRAME_PARAMS_LIST; + m_networkReply->deleteLater(); + m_networkReply = m_networkAccessManager.get(QNetworkRequest(url)); + connect(m_networkReply, SIGNAL(finished()), this, SLOT(httpParamListFinished())); + connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)), + this, SLOT(updateDataReadProgress(qint64,qint64))); +} + +/* Returned Json Example + "_links": { + "git":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d", + "html":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param", + "self":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master" + }, + "download_url":"https://raw.githubusercontent.com/diydrones/ardupilot/master/Tools/Frame_params/Parrot_Bebop.param", + "git_url":"https://api.github.com/repos/diydrones/ardupilot/git/blobs/a7074e606d695566f9a8c87724ad52e5e3baba7d", + "html_url":"https://github.com/diydrones/ardupilot/blob/master/Tools/Frame_params/Parrot_Bebop.param", + "name":"Parrot_Bebop.param","path":"Tools/Frame_params/Parrot_Bebop.param","" + "sha":"a7074e606d695566f9a8c87724ad52e5e3baba7d", + "size":533, + "type":"file", + "url":"https://api.github.com/repos/diydrones/ardupilot/contents/Tools/Frame_params/Parrot_Bebop.param?ref=master" +*/ +void APMRemoteParamsDownloader::startFileDownloadRequest() +{ + QUrl url; + + QJsonObject obj; + + // Find the correct file from the json file list. + while(curr != end) { + obj = (*curr).toObject(); + url = QUrl(obj["download_url"].toString()); + QString name = obj["name"].toString(); + if (name == m_fileToDownload) { + break; + } + curr++; + } + if (curr == end) + return; + + QDir parameterDir(dataLocation); + if (!parameterDir.exists()) + parameterDir.mkpath(dataLocation); + + QString filename = parameterDir.absoluteFilePath(obj["name"].toString()); + + if(m_downloadedParamFile) + m_downloadedParamFile->deleteLater(); + m_downloadedParamFile = new QFile(filename); + m_downloadedParamFile->open(QIODevice::WriteOnly); + + m_networkReply = m_networkAccessManager.get(QNetworkRequest(url)); + connect(m_networkReply, SIGNAL(finished()), this, SLOT(httpFinished())); + connect(m_networkReply, SIGNAL(readyRead()), this, SLOT(httpReadyRead())); + connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDataReadProgress(qint64,qint64))); + curr++; +} + +void APMRemoteParamsDownloader::httpFinished() +{ + m_downloadedParamFile->flush(); + m_downloadedParamFile->close(); + + if (m_networkReply->error()) { + m_downloadedParamFile->remove(); + setStatusText(tr("Download failed: %1.").arg(m_networkReply->errorString())); + } + + m_networkReply->deleteLater(); + m_networkReply = NULL; + delete m_downloadedParamFile; + m_downloadedParamFile = NULL; + + emit finished(); +} + +void APMRemoteParamsDownloader::httpReadyRead() +{ + if (m_downloadedParamFile) + m_downloadedParamFile->write(m_networkReply->readAll()); +} + +void APMRemoteParamsDownloader::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes) +{ + Q_UNUSED(bytesRead); + Q_UNUSED(totalBytes); +} + +void APMRemoteParamsDownloader::httpParamListFinished() +{ + if (m_networkReply->error()) { + qDebug() << "Download failed:" << m_networkReply->errorString(); + return; + } + processDownloadedVersionObject(m_networkReply->readAll()); + startFileDownloadRequest(); +} + +void APMRemoteParamsDownloader::processDownloadedVersionObject(const QByteArray &listObject) +{ + QJsonParseError jsonErrorChecker; + QJsonDocument jsonDocument = QJsonDocument::fromJson(listObject, &jsonErrorChecker); + if (jsonErrorChecker.error != QJsonParseError::NoError) { + qDebug() << "Json error while parsing document:" << jsonErrorChecker.errorString(); + return; + } + + m_documentArray = jsonDocument.array(); + curr = m_documentArray.constBegin(); + end = m_documentArray.constEnd(); +} diff --git a/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h new file mode 100644 index 0000000000000000000000000000000000000000..b635cc77e4ab743f2f448d64267a81c0aa64e7d8 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h @@ -0,0 +1,47 @@ +#ifndef APMREMOTEPARAMSCONTROLLER_H +#define APMREMOTEPARAMSCONTROLLER_H + +#include +#include +#include +#include + +class QNetworkReply; +class QFile; +class QUrl; + +class APMRemoteParamsDownloader : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString statusText READ statusText) +public: + explicit APMRemoteParamsDownloader(const QString& file); + QString statusText() const; +public slots: + void refreshParamList(); + void httpParamListFinished(); + void httpFinished(); + void httpReadyRead(); + void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes); +private: + void setStatusText(const QString& text); + void startFileDownloadRequest(); + void manualListSetup(); + void processDownloadedVersionObject(const QByteArray& listObject); + void startDownloadingRemoteParams(); +signals: + void finished(); +private: + QString m_fileToDownload; + QString m_statusText; + QNetworkAccessManager m_networkAccessManager; + QNetworkReply* m_networkReply; + QFile* m_downloadedParamFile; + + // the list of needed documents. + QJsonArray m_documentArray; + QJsonArray::const_iterator curr; + QJsonArray::const_iterator end; +}; + +#endif // APMREMOTEPARAMSCONTROLLER_H diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponent.cc b/src/AutoPilotPlugins/APM/APMSafetyComponent.cc index 1346fa6e138172913a12da3d9a8ec09e8b29079a..805c02c24af88ba74df3b4ff28fe2e4874a3e3dc 100644 --- a/src/AutoPilotPlugins/APM/APMSafetyComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSafetyComponent.cc @@ -27,6 +27,7 @@ #include "APMSafetyComponent.h" #include "QGCQmlWidgetHolder.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" APMSafetyComponent::APMSafetyComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent) diff --git a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc index 49f4b599fe3db6326037e8feb4649943937355e8..4b1e088d8bd3f908d7e9dad1e9db72d753b192b4 100644 --- a/src/AutoPilotPlugins/APM/APMSensorsComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSensorsComponent.cc @@ -24,6 +24,7 @@ #include "APMSensorsComponent.h" #include "APMAutoPilotPlugin.h" #include "APMSensorsComponentController.h" +#include "APMAirframeComponent.h" // These two list must be kept in sync diff --git a/src/AutoPilotPlugins/APM/APMTuningComponent.cc b/src/AutoPilotPlugins/APM/APMTuningComponent.cc index ca61ec1d599568d9d0ee8a2d74c52e0c36a46d45..7275d9829a98d771b201a287993715678f9b69f0 100644 --- a/src/AutoPilotPlugins/APM/APMTuningComponent.cc +++ b/src/AutoPilotPlugins/APM/APMTuningComponent.cc @@ -23,6 +23,7 @@ #include "APMTuningComponent.h" #include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" APMTuningComponent::APMTuningComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) : APMComponent(vehicle, autopilot, parent) diff --git a/src/AutoPilotPlugins/APM/AirframeFactMetaData.xml b/src/AutoPilotPlugins/APM/AirframeFactMetaData.xml new file mode 100644 index 0000000000000000000000000000000000000000..b41926c02ffa0d4dd09607997ee020d52ae42656 --- /dev/null +++ b/src/AutoPilotPlugins/APM/AirframeFactMetaData.xml @@ -0,0 +1,30 @@ + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AutoPilotPlugins/AutoPilotPlugin.h b/src/AutoPilotPlugins/AutoPilotPlugin.h index 8e24bb5c6f82f508dca8e2380dcd84d36eca8fd1..649542ae9df79e8d3512a6e720b325cc79cc404d 100644 --- a/src/AutoPilotPlugins/AutoPilotPlugin.h +++ b/src/AutoPilotPlugins/AutoPilotPlugin.h @@ -1,148 +1,148 @@ -/*===================================================================== - - QGroundControl Open Source Ground Control Station - - (c) 2009 - 2014 QGROUNDCONTROL PROJECT - - 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 . - - ======================================================================*/ - -/// @file -/// @author Don Gagne - -#ifndef AUTOPILOTPLUGIN_H -#define AUTOPILOTPLUGIN_H - -#include -#include -#include -#include - -#include "VehicleComponent.h" -#include "FactSystem.h" -#include "Vehicle.h" - -class ParameterLoader; -class Vehicle; -class FirmwarePlugin; - -/// This is the base class for AutoPilot plugins -/// -/// The AutoPilotPlugin class is an abstract base class which represent the methods and objects -/// which are specific to a certain AutoPilot. This is the only place where AutoPilot specific -/// code should reside in QGroundControl. The remainder of the QGroundControl source is -/// generic to a common mavlink implementation. - -class AutoPilotPlugin : public QObject -{ - Q_OBJECT - -public: - AutoPilotPlugin(Vehicle* vehicle, QObject* parent); - ~AutoPilotPlugin(); - - /// true: parameters are ready for use - Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged) - - /// true: parameters are missing from firmware response, false: all parameters received from firmware - Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) - - /// List of VehicleComponent objects - Q_PROPERTY(QVariantList vehicleComponents READ vehicleComponents CONSTANT) - - /// false: One or more vehicle components require setup - Q_PROPERTY(bool setupComplete READ setupComplete NOTIFY setupCompleteChanged) - - /// Reset all parameters to their default values - Q_INVOKABLE void resetAllParametersToDefaults(void); - - /// Re-request the full set of parameters from the autopilot - Q_INVOKABLE void refreshAllParameters(void); - - /// Request a refresh on the specific parameter - Q_INVOKABLE void refreshParameter(int componentId, const QString& name); - - /// Request a refresh on all parameters that begin with the specified prefix - Q_INVOKABLE void refreshParametersPrefix(int componentId, const QString& namePrefix); - - /// Returns true if the specifed parameter exists from the default component - Q_INVOKABLE bool parameterExists(int componentId, const QString& name); - - /// Returns all parameter names - QStringList parameterNames(int componentId); - - /// Returns the specified parameter Fact from the default component - /// WARNING: Returns a default Fact if parameter does not exists. If that possibility exists, check for existince first with - /// parameterExists. - Fact* getParameterFact(int componentId, const QString& name); - - /// Writes the parameter facts to the specified stream - void writeParametersToStream(QTextStream &stream); - - /// Reads the parameters from the stream and updates values - /// @return Errors during load. Empty string for no errors - QString readParametersFromStream(QTextStream &stream); - - /// Returns true if the specifed fact exists - Q_INVOKABLE bool factExists(FactSystem::Provider_t provider, ///< fact provider - int componentId, ///< fact component, -1=default component - const QString& name); ///< fact name - - /// Returns the specified Fact. - /// WARNING: Will assert if fact does not exists. If that possibility exists, check for existince first with - /// factExists. - Fact* getFact(FactSystem::Provider_t provider, ///< fact provider - int componentId, ///< fact component, -1=default component - const QString& name); ///< fact name - - const QMap >& getGroupMap(void); - - // Must be implemented by derived class - virtual const QVariantList& vehicleComponents(void) = 0; - - // Property accessors - bool parametersReady(void) { return _parametersReady; } - bool missingParameters(void) { return _missingParameters; } - bool setupComplete(void); - - Vehicle* vehicle(void) { return _vehicle; } - -signals: - void parametersReadyChanged(bool parametersReady); - void missingParametersChanged(bool missingParameters); - void setupCompleteChanged(bool setupComplete); - void parameterListProgress(float value); - -protected: - /// All access to AutoPilotPugin objects is through getInstanceForAutoPilotPlugin - AutoPilotPlugin(QObject* parent = NULL) : QObject(parent) { } - - Vehicle* _vehicle; - FirmwarePlugin* _firmwarePlugin; - bool _parametersReady; - bool _missingParameters; - bool _setupComplete; - -private slots: - void _uasDisconnected(void); - void _parametersReadyChanged(bool parametersReady); - -private: - void _recalcSetupComplete(void); -}; - -#endif + /*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2014 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + + /// @file + /// @author Don Gagne + + #ifndef AUTOPILOTPLUGIN_H + #define AUTOPILOTPLUGIN_H + + #include + #include + #include + #include + + #include "VehicleComponent.h" + #include "FactSystem.h" + #include "Vehicle.h" + + class ParameterLoader; + class Vehicle; + class FirmwarePlugin; + + /// This is the base class for AutoPilot plugins + /// + /// The AutoPilotPlugin class is an abstract base class which represent the methods and objects + /// which are specific to a certain AutoPilot. This is the only place where AutoPilot specific + /// code should reside in QGroundControl. The remainder of the QGroundControl source is + /// generic to a common mavlink implementation. + + class AutoPilotPlugin : public QObject + { + Q_OBJECT + + public: + AutoPilotPlugin(Vehicle* vehicle, QObject* parent); + ~AutoPilotPlugin(); + + /// true: parameters are ready for use + Q_PROPERTY(bool parametersReady READ parametersReady NOTIFY parametersReadyChanged) + + /// true: parameters are missing from firmware response, false: all parameters received from firmware + Q_PROPERTY(bool missingParameters READ missingParameters NOTIFY missingParametersChanged) + + /// List of VehicleComponent objects + Q_PROPERTY(QVariantList vehicleComponents READ vehicleComponents CONSTANT) + + /// false: One or more vehicle components require setup + Q_PROPERTY(bool setupComplete READ setupComplete NOTIFY setupCompleteChanged) + + /// Reset all parameters to their default values + Q_INVOKABLE void resetAllParametersToDefaults(void); + + /// Re-request the full set of parameters from the autopilot + Q_INVOKABLE void refreshAllParameters(void); + + /// Request a refresh on the specific parameter + Q_INVOKABLE void refreshParameter(int componentId, const QString& name); + + /// Request a refresh on all parameters that begin with the specified prefix + Q_INVOKABLE void refreshParametersPrefix(int componentId, const QString& namePrefix); + + /// Returns true if the specifed parameter exists from the default component + Q_INVOKABLE bool parameterExists(int componentId, const QString& name); + + /// Returns all parameter names + QStringList parameterNames(int componentId); + + /// Returns the specified parameter Fact from the default component + /// WARNING: Returns a default Fact if parameter does not exists. If that possibility exists, check for existince first with + /// parameterExists. + Fact* getParameterFact(int componentId, const QString& name); + + /// Writes the parameter facts to the specified stream + void writeParametersToStream(QTextStream &stream); + + /// Reads the parameters from the stream and updates values + /// @return Errors during load. Empty string for no errors + QString readParametersFromStream(QTextStream &stream); + + /// Returns true if the specifed fact exists + Q_INVOKABLE bool factExists(FactSystem::Provider_t provider, ///< fact provider + int componentId, ///< fact component, -1=default component + const QString& name); ///< fact name + + /// Returns the specified Fact. + /// WARNING: Will assert if fact does not exists. If that possibility exists, check for existince first with + /// factExists. + Fact* getFact(FactSystem::Provider_t provider, ///< fact provider + int componentId, ///< fact component, -1=default component + const QString& name); ///< fact name + + const QMap >& getGroupMap(void); + + // Must be implemented by derived class + virtual const QVariantList& vehicleComponents(void) = 0; + + // Property accessors + bool parametersReady(void) { return _parametersReady; } + bool missingParameters(void) { return _missingParameters; } + bool setupComplete(void); + + Vehicle* vehicle(void) { return _vehicle; } + + signals: + void parametersReadyChanged(bool parametersReady); + void missingParametersChanged(bool missingParameters); + void setupCompleteChanged(bool setupComplete); + void parameterListProgress(float value); + + protected: + /// All access to AutoPilotPugin objects is through getInstanceForAutoPilotPlugin + AutoPilotPlugin(QObject* parent = NULL) : QObject(parent) { } + + Vehicle* _vehicle; + FirmwarePlugin* _firmwarePlugin; + bool _parametersReady; + bool _missingParameters; + bool _setupComplete; + + private slots: + void _uasDisconnected(void); + void _parametersReadyChanged(bool parametersReady); + + private: + void _recalcSetupComplete(void); + }; + + #endif diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 5dc5193e93b06f674215ab302ae8480a7b3b9ae6..2ce5823e0469bf03bb79ce20a9409b2a06bf55cf 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -77,6 +77,7 @@ #include "APM/ArduCopterFirmwarePlugin.h" #include "APM/ArduPlaneFirmwarePlugin.h" #include "APM/ArduRoverFirmwarePlugin.h" +#include "APM/APMAirframeComponentController.h" #include "PX4/PX4FirmwarePlugin.h" #include "Vehicle.h" #include "MavlinkQmlSingleton.h" @@ -378,9 +379,10 @@ void QGCApplication::_initCommon(void) qmlRegisterUncreatableType ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only"); qmlRegisterUncreatableType ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only"); - qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMFlightModesComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "FlightModesComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMAirframeComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "AirframeComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "APMSensorsComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "SensorsComponentController"); diff --git a/src/QmlControls/QGCView.qml b/src/QmlControls/QGCView.qml index 1536effc22393a6733df29dd25d399d3d6bf233b..359d4fc5615cab47c59ae75c6ea53c7c6a4efc0c 100644 --- a/src/QmlControls/QGCView.qml +++ b/src/QmlControls/QGCView.qml @@ -96,7 +96,7 @@ FactPanel { __rejectButton.text = "Cancel" __rejectButton.visible = true } else if (buttons & StandardButton.Close) { - __rejectButton.text = "Cancel" + __rejectButton.text = "Close" __rejectButton.visible = true } else if (buttons & StandardButton.No) { __rejectButton.text = "No"