From ff32b9fe14a40f5bf1ca440fcd410b0c859ec133 Mon Sep 17 00:00:00 2001 From: Tomaz Canabrava Date: Mon, 9 Nov 2015 17:16:14 -0200 Subject: [PATCH] Add the initial stub for the AirFrame configuration for APM This commit introduces the APM Airframe configuration. The interface is the same as the PX4 one, but the way we deal with the uas is a bit different Since the APM stack doesn't provide a xml with airframe definitions a new one was created by hand with only the values that we need, wich will trigger a download of the parameters file from the mavlink github Now it correctly handles the FRAME variable and it's faster regarding the download of the parameters for each type of Frame. Only show Airframes for ArduCopter, not for ArduRover nor ArduPlane Signed-off-by: Tomaz Canabrava --- qgcresources.qrc | 3 + qgroundcontrol.pro | 8 + src/AutoPilotPlugins/APM/APMAirframeComponent.cc | 13 +- src/AutoPilotPlugins/APM/APMAirframeComponent.qml | 207 +++++++++++++- .../APM/APMAirframeComponentAirframes.cc | 60 +++++ .../APM/APMAirframeComponentAirframes.h | 62 +++++ .../APM/APMAirframeComponentController.cc | 208 +++++++++++++++ .../APM/APMAirframeComponentController.h | 138 ++++++++++ .../APM/APMAirframeComponentSummary.qml | 30 +-- src/AutoPilotPlugins/APM/APMAirframeLoader.cc | 100 +++++++ src/AutoPilotPlugins/APM/APMAirframeLoader.h | 59 ++++ src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc | 45 ++-- src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h | 15 +- src/AutoPilotPlugins/APM/APMComponent.cc | 4 +- .../APM/APMFlightModesComponent.cc | 2 + src/AutoPilotPlugins/APM/APMRadioComponent.cc | 1 + .../APM/APMRemoteParamsDownloader.cc | 181 +++++++++++++ .../APM/APMRemoteParamsDownloader.h | 47 ++++ src/AutoPilotPlugins/APM/APMSafetyComponent.cc | 1 + src/AutoPilotPlugins/APM/APMSensorsComponent.cc | 1 + src/AutoPilotPlugins/APM/APMTuningComponent.cc | 1 + src/AutoPilotPlugins/APM/AirframeFactMetaData.xml | 30 +++ src/AutoPilotPlugins/AutoPilotPlugin.h | 296 ++++++++++----------- src/QGCApplication.cc | 4 +- src/QmlControls/QGCView.qml | 2 +- 25 files changed, 1312 insertions(+), 206 deletions(-) create mode 100644 src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc create mode 100644 src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h create mode 100644 src/AutoPilotPlugins/APM/APMAirframeComponentController.cc create mode 100644 src/AutoPilotPlugins/APM/APMAirframeComponentController.h create mode 100644 src/AutoPilotPlugins/APM/APMAirframeLoader.cc create mode 100644 src/AutoPilotPlugins/APM/APMAirframeLoader.h create mode 100644 src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.cc create mode 100644 src/AutoPilotPlugins/APM/APMRemoteParamsDownloader.h create mode 100644 src/AutoPilotPlugins/APM/AirframeFactMetaData.xml diff --git a/qgcresources.qrc b/qgcresources.qrc index cc3b28f..52a8881 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 4156b72..fed4ba2 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 1c90064..19899f1 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 e03e3e9..1a6551e 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 0000000..ca356f2 --- /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 0000000..7d33de2 --- /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 0000000..26ff996 --- /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 0000000..ef799ab --- /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 975a6f8..3e697b1 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 0000000..1a189eb --- /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 0000000..5d8d4e6 --- /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 b04d522..d8254a3 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 c26dee7..1102cf1 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 ec3cbf9..e5b745b 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 7745654..80b9baa 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 c42a1d5..5cbed19 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 0000000..8b4834d --- /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 0000000..b635cc7 --- /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 1346fa6..805c02c 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 49f4b59..4b1e088 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 ca61ec1..7275d98 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 0000000..b41926c --- /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 8e24bb5..649542a 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 5dc5193..2ce5823 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 1536eff..359d4fc 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"