QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
VTOLLandingPatternMapVisual.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtLocation
4import QtPositioning
5import QtQuick.Layouts
6
7import QGroundControl
8import QGroundControl.Controls
9import QGroundControl.FlightMap
10
11Item {
12 id: _root
13
14 property var map ///< Map control to place item in
15
16 signal clicked(int sequenceNumber)
17
18 readonly property real _landingWidthMeters: 15
19 readonly property real _landingLengthMeters: 100
20
21 property var _missionItem: object
22 property var _mouseArea
23 property var _dragAreas: [ ]
24 property var _flightPath
25 property var _loiterPointObject
26 property var _landingPointObject
27 property bool _useLoiterToAlt: _missionItem.useLoiterToAlt.rawValue
28 property real _landingAreaBearing: _missionItem.landingCoordinate.azimuthTo(_missionItem.slopeStartCoordinate)
29
30 function hideItemVisuals() {
31 objMgr.destroyObjects()
32 }
33
34 function showItemVisuals() {
35 if (objMgr.rgDynamicObjects.length === 0) {
36 _loiterPointObject = objMgr.createObject(finalApproachPointComponent, map, true /* parentObjectIsMap */)
37 _landingPointObject = objMgr.createObject(landingPointComponent, map, true /* parentObjectIsMap */)
38
39 var rgComponents = [ flightPathComponent, loiterRadiusComponent ]
40 objMgr.createObjects(rgComponents, map, true /* parentObjectIsMap */)
41 }
42 }
43
44 function hideMouseArea() {
45 if (_mouseArea) {
46 _mouseArea.destroy()
47 _mouseArea = undefined
48 }
49 }
50
51 function showMouseArea() {
52 if (!_mouseArea) {
53 _mouseArea = mouseAreaComponent.createObject(map)
54 }
55 }
56
57 function hideDragAreas() {
58 for (var i=0; i<_dragAreas.length; i++) {
59 _dragAreas[i].destroy()
60 }
61 _dragAreas = [ ]
62 }
63
64 function showDragAreas() {
65 if (_dragAreas.length === 0) {
66 _dragAreas.push(loiterDragAreaComponent.createObject(map))
67 _dragAreas.push(landDragAreaComponent.createObject(map))
68 }
69 }
70
71 function _setFlightPath() {
72 if (_useLoiterToAlt) {
73 _flightPath = [ _missionItem.slopeStartCoordinate, _missionItem.landingCoordinate ]
74 } else {
75 _flightPath = [ _missionItem.finalApproachCoordinate, _missionItem.landingCoordinate ]
76 }
77 }
78
79 QGCDynamicObjectManager {
80 id: objMgr
81 }
82
83 Component.onCompleted: {
84 if (_missionItem.landingCoordSet) {
85 showItemVisuals()
86 if (!_missionItem.flyView && _missionItem.isCurrentItem) {
87 showDragAreas()
88 }
89 _setFlightPath()
90 } else if (!_missionItem.flyView && _missionItem.isCurrentItem) {
91 showMouseArea()
92 }
93 }
94
95 Component.onDestruction: {
96 hideDragAreas()
97 hideMouseArea()
98 hideItemVisuals()
99 }
100
101 on_UseLoiterToAltChanged: _setFlightPath()
102
103 Connections {
104 target: _missionItem
105
106 onIsCurrentItemChanged: {
107 if (_missionItem.flyView) {
108 return
109 }
110 if (_missionItem.isCurrentItem) {
111 if (_missionItem.landingCoordSet) {
112 showDragAreas()
113 } else {
114 showMouseArea()
115 }
116 } else {
117 hideMouseArea()
118 hideDragAreas()
119 }
120 }
121
122 onLandingCoordSetChanged: {
123 if (_missionItem.flyView) {
124 return
125 }
126 if (_missionItem.landingCoordSet) {
127 hideMouseArea()
128 showItemVisuals()
129 showDragAreas()
130 _setFlightPath()
131 } else if (_missionItem.isCurrentItem) {
132 hideDragAreas()
133 showMouseArea()
134 }
135 }
136
137 onLandingCoordinateChanged: _setFlightPath()
138 onSlopeStartCoordinateChanged: _setFlightPath()
139 onFinalApproachCoordinateChanged: _setFlightPath()
140 }
141
142 // Mouse area to capture landing point coordindate
143 Component {
144 id: mouseAreaComponent
145
146 MouseArea {
147 anchors.fill: map
148 z: QGroundControl.zOrderMapItems + 1 // Over item indicators
149
150 readonly property int _decimalPlaces: 8
151
152 onClicked: (mouse) => {
153 var coordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y), false /* clipToViewPort */)
154 coordinate.latitude = coordinate.latitude.toFixed(_decimalPlaces)
155 coordinate.longitude = coordinate.longitude.toFixed(_decimalPlaces)
156 coordinate.altitude = coordinate.altitude.toFixed(_decimalPlaces)
157 _missionItem.landingCoordinate = coordinate
158 _missionItem.setLandingHeadingToTakeoffHeading()
159 }
160 }
161 }
162
163 // Control which is used to drag the final approach point
164 Component {
165 id: loiterDragAreaComponent
166
167 MissionItemIndicatorDrag {
168 mapControl: _root.map
169 itemIndicator: _loiterPointObject
170 itemCoordinate: _missionItem.finalApproachCoordinate
171
172 property bool _preventReentrancy: false
173
174 onItemCoordinateChanged: {
175 if (!_preventReentrancy) {
176 if (Drag.active) {
177 _preventReentrancy = true
178 var angle = _missionItem.landingCoordinate.azimuthTo(itemCoordinate)
179 var distance = _missionItem.landingCoordinate.distanceTo(_missionItem.finalApproachCoordinate)
180 _missionItem.finalApproachCoordinate = _missionItem.landingCoordinate.atDistanceAndAzimuth(distance, angle)
181 _preventReentrancy = false
182 }
183 }
184 }
185 }
186 }
187
188 // Control which is used to drag the landing point
189 Component {
190 id: landDragAreaComponent
191
192 MissionItemIndicatorDrag {
193 mapControl: _root.map
194 itemIndicator: _landingPointObject
195 itemCoordinate: _missionItem.landingCoordinate
196
197 onItemCoordinateChanged: _missionItem.landingCoordinate = itemCoordinate
198 }
199 }
200
201 // Flight path
202 Component {
203 id: flightPathComponent
204
205 MapPolyline {
206 z: QGroundControl.zOrderMapItems - 1 // Under item indicators
207 line.color: "#be781c"
208 line.width: 2
209 path: _flightPath
210 }
211 }
212
213 // Final approach point
214 Component {
215 id: finalApproachPointComponent
216
217 MapQuickItem {
218 anchorPoint.x: sourceItem.anchorPointX
219 anchorPoint.y: sourceItem.anchorPointY
220 z: QGroundControl.zOrderMapItems
221 coordinate: _missionItem.finalApproachCoordinate
222
223 sourceItem:
224 MissionItemIndexLabel {
225 index: _missionItem.sequenceNumber
226 label: _useLoiterToAlt ? qsTr("Loiter") : qsTr("Approach")
227 checked: _missionItem.isCurrentItem
228
229 onClicked: _root.clicked(_missionItem.sequenceNumber)
230 }
231 }
232 }
233
234 // Landing point
235 Component {
236 id: landingPointComponent
237
238 MapQuickItem {
239 anchorPoint.x: sourceItem.anchorPointX
240 anchorPoint.y: sourceItem.anchorPointY
241 z: QGroundControl.zOrderMapItems
242 coordinate: _missionItem.landingCoordinate
243
244 sourceItem:
245 MissionItemIndexLabel {
246 index: _missionItem.lastSequenceNumber
247 label: qsTr("Land")
248 checked: _missionItem.isCurrentItem
249
250 onClicked: _root.clicked(_missionItem.sequenceNumber)
251 }
252 }
253 }
254
255 Component {
256 id: loiterRadiusComponent
257
258 MapCircle {
259 z: QGroundControl.zOrderMapItems
260 center: _missionItem.finalApproachCoordinate
261 radius: _missionItem.loiterRadius.rawValue
262 border.width: 2
263 border.color: "green"
264 color: "transparent"
265 visible: _useLoiterToAlt
266 }
267 }
268}