Commit 27461b23 authored by Don Gagne's avatar Don Gagne

Merge pull request #2415 from tcanabrava/APMAirframesV8

Add the initial stub for the AirFrame configuration for APM
parents 46604020 ff32b9fe
......@@ -208,6 +208,9 @@
<file alias="AirframeFactMetaData.xml">src/AutoPilotPlugins/PX4/AirframeFactMetaData.xml</file>
<file alias="ParameterFactMetaData.xml">src/AutoPilotPlugins/PX4/ParameterFactMetaData.xml</file>
</qresource>
<qresource prefix="/AutoPilotPlugins/APM">
<file alias="AirframeFactMetaData.xml">src/AutoPilotPlugins/APM/AirframeFactMetaData.xml</file>
</qresource>
<qresource prefix="/FirmwarePlugin/APM">
<file alias="apm.pdef.xml">src/FirmwarePlugin/APM/apm.pdef.xml</file>
......
......@@ -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 \
......
......@@ -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
......
......@@ -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
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMAirframeComponentAirframes.h"
#include "APMAirframeComponentController.h"
QMap<QString, APMAirframeComponentAirframes::AirframeType_t*> APMAirframeComponentAirframes::rgAirframeTypes;
QMap<QString, APMAirframeComponentAirframes::AirframeType_t*>& APMAirframeComponentAirframes::get() {
return rgAirframeTypes;
}
void APMAirframeComponentAirframes::insert(const QString& group, int groupId, const QString& image,const QString& name, const QString& file)
{
AirframeType_t *g;
if (!rgAirframeTypes.contains(group)) {
g = new AirframeType_t;
g->name = group;
g->type = groupId;
g->imageResource = 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<AirframeType_t*> valueList = get().values();
foreach(AirframeType_t *pType, valueList) {
qDeleteAll(pType->rgAirframeInfo);
delete pType;
}
rgAirframeTypes.clear();
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef APMAirframeComponentAirframes_H
#define APMAirframeComponentAirframes_H
#include <QObject>
#include <QQuickItem>
#include <QList>
#include <QMap>
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
class APMAirframe;
/// MVC Controller for AirframeComponent.qml.
class APMAirframeComponentAirframes
{
public:
typedef struct {
QString name;
QString imageResource;
int type;
QList<APMAirframe*> rgAirframeInfo;
} AirframeType_t;
typedef QMap<QString, AirframeType_t*> AirframeTypeMap;
static AirframeTypeMap& get();
static void clear();
static void insert(const QString& group, int groupId, const QString& image,const QString& name = QString(), const QString& file = QString());
protected:
static AirframeTypeMap rgAirframeTypes;
private:
};
#endif
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMAirframeComponentController.h"
#include "APMAirframeComponentAirframes.h"
#include "APMRemoteParamsDownloader.h"
#include "QGCMAVLink.h"
#include "MultiVehicleManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCApplication.h"
#include <QVariant>
#include <QQmlProperty>
bool APMAirframeComponentController::_typesRegistered = false;
APMAirframeComponentController::APMAirframeComponentController(void) :
_airframeTypesModel(new QmlObjectListModel(this))
{
if (!_typesRegistered) {
_typesRegistered = true;
qmlRegisterUncreatableType<APMAirframeType>("QGroundControl.Controllers", 1, 0, "APMAiframeType", "Can only reference APMAirframeType");
qmlRegisterUncreatableType<APMAirframe>("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<APMAirframeType*>(_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(&parametersFile);
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());
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#ifndef APMAirframeComponentController_H
#define APMAirframeComponentController_H
#include <QObject>
#include <QQuickItem>
#include <QList>
#include <QAbstractListModel>
#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
......@@ -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"
}
*/
}
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include "APMAirframeLoader.h"
#include "QGCApplication.h"
#include "QGCLoggingCategory.h"
#include "APMAirframeComponentAirframes.h"
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
QGC_LOGGING_CATEGORY(APMAirframeLoaderLog, "APMAirframeLoaderLog")
bool APMAirframeLoader::_airframeMetaDataLoaded = false;
APMAirframeLoader::APMAirframeLoader(AutoPilotPlugin* autopilot, UASInterface* uas, QObject* parent)
{
Q_UNUSED(autopilot);
Q_UNUSED(uas);
Q_UNUSED(parent);
Q_ASSERT(uas);
}
/// Load Airframe Fact meta data
void APMAirframeLoader::loadAirframeFactMetaData(void)
{
if (_airframeMetaDataLoaded) {
return;
}
qCDebug(APMAirframeLoaderLog) << "Loading APM airframe fact meta data";
Q_ASSERT(APMAirframeComponentAirframes::get().count() == 0);
QString airframeFilename = ":/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;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef APMAirframeLoader_H
#define APMAirframeLoader_H
#include <QObject>
#include <QMap>
#include <QXmlStreamReader>
#include <QLoggingCategory>
#include "ParameterLoader.h"
#include "FactSystem.h"
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
/// @file APMAirframeLoader.h
/// @author Lorenz Meier <lm@qgroundcontrol.org>
Q_DECLARE_LOGGING_CATEGORY(APMAirframeLoaderLog)
/// Collection of Parameter Facts for PX4 AutoPilot
class APMAirframeLoader : QObject
{
Q_OBJECT
public:
/// @param uas Uas which this set of facts is associated with
APMAirframeLoader(AutoPilotPlugin* autpilot,UASInterface* uas, QObject* parent = NULL);
static void loadAirframeFactMetaData(void);
private:
static bool _airframeMetaDataLoaded; ///< true: parameter meta data already loaded
static QMap<QString, FactMetaData*> _mapParameterName2FactMetaData; ///< Maps from a parameter name to FactMetaData
};
#endif // APMAirframeLoader_H
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#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<ArduCopterFirmwarePlugin*>(_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);
}
......@@ -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
......@@ -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);
}
}
......
......@@ -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),
......
......@@ -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),
......
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "APMRemoteParamsDownloader.h"
#include <QMessageBox>
#include <QDesktopServices>
#include <QFile>
#include <QFileDialog>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QCryptographicHash>
#include <QApplication>
#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();
}
#ifndef APMREMOTEPARAMSCONTROLLER_H
#define APMREMOTEPARAMSCONTROLLER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QJsonArray>
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
......@@ -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)
......
......@@ -24,6 +24,7 @@
#include "APMSensorsComponent.h"
#include "APMAutoPilotPlugin.h"
#include "APMSensorsComponentController.h"
#include "APMAirframeComponent.h"
// These two list must be kept in sync
......
......@@ -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)
......
<?xml version='1.0' encoding='UTF-8'?>
<airframes>
<version>1</version>
<airframe_group image="AirframeQuadRotorPlus.png" name="Plus Style" id="0">
<airframe name="3DR Aero M" file="3DR_AERO_M.param"/>
<airframe name="3DR Aero RTF" file="3DR_Aero_RTF.param"/>
<airframe name="3DR Rover" file="3DR_Rover.param"/>
<airframe name="3DR Tarot" file="3DR_Tarot.bgsc"/>
<airframe name="Parrot Bebop" file="Parrot_Bebop.param"/>
<airframe name="Storm32" file="SToRM32-MAVLink.param"/>
</airframe_group>
<airframe_group image="AirframeQuadRotorX.png" name="X Style" id="1">
<airframe name="3DR X8-M RTF" file="3DR_X8-M_RTF.param"/>
<airframe name="3DR Y6A" file="3DR_Y6A_RTF.param"/>
<airframe name="3DR X8+ RTF" file="3DR_X8+_RTF.param"/>
<airframe name="3DR QUAD X4 RTF" file="3DR_QUAD_X4_RTF.param"/>
<airframe name="3DR X8" file="3DR_X8_RTF.param"/>
</airframe_group>
<airframe_group image="AirframeSimulation.png" name="V Style" id="2">
<airframe name="Iris with GoPro" file="Iris with Front Mount Go Pro.param"/>
<airframe name="Iris with Tarot" file="Iris with Tarot Gimbal.param"/>
<airframe name="3DR Iris+" file="3DR_Iris+.param"/>
<airframe name="Iris" file="Iris.param"/>
</airframe_group>
<airframe_group image="AirframeQuadRotorH.png" name="H Style" id="3">
</airframe_group>
<airframe_group image="AirframeHexaRotorX.png" name="Y6B" id="10">
<airframe name="3DR Y6B" file="3DR_Y6B_RTF.param"/>
</airframe_group>
<airframes>
This diff is collapsed.
......@@ -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<JoystickManager> ("QGroundControl.JoystickManager", 1, 0, "JoystickManager", "Reference only");
qmlRegisterUncreatableType<Joystick> ("QGroundControl.JoystickManager", 1, 0, "Joystick", "Reference only");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<ParameterEditorController> ("QGroundControl.Controllers", 1, 0, "ParameterEditorController");
qmlRegisterType<APMFlightModesComponentController> ("QGroundControl.Controllers", 1, 0, "APMFlightModesComponentController");
qmlRegisterType<FlightModesComponentController> ("QGroundControl.Controllers", 1, 0, "FlightModesComponentController");
qmlRegisterType<APMAirframeComponentController> ("QGroundControl.Controllers", 1, 0, "APMAirframeComponentController");
qmlRegisterType<AirframeComponentController> ("QGroundControl.Controllers", 1, 0, "AirframeComponentController");
qmlRegisterType<APMSensorsComponentController> ("QGroundControl.Controllers", 1, 0, "APMSensorsComponentController");
qmlRegisterType<SensorsComponentController> ("QGroundControl.Controllers", 1, 0, "SensorsComponentController");
......
......@@ -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"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment