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
169 DroneModelDjiF450 {
170 id: droneDji3DModel
171
172 altitudeBias: _altitudeBias
173 gpsRef: _backendQml.gpsRef
174 modelScale: Qt.vector3d(0.05, 0.05, 0.05)
175 vehicle: _vehicle
176 }
177
178 Viewer3DInstancing {
179 id: waypointInstancing
180
181 }
182
183 Model {
184 id: _waypointConeModel
185
186 instancing: waypointInstancing
187 instancingLodMax: 5000
188 opacity: 0.8
189 pickable: true
190 source: "#Cone"
191
192 materials: DefaultMaterial {
193 diffuseColor: "white"
194 }
195 }
196
197 Repeater3D {
198 model: missionWaypointListModel
199
200 delegate: Node {
201 position: Qt.vector3d(model.x * 10, model.y * 10, (model.z + _altitudeBias) * 10)
202
203 LookAtNode {
204 position.x: -6
205 position.z: 30
206 target: _camera
207
208 QGCLabel {
209 color: "black"
210 font.pixelSize: 20
211 text: (model.itemName === "W") ? String(model.index) : model.itemName
212 }
213 }
214 }
215 }
216
217 Viewer3DInstancing {
218 id: pathInstancing
219
220 }
221
222 Model {
223 instancing: pathInstancing
224 instancingLodMax: 8000
225 source: "#Cylinder"
226
227 materials: DefaultMaterial {
228 diffuseColor: "white"
229 }
230 }
231
232 Connections {
233 function onVisualItemsReset() {
234 addMissionItemsToListModel();
235 addSegmentToMissionPathModel();
236 }
237
238 enabled: target !== null
239 target: _missionController
240 }
241
242 Connections {
243 function onGpsRefChanged() {
244 addMissionItemsToListModel();
245 addSegmentToMissionPathModel();
246 }
247
248 enabled: target !== null
249 target: _backendQml
250 }
251
252 Connections {
253 function onHomePositionChanged() {
254 if (_rtlActive) {
255 addMissionItemsToListModel();
256 addSegmentToMissionPathModel();
257 }
258 }
259
260 enabled: target !== null
261 target: _vehicle
262 }
263}