Commit 806f3188 authored by Don Gagne's avatar Don Gagne

Merge pull request #1410 from DonLakeFlyer/AirframeConfigQml

Airframe config converted to Qml
parents 1da8917d 430d5473
......@@ -333,7 +333,6 @@ FORMS += \
src/ui/JoystickAxis.ui \
src/ui/configuration/terminalconsole.ui \
src/ui/configuration/SerialSettingsDialog.ui \
src/ui/px4_configuration/QGCPX4AirframeConfig.ui \
src/ui/px4_configuration/PX4RCCalibration.ui \
src/ui/QGCUASFileView.ui \
src/QGCQmlWidgetHolder.ui \
......@@ -464,7 +463,6 @@ HEADERS += \
src/uas/UASParameterDataModel.h \
src/uas/UASParameterCommsMgr.h \
src/ui/QGCPendingParamWidget.h \
src/ui/px4_configuration/QGCPX4AirframeConfig.h \
src/ui/QGCBaseParamWidget.h \
src/ui/px4_configuration/PX4RCCalibration.h \
src/ui/px4_configuration/RCValueWidget.h \
......@@ -609,7 +607,6 @@ SOURCES += \
src/uas/UASParameterDataModel.cc \
src/uas/UASParameterCommsMgr.cc \
src/ui/QGCPendingParamWidget.cc \
src/ui/px4_configuration/QGCPX4AirframeConfig.cc \
src/ui/QGCBaseParamWidget.cc \
src/ui/px4_configuration/PX4RCCalibration.cc \
src/ui/px4_configuration/RCValueWidget.cc \
......@@ -733,6 +730,8 @@ HEADERS+= \
src/AutoPilotPlugins/PX4/FlightModesComponent.h \
src/AutoPilotPlugins/PX4/FlightModesComponentController.h \
src/AutoPilotPlugins/PX4/AirframeComponent.h \
src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h \
src/AutoPilotPlugins/PX4/AirframeComponentController.h \
src/AutoPilotPlugins/PX4/SensorsComponent.h \
src/AutoPilotPlugins/PX4/SensorsComponentController.h \
src/AutoPilotPlugins/PX4/SafetyComponent.h \
......@@ -756,6 +755,8 @@ SOURCES += \
src/AutoPilotPlugins/PX4/FlightModesComponent.cc \
src/AutoPilotPlugins/PX4/FlightModesComponentController.cc \
src/AutoPilotPlugins/PX4/AirframeComponent.cc \
src/AutoPilotPlugins/PX4/AirframeComponentAirframes.cc \
src/AutoPilotPlugins/PX4/AirframeComponentController.cc \
src/AutoPilotPlugins/PX4/SensorsComponent.cc \
src/AutoPilotPlugins/PX4/SensorsComponentController.cc \
src/AutoPilotPlugins/PX4/SafetyComponent.cc \
......
......@@ -244,11 +244,13 @@
<qresource prefix="/qml">
<file alias="test.qml">src/test.qml</file>
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="QGroundControl/FactControls/qmldir">src/FactSystem/FactControls/qmldir</file>
<file alias="QGroundControl/FactControls/FactLabel.qml">src/FactSystem/FactControls/FactLabel.qml</file>
<file alias="QGroundControl/FactControls/FactTextField.qml">src/FactSystem/FactControls/FactTextField.qml</file>
<file alias="QGroundControl/FactControls/FactCheckBox.qml">src/FactSystem/FactControls/FactCheckBox.qml</file>
<file alias="QGroundControl/FactControls/FactComboBox.qml">src/FactSystem/FactControls/FactComboBox.qml</file>
<file alias="QGroundControl/Controls/qmldir">src/QmlControls/qmldir</file>
<file alias="QGroundControl/Controls/QGCButton.qml">src/QmlControls/QGCButton.qml</file>
<file alias="QGroundControl/Controls/QGCRadioButton.qml">src/QmlControls/QGCRadioButton.qml</file>
......@@ -262,10 +264,13 @@
<file alias="QGroundControl/Controls/IndicatorButton.qml">src/QmlControls/IndicatorButton.qml</file>
<file alias="QGroundControl/Controls/VehicleRotationCal.qml">src/QmlControls/VehicleRotationCal.qml</file>
<file alias="QGroundControl/Controls/arrow-down.png">src/QmlControls/arrow-down.png</file>
<file alias="octo_x.png">files/images/px4/airframes/octo_x.png</file>
<file alias="px4fmu_2.x.png">files/images/px4/boards/px4fmu_2.x.png</file>
<file alias="SetupViewButtonsConnected.qml">src/VehicleSetup/SetupViewButtonsConnected.qml</file>
<file alias="SetupViewButtonsDisconnected.qml">src/VehicleSetup/SetupViewButtonsDisconnected.qml</file>
<file alias="VehicleSummary.qml">src/VehicleSetup/VehicleSummary.qml</file>
<file alias="FirmwareUpgrade.qml">src/VehicleSetup/FirmwareUpgrade.qml</file>
<file alias="SafetyComponent.qml">src/AutoPilotPlugins/PX4/SafetyComponent.qml</file>
......@@ -283,12 +288,27 @@
<file alias="SafetyComponentHome.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentHome.png</file>
<file alias="SafetyComponentArrowDown.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentArrowDown.png</file>
<file alias="SafetyComponentPlane.png">src/AutoPilotPlugins/PX4/Images/SafetyComponentPlane.png</file>
<file alias="VehicleDown.png">src/AutoPilotPlugins/PX4/Images/VehicleDown.png</file>
<file alias="VehicleUpsideDown.png">src/AutoPilotPlugins/PX4/Images/VehicleUpsideDown.png</file>
<file alias="VehicleLeft.png">src/AutoPilotPlugins/PX4/Images/VehicleLeft.png</file>
<file alias="VehicleRight.png">src/AutoPilotPlugins/PX4/Images/VehicleRight.png</file>
<file alias="VehicleNoseDown.png">src/AutoPilotPlugins/PX4/Images/VehicleNoseDown.png</file>
<file alias="VehicleTailDown.png">src/AutoPilotPlugins/PX4/Images/VehicleTailDown.png</file>
<!-- Airframe component resourecs -->
<file alias="AirframeComponent.qml">src/AutoPilotPlugins/PX4/AirframeComponent.qml</file>
<file alias="AirframeStandardPlane.png">src/AutoPilotPlugins/PX4/Images/AirframeStandardPlane.png</file>
<file alias="AirframeFlyingWing.png">src/AutoPilotPlugins/PX4/Images/AirframeFlyingWing.png</file>
<file alias="AirframeQuadRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorX.png</file>
<file alias="AirframeQuadRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorPlus.png</file>
<file alias="AirframeOctoRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorX.png</file>
<file alias="AirframeOctoRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeOctoRotorPlus.png</file>
<file alias="AirframeHexaRotorX.png">src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorX.png</file>
<file alias="AirframeHexaRotorPlus.png">src/AutoPilotPlugins/PX4/Images/AirframeHexaRotorPlus.png</file>
<file alias="AirframeQuadRotorH.png">src/AutoPilotPlugins/PX4/Images/AirframeQuadRotorH.png</file>
<file alias="AirframeSimulation.png">src/AutoPilotPlugins/PX4/Images/AirframeSimulation.png</file>
<file alias="QGroundControl/Controls/subMenuButtonImage.png">files/Setup/cogwheels.png</file>
<file alias="QGroundControl/Controls/SensorsComponentIcon.png">src/AutoPilotPlugins/PX4/Images/SensorsComponentIcon.png</file>
<file alias="QGroundControl/Controls/RadioComponentIcon.png">src/AutoPilotPlugins/PX4/Images/RadioComponentIcon.png</file>
......@@ -298,12 +318,14 @@
<file alias="QGroundControl/Controls/PowerComponentIcon.png">src/AutoPilotPlugins/PX4/Images/PowerComponentIcon.png</file>
<file alias="QGroundControl/Controls/FirmwareUpgradeIcon.png">src/VehicleSetup/FirmwareUpgradeIcon.png</file>
<file alias="QGroundControl/Controls/VehicleSummaryIcon.png">src/VehicleSetup/VehicleSummaryIcon.png</file>
<file alias="PowerComponentBattery_01cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_01cell.svg</file>
<file alias="PowerComponentBattery_02cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_02cell.svg</file>
<file alias="PowerComponentBattery_03cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_03cell.svg</file>
<file alias="PowerComponentBattery_04cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_04cell.svg</file>
<file alias="PowerComponentBattery_05cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_05cell.svg</file>
<file alias="PowerComponentBattery_06cell.svg">src/AutoPilotPlugins/PX4/Images/PowerComponentBattery_06cell.svg</file>
<file alias="MainToolBar.qml">src/ui/toolbar/MainToolBar.qml</file>
<file alias="FlightDisplay.qml">src/ui/flightdisplay/FlightDisplay.qml</file>
<file alias="QGroundControl/HUDControls/qmldir">src/ui/flightdisplay/components/qmldir</file>
......
......@@ -25,7 +25,7 @@
/// @author Don Gagne <don@thegagnes.com>
#include "AirframeComponent.h"
#include "QGCPX4AirframeConfig.h"
#include "QGCQmlWidgetHolder.h"
#if 0
// Broken by latest mavlink module changes. Not used yet. Comment out for now.
......@@ -179,7 +179,14 @@ QStringList AirframeComponent::paramFilterList(void) const
QWidget* AirframeComponent::setupWidget(void) const
{
return new QGCPX4AirframeConfig;
QGCQmlWidgetHolder* holder = new QGCQmlWidgetHolder();
Q_CHECK_PTR(holder);
holder->setAutoPilot(_autopilot);
holder->setSource(QUrl::fromUserInput("qrc:/qml/AirframeComponent.qml"));
return holder;
}
QUrl AirframeComponent::summaryQmlSource(void) const
......
/*=====================================================================
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/>.
======================================================================*/
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Controllers 1.0
Rectangle {
AirframeComponentController { id: controller }
QGCPalette { id: qgcPal; colorGroupEnabled: true }
color: qgcPal.window
Column {
anchors.fill: parent
QGCLabel {
text: "AIRFRAME CONFIG"
font.pointSize: 20
}
Item { height: 20; width: 10 } // spacer
Row {
width: parent.width
QGCLabel {
width: parent.width - applyButton.width
text: "Select you airframe type and specific vehicle bellow. Click 'Apply and Restart' when ready and your vehicle will be disconnected, rebooted to the new settings and re-connected."
wrapMode: Text.WordWrap
}
QGCButton {
id: applyButton
text: "Apply and Restart"
onClicked: { controller.changeAutostart() }
}
}
Item { height: 20; width: 10 } // spacer
Flow {
width: parent.width
spacing: 10
ExclusiveGroup {
id: airframeTypeExclusive
}
Repeater {
model: controller.airframeTypes
// Outer summary item rectangle
Rectangle {
readonly property real titleHeight: 30
readonly property real innerMargin: 10
width: 250
height: 200
color: qgcPal.windowShade
Rectangle {
id: title
width: parent.width
height: parent.titleHeight
color: qgcPal.windowShadeDark
Text {
anchors.fill: parent
color: qgcPal.buttonText
font.pixelSize: 12
text: modelData.name
verticalAlignment: TextEdit.AlignVCenter
horizontalAlignment: TextEdit.AlignHCenter
}
}
Image {
id: image
x: innerMargin
width: parent.width - (innerMargin * 2)
height: parent.height - title.height - combo.height - (innerMargin * 3)
anchors.topMargin: innerMargin
anchors.top: title.bottom
source: modelData.imageResource
fillMode: Image.PreserveAspectFit
smooth: true
}
QGCCheckBox {
id: airframeCheckBox
anchors.bottom: image.bottom
anchors.right: image.right
checked: modelData.name == controller.currentAirframeType
exclusiveGroup: airframeTypeExclusive
onCheckedChanged: {
if (checked && combo.currentIndex != -1) {
controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
}
}
}
QGCComboBox {
id: combo
objectName: modelData.airframeType + "ComboBox"
x: innerMargin
anchors.topMargin: innerMargin
anchors.top: image.bottom
width: parent.width - (innerMargin * 2)
model: modelData.airframes
currentIndex: (modelData.name == controller.currentAirframeType) ? controller.currentVehicleIndex : 0
onCurrentIndexChanged: {
if (airframeCheckBox.checked) {
controller.autostartId = modelData.airframes[currentIndex].autostartId
}
}
}
}
}
}
}
}
/*=====================================================================
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 "AirframeComponentAirframes.h"
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoStandardPlane[] = {
{ "Multiplex Easystar 1/2", 2100 },
{ "Hobbyking Bixler 1/2", 2101 },
{ "3DR Skywalker", 2102 },
{ "Skyhunter (1800 mm)", 2103 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoSimulation[] = {
{ "Plane (HilStar, X-Plane)", 1000 },
{ "Plane (Rascal, FlightGear)", 1004 },
{ "Quad X HIL", 1001 },
{ "Quad + HIL", 1003 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoFlyingWing[] = {
{ "Z-84 Wing Wing (845 mm)", 3033 },
{ "TBS Caipirinha (850 mm)", 3100 },
{ "Bormatec Camflyer Q (800 mm)", 3030 },
{ "FX-61 Phantom FPV (1550 mm)", 3031 },
{ "FX-79 Buffalo (2000 mm)", 3034 },
{ "Skywalker X5 (1180 mm)", 3032 },
{ "Viper v2 (3000 mm)", 3035 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoQuadRotorX[] = {
{ "DJI F330 8\" Quad", 4010 },
{ "DJI F450 10\" Quad", 4011 },
{ "X frame Quad UAVCAN", 4012 },
{ "AR.Drone Frame Quad", 4008 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoQuadRotorPlus[] = {
{ "Generic 10\" Quad +", 5001 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoHexaRotorX[] = {
{ "Standard 10\" Hexa X", 6001 },
{ "Coaxial 10\" Hexa X", 11001 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoHexaRotorPlus[] = {
{ "Standard 10\" Hexa", 7001 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoOctoRotorX[] = {
{ "Standard 10\" Octo", 8001 },
{ "Coaxial 10\" Octo", 12001 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoOctoRotorPlus[] = {
{ "Standard 10\" Octo", 9001 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeInfo_t AirframeComponentAirframes::_rgAirframeInfoQuadRotorH[] = {
{ "3DR Iris", 10016 },
{ "TBS Discovery", 10015 },
{ "SteadiDrone QU4D", 10017 },
{ NULL, 0 }
};
const AirframeComponentAirframes::AirframeType_t AirframeComponentAirframes::rgAirframeTypes[] = {
{ "Standard Airplane", "qrc:/qml/AirframeStandardPlane.png", AirframeComponentAirframes::_rgAirframeInfoStandardPlane },
{ "Flying Wing", "qrc:/qml/AirframeFlyingWing.png", AirframeComponentAirframes::_rgAirframeInfoFlyingWing },
{ "QuadRotor X", "qrc:/qml/AirframeQuadRotorX.png", AirframeComponentAirframes::_rgAirframeInfoQuadRotorX },
{ "QuadRotor +", "qrc:/qml/AirframeQuadRotorPlus.png", AirframeComponentAirframes::_rgAirframeInfoQuadRotorPlus },
{ "HexaRotor X", "qrc:/qml/AirframeHexaRotorX.png", AirframeComponentAirframes::_rgAirframeInfoHexaRotorX },
{ "HexaRotor +", "qrc:/qml/AirframeHexaRotorPlus.png", AirframeComponentAirframes::_rgAirframeInfoHexaRotorPlus },
{ "OctoRotor X", "qrc:/qml/AirframeOctoRotorX.png", AirframeComponentAirframes::_rgAirframeInfoOctoRotorX },
{ "OctoRotor +", "qrc:/qml/AirframeOctoRotorPlus.png", AirframeComponentAirframes::_rgAirframeInfoOctoRotorPlus },
{ "QuadRotor H", "qrc:/qml/AirframeQuadRotorH.png", AirframeComponentAirframes::_rgAirframeInfoQuadRotorH },
{ "Simulation", "qrc:/qml/AirframeSimulation.png", AirframeComponentAirframes::_rgAirframeInfoSimulation },
{ NULL, NULL, NULL }
};
/*=====================================================================
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 AIRFRAMECOMPONENTAIRFRAMES_H
#define AIRFRAMECOMPONENTAIRFRAMES_H
#include <QObject>
#include <QQuickItem>
#include <QList>
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
/// MVC Controller for AirframeComponent.qml.
class AirframeComponentAirframes
{
public:
typedef struct {
const char* name;
int autostartId;
} AirframeInfo_t;
typedef struct {
const char* name;
const char* imageResource;
const AirframeInfo_t* rgAirframeInfo;
} AirframeType_t;
public:
static const AirframeType_t rgAirframeTypes[];
private:
static const AirframeInfo_t _rgAirframeInfoStandardPlane[];
static const AirframeInfo_t _rgAirframeInfoFlyingWing[];
static const AirframeInfo_t _rgAirframeInfoQuadRotorX[];
static const AirframeInfo_t _rgAirframeInfoQuadRotorPlus[];
static const AirframeInfo_t _rgAirframeInfoOctoRotorX[];
static const AirframeInfo_t _rgAirframeInfoOctoRotorPlus[];
static const AirframeInfo_t _rgAirframeInfoHexaRotorX[];
static const AirframeInfo_t _rgAirframeInfoHexaRotorPlus[];
static const AirframeInfo_t _rgAirframeInfoQuadRotorH[];
static const AirframeInfo_t _rgAirframeInfoSimulation[];
};
#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 "AirframeComponentController.h"
#include "AirframeComponentAirframes.h"
#include "QGCMAVLink.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCApplication.h"
#include "QGCMessageBox.h"
#include <QVariant>
#include <QQmlProperty>
bool AirframeComponentController::_typesRegistered = false;
AirframeComponentController::AirframeComponentController(QObject* parent) :
QObject(parent),
_uas(NULL),
_autoPilotPlugin(NULL)
{
_uas = UASManager::instance()->getActiveUAS();
Q_ASSERT(_uas);
_autoPilotPlugin = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(_uas);
Q_ASSERT(_autoPilotPlugin);
Q_ASSERT(_autoPilotPlugin->pluginReady());
if (!_typesRegistered) {
_typesRegistered = true;
qmlRegisterUncreatableType<AirframeType>("QGroundControl.Controllers", 1, 0, "AiframeType", "Can only reference AirframeType");
qmlRegisterUncreatableType<Airframe>("QGroundControl.Controllers", 1, 0, "Aiframe", "Can only reference Airframe");
}
// Load up member variables
bool autostartFound = false;
_autostartId = _autoPilotPlugin->getParameterFact("SYS_AUTOSTART")->value().toInt();
for (const AirframeComponentAirframes::AirframeType_t* pType=&AirframeComponentAirframes::rgAirframeTypes[0]; pType->name != NULL; pType++) {
AirframeType* airframeType = new AirframeType(pType->name, pType->imageResource, this);
Q_CHECK_PTR(airframeType);
int index = 0;
for (const AirframeComponentAirframes::AirframeInfo_t* pInfo=&pType->rgAirframeInfo[0]; pInfo->name != NULL; pInfo++) {
if (_autostartId == pInfo->autostartId) {
Q_ASSERT(!autostartFound);
autostartFound = true;
_currentAirframeType = pType->name;
_currentVehicleName = pInfo->name;
_currentVehicleIndex = index;
}
airframeType->addAirframe(pInfo->name, pInfo->autostartId);
index++;
}
_airframeTypes.append(QVariant::fromValue(airframeType));
}
// FIXME: Should be a user error
Q_UNUSED(autostartFound);
Q_ASSERT(autostartFound);
}
AirframeComponentController::~AirframeComponentController()
{
}
void AirframeComponentController::changeAutostart(void)
{
LinkManager* linkManager = LinkManager::instance();
if (linkManager->getLinks().count() > 1) {
QGCMessageBox::warning("Airframe Config", "You cannot change airframe configuration while connected to multiple vehicles.");
return;
}
_autoPilotPlugin->getParameterFact("SYS_AUTOSTART")->setValue(_autostartId);
_autoPilotPlugin->getParameterFact("SYS_AUTOCONFIG")->setValue(1);
// Wait for the parameters to come back to us
qgcApp()->setOverrideCursor(Qt::WaitCursor);
int waitSeconds = 10;
bool success = false;
QGCUASParamManagerInterface* paramMgr = _uas->getParamManager();
while (true) {
if (paramMgr->countPendingParams() == 0) {
success = true;
break;
}
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
QGC::SLEEP::sleep(1);
if (--waitSeconds == 0) {
break;
}
}
if (!success) {
qgcApp()->restoreOverrideCursor();
QGCMessageBox::critical("Airframe Config", "Airframe Config parameters not received back from vehicle. Config has not been set.");
return;
}
_uas->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
QGC::SLEEP::sleep(1);
qgcApp()->processEvents(QEventLoop::ExcludeUserInputEvents);
qgcApp()->reconnectAfterWait(5);
}
AirframeType::AirframeType(const QString& name, const QString& imageResource, QObject* parent) :
QObject(parent),
_name(name),
_imageResource(imageResource)
{
}
AirframeType::~AirframeType()
{
}
void AirframeType::addAirframe(const QString& name, int autostartId)
{
Airframe* airframe = new Airframe(name, autostartId);
Q_CHECK_PTR(airframe);
_airframes.append(QVariant::fromValue(airframe));
}
Airframe::Airframe(const QString& name, int autostartId, QObject* parent) :
QObject(parent),
_name(name),
_autostartId(autostartId)
{
}
Airframe::~Airframe()
{
}
/*=====================================================================
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 AIRFRAMECOMPONENTCONTROLLER_H
#define AIRFRAMECOMPONENTCONTROLLER_H
#include <QObject>
#include <QQuickItem>
#include <QList>
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
/// MVC Controller for AirframeComponent.qml.
class AirframeComponentController : public QObject
{
Q_OBJECT
public:
AirframeComponentController(QObject* parent = NULL);
~AirframeComponentController();
Q_PROPERTY(QVariantList airframeTypes MEMBER _airframeTypes CONSTANT)
Q_PROPERTY(QString currentAirframeType MEMBER _currentAirframeType CONSTANT)
Q_PROPERTY(QString currentVehicleName MEMBER _currentVehicleName CONSTANT)
Q_PROPERTY(int currentVehicleIndex MEMBER _currentVehicleIndex CONSTANT)
Q_PROPERTY(int autostartId MEMBER _autostartId NOTIFY autostartIdChanged)
Q_INVOKABLE void changeAutostart(void);
int currentAirframeIndex(void);
void setCurrentAirframeIndex(int newIndex);
signals:
void autostartIdChanged(int newAutostartId);
private:
static bool _typesRegistered;
UASInterface* _uas;
AutoPilotPlugin* _autoPilotPlugin;
QVariantList _airframeTypes;
QString _currentAirframeType;
QString _currentVehicleName;
int _currentVehicleIndex;
int _autostartId;
};
class Airframe : public QObject
{
Q_OBJECT
public:
Airframe(const QString& name, int autostartId, QObject* parent = NULL);
~Airframe();
Q_PROPERTY(QString text MEMBER _name CONSTANT)
Q_PROPERTY(int autostartId MEMBER _autostartId CONSTANT)
private:
QString _name;
int _autostartId;
};
class AirframeType : public QObject
{
Q_OBJECT
public:
AirframeType(const QString& name, const QString& imageResource, QObject* parent = NULL);
~AirframeType();
Q_PROPERTY(QString name MEMBER _name CONSTANT)
Q_PROPERTY(QString imageResource MEMBER _imageResource CONSTANT)
Q_PROPERTY(QVariantList airframes MEMBER _airframes CONSTANT)
void addAirframe(const QString& name, int autostartId);
private:
QString _name;
QString _imageResource;
QVariantList _airframes;
};
#endif
......@@ -5,11 +5,14 @@ import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Controllers 1.0
Column {
anchors.fill: parent
anchors.margins: 8
AirframeComponentController { id: controller }
Row {
width: parent.width
......@@ -24,12 +27,24 @@ Column {
Row {
width: parent.width
QGCLabel { id: airframe; text: "Airframe:" }
QGCLabel { id: airframeType; text: "Airframe type:" }
QGCLabel {
property Fact fact: Fact { name: "SYS_AUTOSTART" }
horizontalAlignment: Text.AlignRight
width: parent.width - airframeType.contentWidth
text: fact.value == 0 ? "Setup required" : controller.currentAirframeType
}
}
Row {
width: parent.width
QGCLabel { id: vehicle; text: "Vehicle:" }
QGCLabel {
property Fact fact: Fact { name: "SYS_AUTOSTART" }
horizontalAlignment: Text.AlignRight
width: parent.width - airframe.contentWidth
text: fact.value == 0 ? "Setup required" : fact.value
width: parent.width - vehicle.contentWidth
text: fact.value == 0 ? "Setup required" : controller.currentVehicleName
}
}
}
......@@ -27,6 +27,7 @@
#include "QGCUASParamManagerInterface.h"
#include "PX4ParameterFacts.h"
#include "FlightModesComponentController.h"
#include "AirframeComponentController.h"
#include "QGCMessageBox.h"
/// @file
......@@ -76,6 +77,7 @@ PX4AutoPilotPlugin::PX4AutoPilotPlugin(UASInterface* uas, QObject* parent) :
Q_ASSERT(uas);
qmlRegisterType<FlightModesComponentController>("QGroundControl.Controllers", 1, 0, "FlightModesComponentController");
qmlRegisterType<AirframeComponentController>("QGroundControl.Controllers", 1, 0, "AirframeComponentController");
_parameterFacts = new PX4ParameterFacts(uas, this);
Q_CHECK_PTR(_parameterFacts);
......
......@@ -581,3 +581,26 @@ void QGCApplication::_loadCurrentStyle(void)
// Finally restore the cursor before returning.
restoreOverrideCursor();
}
void QGCApplication::reconnectAfterWait(int waitSeconds)
{
LinkManager* linkManager = LinkManager::instance();
Q_ASSERT(linkManager);
Q_ASSERT(linkManager->getLinks().count() == 1);
LinkInterface* link = linkManager->getLinks()[0];
// Save the link configuration so we can restart the link laster
_reconnectLinkConfig = linkManager->getLinks()[0]->getLinkConfiguration();
// Disconnect and wait
linkManager->disconnectLink(link);
QTimer::singleShot(waitSeconds * 1000, this, &QGCApplication::_reconnect);
}
void QGCApplication::_reconnect(void)
{
qgcApp()->restoreOverrideCursor();
LinkManager::instance()->createConnectedLink(_reconnectLinkConfig);
}
\ No newline at end of file
......@@ -34,6 +34,8 @@
#include <QApplication>
#include "LinkConfiguration.h"
#ifdef QGC_RTLAB_ENABLED
#include "OpalLink.h"
#endif
......@@ -93,6 +95,9 @@ public:
/// Set the current UI style
void setStyle(bool styleIsDark);
/// Disconnects the current link and waits for the specified number of seconds before reconnecting.
void reconnectAfterWait(int waitSeconds);
public slots:
/// You can connect to this slot to show an information message box from a different thread.
void informationMessageBoxOnMainThread(const QString& title, const QString& msg);
......@@ -132,6 +137,9 @@ public:
static QGCApplication* _app; ///< Our own singleton. Should be reference directly by qgcApp
private slots:
void _reconnect(void);
private:
void _createSingletons(void);
void _destroySingletons(void);
......@@ -153,6 +161,8 @@ private:
static const char* _lightStyleFile;
bool _styleIsDark; ///< true: dark style, false: light style
LinkConfiguration* _reconnectLinkConfig; ///< Configuration to reconnect for reconnectAfterWai
/// Unit Test have access to creating and destroying singletons
friend class UnitTest;
};
......
......@@ -169,9 +169,12 @@ bool LinkManager::disconnectAll()
{
bool allDisconnected = true;
foreach (SharedLinkInterface sharedLink, _links) {
// Make a copy so the list is modified out from under us
QList<SharedLinkInterface> links = _links;
foreach (SharedLinkInterface sharedLink, links) {
Q_ASSERT(sharedLink.data());
if (!sharedLink.data()->_disconnect()) {
if (!disconnectLink(sharedLink.data())) {
allDisconnected = false;
}
}
......
#include <QProgressDialog>
#include <QDebug>
#include <QTimer>
#include "QGCPX4AirframeConfig.h"
#include "ui_QGCPX4AirframeConfig.h"
#include "UASManager.h"
#include "LinkManager.h"
#include "UAS.h"
#include "QGC.h"
#include "QGCMessageBox.h"
QGCPX4AirframeConfig::QGCPX4AirframeConfig(QWidget *parent) :
QWidget(parent),
mav(NULL),
progress(NULL),
pendingParams(0),
configState(CONFIG_STATE_ABORT),
selectedId(-1),
ui(new Ui::QGCPX4AirframeConfig)
{
ui->setupUi(this);
// Fill the lists here manually in accordance with the list from:
// https://github.com/PX4/Firmware/blob/master/ROMFS/px4fmu_common/init.d/rcS
ui->simComboBox->addItem(tr("Plane (HilStar, X-Plane)"), 1000);
ui->simComboBox->addItem(tr("Plane (Rascal, FlightGear)"), 1004);
ui->simComboBox->addItem(tr("Quad X HIL"), 1001);
ui->simComboBox->addItem(tr("Quad + HIL"), 1003);
connect(ui->simPushButton, SIGNAL(clicked()), this, SLOT(simSelected()));
connect(ui->simComboBox, SIGNAL(activated(int)), this, SLOT(simSelected(int)));
ui->simPushButton->setEnabled(ui->simComboBox->count() > 0);
ui->planeComboBox->addItem(tr("Multiplex Easystar 1/2"), 2100);
ui->planeComboBox->addItem(tr("Hobbyking Bixler 1/2"), 2101);
ui->planeComboBox->addItem(tr("3DR Skywalker"), 2102);
ui->planeComboBox->addItem(tr("Skyhunter (1800 mm)"), 2103);
connect(ui->planePushButton, SIGNAL(clicked()), this, SLOT(planeSelected()));
connect(ui->planeComboBox, SIGNAL(activated(int)), this, SLOT(planeSelected(int)));
ui->planePushButton->setEnabled(ui->planeComboBox->count() > 0);
ui->flyingWingComboBox->addItem(tr("Z-84 Wing Wing (845 mm)"), 3033);
ui->flyingWingComboBox->addItem(tr("TBS Caipirinha (850 mm)"), 3100);
ui->flyingWingComboBox->addItem(tr("Bormatec Camflyer Q (800 mm)"), 3030);
ui->flyingWingComboBox->addItem(tr("FX-61 Phantom FPV (1550 mm)"), 3031);
ui->flyingWingComboBox->addItem(tr("FX-79 Buffalo (2000 mm)"), 3034);
ui->flyingWingComboBox->addItem(tr("Skywalker X5 (1180 mm)"), 3032);
ui->flyingWingComboBox->addItem(tr("Viper v2 (3000 mm)"), 3035);
connect(ui->flyingWingPushButton, SIGNAL(clicked()), this, SLOT(flyingWingSelected()));
connect(ui->flyingWingComboBox, SIGNAL(activated(int)), this, SLOT(flyingWingSelected(int)));
ui->quadXComboBox->addItem(tr("DJI F330 8\" Quad"), 4010);
ui->quadXComboBox->addItem(tr("DJI F450 10\" Quad"), 4011);
ui->quadXComboBox->addItem(tr("X frame Quad UAVCAN"), 4012);
ui->quadXComboBox->addItem(tr("AR.Drone Frame Quad"), 4008);
// ui->quadXComboBox->addItem(tr("DJI F330 with MK BLCTRL"), 4017);
// ui->quadXComboBox->addItem(tr("Mikrokopter X frame"), 4019);
connect(ui->quadXPushButton, SIGNAL(clicked()), this, SLOT(quadXSelected()));
connect(ui->quadXComboBox, SIGNAL(activated(int)), this, SLOT(quadXSelected(int)));
ui->quadXPushButton->setEnabled(ui->quadXComboBox->count() > 0);
ui->quadPlusComboBox->addItem(tr("Generic 10\" Quad +"), 5001);
// ui->quadXComboBox->addItem(tr("Mikrokopter + frame"), 5020);
connect(ui->quadPlusPushButton, SIGNAL(clicked()), this, SLOT(quadPlusSelected()));
connect(ui->quadPlusComboBox, SIGNAL(activated(int)), this, SLOT(quadPlusSelected(int)));
ui->quadPlusPushButton->setEnabled(ui->quadPlusComboBox->count() > 0);
ui->hexaXComboBox->addItem(tr("Standard 10\" Hexa X"), 6001);
ui->hexaXComboBox->addItem(tr("Coaxial 10\" Hexa X"), 11001);
connect(ui->hexaXPushButton, SIGNAL(clicked()), this, SLOT(hexaXSelected()));
connect(ui->hexaXComboBox, SIGNAL(activated(int)), this, SLOT(hexaXSelected(int)));
ui->hexaXPushButton->setEnabled(ui->hexaXComboBox->count() > 0);
ui->hexaPlusComboBox->addItem(tr("Standard 10\" Hexa"), 7001);
connect(ui->hexaPlusPushButton, SIGNAL(clicked()), this, SLOT(hexaPlusSelected()));
connect(ui->hexaPlusComboBox, SIGNAL(activated(int)), this, SLOT(hexaPlusSelected(int)));
ui->hexaPlusPushButton->setEnabled(ui->hexaPlusComboBox->count() > 0);
ui->octoXComboBox->addItem(tr("Standard 10\" Octo"), 8001);
ui->octoXComboBox->addItem(tr("Coaxial 10\" Octo"), 12001);
connect(ui->octoXPushButton, SIGNAL(clicked()), this, SLOT(octoXSelected()));
connect(ui->octoXComboBox, SIGNAL(activated(int)), this, SLOT(octoXSelected(int)));
ui->octoXPushButton->setEnabled(ui->octoXComboBox->count() > 0);
ui->octoPlusComboBox->addItem(tr("Standard 10\" Octo"), 9001);
connect(ui->octoPlusPushButton, SIGNAL(clicked()), this, SLOT(octoPlusSelected()));
connect(ui->octoPlusComboBox, SIGNAL(activated(int)), this, SLOT(octoPlusSelected(int)));
ui->octoPlusPushButton->setEnabled(ui->octoPlusComboBox->count() > 0);
ui->hComboBox->addItem(tr("3DR Iris"), 10016);
ui->hComboBox->addItem(tr("TBS Discovery"), 10015);
ui->hComboBox->addItem(tr("SteadiDrone QU4D"), 10017);
connect(ui->hPushButton, SIGNAL(clicked()), this, SLOT(hSelected()));
connect(ui->hComboBox, SIGNAL(activated(int)), this, SLOT(hSelected(int)));
ui->hPushButton->setEnabled(ui->hComboBox->count() > 0);
connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(applyAndReboot()));
connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(setActiveUAS(UASInterface*)));
uncheckAll();
setActiveUAS(UASManager::instance()->getActiveUAS());
}
void QGCPX4AirframeConfig::parameterChanged(int uas, int component, QString parameterName, QVariant value)
{
Q_UNUSED(uas);
Q_UNUSED(component);
if (parameterName.contains("SYS_AUTOSTART"))
{
int index = value.toInt();
if (index > 0) {
setAirframeID(index);
ui->statusLabel->setText(tr("Onboard start script ID: #%1").arg(index));
} else {
uncheckAll();
ui->statusLabel->setText(tr("System not configured for autostart."));
}
}
}
void QGCPX4AirframeConfig::setActiveUAS(UASInterface* uas)
{
if (mav)
{
disconnect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, SLOT(parameterChanged(int,int,QString,QVariant)));
mav = NULL;
}
if (!uas)
return;
mav = uas;
paramMgr = mav->getParamManager();
connect(mav, SIGNAL(parameterChanged(int,int,QString,QVariant)), this, SLOT(parameterChanged(int,int,QString,QVariant)));
// If the parameters are ready, we aren't going to get paramterChanged signals. So fake them in order to make the UI work.
if (uas->getParamManager()->parametersReady()) {
QVariant value;
static const char* param = "SYS_AUTOSTART";
QGCUASParamManagerInterface* paramMgr = uas->getParamManager();
QList<int> compIds = paramMgr->getComponentForParam(param);
Q_ASSERT(compIds.count() == 1);
paramMgr->getParameterValue(compIds[0], param, value);
parameterChanged(uas->getUASID(), compIds[0], param, value);
}
}
void QGCPX4AirframeConfig::uncheckAll()
{
ui->planePushButton->setChecked(false);
ui->flyingWingPushButton->setChecked(false);
ui->quadXPushButton->setChecked(false);
ui->quadPlusPushButton->setChecked(false);
ui->hexaXPushButton->setChecked(false);
ui->hexaPlusPushButton->setChecked(false);
ui->octoXPushButton->setChecked(false);
ui->octoPlusPushButton->setChecked(false);
ui->hPushButton->setChecked(false);
}
void QGCPX4AirframeConfig::setAirframeID(int id)
{
qDebug() << "setAirframeID" << id;
ui->statusLabel->setText(tr("Start script ID: #%1").arg(id));
selectedId = id;
// XXX too much boilerplate code here - this widget is really just
// a quick hack to get started
uncheckAll();
if (id >= 1000 && id < 2000)
{
ui->simPushButton->setChecked(true);
ui->simComboBox->setCurrentIndex(ui->simComboBox->findData(id));
ui->statusLabel->setText(tr("Selected simulation (ID: #%1)").arg(selectedId));
}
else if (id >= 2000 && id < 3000)
{
ui->planePushButton->setChecked(true);
ui->planeComboBox->setCurrentIndex(ui->planeComboBox->findData(id));
ui->statusLabel->setText(tr("Selected plane (ID: #%1)").arg(selectedId));
}
else if (id >= 3000 && id < 4000)
{
ui->flyingWingPushButton->setChecked(true);
ui->flyingWingComboBox->setCurrentIndex(ui->flyingWingComboBox->findData(id));
ui->statusLabel->setText(tr("Selected flying wing (ID: #%1)").arg(selectedId));
}
else if (id >= 4000 && id < 5000) {
ui->quadXPushButton->setChecked(true);
ui->quadXComboBox->setCurrentIndex(ui->quadXComboBox->findData(id));
ui->statusLabel->setText(tr("Selected quadrotor in X config (ID: #%1)").arg(selectedId));
}
else if (id >= 5000 && id < 6000) {
ui->quadPlusPushButton->setChecked(true);
ui->quadPlusComboBox->setCurrentIndex(ui->quadPlusComboBox->findData(id));
ui->statusLabel->setText(tr("Selected quadrotor in + config (ID: #%1)").arg(selectedId));
}
else if (id >= 6000 && id < 7000) {
ui->hexaXPushButton->setChecked(true);
ui->hexaXComboBox->setCurrentIndex(ui->hexaXComboBox->findData(id));
ui->statusLabel->setText(tr("Selected hexarotor in X config (ID: #%1)").arg(selectedId));
}
else if (id >= 7000 && id < 8000) {
ui->hexaPlusPushButton->setChecked(true);
ui->hexaPlusComboBox->setCurrentIndex(ui->hexaPlusComboBox->findData(id));
ui->statusLabel->setText(tr("Selected hexarotor in + config (ID: #%1)").arg(selectedId));
}
else if (id >= 8000 && id < 9000) {
ui->octoXPushButton->setChecked(true);
ui->octoXComboBox->setCurrentIndex(ui->octoXComboBox->findData(id));
ui->statusLabel->setText(tr("Selected octorotor in X config (ID: #%1)").arg(selectedId));
}
else if (id >= 9000 && id < 10000) {
ui->octoPlusPushButton->setChecked(true);
ui->octoPlusComboBox->setCurrentIndex(ui->octoPlusComboBox->findData(id));
ui->statusLabel->setText(tr("Selected octorotor in + config (ID: #%1)").arg(selectedId));
}
else if (id >= 10000 && id < 11000)
{
ui->hPushButton->setChecked(true);
ui->hComboBox->setCurrentIndex(ui->hComboBox->findData(id));
ui->statusLabel->setText(tr("Selected H frame multirotor (ID: #%1)").arg(selectedId));
}
}
void QGCPX4AirframeConfig::applyAndReboot()
{
// Guard against the case of an edit where we didn't receive all params yet
if (selectedId <= 0)
{
QGCMessageBox::warning(tr("No airframe selected"),
tr("Please select an airframe first."));
return;
}
if (!mav)
return;
if (paramMgr->countOnboardParams() == 0 &&
paramMgr->countPendingParams() == 0)
{
paramMgr->requestParameterList();
QGC::SLEEP::msleep(300);
}
QList<int> components = paramMgr->getComponentForParam("SYS_AUTOSTART");
// Guard against the case of an edit where we didn't receive all params yet
if (paramMgr->countPendingParams() > 0 || components.count() == 0)
{
QGCMessageBox::information(tr("Parameter sync with UAS not yet complete"),
tr("Please wait a few moments and retry"));
return;
}
// Guard against multiple components responding - this will never show in practice
if (components.count() != 1) {
QGCMessageBox::warning(tr("Invalid system setup detected"),
tr("None or more than one component advertised to provide the main system configuration option. This is an invalid system setup - please check your autopilot."));
return;
}
// This is really evil: 'fake' a thread by
// periodic work queue calls and clock
// through a small state machine
// ugh.. if we just had time to do this properly.
// To the reader who can't program and wants to whine:
// this is not beautiful, but technically completely
// sound. If you want to fix it, you'd be welcome
// to rebase the link, param manager and UI classes
// on a proper threading framework - which I'd love to do
// if I just had more time..
configState = CONFIG_STATE_SEND;
QTimer::singleShot(200, this, SLOT(checkConfigState()));
setEnabled(false);
}
void QGCPX4AirframeConfig::checkConfigState()
{
if (configState == CONFIG_STATE_SEND)
{
QList<int> components = paramMgr->getComponentForParam("SYS_AUTOSTART");
qDebug() << "Setting comp" << components.first() << "SYS_AUTOSTART" << (qint32)selectedId;
paramMgr->setPendingParam(components.first(),"SYS_AUTOSTART", (qint32)selectedId);
//need to set autoconfig in order for PX4 to pick up the selected airframe params
if (ui->defaultGainsCheckBox->checkState() == Qt::Checked)
setAutoConfig(true);
// Send pending params and then write them to persistent storage when done
paramMgr->sendPendingParameters(true);
configState = CONFIG_STATE_WAIT_PENDING;
pendingParams = 0;
QTimer::singleShot(2000, this, SLOT(checkConfigState()));
return;
}
if (configState == CONFIG_STATE_WAIT_PENDING) {
// Guard against the case of an edit where we didn't receive all params yet
if (paramMgr->countPendingParams() > 0)
{
if (pendingParams == 0) {
pendingParams = paramMgr->countPendingParams();
if (progress)
delete progress;
progress = new QProgressDialog("Writing parameters", "Abort Send", 0, pendingParams, this);
progress->setWindowModality(Qt::WindowModal);
progress->setMinimumDuration(2000);
}
qDebug() << "PENDING" << paramMgr->countPendingParams() << "PROGRESS" << pendingParams - paramMgr->countPendingParams();
progress->setValue(pendingParams - paramMgr->countPendingParams());
if (progress->wasCanceled()) {
configState = CONFIG_STATE_ABORT;
setEnabled(true);
pendingParams = 0;
return;
}
} else {
pendingParams = 0;
configState = CONFIG_STATE_REBOOT;
}
qDebug() << "PENDING PARAMS WAIT PENDING: " << paramMgr->countPendingParams();
QTimer::singleShot(1000, this, SLOT(checkConfigState()));
return;
}
if (configState == CONFIG_STATE_REBOOT) {
// Reboot
//TODO right now this relies upon the above send & persist finishing before the reboot command is received...
unsigned pendingMax = 17;
qDebug() << "PENDING PARAMS REBOOT BEFORE" << pendingParams;
if (pendingParams == 0) {
pendingParams = 1;
if (progress)
delete progress;
progress = new QProgressDialog("Waiting for autopilot reboot", "Abort", 0, pendingMax, this);
progress->setWindowModality(Qt::WindowModal);
qDebug() << "Waiting for reboot, pending" << pendingParams;
} else {
if (progress->wasCanceled()) {
configState = CONFIG_STATE_ABORT;
setEnabled(true);
pendingParams = 0;
return;
}
}
if (pendingParams == 3) {
qDebug() << "REQUESTING REBOOT";
mav->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
mav->executeCommand(MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, 1, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0);
}
if (pendingParams == 4) {
qDebug() << "DISCONNECT AIRFRAME";
LinkManager::instance()->disconnectAll();
}
if (pendingParams == 14) {
qDebug() << "CONNECT AIRFRAME";
LinkManager::instance()->connectAll();
}
if (pendingParams < pendingMax) {
progress->setValue(pendingParams);
QTimer::singleShot(1000, this, SLOT(checkConfigState()));
} else {
paramMgr->requestParameterList();
progress->setValue(pendingMax);
configState = CONFIG_STATE_ABORT;
pendingParams = 0;
setEnabled(true);
return;
}
qDebug() << "PENDING PARAMS REBOOT AFTER:" << pendingParams;
pendingParams++;
return;
}
}
void QGCPX4AirframeConfig::setAutoConfig(bool enabled)
{
if (!mav)
return;
paramMgr->setPendingParam(0, "SYS_AUTOCONFIG", (qint32) ((enabled) ? 1 : 0));
}
void QGCPX4AirframeConfig::simSelected()
{
simSelected(ui->simComboBox->currentIndex());
}
void QGCPX4AirframeConfig::simSelected(int index)
{
int system_index = ui->simComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::flyingWingSelected()
{
flyingWingSelected(ui->flyingWingComboBox->currentIndex());
}
void QGCPX4AirframeConfig::flyingWingSelected(int index)
{
int system_index = ui->flyingWingComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::planeSelected()
{
planeSelected(ui->planeComboBox->currentIndex());
}
void QGCPX4AirframeConfig::planeSelected(int index)
{
int system_index = ui->planeComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::quadXSelected()
{
quadXSelected(ui->quadXComboBox->currentIndex());
}
void QGCPX4AirframeConfig::quadXSelected(int index)
{
int system_index = ui->quadXComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::quadPlusSelected()
{
quadPlusSelected(ui->quadPlusComboBox->currentIndex());
}
void QGCPX4AirframeConfig::quadPlusSelected(int index)
{
int system_index = ui->quadPlusComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::hexaXSelected()
{
hexaXSelected(ui->hexaXComboBox->currentIndex());
}
void QGCPX4AirframeConfig::hexaXSelected(int index)
{
int system_index = ui->hexaXComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::hexaPlusSelected()
{
hexaPlusSelected(ui->hexaPlusComboBox->currentIndex());
}
void QGCPX4AirframeConfig::hexaPlusSelected(int index)
{
int system_index = ui->hexaPlusComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::octoXSelected()
{
octoXSelected(ui->octoXComboBox->currentIndex());
}
void QGCPX4AirframeConfig::octoXSelected(int index)
{
int system_index = ui->octoXComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::octoPlusSelected()
{
octoPlusSelected(ui->octoPlusComboBox->currentIndex());
}
void QGCPX4AirframeConfig::octoPlusSelected(int index)
{
int system_index = ui->octoPlusComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
void QGCPX4AirframeConfig::hSelected()
{
hSelected(ui->hComboBox->currentIndex());
}
void QGCPX4AirframeConfig::hSelected(int index)
{
int system_index = ui->hComboBox->itemData(index).toInt();
setAirframeID(system_index);
}
QGCPX4AirframeConfig::~QGCPX4AirframeConfig()
{
delete ui;
}
#ifndef QGCPX4AIRFRAMECONFIG_H
#define QGCPX4AIRFRAMECONFIG_H
#include <QWidget>
#include <UASInterface.h>
class QProgressDialog;
namespace Ui {
class QGCPX4AirframeConfig;
}
class QGCPX4AirframeConfig : public QWidget
{
Q_OBJECT
public:
explicit QGCPX4AirframeConfig(QWidget *parent = 0);
~QGCPX4AirframeConfig();
public slots:
/**
* @brief Set the system currently operated on by this widget
* @param uas The currently active / configured system
*/
void setActiveUAS(UASInterface* uas);
/**
* @brief Handle parameter changes
* @param uas
* @param component
* @param parameterName
* @param value
*/
void parameterChanged(int uas, int component, QString parameterName, QVariant value);
/**
* @brief Quadrotor in X configuration has been selected
*/
void quadXSelected();
/**
* @brief Quadrotor in X configuration has been selected with sub-type
* @param index The autostart index which maps to a particular sub-type
*/
void quadXSelected(int index);
void simSelected();
void simSelected(int index);
void planeSelected();
void planeSelected(int index);
void flyingWingSelected();
void flyingWingSelected(int index);
void quadPlusSelected();
void quadPlusSelected(int index);
void hexaXSelected();
void hexaXSelected(int index);
void hexaPlusSelected();
void hexaPlusSelected(int index);
void octoXSelected();
void octoXSelected(int index);
void octoPlusSelected();
void octoPlusSelected(int index);
void hSelected();
void hSelected(int index);
/**
* @brief Apply changes and reboot system
*/
void applyAndReboot();
protected slots:
void checkConfigState();
protected:
/**
* @brief Set the ID of the current airframe
* @param id the ID as defined by the PX4 SYS_AUTOSTART enum
*/
void setAirframeID(int id);
/**
* @brief Enable automatic configuration
* @param enabled If true, the system sets the default gains for this platform on the next boot
*/
void setAutoConfig(bool enabled);
void uncheckAll();
enum CONFIG_STATE {
CONFIG_STATE_ABORT = 0,
CONFIG_STATE_SEND,
CONFIG_STATE_WAIT_PENDING,
CONFIG_STATE_REBOOT
};
private:
UASInterface* mav;
QGCUASParamManagerInterface *paramMgr;
QProgressDialog* progress;
unsigned pendingParams;
enum CONFIG_STATE configState;
int selectedId;
Ui::QGCPX4AirframeConfig *ui;
};
#endif // QGCPX4AIRFRAMECONFIG_H
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QGCPX4AirframeConfig</class>
<widget class="QWidget" name="QGCPX4AirframeConfig">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>802</width>
<height>471</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>802</width>
<height>471</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="2">
<widget class="QCheckBox" name="defaultGainsCheckBox">
<property name="text">
<string>Set default airframe settings</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QScrollArea" name="scrollArea">
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>761</width>
<height>611</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="planePushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/plane_aert.png</normaloff>:/files/images/px4/airframes/plane_aert.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="planeComboBox"/>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Standard Plane</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="flyingWingPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/flying_wing.png</normaloff>:/files/images/px4/airframes/flying_wing.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="flyingWingComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Flying Wing</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="quadXPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/quad_x.png</normaloff>:/files/images/px4/airframes/quad_x.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="quadXComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Quadrotor X</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="3">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QPushButton" name="quadPlusPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/quad_+.png</normaloff>:/files/images/px4/airframes/quad_+.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="quadPlusComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Quadrotor +</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QPushButton" name="hexaXPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/hexa_x.png</normaloff>:/files/images/px4/airframes/hexa_x.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="hexaXComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Hexarotor X</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QPushButton" name="hexaPlusPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/hexa_+.png</normaloff>:/files/images/px4/airframes/hexa_+.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="hexaPlusComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Hexarotor +</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="2">
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QPushButton" name="octoXPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/octo_x.png</normaloff>:/files/images/px4/airframes/octo_x.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="octoXComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Octorotor X</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="3">
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QPushButton" name="octoPlusPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/octo_+.png</normaloff>:/files/images/px4/airframes/octo_+.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="octoPlusComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Octorotor +</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QPushButton" name="hPushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../qgroundcontrol.qrc">
<normaloff>:/files/images/px4/airframes/quad_h.png</normaloff>:/files/images/px4/airframes/quad_h.png</iconset>
</property>
<property name="iconSize">
<size>
<width>120</width>
<height>120</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="hComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>H Frame</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QPushButton" name="simPushButton">
<property name="text">
<string>Simulation Setup</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="simComboBox"/>
</item>
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>Simulation / Experimental</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="applyButton">
<property name="text">
<string>Apply and Restart</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="statusLabel">
<property name="text">
<string>No changes values</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources>
<include location="../../../qgroundcontrol.qrc"/>
</resources>
<connections/>
</ui>
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