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