QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SafetyComponent.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Layouts
4
5import QGroundControl
6import QGroundControl.FactControls
7import QGroundControl.Controls
8
9SetupPage {
10 id: safetyPage
11 pageComponent: pageComponent
12 Component {
13 id: pageComponent
14
15 Item {
16 width: Math.max(availableWidth, outerColumn.width)
17 height: outerColumn.height
18
19 FactPanelController {
20 id: controller
21 }
22
23 readonly property string hitlParam: "SYS_HITL"
24
25 property real _margins: ScreenTools.defaultFontPixelHeight
26 property real _labelWidth: ScreenTools.defaultFontPixelWidth * 30
27 property real _editFieldWidth: ScreenTools.defaultFontPixelWidth * 20
28 property real _imageHeight: ScreenTools.defaultFontPixelHeight * 3
29 property real _imageWidth: _imageHeight * 2
30
31 property Fact _enableLogging: controller.getParameterFact(-1, "SDLOG_MODE")
32 property Fact _fenceAction: controller.getParameterFact(-1, "GF_ACTION")
33 property Fact _fenceRadius: controller.getParameterFact(-1, "GF_MAX_HOR_DIST")
34 property Fact _fenceAlt: controller.getParameterFact(-1, "GF_MAX_VER_DIST")
35 property Fact _rtlLandDelay: controller.getParameterFact(-1, "RTL_LAND_DELAY")
36 property Fact _lowBattAction: controller.getParameterFact(-1, "COM_LOW_BAT_ACT")
37 property Fact _rcLossAction: controller.getParameterFact(-1, "NAV_RCL_ACT")
38 property Fact _dlLossAction: controller.getParameterFact(-1, "NAV_DLL_ACT")
39 property Fact _disarmLandDelay: controller.getParameterFact(-1, "COM_DISARM_LAND")
40 property Fact _collisionPrevention: controller.getParameterFact(-1, "CP_DIST")
41 property Fact _landSpeedMC: controller.getParameterFact(-1, "MPC_LAND_SPEED", false)
42 property bool _hitlAvailable: controller.parameterExists(-1, hitlParam)
43 property Fact _hitlEnabled: controller.getParameterFact(-1, hitlParam, false)
44
45 ColumnLayout {
46 id: outerColumn
47 spacing: _margins
48 anchors.horizontalCenter: parent.horizontalCenter
49
50 QGCLabel {
51 text: qsTr("Low Battery Failsafe Trigger")
52 }
53
54 Rectangle {
55 width: mainRow.width + (_margins * 2)
56 height: mainRow.height + (_margins * 2)
57 color: qgcPal.windowShade
58 Row {
59 id: mainRow
60 spacing: _margins
61 anchors.centerIn: parent
62 Item {
63 width: _imageWidth
64 height: _imageHeight
65 anchors.verticalCenter: parent.verticalCenter
66 Image {
67 mipmap: true
68 fillMode: Image.PreserveAspectFit
69 source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/LowBatteryLight.svg" : "/qmlimages/LowBattery.svg"
70 height: _imageHeight
71 anchors.centerIn: parent
72 }
73 }
74 GridLayout {
75 columns: 2
76 anchors.verticalCenter: parent.verticalCenter
77
78 QGCLabel {
79 text: qsTr("Failsafe Action:")
80 Layout.minimumWidth:_labelWidth
81 Layout.fillWidth: true
82 }
83 FactComboBox {
84 fact: _lowBattAction
85 indexModel: false
86 Layout.minimumWidth:_editFieldWidth
87 Layout.fillWidth: true
88 }
89
90 QGCLabel {
91 text: qsTr("Battery Warn Level:")
92 Layout.fillWidth: true
93 }
94 FactTextField {
95 fact: controller.getParameterFact(-1, "BAT_LOW_THR")
96 Layout.fillWidth: true
97 }
98
99 QGCLabel {
100 text: qsTr("Battery Failsafe Level:")
101 Layout.fillWidth: true
102 }
103 FactTextField {
104 fact: controller.getParameterFact(-1, "BAT_CRIT_THR")
105 Layout.fillWidth: true
106 }
107
108 QGCLabel {
109 text: qsTr("Battery Emergency Level:")
110 Layout.fillWidth: true
111 }
112 FactTextField {
113 fact: controller.getParameterFact(-1, "BAT_EMERGEN_THR")
114 Layout.fillWidth: true
115 }
116 }
117 }
118 }
119
120 QGCLabel {
121 text: qsTr("Object Detection")
122 }
123
124 Rectangle {
125 width: mainRow.width + (_margins * 2)
126 height: odRow.height + (_margins * 2)
127 color: qgcPal.windowShade
128 Row {
129 id: odRow
130 spacing: _margins
131 anchors.centerIn: parent
132 Item {
133 width: _imageWidth
134 height: _imageHeight
135 anchors.verticalCenter: parent.verticalCenter
136 QGCColoredImage {
137 color: qgcPal.text
138 source: "/qmlimages/ObjectAvoidance.svg"
139 height: _imageHeight
140 width: _imageHeight * 2
141 anchors.centerIn: parent
142 }
143 }
144 GridLayout {
145 columns: 2
146 anchors.verticalCenter: parent.verticalCenter
147
148 QGCLabel {
149 text: qsTr("Collision Prevention:")
150 Layout.minimumWidth:_labelWidth
151 Layout.fillWidth: true
152 }
153 QGCComboBox {
154 model: [qsTr("Disabled"), qsTr("Enabled")]
155 enabled: _collisionPrevention
156 Layout.minimumWidth:_editFieldWidth
157 Layout.fillWidth: true
158 currentIndex: _collisionPrevention ? (_collisionPrevention.rawValue > 0 ? 1 : 0) : 0
159 onActivated: (index) => {
160 if(_collisionPrevention) {
161 _collisionPrevention.value = index > 0 ? 5 : -1
162 console.log('Collision prevention enabled: ' + _collisionPrevention.value)
163 showObstacleDistanceOverlayCheckBox.checked = _collisionPrevention.value > 0
164 }
165 }
166 }
167
168 QGCLabel {
169 text: qsTr("Minimum Distance: (") + QGroundControl.unitsConversion.appSettingsHorizontalDistanceUnitsString + ")"
170 Layout.fillWidth: true
171 Layout.alignment: Qt.AlignVCenter
172 }
173 QGCSlider {
174 width: _editFieldWidth
175 enabled: _collisionPrevention && _collisionPrevention.rawValue > 0
176 Layout.minimumWidth:_editFieldWidth
177 Layout.minimumHeight: ScreenTools.defaultFontPixelHeight * 2
178 Layout.fillWidth: true
179 Layout.fillHeight: true
180 to: QGroundControl.unitsConversion.metersToAppSettingsHorizontalDistanceUnits(15)
181 from: QGroundControl.unitsConversion.metersToAppSettingsHorizontalDistanceUnits(1)
182 stepSize: 1
183 displayValue: true
184 live: false
185 Layout.alignment: Qt.AlignVCenter
186 value: {
187 if (_collisionPrevention && _collisionPrevention.rawValue > 0) {
188 return QGroundControl.unitsConversion.metersToAppSettingsHorizontalDistanceUnits(_collisionPrevention.rawValue)
189 } else {
190 return 1;
191 }
192 }
193 onValueChanged: {
194 if(_collisionPrevention) {
195 //-- Negative means disabled
196 if(_collisionPrevention.rawValue >= 0) {
197 _collisionPrevention.rawValue = QGroundControl.unitsConversion.appSettingsHorizontalDistanceUnitsToMeters(value)
198 }
199 }
200 }
201 }
202
203 FactCheckBox {
204 id: showObstacleDistanceOverlayCheckBox
205 text: qsTr("Show obstacle distance overlay")
206 visible: _showObstacleDistanceOverlay.visible
207 fact: _showObstacleDistanceOverlay
208
209 property Fact _showObstacleDistanceOverlay: QGroundControl.settingsManager.flyViewSettings.showObstacleDistanceOverlay
210 }
211 }
212 }
213 }
214
215 QGCLabel {
216 text: qsTr("RC Loss Failsafe Trigger")
217 }
218
219 Rectangle {
220 width: mainRow.width + (_margins * 2)
221 height: rcLossGrid.height + (_margins * 2)
222 color: qgcPal.windowShade
223 Row {
224 id: rcLossGrid
225 spacing: _margins
226 anchors.centerIn: parent
227 Item {
228 width: _imageWidth
229 height: _imageHeight
230 anchors.verticalCenter: parent.verticalCenter
231 Image {
232 mipmap: true
233 fillMode: Image.PreserveAspectFit
234 source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/RCLossLight.svg" : "/qmlimages/RCLoss.svg"
235 height: _imageHeight
236 anchors.centerIn: parent
237 }
238 }
239 GridLayout {
240 columns: 2
241 anchors.verticalCenter: parent.verticalCenter
242
243 QGCLabel {
244 text: qsTr("Failsafe Action:")
245 Layout.minimumWidth:_labelWidth
246 Layout.fillWidth: true
247 }
248 FactComboBox {
249 fact: _rcLossAction
250 indexModel: false
251 Layout.minimumWidth:_editFieldWidth
252 Layout.fillWidth: true
253 }
254
255 QGCLabel {
256 text: qsTr("RC Loss Timeout:")
257 Layout.fillWidth: true
258 }
259 FactTextField {
260 fact: controller.getParameterFact(-1, "COM_RC_LOSS_T")
261 Layout.fillWidth: true
262 }
263 }
264 }
265 }
266
267 QGCLabel {
268 text: qsTr("Data Link Loss Failsafe Trigger")
269 }
270
271 Rectangle {
272 width: mainRow.width + (_margins * 2)
273 height: dataLinkLossGrid.height + (_margins * 2)
274 color: qgcPal.windowShade
275 Row {
276 id: dataLinkLossGrid
277 spacing: _margins
278 anchors.centerIn: parent
279 Item {
280 width: _imageWidth
281 height: _imageHeight
282 anchors.verticalCenter: parent.verticalCenter
283 Image {
284 mipmap: true
285 fillMode: Image.PreserveAspectFit
286 source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/DatalinkLossLight.svg" : "/qmlimages/DatalinkLoss.svg"
287 height: _imageHeight
288 anchors.centerIn: parent
289 }
290 }
291 GridLayout {
292 columns: 2
293 anchors.verticalCenter: parent.verticalCenter
294
295 QGCLabel {
296 text: qsTr("Failsafe Action:")
297 Layout.minimumWidth:_labelWidth
298 Layout.fillWidth: true
299 }
300 FactComboBox {
301 fact: _dlLossAction
302 indexModel: false
303 Layout.minimumWidth:_editFieldWidth
304 Layout.fillWidth: true
305 }
306
307 QGCLabel {
308 text: qsTr("Data Link Loss Timeout:")
309 Layout.fillWidth: true
310 }
311 FactTextField {
312 fact: controller.getParameterFact(-1, "COM_DL_LOSS_T")
313 Layout.fillWidth: true
314 }
315 }
316 }
317 }
318
319 QGCLabel {
320 text: qsTr("Geofence Failsafe Trigger")
321 }
322
323 Rectangle {
324 width: mainRow.width + (_margins * 2)
325 height: geoFenceGrid.height + (_margins * 2)
326 color: qgcPal.windowShade
327 Row {
328 id: geoFenceGrid
329 spacing: _margins
330 anchors.centerIn: parent
331 Item {
332 width: _imageWidth
333 height: _imageHeight
334 anchors.verticalCenter: parent.verticalCenter
335 Image {
336 mipmap: true
337 fillMode: Image.PreserveAspectFit
338 source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/GeoFenceLight.svg" : "/qmlimages/GeoFence.svg"
339 height: _imageHeight
340 anchors.centerIn: parent
341 }
342 }
343
344 GridLayout {
345 columns: 2
346 anchors.verticalCenter: parent.verticalCenter
347
348 QGCLabel {
349 text: qsTr("Action on breach:")
350 Layout.minimumWidth:_labelWidth
351 Layout.fillWidth: true
352 }
353 FactComboBox {
354 fact: _fenceAction
355 indexModel: false
356 Layout.minimumWidth:_editFieldWidth
357 Layout.fillWidth: true
358 }
359
360 QGCCheckBox {
361 id: fenceRadiusCheckBox
362 text: qsTr("Max Radius:")
363 checked: _fenceRadius.value > 0
364 onClicked: _fenceRadius.value = checked ? 100 : 0
365 Layout.fillWidth: true
366 }
367 FactTextField {
368 fact: _fenceRadius
369 enabled: fenceRadiusCheckBox.checked
370 Layout.fillWidth: true
371 }
372
373 QGCCheckBox {
374 id: fenceAltMaxCheckBox
375 text: qsTr("Max Altitude:")
376 checked: _fenceAlt ? _fenceAlt.value > 0 : false
377 onClicked: _fenceAlt.value = checked ? 100 : 0
378 Layout.fillWidth: true
379 }
380 FactTextField {
381 fact: _fenceAlt
382 enabled: fenceAltMaxCheckBox.checked
383 Layout.fillWidth: true
384 }
385 }
386 }
387 }
388
389 QGCLabel {
390 text: qsTr("Return To Launch Settings")
391 }
392
393 Rectangle {
394 width: mainRow.width + (_margins * 2)
395 height: returnHomeGrid.height + (_margins * 2)
396 color: qgcPal.windowShade
397 Row {
398 id: returnHomeGrid
399 spacing: _margins
400 anchors.centerIn: parent
401 Item {
402 width: _imageWidth
403 height: _imageHeight
404 anchors.verticalCenter: parent.verticalCenter
405 QGCColoredImage {
406 color: qgcPal.text
407 source: controller.vehicle.fixedWing ? "/qmlimages/ReturnToHomeAltitude.svg" : "/qmlimages/ReturnToHomeAltitudeCopter.svg"
408 height: _imageHeight
409 width: _imageHeight * 2
410 anchors.centerIn: parent
411 }
412 }
413 GridLayout {
414 columns: 2
415 anchors.verticalCenter: parent.verticalCenter
416
417 QGCLabel {
418 text: qsTr("Climb to altitude of:")
419 Layout.minimumWidth: _labelWidth
420 Layout.fillWidth: true
421 }
422 FactTextField {
423 fact: controller.getParameterFact(-1, "RTL_RETURN_ALT")
424 Layout.minimumWidth: _editFieldWidth
425 Layout.fillWidth: true
426 }
427
428 QGCLabel {
429 text: qsTr("Return to launch, then:")
430 Layout.columnSpan: 2
431 }
432 Row {
433 Layout.columnSpan: 2
434 Item { width: ScreenTools.defaultFontPixelWidth; height: 1 }
435 QGCRadioButton {
436 id: homeLandRadio
437 checked: _rtlLandDelay ? _rtlLandDelay.value === 0 : false
438 text: qsTr("Land immediately")
439 onClicked: _rtlLandDelay.value = 0
440 }
441 }
442 Row {
443 Layout.columnSpan: 2
444 Item { width: ScreenTools.defaultFontPixelWidth; height: 1 }
445 QGCRadioButton {
446 id: homeLoiterNoLandRadio
447 checked: _rtlLandDelay ? _rtlLandDelay.value < 0 : false
448 text: qsTr("Loiter and do not land")
449 onClicked: _rtlLandDelay.value = -1
450 }
451 }
452 Row {
453 Layout.columnSpan: 2
454 Item { width: ScreenTools.defaultFontPixelWidth; height: 1 }
455 QGCRadioButton {
456 id: homeLoiterLandRadio
457 checked: _rtlLandDelay ? _rtlLandDelay.value > 0 : false
458 text: qsTr("Loiter and land after specified time")
459 onClicked: _rtlLandDelay.value = 60
460 }
461 }
462
463 QGCLabel {
464 text: qsTr("Loiter Time")
465 Layout.fillWidth: true
466 }
467 FactTextField {
468 fact: controller.getParameterFact(-1, "RTL_LAND_DELAY")
469 enabled: homeLoiterLandRadio.checked === true
470 Layout.fillWidth: true
471 }
472
473 QGCLabel {
474 text: qsTr("Loiter Altitude")
475 Layout.fillWidth: true
476 }
477 FactTextField {
478 fact: controller.getParameterFact(-1, "RTL_DESCEND_ALT")
479 enabled: homeLoiterLandRadio.checked === true || homeLoiterNoLandRadio.checked === true
480 Layout.fillWidth: true
481 }
482 }
483 }
484 }
485
486 QGCLabel {
487 text: qsTr("Land Mode Settings")
488 }
489
490 Rectangle {
491 width: mainRow.width + (_margins * 2)
492 height: landModeGrid.height + (_margins * 2)
493 color: qgcPal.windowShade
494 Row {
495 id: landModeGrid
496 spacing: _margins
497 anchors.centerIn: parent
498 Item {
499 width: _imageWidth
500 height: _imageHeight
501 anchors.verticalCenter: parent.verticalCenter
502 QGCColoredImage {
503 color: qgcPal.text
504 source: controller.vehicle.fixedWing ? "/qmlimages/LandMode.svg" : "/qmlimages/LandModeCopter.svg"
505 height: _imageHeight
506 width: _imageHeight
507 anchors.centerIn: parent
508 }
509 }
510 GridLayout {
511 columns: 2
512 anchors.verticalCenter: parent.verticalCenter
513
514 QGCLabel {
515 id: landVelocityLabel
516 text: qsTr("Landing Descent Rate:")
517 visible: controller.vehicle && !controller.vehicle.fixedWing
518 Layout.minimumWidth:_labelWidth
519 Layout.fillWidth: true
520 }
521 FactTextField {
522 fact: _landSpeedMC
523 visible: controller.vehicle && !controller.vehicle.fixedWing
524 Layout.minimumWidth:_editFieldWidth
525 Layout.fillWidth: true
526 }
527
528 QGCCheckBox {
529 id: disarmDelayCheckBox
530 text: qsTr("Disarm After:")
531 checked: _disarmLandDelay.value > 0
532 onClicked: _disarmLandDelay.value = checked ? 2 : 0
533 Layout.fillWidth: true
534 }
535 FactTextField {
536 fact: _disarmLandDelay
537 enabled: disarmDelayCheckBox.checked
538 Layout.fillWidth: true
539 }
540 }
541 }
542 }
543
544 QGCLabel {
545 text: qsTr("Vehicle Telemetry Logging")
546 }
547
548 Rectangle {
549 width: mainRow.width + (_margins * 2)
550 height: loggingGrid.height + (_margins * 2)
551 color: qgcPal.windowShade
552 Row {
553 id: loggingGrid
554 spacing: _margins
555 anchors.centerIn: parent
556 Item {
557 width: _imageWidth
558 height: _imageHeight
559 anchors.verticalCenter: parent.verticalCenter
560 Image {
561 mipmap: true
562 fillMode: Image.PreserveAspectFit
563 source: qgcPal.globalTheme === QGCPalette.Light ? "/qmlimages/no-logging-light.svg" : "/qmlimages/no-logging.svg"
564 height: _imageHeight
565 anchors.centerIn: parent
566 }
567 }
568 GridLayout {
569 columns: 2
570 anchors.verticalCenter: parent.verticalCenter
571 QGCLabel {
572 text: qsTr("Telemetry logging to vehicle storage:")
573 Layout.minimumWidth:_labelWidth
574 Layout.fillWidth: true
575 }
576 QGCComboBox {
577 model: [qsTr("Disabled"), qsTr("Enabled")]
578 enabled: _enableLogging
579 Layout.minimumWidth:_editFieldWidth
580 Layout.fillWidth: true
581 Component.onCompleted: {
582 currentIndex = _enableLogging ? (_enableLogging.value >= 0 ? 1 : 0) : 0
583 }
584 onActivated: (index) => {
585 if(_enableLogging) {
586 _enableLogging.value = index > 0 ? 0 : -1
587 }
588 }
589 }
590 }
591 }
592 }
593
594 QGCLabel {
595 text: qsTr("Hardware in the Loop Simulation")
596 visible: _hitlAvailable
597 }
598
599 Rectangle {
600 width: mainRow.width + (_margins * 2)
601 height: hitlGrid.height + (_margins * 2)
602 color: qgcPal.windowShade
603 visible: _hitlAvailable
604 Row {
605 id: hitlGrid
606 spacing: _margins
607 anchors.centerIn: parent
608 Item {
609 width: _imageWidth
610 height: _imageHeight
611 anchors.verticalCenter: parent.verticalCenter
612 QGCColoredImage {
613 color: qgcPal.text
614 source: "/qmlimages/HITL.svg"
615 height: _imageHeight
616 width: _imageHeight
617 anchors.centerIn: parent
618 }
619 }
620 GridLayout {
621 columns: 2
622 anchors.verticalCenter: parent.verticalCenter
623 QGCLabel {
624 text: qsTr("HITL Enabled:")
625 Layout.minimumWidth:_labelWidth
626 Layout.fillWidth: true
627 }
628 FactComboBox {
629 fact: _hitlEnabled
630 indexModel: false
631 Layout.minimumWidth:_editFieldWidth
632 Layout.fillWidth: true
633 }
634 }
635 }
636 }
637 }
638 }
639 }
640}