QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
Viewer3DVehicleItems.qml
Go to the documentation of this file.
1import QGroundControl
2import QGroundControl.Controls
3import QGroundControl.Viewer3D
4import QtQuick3D
5import QtQuick3D.Helpers
6
7Node {
8 id: vehicle3DBody
9
10 property var _altitudeBias: _viewer3DSetting.altitudeBias.rawValue
11 property var _backendQml: null
12 property Node _camera: null
13 property var _missionController: (_planMasterController) ? (_planMasterController.missionController) : (null)
14 property var _planMasterController: null
15 property bool _rtlActive: false
16 property var _vehicle: null
17 property var _viewer3DSetting: QGroundControl.settingsManager.viewer3DSettings
18 property alias waypointConeModel: _waypointConeModel
19 property alias waypointInstancing: waypointInstancing
20
21 function addMissionItemsToListModel() {
22 missionWaypointListModel.clear();
23 waypointInstancing.selectedIndex = -1;
24 waypointInstancing.clear();
25 var _geo2EnuCopy = geo2Enu;
26 var launchItemCoordinate = null;
27 var _missionItemPrevious = null;
28 _rtlActive = false;
29
30 for (var i = 0; i < _missionController.visualItems.count; i++) {
31 var _missionItem = _missionController.visualItems.get(i);
32 if (isLaunchItem(_missionItem)) {
33 launchItemCoordinate = _missionItem.coordinate;
34 continue;
35 }
36 if (isItemAcceptable(_missionItem)) {
37 if (isReturnToLaunchItem(_missionItem)) {
38 _rtlActive = true;
39 _geo2EnuCopy.coordinate = (_vehicle.homePosition) ? (_vehicle.homePosition) : (_missionItem.coordinate);
40 _geo2EnuCopy.coordinate.altitude = _missionItemPrevious.altitude.value;
41 } else {
42 _geo2EnuCopy.coordinate = _missionItem.coordinate;
43 _geo2EnuCopy.coordinate.altitude = _missionItem.altitude.value;
44 }
45 var name = getItemName(_missionItem);
46 var lx = _geo2EnuCopy.localCoordinate.x;
47 var ly = _geo2EnuCopy.localCoordinate.y;
48 var lz = _geo2EnuCopy.coordinate.altitude;
49 missionWaypointListModel.append({
50 "x": lx,
51 "y": ly,
52 "z": lz,
53 "itemName": name,
54 "index": _missionItem.sequenceNumber
55 });
56 waypointInstancing.addEntry(Qt.vector3d(lx * 10, ly * 10, (lz + _altitudeBias) * 10), Qt.vector3d(0.1, 0.1, 0.1), Quaternion.fromEulerAngles(Qt.vector3d(90, 0, 0)), waypointColor(name));
57 if (name === "L" || name === "W") {
58 _missionItemPrevious = _missionItem;
59 }
60 }
61 }
62 }
63
64 function addSegmentToMissionPathModel() {
65 pathInstancing.clear();
66 var _geo2EnuCopy = geo2Enu;
67
68 var _missionItem;
69 var _missionItemPrevious = null;
70 var launchItemCoordinate;
71
72 for (var i = 0; i < _missionController.visualItems.count; i++) {
73 _missionItem = _missionController.visualItems.get(i);
74 if (isLaunchItem(_missionItem)) {
75 launchItemCoordinate = _missionItem.coordinate;
76 continue;
77 }
78 if (_missionItem.isTakeoffItem) {
79 _missionItemPrevious = _missionItem;
80 continue;
81 }
82 if (_missionItemPrevious === null) {
83 continue;
84 }
85 if (getItemName(_missionItem) === "L" || getItemName(_missionItem) === "W") {
86 _geo2EnuCopy.coordinate = _missionItemPrevious.coordinate;
87 _geo2EnuCopy.coordinate.altitude = _missionItemPrevious.altitude.value;
88 var p1 = Qt.vector3d(_geo2EnuCopy.localCoordinate.x * 10, _geo2EnuCopy.localCoordinate.y * 10, (_geo2EnuCopy.coordinate.altitude + _altitudeBias) * 10);
89
90 if (isReturnToLaunchItem(_missionItem)) {
91 _geo2EnuCopy.coordinate = (_vehicle.homePosition) ? (_vehicle.homePosition) : (_missionItem.coordinate);
92 _geo2EnuCopy.coordinate.altitude = _missionItemPrevious.altitude.value;
93 } else {
94 _geo2EnuCopy.coordinate = _missionItem.coordinate;
95 _geo2EnuCopy.coordinate.altitude = _missionItem.altitude.value;
96 }
97 var p2 = Qt.vector3d(_geo2EnuCopy.localCoordinate.x * 10, _geo2EnuCopy.localCoordinate.y * 10, (_geo2EnuCopy.coordinate.altitude + _altitudeBias) * 10);
98
99 var color = isReturnToLaunchItem(_missionItem) ? "red" : "orange";
100 pathInstancing.addLineSegment(p1, p2, 8, color);
101 _missionItemPrevious = _missionItem;
102 }
103 }
104 }
105
106 function getItemName(missionItem) {
107 if (isLaunchItem(missionItem) || isReturnToLaunchItem(missionItem)) {
108 return qsTr("L");
109 }
110
111 if (missionItem.isTakeoffItem) {
112 return qsTr("T"); //Takeoff
113 }
114
115 if (missionItem.specifiesCoordinate) {
116 switch (missionItem.command) {
117 case 16:
118 return qsTr("W"); //Waypoint
119 case 22:
120 return qsTr("T"); //Takeoff
121 case 195:
122 return qsTr("R"); //ROI
123 case 201:
124 return qsTr("R"); //ROI DEPRECATED
125 }
126 }
127 return qsTr("null");
128 }
129
130 function isItemAcceptable(missionItem) {
131 const acceptableCmdIds = [16 // Waypoint
132 , 20 // Return To Launch
133 , 22 //Takeoff
134 , 195 // ROI
135 , 201 // ROI DEPRECATED
136 ,]; // based on MavCmdInfoCommon.json file
137 return acceptableCmdIds.includes(missionItem.command);
138 }
139
140 function isLaunchItem(missionItem) {
141 return missionItem.abbreviation === "L";
142 }
143
144 function isReturnToLaunchItem(missionItem) {
145 return missionItem.command === 20;
146 }
147
148 function waypointColor(itemName) {
149 if (itemName === "T")
150 return "green";
151 if (itemName === "R")
152 return "red";
153 if (itemName === "L")
154 return "orange";
155 return "black";
156 }
157
158 Viewer3DGeoCoordinateType {
159 id: geo2Enu
160
161 gpsRef: _backendQml.gpsRef
162 }
163
164 ListModel {
165 id: missionWaypointListModel
166 }
167
168 Component.onDestruction: {
169 // This is necessary insurance to prevent crashes after destruction when "keepSceneAlive" setting is disabled.
170 missionWaypointListModel.clear()
171 }
172
173 DroneModelDjiF450 {
174 id: droneDji3DModel
175
176 altitudeBias: _altitudeBias
177 gpsRef: _backendQml.gpsRef
178 modelScale: Qt.vector3d(0.05, 0.05, 0.05)
179 vehicle: _vehicle
180 }
181
182 Viewer3DInstancing {
183 id: waypointInstancing
184
185 }
186
187 Model {
188 id: _waypointConeModel
189
190 instancing: waypointInstancing
191 instancingLodMax: 5000
192 opacity: 0.8
193 pickable: true
194 source: "#Cone"
195
196 materials: DefaultMaterial {
197 diffuseColor: "white"
198 }
199 }
200
201 Repeater3D {
202 model: missionWaypointListModel
203
204 delegate: Node {
205 position: Qt.vector3d(model.x * 10, model.y * 10, (model.z + _altitudeBias) * 10)
206
207 LookAtNode {
208 position.x: -6
209 position.z: 30
210 target: _camera
211
212 QGCLabel {
213 color: "black"
214 font.pixelSize: 20
215 text: (model.itemName === "W") ? String(model.index) : model.itemName
216 }
217 }
218 }
219 }
220
221 Viewer3DInstancing {
222 id: pathInstancing
223
224 }
225
226 Model {
227 instancing: pathInstancing
228 instancingLodMax: 8000
229 source: "#Cylinder"
230
231 materials: DefaultMaterial {
232 diffuseColor: "white"
233 }
234 }
235
236 Connections {
237 function onVisualItemsReset() {
238 addMissionItemsToListModel();
239 addSegmentToMissionPathModel();
240 }
241
242 enabled: target !== null
243 target: _missionController
244 }
245
246 Connections {
247 function onGpsRefChanged() {
248 addMissionItemsToListModel();
249 addSegmentToMissionPathModel();
250 }
251
252 enabled: target !== null
253 target: _backendQml
254 }
255
256 Connections {
257 function onHomePositionChanged() {
258 if (_rtlActive) {
259 addMissionItemsToListModel();
260 addSegmentToMissionPathModel();
261 }
262 }
263
264 enabled: target !== null
265 target: _vehicle
266 }
267}