diff --git a/ChangeLog.md b/ChangeLog.md index 36b7e0b..5413d20 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -46,20 +46,24 @@ Note: This file only contains high level features or important fixes. * ArduPilot: Support configurable mavlink stream rates. Available from Settings/Mavlink page. * Major rewrite and bug fix pass through Structure Scan. Previous version had such bad problems that it can no longer be supported. Plans with Structure Scan will need to be recreated. New QGC will not load old Structure Scan plans. -### 3.5.4 - Not yet released +### 3.5.5 - Not yet released +* Fix mavlink message memset which cause wrong commands to be sent on ArduPilot GotoLocation. +* Disable Pause when fixed wing is on landing approach. + +### 3.5.4 - Stable * Update windows drivers * Add support for FMUK66 flashing/connection * Guard against null geometry coming from gstreamer which can cause crashes * Add .apj file selection support to custom firmware flash -### 3.5.3 - Stable +### 3.5.3 * Change minimum RTK Survey-In limit to 0.01 meters * Change Windows driver detection logic * Fix crash when clicking on GeoFence polygon vertex * PX4: Fix missing ```MC_YAW_FF``` parameter in PID Tuning * ArduPilot: Fix parameter file save generating bad characters from git hash -### 3.5.2 - Stable +### 3.5.2 * Fix Ubuntu AppImage startup failure ### 3.5.1 diff --git a/src/Audio/AudioOutput.cc b/src/Audio/AudioOutput.cc index 98e9498..0662ed9 100644 --- a/src/Audio/AudioOutput.cc +++ b/src/Audio/AudioOutput.cc @@ -142,6 +142,9 @@ QString AudioOutput::fixTextMessageForAudio(const QString& string) { if(result.contains("PREARM", Qt::CaseInsensitive)) { result.replace("PREARM", "pre arm", Qt::CaseInsensitive); } + if(result.contains("PITOT", Qt::CaseInsensitive)) { + result.replace("PITOT", "pee toe", Qt::CaseInsensitive); + } // Convert negative numbers QRegularExpression re(QStringLiteral("(-)[0-9]*\\.?[0-9]")); diff --git a/src/FlightDisplay/FlightDisplayView.qml b/src/FlightDisplay/FlightDisplayView.qml index b04dbb4..cc54bc7 100644 --- a/src/FlightDisplay/FlightDisplayView.qml +++ b/src/FlightDisplay/FlightDisplayView.qml @@ -593,12 +593,6 @@ Item { visible: _guidedController.showContinueMission }, { - title: _guidedController.resumeMissionTitle, - text: _guidedController.resumeMissionMessage, - action: _guidedController.actionResumeMission, - visible: _guidedController.showResumeMission - }, - { title: _guidedController.changeAltTitle, text: _guidedController.changeAltMessage, action: _guidedController.actionChangeAlt, diff --git a/src/FlightDisplay/FlightDisplayViewVideo.qml b/src/FlightDisplay/FlightDisplayViewVideo.qml index 3aea979..7ea5d7d 100644 --- a/src/FlightDisplay/FlightDisplayViewVideo.qml +++ b/src/FlightDisplay/FlightDisplayViewVideo.qml @@ -75,54 +75,67 @@ Item { //-- Fit Width return _ar != 0.0 ? parent.width * (1 / _ar) : parent.height } - //-- Main Video - QGCVideoBackground { - id: videoContent - height: parent.getHeight() - width: parent.getWidth() - anchors.centerIn: parent - receiver: _videoReceiver - display: _videoReceiver && _videoReceiver.videoSurface - visible: _videoReceiver && _videoReceiver.videoRunning && !(QGroundControl.videoManager.hasThermal && _camera.thermalMode === QGCCameraControl.THERMAL_FULL) - Connections { - target: _videoReceiver - onImageFileChanged: { - videoContent.grabToImage(function(result) { - if (!result.saveToFile(_videoReceiver.imageFile)) { - console.error('Error capturing video frame'); - } - }); + Component { + id: videoBackgroundComponent + QGCVideoBackground { + id: videoContent + receiver: _videoReceiver + display: _videoReceiver && _videoReceiver.videoSurface + + Connections { + target: _videoReceiver + onImageFileChanged: { + videoContent.grabToImage(function(result) { + if (!result.saveToFile(_videoReceiver.imageFile)) { + console.error('Error capturing video frame'); + } + }); + } + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + height: parent.height + width: 1 + x: parent.width * 0.33 + visible: _showGrid && !QGroundControl.videoManager.fullScreen + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + height: parent.height + width: 1 + x: parent.width * 0.66 + visible: _showGrid && !QGroundControl.videoManager.fullScreen + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + width: parent.width + height: 1 + y: parent.height * 0.33 + visible: _showGrid && !QGroundControl.videoManager.fullScreen + } + Rectangle { + color: Qt.rgba(1,1,1,0.5) + width: parent.width + height: 1 + y: parent.height * 0.66 + visible: _showGrid && !QGroundControl.videoManager.fullScreen } - } - Rectangle { - color: Qt.rgba(1,1,1,0.5) - height: parent.height - width: 1 - x: parent.width * 0.33 - visible: _showGrid && !QGroundControl.videoManager.fullScreen - } - Rectangle { - color: Qt.rgba(1,1,1,0.5) - height: parent.height - width: 1 - x: parent.width * 0.66 - visible: _showGrid && !QGroundControl.videoManager.fullScreen - } - Rectangle { - color: Qt.rgba(1,1,1,0.5) - width: parent.width - height: 1 - y: parent.height * 0.33 - visible: _showGrid && !QGroundControl.videoManager.fullScreen - } - Rectangle { - color: Qt.rgba(1,1,1,0.5) - width: parent.width - height: 1 - y: parent.height * 0.66 - visible: _showGrid && !QGroundControl.videoManager.fullScreen } } + Loader { + // GStreamer is causing crashes on Lenovo laptop OpenGL Intel drivers. In order to workaround this + // we don't load a QGCVideoBackground object when video is disabled. This prevents any video rendering + // code from running. Setting QGCVideoBackground.receiver/display = null does not work to prevent any + // video OpenGL from being generated. Hence the Loader to completely remove it. + height: parent.getHeight() + width: parent.getWidth() + anchors.centerIn: parent + visible: _videoReceiver && _videoReceiver.videoRunning + sourceComponent: videoDisabled ? null : videoBackgroundComponent + + property bool videoDisabled: QGroundControl.settingsManager.videoSettings.videoSource.rawValue === QGroundControl.settingsManager.videoSettings.disabledVideoSource + } + //-- Thermal Image Item { id: thermalItem diff --git a/src/FlightDisplay/GuidedActionsController.qml b/src/FlightDisplay/GuidedActionsController.qml index 8c09955..636cc4b 100644 --- a/src/FlightDisplay/GuidedActionsController.qml +++ b/src/FlightDisplay/GuidedActionsController.qml @@ -101,10 +101,10 @@ Item { property bool showLand: _guidedActionsEnabled && activeVehicle.guidedModeSupported && _vehicleArmed && !activeVehicle.fixedWing && !_vehicleInLandMode property bool showStartMission: _guidedActionsEnabled && _missionAvailable && !_missionActive && !_vehicleFlying property bool showContinueMission: _guidedActionsEnabled && _missionAvailable && !_missionActive && _vehicleArmed && _vehicleFlying && (_currentMissionIndex < _missionItemCount - 1) - property bool showPause: _guidedActionsEnabled && _vehicleArmed && activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused - property bool showChangeAlt: _guidedActionsEnabled && _vehicleFlying && activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive - property bool showOrbit: _guidedActionsEnabled && !_hideOrbit && _vehicleFlying && activeVehicle.orbitModeSupported && !_missionActive - property bool showLandAbort: _guidedActionsEnabled && _vehicleFlying && activeVehicle.fixedWing && _vehicleLanding + property bool showPause: _guidedActionsEnabled && _vehicleArmed && _activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused && !_fixedWingOnApproach + property bool showChangeAlt: _guidedActionsEnabled && _vehicleFlying && _activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive + property bool showOrbit: _guidedActionsEnabled && !_hideOrbit && _vehicleFlying && _activeVehicle.orbitModeSupported && !_missionActive + property bool showLandAbort: _guidedActionsEnabled && _vehicleFlying && _fixedWingOnApproach property bool showGotoLocation: _guidedActionsEnabled && _vehicleFlying // Note: The '_missionItemCount - 2' is a hack to not trigger resume mission when a mission ends with an RTL item @@ -130,7 +130,8 @@ Item { property bool _hideEmergenyStop: !QGroundControl.corePlugin.options.guidedBarShowEmergencyStop property bool _hideOrbit: !QGroundControl.corePlugin.options.guidedBarShowOrbit property bool _vehicleWasFlying: false - property bool _rcRSSIAvailable: activeVehicle ? activeVehicle.rcRSSI > 0 && activeVehicle.rcRSSI <= 100 : false + property bool _rcRSSIAvailable: _activeVehicle ? _activeVehicle.rcRSSI > 0 && _activeVehicle.rcRSSI <= 100 : false + property bool _fixedWingOnApproach: _activeVehicle ? _activeVehicle.fixedWing && _vehicleLanding : false // You can turn on log output for GuidedActionsController by turning on GuidedActionsControllerLog category property bool __guidedModeSupported: activeVehicle ? activeVehicle.guidedModeSupported : false diff --git a/src/MissionManager/FWLandingPattern.FactMetaData.json b/src/MissionManager/FWLandingPattern.FactMetaData.json index 1970cdb..61906dd 100644 --- a/src/MissionManager/FWLandingPattern.FactMetaData.json +++ b/src/MissionManager/FWLandingPattern.FactMetaData.json @@ -20,7 +20,7 @@ }, { "name": "LoiterAltitude", - "shortDescription": "Aircraft will proceed to the loiter point and loiter until it reaches this altitude. Once altitude is reached the aircraft will proceed to land.", + "shortDescription": "Aircraft will proceed to the loiter point and loiter downwards until it reaches this approach altitude. Once altitude is reached the aircraft will proceed to land.", "type": "double", "units": "m", "decimalPlaces": 1, diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index d8a7b17..f09d1dc 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -560,6 +560,12 @@ bool QGCApplication::_initForNormalAppBoot() _qmlAppEngine = toolbox()->corePlugin()->createRootWindow(this); + // Safe to show popup error messages now that main window is created + UASMessageHandler* msgHandler = qgcApp()->toolbox()->uasMessageHandler(); + if (msgHandler) { + msgHandler->showErrorsInToolbar(); + } + // Now that main window is up check for lost log files connect(this, &QGCApplication::checkForLostLogFiles, toolbox()->mavlinkProtocol(), &MAVLinkProtocol::checkForLostLogFiles); emit checkForLostLogFiles(); diff --git a/src/QmlControls/PreFlightCheckList.qml b/src/QmlControls/PreFlightCheckList.qml new file mode 100644 index 0000000..692ce33 --- /dev/null +++ b/src/QmlControls/PreFlightCheckList.qml @@ -0,0 +1,106 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 + +Rectangle { + width: mainColumn.width + 3*ScreenTools.defaultFontPixelWidth + height: mainColumn.height + ScreenTools.defaultFontPixelHeight + color: qgcPal.windowShade + radius: 3 + + property alias model: checkListRepeater.model + + function setResetEnabled(resetEnabled) { + resetButton.enabled = resetEnabled + } + + property bool _passed: false + + function _handleGroupPassedChanged(index, passed) { + if (passed) { + // Collapse current group + var group = checkListRepeater.itemAt(index) + group._checked = false + // Expand next group + if (index + 1 < checkListRepeater.count) { + group = checkListRepeater.itemAt(index + 1) + group.enabled = true + group._checked = true + } + } + _passed = passed + } + + // We delay the updates when a group passes so the user can see all items green for a moment prior to hiding + Timer { + id: delayedGroupPassed + interval: 750 + + property int index + + onTriggered: _handleGroupPassedChanged(index, true /* passed */) + } + + Column { + id: mainColumn + width: 40*ScreenTools.defaultFontPixelWidth + spacing: 0.8*ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: 0.6*ScreenTools.defaultFontPixelWidth + anchors.leftMargin: 1.5*ScreenTools.defaultFontPixelWidth + + function groupPassedChanged(index, passed) { + if (passed) { + delayedGroupPassed.index = index + delayedGroupPassed.restart() + } else { + _handleGroupPassedChanged(index, passed) + } + } + + // Header/title of checklist + Item { + width: parent.width + height: 1.75*ScreenTools.defaultFontPixelHeight + + QGCLabel { + text: qsTr("Pre-Flight Checklist %1").arg(_passed ? qsTr("(passed)") : "") + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + font.pointSize: ScreenTools.mediumFontPointSize + } + QGCButton { + id: resetButton + width: 1.2*ScreenTools.defaultFontPixelHeight + height: 1.2*ScreenTools.defaultFontPixelHeight + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + opacity : 0.2+0.8*(QGroundControl.multiVehicleManager.vehicles.count > 0) + tooltip: qsTr("Reset the checklist (e.g. after a vehicle reboot)") + + onClicked: model.reset() + + Image { source:"/qmlimages/MapSyncBlack.svg" ; anchors.fill: parent } + } + } + + // All check list items + Repeater { + id: checkListRepeater + } + } // Column +} //Rectangle diff --git a/src/Settings/VideoSettings.h b/src/Settings/VideoSettings.h index 431e5a3..5b27721 100644 --- a/src/Settings/VideoSettings.h +++ b/src/Settings/VideoSettings.h @@ -41,6 +41,7 @@ public: Q_PROPERTY(QString udp265VideoSource READ udp265VideoSource CONSTANT) Q_PROPERTY(QString tcpVideoSource READ tcpVideoSource CONSTANT) Q_PROPERTY(QString mpegtsVideoSource READ mpegtsVideoSource CONSTANT) + Q_PROPERTY(QString disabledVideoSource READ disabledVideoSource CONSTANT) bool streamConfigured (); QString rtspVideoSource () { return videoSourceRTSP; } @@ -48,6 +49,7 @@ public: QString udp265VideoSource () { return videoSourceUDPH265; } QString tcpVideoSource () { return videoSourceTCP; } QString mpegtsVideoSource () { return videoSourceMPEGTS; } + QString disabledVideoSource () { return videoDisabled; } static const char* videoSourceNoVideo; static const char* videoDisabled;