diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 319f391e999252fe6f2babc8bfd5586422cf79da..f89dcb2c91ff48d16ca6a8fe18040ee6ac85f987 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -81,6 +81,7 @@ src/PlanView/FWLandingPatternMapVisual.qml src/PlanView/GeoFenceEditor.qml src/PlanView/GeoFenceMapVisuals.qml + src/QmlControls/HeightIndicator.qml src/QmlControls/IndicatorButton.qml src/QmlControls/JoystickThumbPad.qml src/QmlControls/LogReplayStatusBar.qml diff --git a/src/PlanView/FWLandingPatternMapVisual.qml b/src/PlanView/FWLandingPatternMapVisual.qml index 0c9e70e580bb2bd16d3e1c979a985def0a8844b1..fbb1a41e6e9a02a44ab9905420209ca25ce98351 100644 --- a/src/PlanView/FWLandingPatternMapVisual.qml +++ b/src/PlanView/FWLandingPatternMapVisual.qml @@ -11,6 +11,7 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 import QtLocation 5.3 import QtPositioning 5.3 +import QtQuick.Layouts 1.11 import QGroundControl 1.0 import QGroundControl.ScreenTools 1.0 @@ -29,13 +30,28 @@ Item { readonly property real _landingWidthMeters: 15 readonly property real _landingLengthMeters: 100 - property var _missionItem: object + property var _missionItem: object property var _mouseArea - property var _dragAreas: [ ] + property var _dragAreas: [ ] property var _flightPath - property real _landingAreaBearing: _missionItem.landingCoordinate.azimuthTo(_missionItem.loiterTangentCoordinate) + property real _landingAreaBearing: _missionItem.landingCoordinate.azimuthTo(_missionItem.loiterTangentCoordinate) property var _loiterPointObject property var _landingPointObject + property real _transitionAltitudeMeters + property real _midSlopeAltitudeMeters + property real _landingAltitudeMeters: _missionItem.landingAltitude.rawValue + property real _loiterAltitudeMeters: _missionItem.loiterAltitude.rawValue + + function _calcGlideSlopeHeights() { + var adjacent = _missionItem.landingCoordinate.distanceTo(_missionItem.loiterTangentCoordinate) + var opposite = _loiterAltitudeMeters - _landingAltitudeMeters + var angleRadians = Math.atan(opposite / adjacent) + var transitionDistance = _landingLengthMeters / 2 + var glideSlopeDistance = adjacent - transitionDistance + + _transitionAltitudeMeters = Math.tan(angleRadians) * (transitionDistance) + _midSlopeAltitudeMeters = Math.tan(angleRadians) * (transitionDistance + (glideSlopeDistance / 2)) + } function hideItemVisuals() { objMgr.destroyObjects() @@ -46,7 +62,9 @@ Item { _loiterPointObject = objMgr.createObject(loiterPointComponent, map, true /* parentObjectIsMap */) _landingPointObject = objMgr.createObject(landingPointComponent, map, true /* parentObjectIsMap */) - var rgComponents = [ flightPathComponent, loiterRadiusComponent, landingAreaComponent, landingAreaLabelComponent, glideSlopeComponent, glideSlopeLabelComponent ] + var rgComponents = [ flightPathComponent, loiterRadiusComponent, landingAreaComponent, landingAreaLabelComponent, + glideSlopeComponent, glideSlopeLabelComponent, transitionHeightComponent, midGlideSlopeHeightComponent, + approachHeightComponent ] objMgr.createObjects(rgComponents, map, true /* parentObjectIsMap */) } } @@ -105,6 +123,9 @@ Item { hideItemVisuals() } + on_LandingAltitudeMetersChanged: _calcGlideSlopeHeights() + on_LoiterAltitudeMetersChanged: _calcGlideSlopeHeights() + Connections { target: _missionItem @@ -139,8 +160,15 @@ Item { } } - onLandingCoordinateChanged: _setFlightPath() - onLoiterTangentCoordinateChanged: _setFlightPath() + onLandingCoordinateChanged: { + _calcGlideSlopeHeights() + _setFlightPath() + } + + onLoiterTangentCoordinateChanged: { + _calcGlideSlopeHeights() + _setFlightPath() + } } // Mouse area to capture landing point coordindate @@ -295,7 +323,7 @@ Item { id: glideSlopeLabelComponent MapQuickItem { - anchorPoint.x: 0 + anchorPoint.x: sourceItem._rawBearing > 180 ? sourceItem.contentWidth : 0 anchorPoint.y: sourceItem.contentHeight / 2 z: QGroundControl.zOrderMapItems visible: _missionItem.isCurrentItem @@ -320,7 +348,7 @@ Item { } transform: Rotation { - origin.x: 0 + origin.x: sourceItem._rawBearing > 180 ? sourceItem.contentWidth : 0 origin.y: glideSlopeLabel.contentHeight / 2 angle: glideSlopeLabel._adjustedBearing } @@ -402,4 +430,84 @@ Item { } } } + + Component { + id: transitionHeightComponent + + MapQuickItem { + anchorPoint.x: sourceItem.width / 2 + anchorPoint.y: 0 + z: QGroundControl.zOrderMapItems + visible: _missionItem.isCurrentItem + + sourceItem: HeightIndicator { + heightText: QGroundControl.metersToAppSettingsDistanceUnits(_transitionAltitudeMeters).toFixed(1) + " " + + QGroundControl.appSettingsDistanceUnitsString + } + + function recalc() { + var centeredCoordinate = _missionItem.landingCoordinate.atDistanceAndAzimuth(_landingLengthMeters / 2, _landingAreaBearing) + var angleIncrement = _landingAreaBearing > 180 ? -90 : 90 + coordinate = centeredCoordinate.atDistanceAndAzimuth(_landingWidthMeters, _landingAreaBearing + angleIncrement) + } + + Component.onCompleted: recalc() + + Connections { + target: _missionItem + onLandingCoordinateChanged: recalc() + onLoiterTangentCoordinateChanged: recalc() + } + + } + } + + Component { + id: midGlideSlopeHeightComponent + + MapQuickItem { + anchorPoint.x: sourceItem.width / 2 + anchorPoint.y: 0 + z: QGroundControl.zOrderMapItems + visible: _missionItem.isCurrentItem + + sourceItem: HeightIndicator { + heightText: QGroundControl.metersToAppSettingsDistanceUnits(_midSlopeAltitudeMeters).toFixed(1) + " " + + QGroundControl.appSettingsDistanceUnitsString + } + + function recalc() { + var transitionCoordinate = _missionItem.landingCoordinate.atDistanceAndAzimuth(_landingLengthMeters / 2, _landingAreaBearing) + var halfDistance = transitionCoordinate.distanceTo(_missionItem.loiterTangentCoordinate) / 2 + var centeredCoordinate = transitionCoordinate.atDistanceAndAzimuth(halfDistance, _landingAreaBearing) + var angleIncrement = _landingAreaBearing > 180 ? -90 : 90 + coordinate = centeredCoordinate.atDistanceAndAzimuth(_landingWidthMeters / 2, _landingAreaBearing + angleIncrement) + } + + Component.onCompleted: recalc() + + Connections { + target: _missionItem + onLandingCoordinateChanged: recalc() + onLoiterTangentCoordinateChanged: recalc() + } + + } + } + + Component { + id: approachHeightComponent + + MapQuickItem { + anchorPoint.x: sourceItem.width / 2 + anchorPoint.y: 0 + z: QGroundControl.zOrderMapItems + visible: _missionItem.isCurrentItem + coordinate: _missionItem.loiterTangentCoordinate + + sourceItem: HeightIndicator { + heightText: _missionItem.loiterAltitude.value.toFixed(1) + " " + QGroundControl.appSettingsDistanceUnitsString + } + } + } } diff --git a/src/QmlControls/HeightIndicator.qml b/src/QmlControls/HeightIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..ad86efe207efff4ee644d33d609b28fa5358a881 --- /dev/null +++ b/src/QmlControls/HeightIndicator.qml @@ -0,0 +1,46 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.11 + +import QGroundControl.ScreenTools 1.0 + +ColumnLayout { + spacing: 0 + + property color textColor: "white" + property string heightText: "30 ft" + + Rectangle { + width: ScreenTools.defaultFontPixelWidth * 3 + height: 1 + color: textColor + Layout.alignment: Qt.AlignHCenter + } + + Rectangle { + width: 1 + height: ScreenTools.defaultFontPixelWidth * 1 + color: textColor + Layout.alignment: Qt.AlignHCenter + } + + QGCLabel { + text: heightText + color: textColor + Layout.alignment: Qt.AlignHCenter + } + + Rectangle { + width: 1 + height: ScreenTools.defaultFontPixelWidth * 1 + color: textColor + Layout.alignment: Qt.AlignHCenter + } + + Rectangle { + width: ScreenTools.defaultFontPixelWidth * 3 + height: 1 + color: textColor + Layout.alignment: Qt.AlignHCenter + } +} diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir index b18732f4c1f17df14add6e9258610fc0c43b57e6..b0e8cb7c7154eadd5eea21be4d2d8896dcd225b0 100644 --- a/src/QmlControls/QGroundControl/Controls/qmldir +++ b/src/QmlControls/QGroundControl/Controls/qmldir @@ -19,6 +19,7 @@ FlightModeMenu 1.0 FlightModeMenu.qml GeoFenceEditor 1.0 GeoFenceEditor.qml GeoFenceMapVisuals 1.0 GeoFenceMapVisuals.qml HackFileDialog 1.0 HackFileDialog.qml +HeightIndicator 1.0 HeightIndicator.qml IndicatorButton 1.0 IndicatorButton.qml JoystickThumbPad 1.0 JoystickThumbPad.qml LogReplayStatusBar 1.0 LogReplayStatusBar.qml