Commit 4362d4e5 authored by Gus Grubba's avatar Gus Grubba

Merge branch 'Stable_V3.2' of https://github.com/mavlink/qgroundcontrol into cameraControl

# Conflicts:
#	src/Vehicle/Vehicle.h
parents 54dd2f7a 124af659
......@@ -35,7 +35,7 @@ installer {
QMAKE_POST_LINK += && hdiutil create -verbose -stretch 4g -layout SPUD -srcfolder $${DESTDIR}/$${TARGET}.app -volname $${TARGET} $${DESTDIR}/package/$${TARGET}.dmg
}
WindowsBuild {
QMAKE_POST_LINK += $$escape_expand(\\n) cd $$BASEDIR_WIN && $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /DAPPNAME="\"$${QGC_APP_NAME}\"" /DEXENAME="\"$${TARGET}\"" /DORGNAME="\"$${QGC_ORG_NAME}\"" /DDESTDIR=$${DESTDIR} /NOCD "\"/XOutFile $${DESTDIR_WIN}\\$${TARGET}-installer.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi")
QMAKE_POST_LINK += $$escape_expand(\\n) cd $$BASEDIR_WIN && $$quote("\"C:\\Program Files \(x86\)\\NSIS\\makensis.exe\"" /DINSTALLER_ICON="\"$${QGC_INSTALLER_ICON}\"" /DHEADER_BITMAP="\"$${QGC_INSTALLER_HEADER_BITMAP}\"" /DAPPNAME="\"$${QGC_APP_NAME}\"" /DEXENAME="\"$${TARGET}\"" /DORGNAME="\"$${QGC_ORG_NAME}\"" /DDESTDIR=$${DESTDIR} /NOCD "\"/XOutFile $${DESTDIR_WIN}\\$${TARGET}-installer.exe\"" "$$BASEDIR_WIN\\deploy\\qgroundcontrol_installer.nsi")
OTHER_FILES += deploy/qgroundcontrol_installer.nsi
}
LinuxBuild {
......
......@@ -44,9 +44,9 @@ InstallDir "$PROGRAMFILES\${APPNAME}"
SetCompressor /SOLID /FINAL lzma
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "installheader.bmp";
!define MUI_ICON "WindowsQGC.ico";
!define MUI_UNICON "WindowsQGC.ico";
!define MUI_HEADERIMAGE_BITMAP "${HEADER_BITMAP}";
!define MUI_ICON "${INSTALLER_ICON}";
!define MUI_UNICON "${INSTALLER_ICON}";
!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
!insertmacro MUI_PAGE_DIRECTORY
......
......@@ -85,6 +85,8 @@
<string>Ground Station Location</string>
<key>UILaunchStoryboardName</key>
<string>QGCLaunchScreen</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>QGroundControl would like to use bluetooth.</string>
<key>UIRequiresFullScreen</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
......
......@@ -55,6 +55,8 @@ iOSBuild {
count(APP_ERROR, 1) {
error("Error building .plist file. 'ForAppStore' builds are only possible through the official build system.")
}
QT += qml-private
CONFIG += qtquickcompiler
QMAKE_INFO_PLIST = $${BASEDIR}/ios/iOSForAppStore-Info.plist
OTHER_FILES += $${BASEDIR}/ios/iOSForAppStore-Info.plist
} else {
......@@ -82,6 +84,10 @@ QGC_ORG_DOMAIN = "org.qgroundcontrol"
QGC_APP_DESCRIPTION = "Open source ground control app provided by QGroundControl dev team"
QGC_APP_COPYRIGHT = "Copyright (C) 2017 QGroundControl Development Team. All rights reserved."
WindowsBuild {
QGC_INSTALLER_ICON = "WindowsQGC.ico"
QGC_INSTALLER_HEADER_BITMAP = "installheader.bmp"
}
# Load additional config flags from user_config.pri
exists(user_config.pri):infile(user_config.pri, CONFIG) {
......
......@@ -74,6 +74,7 @@
<file alias="QGroundControl/Controls/MissionItemStatus.qml">src/PlanView/MissionItemStatus.qml</file>
<file alias="QGroundControl/Controls/ModeSwitchDisplay.qml">src/QmlControls/ModeSwitchDisplay.qml</file>
<file alias="QGroundControl/Controls/MultiRotorMotorDisplay.qml">src/QmlControls/MultiRotorMotorDisplay.qml</file>
<file alias="QGroundControl/Controls/NoMouseThroughRectangle.qml">src/QmlControls/NoMouseThroughRectangle.qml</file>
<file alias="QGroundControl/Controls/OfflineMapButton.qml">src/QmlControls/OfflineMapButton.qml</file>
<file alias="QGroundControl/Controls/ParameterEditor.qml">src/QmlControls/ParameterEditor.qml</file>
<file alias="QGroundControl/Controls/ParameterEditorDialog.qml">src/QmlControls/ParameterEditorDialog.qml</file>
......
......@@ -60,24 +60,6 @@ SetupPage {
max: 0.25
step: 0.01
}
ListElement {
title: qsTr("Altitude control sensitivity")
description: qsTr("Slide to the left to make altitude control smoother and less twitchy. Slide to the right to make altitude control more accurate and more aggressive.")
param: "MPC_Z_FF"
min: 0
max: 1.0
step: 0.1
}
ListElement {
title: qsTr("Position control sensitivity")
description: qsTr("Slide to the left to make flight in position control mode smoother and less twitchy. Slide to the right to make position control more accurate and more aggressive.")
param: "MPC_XY_FF"
min: 0
max: 1.0
step: 0.1
}
}
}
} // Component
......
......@@ -44,23 +44,6 @@ SetupPage {
step: 0.01
}
ListElement {
title: qsTr("Hover Altitude control sensitivity")
description: qsTr("Slide to the left to make altitude control during hover smoother and less twitchy. Slide to the right to make altitude control more accurate and more aggressive.")
param: "MPC_Z_FF"
min: 0
max: 1.0
step: 0.1
}
ListElement {
title: qsTr("Hover Position control sensitivity")
description: qsTr("Slide to the left to make flight during hover in position control mode smoother and less twitchy. Slide to the right to make position control more accurate and more aggressive.")
param: "MPC_XY_FF"
min: 0
max: 1.0
step: 0.1
}
ListElement {
title: qsTr("Plane Roll sensitivity")
description: qsTr("Slide to the left to make roll control faster and more accurate. Slide to the right if roll oscillates or is too twitchy.")
......
......@@ -17,16 +17,18 @@ CameraMetaData::CameraMetaData(const QString& name,
double focalLength,
bool landscape,
bool fixedOrientation,
double minTriggerInterval,
QObject* parent)
: QObject(parent)
, _name(name)
, _sensorWidth(sensorWidth)
, _sensorHeight(sensorHeight)
, _imageWidth(imageWidth)
, _imageHeight(imageHeight)
, _focalLength(focalLength)
, _landscape(landscape)
, _fixedOrientation(fixedOrientation)
: QObject (parent)
, _name (name)
, _sensorWidth (sensorWidth)
, _sensorHeight (sensorHeight)
, _imageWidth (imageWidth)
, _imageHeight (imageHeight)
, _focalLength (focalLength)
, _landscape (landscape)
, _fixedOrientation (fixedOrientation)
, _minTriggerInterval (minTriggerInterval)
{
}
......@@ -26,6 +26,7 @@ public:
double focalLength,
bool landscape,
bool fixedOrientation,
double minTriggerInterval,
QObject* parent = NULL);
Q_PROPERTY(QString name MEMBER _name CONSTANT) ///< Camera name
......@@ -36,6 +37,7 @@ public:
Q_PROPERTY(double focalLength MEMBER _focalLength CONSTANT) ///< Focal length in millimeters
Q_PROPERTY(bool landscape MEMBER _landscape CONSTANT) ///< true: camera is in landscape orientation
Q_PROPERTY(bool fixedOrientation MEMBER _fixedOrientation CONSTANT) ///< true: camera is in fixed orientation
Q_PROPERTY(double minTriggerInterval MEMBER _minTriggerInterval CONSTANT) ///< Minimum time in seconds between each photo taken, 0 for not specified
private:
QString _name;
......@@ -46,6 +48,7 @@ private:
double _focalLength;
bool _landscape;
bool _fixedOrientation;
double _minTriggerInterval;
};
#endif
......@@ -354,6 +354,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
16,
true,
false,
0,
this);
_cameraList.append(QVariant::fromValue(metaData));
......@@ -365,6 +366,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
5.2,
true,
false,
0,
this);
_cameraList.append(QVariant::fromValue(metaData));
......@@ -376,6 +378,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
10.2,
true,
false,
0,
this);
_cameraList.append(QVariant::fromValue(metaData));
......@@ -387,6 +390,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
4.5,
true,
false,
0,
this);
metaData = new CameraMetaData(tr("Canon EOS-M 22mm"),
......@@ -397,6 +401,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
22,
true,
false,
0,
this);
_cameraList.append(QVariant::fromValue(metaData));
......@@ -408,6 +413,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
16,
true,
false,
0,
this);
_cameraList.append(QVariant::fromValue(metaData));
......@@ -419,6 +425,7 @@ const QVariantList& FirmwarePlugin::cameraList(const Vehicle* vehicle)
10.4,
true,
false,
0,
this);
_cameraList.append(QVariant::fromValue(metaData));
}
......@@ -478,7 +485,7 @@ bool FirmwarePlugin::_setFlightModeAndValidate(Vehicle* vehicle, const QString&
vehicle->setFlightMode(flightMode);
// Wait for vehicle to return flight mode
for (int i=0; i<30; i++) {
for (int i=0; i<13; i++) {
if (vehicle->flightMode() == flightMode) {
flightModeChanged = true;
break;
......
......@@ -76,7 +76,8 @@ PX4FirmwarePlugin::PX4FirmwarePlugin(void)
{ PX4_CUSTOM_MAIN_MODE_RATTITUDE, 0, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_ALTCTL, 0, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_POSCTL, 0, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_SIMPLE, 0, true, false, true },
// simple can't be set by the user right now
{ PX4_CUSTOM_MAIN_MODE_SIMPLE, 0, false, false, true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_LOITER, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_MISSION, true, true, true },
{ PX4_CUSTOM_MAIN_MODE_AUTO, PX4_CUSTOM_SUB_MODE_AUTO_RTL, true, true, true },
......@@ -460,12 +461,15 @@ void PX4FirmwarePlugin::guidedModeChangeAltitude(Vehicle* vehicle, double altitu
void PX4FirmwarePlugin::startMission(Vehicle* vehicle)
{
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle failed to arm."));
return;
}
_setFlightModeAndValidate(vehicle, missionFlightMode());
if (_setFlightModeAndValidate(vehicle, missionFlightMode())) {
if (!_armVehicleAndValidate(vehicle)) {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle rejected arming."));
return;
}
} else {
qgcApp()->showMessage(tr("Unable to start mission: Vehicle not ready."));
}
}
void PX4FirmwarePlugin::setGuidedMode(Vehicle* vehicle, bool guidedMode)
......
......@@ -1234,6 +1234,14 @@ This parameter is used when the magnetometer fusion method is set automatically
<decimal>2</decimal>
<scope>modules/ekf2</scope>
</parameter>
<parameter default="0.05" name="EKF2_RNG_SFE" type="FLOAT">
<short_desc>Range finder range dependant noise scaler</short_desc>
<long_desc>Specifies the increase in range finder noise with range.</long_desc>
<min>0.0</min>
<max>0.2</max>
<unit>m/m</unit>
<scope>modules/ekf2</scope>
</parameter>
<parameter default="5.0" name="EKF2_RNG_GATE" type="FLOAT">
<short_desc>Gate size for range finder fusion</short_desc>
<min>1.0</min>
......@@ -1522,6 +1530,29 @@ Smaller values make the saved mag bias learn slower from flight to flight. Large
<decimal>2</decimal>
<scope>modules/ekf2</scope>
</parameter>
<parameter default="0" name="EKF2_RNG_AID" type="INT32">
<short_desc>Range sensor aid</short_desc>
<long_desc>If this parameter is enabled then the estimator will make use of the range finder measurements to estimate it's height even if range sensor is not the primary height source. It will only do so if conditions for range measurement fusion are met.</long_desc>
<scope>modules/ekf2</scope>
<values>
<value code="1">Range aid enabled</value>
<value code="0">Range aid disabled</value>
</values>
</parameter>
<parameter default="1.0" name="EKF2_RNG_A_VMAX" type="FLOAT">
<short_desc>Maximum horizontal velocity allowed for range aid mode</short_desc>
<long_desc>If the vehicle horizontal speed exceeds this value then the estimator will not fuse range measurements to estimate it's height. This only applies when range aid mode is activated (EKF2_RNG_AID = enabled).</long_desc>
<min>0.1</min>
<max>2</max>
<scope>modules/ekf2</scope>
</parameter>
<parameter default="5.0" name="EKF2_RNG_A_HMAX" type="FLOAT">
<short_desc>Maximum absolute altitude (height above ground level) allowed for range aid mode</short_desc>
<long_desc>If the vehicle absolute altitude exceeds this value then the estimator will not fuse range measurements to estimate it's height. This only applies when range aid mode is activated (EKF2_RNG_AID = enabled).</long_desc>
<min>1.0</min>
<max>10.0</max>
<scope>modules/ekf2</scope>
</parameter>
</group>
<group name="FW Attitude Control">
<parameter default="0.4" name="FW_R_TC" type="FLOAT">
......@@ -2638,6 +2669,21 @@ but also ignore less noise</short_desc>
<value code="0">Disable</value>
</values>
</parameter>
<parameter default="7" name="GPS_UBX_DYNMODEL" type="INT32">
<short_desc>u-blox GPS dynamic platform model</short_desc>
<long_desc>u-blox receivers support different dynamic platform models to adjust the navigation engine to the expected application environment.</long_desc>
<min>0</min>
<max>9</max>
<reboot_required>true</reboot_required>
<scope>drivers/gps</scope>
<values>
<value code="8">airborne with &lt;4g acceleration</value>
<value code="2">stationary</value>
<value code="4">automotive</value>
<value code="7">airborne with &lt;2g acceleration</value>
<value code="6">airborne with &lt;1g acceleration</value>
</values>
</parameter>
</group>
<group name="GPS Failure Navigation">
<parameter default="30.0" name="NAV_GPSF_LT" type="FLOAT">
......@@ -3983,14 +4029,6 @@ if required for the gimbal (only in AUX output mode)</short_desc>
<unit>m/s</unit>
<scope>modules/mc_pos_control</scope>
</parameter>
<parameter default="0.5" name="MPC_Z_FF" type="FLOAT">
<short_desc>Vertical velocity feed forward</short_desc>
<long_desc>Feed forward weight for altitude control in stabilized modes (ALTCTRL, POSCTRL). 0 will give slow responce and no overshot, 1 - fast responce and big overshot.</long_desc>
<min>0.0</min>
<max>1.0</max>
<decimal>2</decimal>
<scope>modules/mc_pos_control</scope>
</parameter>
<parameter default="0.95" name="MPC_XY_P" type="FLOAT">
<short_desc>Proportional gain for horizontal position error</short_desc>
<min>0.0</min>
......@@ -4059,14 +4097,6 @@ if required for the gimbal (only in AUX output mode)</short_desc>
<increment>1</increment>
<scope>modules/mc_pos_control</scope>
</parameter>
<parameter default="0.5" name="MPC_XY_FF" type="FLOAT">
<short_desc>Horizontal velocity feed forward</short_desc>
<long_desc>Feed forward weight for position control in position control mode (POSCTRL). 0 will give slow responce and no overshot, 1 - fast responce and big overshot.</long_desc>
<min>0.0</min>
<max>1.0</max>
<decimal>2</decimal>
<scope>modules/mc_pos_control</scope>
</parameter>
<parameter default="45.0" name="MPC_TILTMAX_AIR" type="FLOAT">
<short_desc>Maximum tilt angle in air</short_desc>
<long_desc>Limits maximum tilt in AUTO and POSCTRL modes during flight.</long_desc>
......@@ -7291,7 +7321,8 @@ This is used for gathering replay logs for the ekf2 module</short_desc>
<scope>modules/sensors</scope>
</parameter>
<parameter default="0" name="SENS_EXT_MAG" type="INT32">
<short_desc>Select primary magnetometer</short_desc>
<short_desc>Select primary magnetometer.
DEPRECATED, only used on V1 hardware</short_desc>
<min>0</min>
<max>2</max>
<scope>modules/sensors</scope>
......
......@@ -34,7 +34,7 @@
/**
* @file px4_custom_mode.h
* PX4 custom flight modes
*
* Copied from PX4 2017-07-08 - https://github.com/PX4/Firmware/blob/master/src/modules/commander/px4_custom_mode.h#L45
*/
#ifndef PX4_CUSTOM_MODE_H_
......@@ -50,8 +50,8 @@ enum PX4_CUSTOM_MAIN_MODE {
PX4_CUSTOM_MAIN_MODE_ACRO,
PX4_CUSTOM_MAIN_MODE_OFFBOARD,
PX4_CUSTOM_MAIN_MODE_STABILIZED,
PX4_CUSTOM_MAIN_MODE_RATTITUDE,
PX4_CUSTOM_MAIN_MODE_SIMPLE
PX4_CUSTOM_MAIN_MODE_RATTITUDE,
PX4_CUSTOM_MAIN_MODE_SIMPLE /* unused, but reserved for future use */
};
enum PX4_CUSTOM_SUB_MODE_AUTO {
......
......@@ -542,6 +542,7 @@ QGCView {
id: guidedActionsController
missionController: _missionController
confirmDialog: guidedActionConfirm
actionList: guidedActionList
altitudeSlider: _altitudeSlider
z: _flightVideoPipControl.z + 1
......
......@@ -240,8 +240,9 @@ FlightMap {
anchorPoint.y: sourceItem.anchorPointY
sourceItem: MissionItemIndexLabel {
checked: true
label: qsTr("G", "Goto here waypoint") // second string is translator's hint.
checked: true
index: -1
label: qsTr("Goto here", "Goto here waypoint")
}
}
......@@ -260,7 +261,7 @@ FlightMap {
anchors.fill: parent
onClicked: {
if (guidedActionsController.showGotoLocation) {
if (guidedActionsController.showGotoLocation && !guidedActionsController.guidedUIVisible) {
_gotoHereCoordinate = flightMap.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
guidedActionsController.confirmAction(guidedActionsController.actionGoto, _gotoHereCoordinate)
}
......
......@@ -16,7 +16,7 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
/// Guided actions confirmation dialog
Rectangle {
NoMouseThroughRectangle {
id: _root
border.color: qgcPal.alertBorder
border.width: 1
......
......@@ -17,7 +17,7 @@ import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
/// Dialog showing list of available guided actions
Rectangle {
NoMouseThroughRectangle {
id: _root
width: actionColumn.width + (_margins * 4)
height: actionColumn.height + (_margins * 4)
......
......@@ -29,6 +29,7 @@ Item {
property var missionController
property var confirmDialog
property var actionList
property var altitudeSlider
readonly property string emergencyStopTitle: qsTr("Emergency Stop")
......@@ -89,13 +90,15 @@ Item {
property bool showLand: _activeVehicle && _activeVehicle.guidedModeSupported && _vehicleArmed && !_activeVehicle.fixedWing && !_vehicleInLandMode
property bool showStartMission: _activeVehicle && _missionAvailable && !_missionActive && !_vehicleFlying
property bool showContinueMission: _activeVehicle && _missionAvailable && !_missionActive && _vehicleFlying && (_currentMissionIndex < missionController.visualItems.count - 1)
property bool showResumeMission: _activeVehicle && !_vehicleFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 2)
property bool showResumeMission: _activeVehicle && !_vehicleArmed && _vehicleWasFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < missionController.visualItems.count - 2)
property bool showPause: _activeVehicle && _vehicleArmed && _activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused
property bool showChangeAlt: (_activeVehicle && _vehicleFlying) && _activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive
property bool showOrbit: !_hideOrbit && _activeVehicle && _vehicleFlying && _activeVehicle.orbitModeSupported && _vehicleArmed && !_missionActive
property bool showLandAbort: _activeVehicle && _vehicleFlying && _activeVehicle.fixedWing && _vehicleLanding
property bool showGotoLocation: _activeVehicle && _activeVehicle.guidedMode && _vehicleFlying
property bool guidedUIVisible: guidedActionConfirm.visible || guidedActionList.visible
property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
property string _flightMode: _activeVehicle ? _activeVehicle.flightMode : ""
property bool _missionAvailable: missionController.containsItems
......@@ -111,6 +114,7 @@ Item {
property int _resumeMissionIndex: missionController.resumeMissionIndex
property bool _hideEmergenyStop: !QGroundControl.corePlugin.options.guidedBarShowEmergencyStop
property bool _hideOrbit: !QGroundControl.corePlugin.options.guidedBarShowOrbit
property bool _vehicleWasFlying: false
// This is a temporary hack to debug a problem with RTL and Pause being disabled at the wrong time
......@@ -125,7 +129,6 @@ Item {
Component.onCompleted: _outputState()
on_ActiveVehicleChanged: _outputState()
on_VehicleArmedChanged: _outputState()
on_VehicleFlyingChanged: _outputState()
on_VehicleInRTLModeChanged: _outputState()
on_VehiclePausedChanged: _outputState()
on__FlightModeChanged: _outputState()
......@@ -134,6 +137,15 @@ Item {
// End of hack
on_VehicleFlyingChanged: {
_outputState()
if (!_vehicleFlying) {
// We use _vehicleWasFLying to help trigger Resume Mission only if the vehicle actually flew and came back down.
// Otherwise it may trigger during the Start Mission sequence due to signal ordering or armed and resume mission index.
_vehicleWasFlying = true
}
}
property var _actionData
on_CurrentMissionIndexChanged: console.log("_currentMissionIndex", _currentMissionIndex)
......@@ -262,6 +274,7 @@ Item {
missionController.resumeMission(missionController.resumeMissionIndex)
break
case actionResumeMissionReady:
_vehicleWasFlying = false
_activeVehicle.startMission()
break
case actionStartMission:
......
......@@ -165,7 +165,9 @@ void CameraSection::appendSectionItems(QList<MissionItem*>& items, QObject* miss
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
_cameraPhotoIntervalDistanceFact.rawValue().toDouble(), // Trigger distance
0, 0, 0, 0, 0, 0, // param 2-7 not used
0, // No shutter integartion
1, // Trigger immediately
0, 0, 0, 0, // param 4-7 not used
true, // autoContinue
false, // isCurrentItem
missionItemParent);
......@@ -313,13 +315,31 @@ bool CameraSection::_scanStopTakingPhotos(QmlObjectListModel* visualItems, int s
return false;
}
bool CameraSection::_scanTriggerDistance(QmlObjectListModel* visualItems, int scanIndex)
bool CameraSection::_scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex)
{
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
if (missionItem.param1() >= 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
if (missionItem.param1() > 0 && missionItem.param2() == 0 && missionItem.param3() == 1 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
cameraAction()->setRawValue(TakePhotoIntervalDistance);
cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
visualItems->removeAt(scanIndex)->deleteLater();
return true;
}
}
}
return false;
}
bool CameraSection::_scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex)
{
SimpleMissionItem* item = visualItems->value<SimpleMissionItem*>(scanIndex);
if (item) {
MissionItem& missionItem = item->missionItem();
if ((MAV_CMD)item->command() == MAV_CMD_DO_SET_CAM_TRIGG_DIST) {
if (missionItem.param1() == 0 && missionItem.param2() == 0 && missionItem.param3() == 0 && missionItem.param4() == 0 && missionItem.param5() == 0 && missionItem.param6() == 0 && missionItem.param7() == 0) {
cameraAction()->setRawValue(TakePhotoIntervalDistance);
cameraPhotoIntervalDistance()->setRawValue(missionItem.param1());
visualItems->removeAt(scanIndex)->deleteLater();
......@@ -415,7 +435,11 @@ bool CameraSection::scanForSection(QmlObjectListModel* visualItems, int scanInde
foundCameraAction = true;
continue;
}
if (!foundCameraAction && _scanTriggerDistance(visualItems, scanIndex)) {
if (!foundCameraAction && _scanTriggerStartDistance(visualItems, scanIndex)) {
foundCameraAction = true;
continue;
}
if (!foundCameraAction && _scanTriggerStopDistance(visualItems, scanIndex)) {
foundCameraAction = true;
continue;
}
......
......@@ -94,7 +94,8 @@ private:
bool _scanTakePhoto(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakePhotosIntervalTime(QmlObjectListModel* visualItems, int scanIndex);
bool _scanStopTakingPhotos(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerStartDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTriggerStopDistance(QmlObjectListModel* visualItems, int scanIndex);
bool _scanTakeVideo(QmlObjectListModel* visualItems, int scanIndex);
bool _scanStopTakingVideo(QmlObjectListModel* visualItems, int scanIndex);
bool _scanSetCameraMode(QmlObjectListModel* visualItems, int scanIndex);
......
......@@ -50,7 +50,14 @@ void CameraSectionTest::init(void)
MissionItem(0, MAV_CMD_IMAGE_START_CAPTURE, MAV_FRAME_MISSION, 0, 48, 0, NAN, NAN, NAN, NAN, true, false),
this);
_validDistanceItem = new SimpleMissionItem(_offlineVehicle,
MissionItem(0, MAV_CMD_DO_SET_CAM_TRIGG_DIST, MAV_FRAME_MISSION, 72, 0, 0, 0, 0, 0, 0, true, false),
MissionItem(0,
MAV_CMD_DO_SET_CAM_TRIGG_DIST,
MAV_FRAME_MISSION,
72, // trigger distance
0, // not shutter integration
1, // trigger immediately
0, 0, 0, 0,
true, false),
this);
_validStartVideoItem = new SimpleMissionItem(_offlineVehicle,
MissionItem(0, // sequence number
......@@ -729,15 +736,15 @@ void CameraSectionTest::_testScanForPhotoIntervalDistanceSection(void)
_commonScanTest(_cameraSection);
/*
MAV_CMD_DO_SET_CAM_TRIGG_DIST Mission command to set CAM_TRIGG_DIST for this flight
Mission Param #1 Camera trigger distance (meters)
Mission Param #2 Empty
Mission Param #3 Empty
MAV_CMD_DO_SET_CAM_TRIGG_DIST Mission command to set camera trigger distance for this flight. The camera is trigerred each time this distance is exceeded. This command can also be used to set the shutter integration time for the camera.
Mission Param #1 Camera trigger distance (meters). 0 to stop triggering.
Mission Param #2 Camera shutter integration time (milliseconds). -1 or 0 to ignore
Mission Param #3 Trigger camera once immediately. (0 = no trigger, 1 = trigger)
Mission Param #4 Empty
Mission Param #5 Empty
Mission Param #6 Empty
Mission Param #7 Empty
*/
*/
SimpleMissionItem* newValidDistanceItem = new SimpleMissionItem(_offlineVehicle, this);
newValidDistanceItem->missionItem() = _validDistanceItem->missionItem();
......@@ -769,7 +776,7 @@ void CameraSectionTest::_testScanForPhotoIntervalDistanceSection(void)
visualItems.clear();
invalidSimpleItem.missionItem() = _validDistanceItem->missionItem();
invalidSimpleItem.missionItem().setParam3(1); // must be 0
invalidSimpleItem.missionItem().setParam3(0); // must be 1
visualItems.append(&invalidSimpleItem);
QCOMPARE(_cameraSection->scanForSection(&visualItems, scanIndex), false);
QCOMPARE(visualItems.count(), 1);
......
......@@ -158,7 +158,10 @@ void MissionController::_newMissionItemsAvailableFromVehicle(bool removeAllReque
qWarning() << "First item is not settings item";
return;
}
settingsItem->setCoordinate(newMissionItems[0]->coordinate());
MissionItem* fakeHomeItem = newMissionItems[0];
if (fakeHomeItem->coordinate().latitude() != 0 || fakeHomeItem->coordinate().longitude() != 0) {
settingsItem->setCoordinate(fakeHomeItem->coordinate());
}
i = 1;
}
......
......@@ -89,6 +89,16 @@ void PlanMasterController::_activeVehicleChanged(Vehicle* activeVehicle)
qCDebug(PlanMasterControllerLog) << "_activeVehicleChanged" << activeVehicle;
if (_managerVehicle) {
// Disconnect old vehicle
disconnect(_managerVehicle->missionManager(), &MissionManager::newMissionItemsAvailable, this, &PlanMasterController::_loadMissionComplete);
disconnect(_managerVehicle->geoFenceManager(), &GeoFenceManager::loadComplete, this, &PlanMasterController::_loadGeoFenceComplete);
disconnect(_managerVehicle->rallyPointManager(), &RallyPointManager::loadComplete, this, &PlanMasterController::_loadRallyPointsComplete);
disconnect(_managerVehicle->missionManager(), &MissionManager::sendComplete, this, &PlanMasterController::_sendMissionComplete);
disconnect(_managerVehicle->geoFenceManager(), &GeoFenceManager::sendComplete, this, &PlanMasterController::_sendGeoFenceComplete);
disconnect(_managerVehicle->rallyPointManager(), &RallyPointManager::sendComplete, this, &PlanMasterController::_sendRallyPointsComplete);
}
bool newOffline = false;
if (activeVehicle == NULL) {
// Since there is no longer an active vehicle we use the offline controller vehicle as the manager vehicle
......@@ -353,6 +363,7 @@ void PlanMasterController::removeAllFromVehicle(void)
_missionController.removeAllFromVehicle();
_geoFenceController.removeAllFromVehicle();
_rallyPointController.removeAllFromVehicle();
setDirty(false);
} else {
qWarning() << "PlanMasterController::removeAllFromVehicle called while offline";
}
......@@ -410,6 +421,14 @@ void PlanMasterController::sendPlanToVehicle(Vehicle* vehicle, const QString& fi
void PlanMasterController::_showPlanFromManagerVehicle(void)
{
if (!_managerVehicle->initialPlanRequestComplete() &&
!_missionController.syncInProgress() &&
!_geoFenceController.syncInProgress() &&
!_rallyPointController.syncInProgress()) {
// Something went wrong with initial load. All controllers are idle, so just force it off
_managerVehicle->forceInitialPlanRequestComplete();
}
// The crazy if structure is to handle the load propogating by itself through the system
if (!_missionController.showPlanFromManagerVehicle()) {
if (!_geoFenceController.showPlanFromManagerVehicle()) {
......
......@@ -253,6 +253,8 @@ void QGCMapPolygon::removeVertex(int vertexIndex)
_polygonPath.removeAt(vertexIndex);
emit pathChanged();
_updateCenter();
}
void QGCMapPolygon::_polygonModelCountChanged(int count)
......@@ -265,9 +267,13 @@ void QGCMapPolygon::_updateCenter(void)
if (!_ignoreCenterUpdates) {
QGeoCoordinate center;
if (_polygonPath.count() > 2) {
QPointF centerPoint = _toPolygonF().boundingRect().center();
center = _coordFromPointF(centerPoint);
if (_polygonPath.count() > 2) {
QPointF centroid(0, 0);
QPolygonF polygonF = _toPolygonF();
for (int i=0; i<polygonF.count(); i++) {
centroid += polygonF[i];
}
center = _coordFromPointF(QPointF(centroid.x() / polygonF.count(), centroid.y() / polygonF.count()));
}
_center = center;
......
......@@ -171,7 +171,8 @@ void QGCMapPolygonTest::_testVertexManipulation(void)
// Vertex removal testing
_mapPolygon->removeVertex(1);
QVERIFY(_multiSpyPolygon->checkOnlySignalByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask));
// There is some double signalling on centerChanged which is not yet fixed, hence checkOnlySignals
QVERIFY(_multiSpyPolygon->checkOnlySignalsByMask(pathChangedMask | polygonDirtyChangedMask | polygonCountChangedMask | centerChangedMask));
QVERIFY(_multiSpyModel->checkOnlySignalByMask(modelDirtyChangedMask | modelCountChangedMask));
QCOMPARE(_mapPolygon->count(), 3);
polyList = _mapPolygon->path();
......
......@@ -35,8 +35,9 @@ Item {
property var _splitHandlesComponent
property var _centerDragHandleComponent
property real _zorderDragHandle: QGroundControl.zOrderMapItems + 2
property real _zorderSplitHandle: QGroundControl.zOrderMapItems + 1
property real _zorderDragHandle: QGroundControl.zOrderMapItems + 3 // Highest to prevent splitting when items overlap
property real _zorderSplitHandle: QGroundControl.zOrderMapItems + 2
property real _zorderCenterHandle: QGroundControl.zOrderMapItems + 1 // Lowest such that drag or split takes precedence
function addVisuals() {
_polygonComponent = polygonComponent.createObject(mapControl)
......@@ -281,7 +282,7 @@ Item {
id: centerDragAreaComponent
MissionItemIndicatorDrag {
z: _zorderDragHandle
z: _zorderCenterHandle
onItemCoordinateChanged: mapPolygon.center = itemCoordinate
onDragStart: mapPolygon.centerDrag = true
onDragStop: mapPolygon.centerDrag = false
......
......@@ -64,7 +64,7 @@
"min": 0,
"max": 85,
"units": "%",
"defaultValue": 10
"defaultValue": 70
},
{
"name": "SideOverlap",
......@@ -74,7 +74,7 @@
"min": 0,
"max": 85,
"units": "%",
"defaultValue": 10
"defaultValue": 70
},
{
"name": "CameraSensorWidth",
......@@ -132,7 +132,7 @@
"name": "CameraTriggerInTurnaround",
"shortDescription": "Camera continues taking images in turnarounds.",
"type": "bool",
"defaultValue": false
"defaultValue": true
},
{
"name": "HoverAndCapture",
......
This diff is collapsed.
......@@ -43,14 +43,15 @@ public:
Q_PROPERTY(Fact* cameraResolutionWidth READ cameraResolutionWidth CONSTANT)
Q_PROPERTY(Fact* cameraResolutionHeight READ cameraResolutionHeight CONSTANT)
Q_PROPERTY(Fact* cameraFocalLength READ cameraFocalLength CONSTANT)
Q_PROPERTY(Fact* fixedValueIsAltitude READ fixedValueIsAltitude CONSTANT)
Q_PROPERTY(Fact* cameraOrientationLandscape READ cameraOrientationLandscape CONSTANT)
Q_PROPERTY(Fact* fixedValueIsAltitude READ fixedValueIsAltitude CONSTANT)
Q_PROPERTY(Fact* manualGrid READ manualGrid CONSTANT)
Q_PROPERTY(Fact* camera READ camera CONSTANT)
Q_PROPERTY(bool cameraOrientationFixed MEMBER _cameraOrientationFixed NOTIFY cameraOrientationFixedChanged)
Q_PROPERTY(bool hoverAndCaptureAllowed READ hoverAndCaptureAllowed CONSTANT)
Q_PROPERTY(bool refly90Degrees READ refly90Degrees WRITE setRefly90Degrees NOTIFY refly90DegreesChanged)
Q_PROPERTY(double cameraMinTriggerInterval MEMBER _cameraMinTriggerInterval NOTIFY cameraMinTriggerIntervalChanged)
Q_PROPERTY(double timeBetweenShots READ timeBetweenShots NOTIFY timeBetweenShotsChanged)
Q_PROPERTY(QVariantList gridPoints READ gridPoints NOTIFY gridPointsChanged)
......@@ -165,14 +166,15 @@ public:
static const char* cameraName;
signals:
void gridPointsChanged (void);
void cameraShotsChanged (int cameraShots);
void coveredAreaChanged (double coveredArea);
void cameraValueChanged (void);
void gridTypeChanged (QString gridType);
void timeBetweenShotsChanged (void);
void cameraOrientationFixedChanged (bool cameraOrientationFixed);
void refly90DegreesChanged (bool refly90Degrees);
void gridPointsChanged (void);
void cameraShotsChanged (int cameraShots);
void coveredAreaChanged (double coveredArea);
void cameraValueChanged (void);
void gridTypeChanged (QString gridType);
void timeBetweenShotsChanged (void);
void cameraOrientationFixedChanged (bool cameraOrientationFixed);
void refly90DegreesChanged (bool refly90Degrees);
void cameraMinTriggerIntervalChanged (double cameraMinTriggerInterval);
private slots:
void _setDirty(void);
......@@ -233,6 +235,7 @@ private:
int _missionCommandCount;
bool _refly90Degrees;
double _additionalFlightDelaySeconds;
double _cameraMinTriggerInterval;
bool _ignoreRecalc;
double _surveyDistance;
......@@ -283,6 +286,7 @@ private:
static const char* _jsonCameraResolutionWidthKey;
static const char* _jsonCameraResolutionHeightKey;
static const char* _jsonCameraFocalLengthKey;
static const char* _jsonCameraMinTriggerIntervalKey;
static const char* _jsonManualGridKey;
static const char* _jsonCameraObjectKey;
static const char* _jsonCameraNameKey;
......
......@@ -57,7 +57,9 @@ Rectangle {
gridTypeCombo.currentIndex = index
if (index != 1) {
// Specific camera is selected
missionItem.cameraOrientationFixed = _vehicleCameraList[index - _gridTypeCamera].fixedOrientation
var camera = _vehicleCameraList[index - _gridTypeCamera]
missionItem.cameraOrientationFixed = camera.fixedOrientation
missionItem.cameraMinTriggerInterval = camera.minTriggerInterval
}
}
}
......@@ -181,6 +183,15 @@ Rectangle {
anchors.right: parent.right
spacing: _margin
QGCLabel {
anchors.left: parent.left
anchors.right: parent.right
text: qsTr("WARNING: Photo interval is below minimum interval (%1 secs) supported by camera.").arg(missionItem.cameraMinTriggerInterval.toFixed(1))
wrapMode: Text.WordWrap
color: qgcPal.warningText
visible: missionItem.manualGrid.value !== true && missionItem.cameraShots > 0 && missionItem.cameraMinTriggerInterval !== 0 && missionItem.cameraMinTriggerInterval > missionItem.timeBetweenShots
}
SectionHeader {
id: cameraHeader
text: qsTr("Camera")
......@@ -207,6 +218,7 @@ Rectangle {
missionItem.manualGrid.value = false
missionItem.camera.value = gridTypeCombo.textAt(index)
missionItem.cameraOrientationFixed = false
missionItem.cameraMinTriggerInterval = 0
} else {
missionItem.manualGrid.value = false
missionItem.camera.value = gridTypeCombo.textAt(index)
......@@ -219,6 +231,7 @@ Rectangle {
missionItem.cameraFocalLength.rawValue = _vehicleCameraList[listIndex].focalLength
missionItem.cameraOrientationLandscape.rawValue = _vehicleCameraList[listIndex].landscape ? 1 : 0
missionItem.cameraOrientationFixed = _vehicleCameraList[listIndex].fixedOrientation
missionItem.cameraMinTriggerInterval = _vehicleCameraList[listIndex].minTriggerInterval
_noCameraValueRecalc = false
recalcFromCameraValues()
}
......@@ -252,12 +265,6 @@ Rectangle {
enabled: cameraTriggerDistanceCheckBox.checked
}
}
FactCheckBox {
text: qsTr("Hover and capture image")
fact: missionItem.hoverAndCapture
visible: missionItem.hoverAndCaptureAllowed
}
}
// Camera based grid ui
......@@ -387,6 +394,23 @@ Rectangle {
}
}
FactCheckBox {
text: qsTr("Hover and capture image")
fact: missionItem.hoverAndCapture
visible: missionItem.hoverAndCaptureAllowed
onClicked: {
if (checked) {
missionItem.cameraTriggerInTurnaround.rawValue = false
}
}
}
FactCheckBox {
text: qsTr("Take images in turnarounds")
fact: missionItem.cameraTriggerInTurnaround
enabled: !missionItem.hoverAndCapture.rawValue
}
SectionHeader {
id: gridHeader
text: qsTr("Grid")
......@@ -418,7 +442,8 @@ Rectangle {
id: windRoseButton
anchors.verticalCenter: angleText.verticalCenter
iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
visible: _vehicle.fixedWing
// Wind Rose is temporarily turned off until bugs are fixed
visible: false//_vehicle.fixedWing
onClicked: {
var cords = windRoseButton.mapToItem(_root, 0, 0)
......@@ -519,7 +544,8 @@ Rectangle {
anchors.verticalCenter: manualAngleText.verticalCenter
Layout.columnSpan: 1
iconSource: qgcPal.globalTheme === QGCPalette.Light ? "/res/wind-roseBlack.svg" : "/res/wind-rose.svg"
visible: _vehicle.fixedWing
// Wind Rose is temporarily turned off until bugs are fixed
visible: false//_vehicle.fixedWing
onClicked: {
var cords = manualWindRoseButton.mapToItem(_root, 0, 0)
......
......@@ -13,7 +13,7 @@ Canvas {
signal clicked
property string label ///< Label to show to the side of the index indicator
property int index: 0 ///< Index to show in the indicator, 0 will show label instead
property int index: 0 ///< Index to show in the indicator, 0 will show single char label instead, -1 first char of label in indicator full label to the side
property bool checked: false
property bool small: false
property var color: checked ? "green" : qgcPal.mapButtonHighlight
......@@ -33,7 +33,7 @@ Canvas {
property real _labelMargin: 2
property real _labelRadius: _indicatorRadius + _labelMargin
property string _label: index === 0 ? "" : label
property string _index: index === 0 ? label : index
property string _index: index === 0 || index === -1 ? label.charAt(0) : index
onColorChanged: requestPaint()
onShowGimbalYawChanged: requestPaint()
......
import QtQuick 2.3
import QtQuick.Controls 1.2
/// This control is used to create a Rectangle control which does not allow mouse events to bleed through to the control
/// which is beneath it.
Rectangle {
MouseArea {
anchors.fill: parent
preventStealing: true
onWheel: { wheel.accepted = true; }
onPressed: { mouse.accepted = true; }
onReleased: { mouse.accepted = true; }
}
}
......@@ -25,6 +25,7 @@ MissionItemMapVisual 1.0 MissionItemMapVisual.qml
MissionItemStatus 1.0 MissionItemStatus.qml
ModeSwitchDisplay 1.0 ModeSwitchDisplay.qml
MultiRotorMotorDisplay 1.0 MultiRotorMotorDisplay.qml
NoMouseThroughRectangle 1.0 NoMouseThroughRectangle.qml
ParameterEditor 1.0 ParameterEditor.qml
ParameterEditorDialog 1.0 ParameterEditorDialog.qml
PlanToolBar 1.0 PlanToolBar.qml
......
......@@ -688,8 +688,8 @@ void Vehicle::_handleGlobalPositionInt(mavlink_message_t& message)
mavlink_global_position_int_t globalPositionInt;
mavlink_msg_global_position_int_decode(&message, &globalPositionInt);
// ArduPilot sends bogus GLOBAL_POSITION_INT messages with lat/lat/alt 0/0/0 even when it has not gps signal
if (globalPositionInt.lat == 0 && globalPositionInt.lon == 0 && globalPositionInt.alt == 0) {
// ArduPilot sends bogus GLOBAL_POSITION_INT messages with lat/lat 0/0 even when it has not gps signal
if (globalPositionInt.lat == 0 && globalPositionInt.lon == 0) {
return;
}
......@@ -723,6 +723,7 @@ void Vehicle::_setCapabilities(uint64_t capabilityBits)
_supportsMissionItemInt = true;
}
_vehicleCapabilitiesKnown = true;
emit capabilitiesKnownChanged(true);
qCDebug(VehicleLog) << QString("Vehicle %1 MISSION_ITEM_INT").arg(_supportsMissionItemInt ? QStringLiteral("supports") : QStringLiteral("does not support"));
}
......@@ -795,7 +796,7 @@ void Vehicle::_handleHilActuatorControls(mavlink_message_t &message)
void Vehicle::_handleCommandAck(mavlink_message_t& message)
{
bool showError = true;
bool showError = false;
mavlink_command_ack_t ack;
mavlink_msg_command_ack_decode(&message, &ack);
......
......@@ -677,6 +677,7 @@ public:
QGCCameraManager* dynamicCameras () { return _cameras; }
bool capabilitiesKnown(void) const { return _vehicleCapabilitiesKnown; }
bool supportsMissionItemInt(void) const { return _supportsMissionItemInt; }
/// @true: When flying a mission the vehicle is always facing towards the next waypoint
......@@ -686,6 +687,8 @@ public:
/// @return: true: initial request is complete, false: initial request is still in progress;
bool initialPlanRequestComplete(void) const { return _initialPlanRequestComplete; }
void forceInitialPlanRequestComplete(void) { _initialPlanRequestComplete = true; }
void _setFlying(bool flying);
void _setLanding(bool landing);
void _setHomePosition(QGeoCoordinate& homeCoord);
......@@ -717,6 +720,7 @@ signals:
void firmwareTypeChanged(void);
void vehicleTypeChanged(void);
void dynamicCamerasChanged();
void capabilitiesKnownChanged(bool capabilitiesKnown);
void messagesReceivedChanged ();
void messagesSentChanged ();
......
......@@ -175,6 +175,13 @@ bool QGCCorePlugin::adjustSettingMetaData(FactMetaData& metaData)
#else
metaData.setRawDefaultValue(true);
return true;
#endif
#if defined(__ios__)
} else if (metaData.name() == AppSettings::savePathName) {
QString appName = qgcApp()->applicationName();
QDir rootDir = QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
metaData.setRawDefaultValue(rootDir.filePath(appName));
return false;
#endif
}
return true; // Show setting in ui
......
......@@ -108,10 +108,11 @@ void MainWindow::deleteInstance(void)
/// by MainWindow::_create method. Hence no other code should have access to
/// constructor.
MainWindow::MainWindow()
: _lowPowerMode(false)
, _showStatusBar(false)
, _mainQmlWidgetHolder(NULL)
, _forceClose(false)
: _mavlinkDecoder (NULL)
, _lowPowerMode (false)
, _showStatusBar (false)
, _mainQmlWidgetHolder (NULL)
, _forceClose (false)
{
_instance = this;
......@@ -272,10 +273,13 @@ MainWindow::MainWindow()
MainWindow::~MainWindow()
{
// Enforce thread-safe shutdown of the mavlink decoder
mavlinkDecoder->finish();
mavlinkDecoder->wait(1000);
mavlinkDecoder->deleteLater();
if (_mavlinkDecoder) {
// Enforce thread-safe shutdown of the mavlink decoder
_mavlinkDecoder->finish();
_mavlinkDecoder->wait(1000);
_mavlinkDecoder->deleteLater();
_mavlinkDecoder = NULL;
}
// This needs to happen before we get into the QWidget dtor
// otherwise the QML engine reads freed data and tries to
......@@ -290,12 +294,18 @@ QString MainWindow::_getWindowGeometryKey()
}
#ifndef __mobile__
void MainWindow::_buildCommonWidgets(void)
MAVLinkDecoder* MainWindow::_mavLinkDecoderInstance(void)
{
// Add generic MAVLink decoder
mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol());
connect(mavlinkDecoder.data(), &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged);
if (!_mavlinkDecoder) {
_mavlinkDecoder = new MAVLinkDecoder(qgcApp()->toolbox()->mavlinkProtocol());
connect(_mavlinkDecoder, &MAVLinkDecoder::valueChanged, this, &MainWindow::valueChanged);
}
return _mavlinkDecoder;
}
void MainWindow::_buildCommonWidgets(void)
{
// Log player
// TODO: Make this optional with a preferences setting or under a "View" menu
logPlayer = new QGCMAVLinkLogPlayer(statusBar());
......@@ -363,7 +373,7 @@ bool MainWindow::_createInnerDockWidget(const QString& widgetName)
widget = new HILDockWidget(widgetName, action, this);
break;
case ANALYZE:
widget = new Linecharts(widgetName, action, mavlinkDecoder, this);
widget = new Linecharts(widgetName, action, _mavLinkDecoderInstance(), this);
break;
}
if(widget) {
......
......@@ -127,7 +127,6 @@ protected:
QSettings settings;
QPointer<MAVLinkDecoder> mavlinkDecoder;
QGCMAVLinkLogPlayer* logPlayer;
#ifdef QGC_MOUSE_ENABLED_WIN
/** @brief 3d Mouse support (WIN only) */
......@@ -181,7 +180,9 @@ private:
void _showDockWidget(const QString &name, bool show);
void _loadVisibleWidgetsSettings(void);
void _storeVisibleWidgetsSettings(void);
MAVLinkDecoder* _mavLinkDecoderInstance(void);
MAVLinkDecoder* _mavlinkDecoder;
bool _lowPowerMode; ///< If enabled, QGC reduces the update rates of all widgets
bool _showStatusBar;
QVBoxLayout* _centralLayout;
......
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