QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SensorsSetup.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Dialogs
4import QtQuick.Layouts
5
6import QGroundControl
7import QGroundControl.FactControls
8import QGroundControl.Controls
9
10/// Page for sensor calibration. This control is used within the SensorsComponent control and can also be used
11/// standalone for custom uis. When using standadalone you can use the various show* bools to show/hide what you want.
12Item {
13 id: _root
14
15 property bool showSensorCalibrationCompass: true ///< true: Show this calibration button
16 property bool showSensorCalibrationGyro: true ///< true: Show this calibration button
17 property bool showSensorCalibrationAccel: true ///< true: Show this calibration button
18 property bool showSensorCalibrationLevel: true ///< true: Show this calibration button
19 property bool showSensorCalibrationAirspeed: true ///< true: Show this calibration button
20 property bool showSetOrientations: true ///< true: Show this calibration button
21 property bool showNextButton: false ///< true: Show Next button which will signal nextButtonClicked
22
23 signal nextButtonClicked
24
25 // Help text which is shown both in the status text area prior to pressing a cal button and in the
26 // pre-calibration dialog.
27
28 readonly property string boardRotationText: qsTr("If the orientation is in the direction of flight, select ROTATION_NONE.")
29 readonly property string compassRotationText: qsTr("If the orientation is in the direction of flight, select ROTATION_NONE.")
30
31 readonly property string compassHelp: qsTr("For Compass calibration you will need to rotate your vehicle through a number of positions.")
32 readonly property string gyroHelp: qsTr("For Gyroscope calibration you will need to place your vehicle on a surface and leave it still.")
33 readonly property string accelHelp: qsTr("For Accelerometer calibration you will need to place your vehicle on all six sides on a perfectly level surface and hold it still in each orientation for a few seconds.")
34 readonly property string levelHelp: qsTr("To level the horizon you need to place the vehicle in its level flight position and leave still.")
35 readonly property string airspeedHelp: qsTr("For Airspeed calibration you will need to keep your airspeed sensor out of any wind and then blow across the sensor. Do not touch the sensor or obstruct any holes during the calibration.")
36
37 readonly property string statusTextAreaDefaultText: qsTr("Start the individual calibration steps by clicking one of the buttons to the left.")
38
39 // Used to pass what type of calibration is being performed to the preCalibrationDialog
40 property string preCalibrationDialogType
41
42 // Used to pass help text to the preCalibrationDialog dialog
43 property string preCalibrationDialogHelp
44
45 property Fact cal_mag0_id: controller.getParameterFact(-1, "CAL_MAG0_ID")
46 property Fact cal_mag1_id: controller.getParameterFact(-1, "CAL_MAG1_ID")
47 property Fact cal_mag2_id: controller.getParameterFact(-1, "CAL_MAG2_ID")
48 property Fact cal_mag0_rot: controller.getParameterFact(-1, "CAL_MAG0_ROT")
49 property Fact cal_mag1_rot: controller.getParameterFact(-1, "CAL_MAG1_ROT")
50 property Fact cal_mag2_rot: controller.getParameterFact(-1, "CAL_MAG2_ROT")
51
52 property Fact cal_gyro0_id: controller.getParameterFact(-1, "CAL_GYRO0_ID")
53 property Fact cal_acc0_id: controller.getParameterFact(-1, "CAL_ACC0_ID")
54
55 property Fact sens_board_rot: controller.getParameterFact(-1, "SENS_BOARD_ROT")
56 property Fact sens_dpres_off: controller.getParameterFact(-1, "SENS_DPRES_OFF")
57
58 // Id > = signals compass available, rot < 0 signals internal compass
59 property bool showCompass0Rot: cal_mag0_id.value > 0 && cal_mag0_rot.value >= 0
60 property bool showCompass1Rot: cal_mag1_id.value > 0 && cal_mag1_rot.value >= 0
61 property bool showCompass2Rot: cal_mag2_id.value > 0 && cal_mag2_rot.value >= 0
62
63 property bool _sensorsHaveFixedOrientation: QGroundControl.corePlugin.options.sensorsHaveFixedOrientation
64 property int _buttonWidth: ScreenTools.defaultFontPixelWidth * 15
65 property string _calMagIdParamFormat: "CAL_MAG#_ID"
66 property string _calMagRotParamFormat: "CAL_MAG#_ROT"
67 property bool _allMagsDisabled: controller.parameterExists(-1, "SYS_HAS_MAG") ? controller.getParameterFact(-1, "SYS_HAS_MAG").value === 0 : false
68 property bool _boardOrientationChangeAllowed: !_sensorsHaveFixedOrientation && setOrientationsDialogShowBoardOrientation
69 property bool _compassOrientationChangeAllowed: !_sensorsHaveFixedOrientation
70 property int _arbitrarilyLargeMaxMagIndex: 50
71
72 function currentMagParamCount() {
73 if (_allMagsDisabled) {
74 return 0
75 } else {
76 for (var index=0; index<_arbitrarilyLargeMaxMagIndex; index++) {
77 var magIdParam = _calMagIdParamFormat.replace("#", index)
78 if (!controller.parameterExists(-1, magIdParam)) {
79 return index
80 }
81 }
82 console.warn("SensorSetup.qml:currentMagParamCount internal error")
83 return -1
84 }
85 }
86
87 function currentExternalMagCount() {
88 if (_allMagsDisabled) {
89 return 0
90 } else {
91 var externalMagCount = 0
92 for (var index=0; index<_arbitrarilyLargeMaxMagIndex; index++) {
93 var magIdParam = _calMagIdParamFormat.replace("#", index)
94 if (controller.parameterExists(-1, magIdParam)) {
95 var calMagIdFact = controller.getParameterFact(-1, magIdParam)
96 var calMagRotFact = controller.getParameterFact(-1, _calMagRotParamFormat.replace("#", index))
97 if (calMagIdFact.value > 0 && calMagRotFact.value >= 0) {
98 externalMagCount++
99 }
100 } else {
101 return externalMagCount
102 }
103 }
104 console.warn("SensorSetup.qml:currentExternalMagCount internal error")
105 return 0
106 }
107 }
108
109 function orientationsButtonVisible() {
110 if (_sensorsHaveFixedOrientation || !showSetOrientations) {
111 return false
112 } else if (_boardOrientationChangeAllowed) {
113 return true
114 } else if (_compassOrientationChangeAllowed && !_allMagsDisabled) {
115 for (var index=0; index<_arbitrarilyLargeMaxMagIndex; index++) {
116 var magIdParam = _calMagIdParamFormat.replace("#", index)
117 if (controller.parameterExists(-1, magIdParam)) {
118 var calMagIdFact = controller.parameterExists(-1, magIdParam)
119 var calMagRotFact = controller.parameterExists(-1, _calMagRotParamFormat.replace("#", index))
120 if (calMagIdFact.value > 0 && calMagRotFact.value >= 0) {
121 // Only external compasses can set orientation
122 return true
123 }
124 }
125 }
126 return false
127 } else {
128 return false
129 }
130 }
131
132 QGCPalette { id: qgcPal; colorGroupEnabled: true }
133
134 SensorsComponentController {
135 id: controller
136 statusLog: statusTextArea
137 progressBar: progressBar
138 compassButton: compassButton
139 gyroButton: gyroButton
140 accelButton: accelButton
141 airspeedButton: airspeedButton
142 levelButton: levelButton
143 cancelButton: cancelButton
144 setOrientationsButton: setOrientationsButton
145 orientationCalAreaHelpText: orientationCalAreaHelpText
146
147 onResetStatusTextArea: statusLog.text = statusTextAreaDefaultText
148
149 onMagCalComplete: {
150 setOrientationsButton.visible = orientationsButtonVisible()
151 setOrientationsDialogShowBoardOrientation = false
152 setOrientationsDialogFactory.open({ title: qsTr("Compass Calibration Complete"), showRebootVehicleButton: true })
153 }
154
155 onWaitingForCancelChanged: {
156 if (controller.waitingForCancel) {
157 waitForCancelDialogFactory.open()
158 }
159 }
160 }
161
162 QGCPopupDialogFactory {
163 id: waitForCancelDialogFactory
164
165 dialogComponent: waitForCancelDialogComponent
166 }
167
168 Component {
169 id: waitForCancelDialogComponent
170
171 QGCSimpleMessageDialog {
172 title: qsTr("Calibration Cancel")
173 text: qsTr("Waiting for Vehicle to response to Cancel. This may take a few seconds.")
174 buttons: 0
175
176 Connections {
177 target: controller
178
179 onWaitingForCancelChanged: {
180 if (!controller.waitingForCancel) {
181 close()
182 }
183 }
184 }
185 }
186 }
187
188 QGCPopupDialogFactory {
189 id: preCalibrationDialogFactory
190
191 dialogComponent: preCalibrationDialogComponent
192 }
193
194 Component {
195 id: preCalibrationDialogComponent
196
197 QGCPopupDialog {
198 buttons: Dialog.Cancel | Dialog.Ok
199
200 onAccepted: {
201 if (preCalibrationDialogType == "gyro") {
202 controller.calibrateGyro()
203 } else if (preCalibrationDialogType == "accel") {
204 controller.calibrateAccel()
205 } else if (preCalibrationDialogType == "level") {
206 controller.calibrateLevel()
207 } else if (preCalibrationDialogType == "compass") {
208 controller.calibrateCompass()
209 } else if (preCalibrationDialogType == "airspeed") {
210 controller.calibrateAirspeed()
211 }
212 }
213
214 ColumnLayout {
215 spacing: ScreenTools.defaultFontPixelHeight
216
217 QGCLabel {
218 Layout.minimumWidth: ScreenTools.defaultFontPixelWidth * 50
219 Layout.preferredWidth: innerColumn.width
220 wrapMode: Text.WordWrap
221 text: preCalibrationDialogHelp
222 }
223
224 Column {
225 id: innerColumn
226 spacing: parent.spacing
227
228 QGCLabel {
229 id: boardRotationHelp
230 wrapMode: Text.WordWrap
231 visible: !_sensorsHaveFixedOrientation && (preCalibrationDialogType == "accel" || preCalibrationDialogType == "compass")
232 text: qsTr("Set autopilot orientation before calibrating.")
233 }
234
235 Column {
236 visible: boardRotationHelp.visible
237 QGCLabel { text: qsTr("Autopilot Orientation") }
238
239 FactComboBox {
240 sizeToContents: true
241 fact: sens_board_rot
242 }
243
244 QGCLabel {
245 wrapMode: Text.WordWrap
246 text: qsTr("ROTATION_NONE indicates component points in direction of flight.")
247 }
248 }
249
250 QGCLabel {
251 wrapMode: Text.WordWrap
252 text: qsTr("Click Ok to start calibration.")
253 }
254 }
255 }
256 }
257 }
258
259 property bool setOrientationsDialogShowBoardOrientation: true
260
261 QGCPopupDialogFactory {
262 id: setOrientationsDialogFactory
263
264 dialogComponent: setOrientationsDialogComponent
265 }
266
267 Component {
268 id: setOrientationsDialogComponent
269
270 QGCPopupDialog {
271 buttons: Dialog.Ok
272
273 property bool showRebootVehicleButton: true
274
275 ColumnLayout {
276 spacing: ScreenTools.defaultFontPixelHeight
277
278 QGCLabel {
279 text: qsTr("Reboot the vehicle prior to flight.")
280 visible: showRebootVehicleButton
281 }
282
283 QGCButton {
284 text: qsTr("Reboot Vehicle")
285 visible: showRebootVehicleButton
286 onClicked: { controller.vehicle.rebootVehicle(); close() }
287 }
288
289 QGCLabel {
290 text: qsTr("Adjust orientations as needed.\n\nROTATION_NONE indicates component points in direction of flight.")
291 visible: _boardOrientationChangeAllowed || (_compassOrientationChangeAllowed && currentExternalMagCount() !== 0)
292 }
293
294 Column {
295 visible: _boardOrientationChangeAllowed
296
297 QGCLabel {
298 text: qsTr("Autopilot Orientation")
299 }
300
301 FactComboBox {
302 sizeToContents: true
303 fact: sens_board_rot
304 }
305 }
306
307 Repeater {
308 model: _compassOrientationChangeAllowed ? currentMagParamCount() : 0
309
310 Column {
311 // id > = signals compass available, rot < 0 signals internal compass
312 visible: calMagIdFact.value > 0 && calMagRotFact.value >= 0
313
314 property Fact calMagIdFact: controller.getParameterFact(-1, _calMagIdParamFormat.replace("#", index))
315 property Fact calMagRotFact: controller.getParameterFact(-1, _calMagRotParamFormat.replace("#", index))
316
317 QGCLabel {
318 text: qsTr("Mag %1 Orientation").arg(index)
319 }
320
321 FactComboBox {
322 sizeToContents: true
323 fact: parent.calMagRotFact
324 }
325 }
326 }
327 } // Column
328 } // QGCPopupDialog
329 } // Component - setOrientationsDialogComponent
330
331 QGCFlickable {
332 id: buttonFlickable
333 anchors.top: parent.top
334 anchors.bottom: parent.bottom
335 width: _buttonWidth
336 contentHeight: buttonColumn.height + buttonColumn.spacing
337
338 Column {
339 id: buttonColumn
340 spacing: ScreenTools.defaultFontPixelHeight / 2
341
342 IndicatorButton {
343 id: compassButton
344 width: _buttonWidth
345 text: qsTr("Compass")
346 indicatorGreen: cal_mag0_id.value !== 0
347 visible: !_allMagsDisabled && QGroundControl.corePlugin.options.showSensorCalibrationCompass && showSensorCalibrationCompass
348
349 onClicked: {
350 preCalibrationDialogType = "compass"
351 preCalibrationDialogHelp = compassHelp
352 preCalibrationDialogFactory.open({ title: qsTr("Calibrate Compass") })
353 }
354 }
355
356 IndicatorButton {
357 id: gyroButton
358 width: _buttonWidth
359 text: qsTr("Gyroscope")
360 indicatorGreen: cal_gyro0_id.value !== 0
361 visible: QGroundControl.corePlugin.options.showSensorCalibrationGyro && showSensorCalibrationGyro
362
363 onClicked: {
364 preCalibrationDialogType = "gyro"
365 preCalibrationDialogHelp = gyroHelp
366 preCalibrationDialogFactory.open({ title: qsTr("Calibrate Gyro") })
367 }
368 }
369
370 IndicatorButton {
371 id: accelButton
372 width: _buttonWidth
373 text: qsTr("Accelerometer")
374 indicatorGreen: cal_acc0_id.value !== 0
375 visible: QGroundControl.corePlugin.options.showSensorCalibrationAccel && showSensorCalibrationAccel
376
377 onClicked: {
378 preCalibrationDialogType = "accel"
379 preCalibrationDialogHelp = accelHelp
380 preCalibrationDialogFactory.open({ title: qsTr("Calibrate Accelerometer") })
381 }
382 }
383
384 IndicatorButton {
385 id: levelButton
386 width: _buttonWidth
387 text: qsTr("Level Horizon")
388 indicatorGreen: true
389 enabled: cal_acc0_id.value !== 0 && cal_gyro0_id.value !== 0
390 visible: QGroundControl.corePlugin.options.showSensorCalibrationLevel && showSensorCalibrationLevel
391
392 onClicked: {
393 preCalibrationDialogType = "level"
394 preCalibrationDialogHelp = levelHelp
395 preCalibrationDialogFactory.open({ title: qsTr("Level Horizon") })
396 }
397 }
398
399 IndicatorButton {
400 id: airspeedButton
401 width: _buttonWidth
402 text: qsTr("Airspeed")
403 visible: vehicleComponent.airspeedCalSupported &&
404 QGroundControl.corePlugin.options.showSensorCalibrationAirspeed &&
405 showSensorCalibrationAirspeed
406 indicatorGreen: sens_dpres_off.value !== 0
407
408 onClicked: {
409 preCalibrationDialogType = "airspeed"
410 preCalibrationDialogHelp = airspeedHelp
411 preCalibrationDialogFactory.open({ title: qsTr("Calibrate Airspeed") })
412 }
413 }
414
415 QGCButton {
416 id: cancelButton
417 width: _buttonWidth
418 text: qsTr("Cancel")
419 enabled: false
420 onClicked: controller.cancelCalibration()
421 }
422
423
424 QGCButton {
425 id: nextButton
426 width: _buttonWidth
427 text: qsTr("Next")
428 visible: showNextButton
429 onClicked: _root.nextButtonClicked()
430 }
431
432 QGCButton {
433 id: setOrientationsButton
434 width: _buttonWidth
435 text: qsTr("Orientations")
436 visible: orientationsButtonVisible()
437
438 onClicked: {
439 setOrientationsDialogShowBoardOrientation = true
440 setOrientationsDialogFactory.open({ title: qsTr("Set Orientations"), showRebootVehicleButton: false })
441 }
442 }
443 } // Column - Buttons
444 } // QGCFLickable - Buttons
445
446 Column {
447 anchors.leftMargin: ScreenTools.defaultFontPixelWidth / 2
448 anchors.left: buttonFlickable.right
449 anchors.right: parent.right
450 anchors.top: parent.top
451 anchors.bottom: parent.bottom
452
453 ProgressBar {
454 id: progressBar
455 anchors.left: parent.left
456 anchors.right: parent.right
457 }
458
459 Item { height: ScreenTools.defaultFontPixelHeight; width: 10 } // spacer
460
461 Item {
462 property int calDisplayAreaWidth: parent.width
463
464 width: parent.width
465 height: parent.height - y
466
467 TextArea {
468 id: statusTextArea
469 width: parent.calDisplayAreaWidth
470 height: parent.height
471 readOnly: true
472 text: statusTextAreaDefaultText
473 color: qgcPal.text
474 background: Rectangle { color: qgcPal.windowShade }
475 }
476
477 Rectangle {
478 id: orientationCalArea
479 width: parent.calDisplayAreaWidth
480 height: parent.height
481 visible: controller.showOrientationCalArea
482 color: qgcPal.windowShade
483
484 QGCLabel {
485 id: orientationCalAreaHelpText
486 anchors.margins: ScreenTools.defaultFontPixelWidth
487 anchors.top: orientationCalArea.top
488 anchors.left: orientationCalArea.left
489 width: parent.width
490 wrapMode: Text.WordWrap
491 font.pointSize: ScreenTools.mediumFontPointSize
492 }
493
494 Flow {
495 anchors.topMargin: ScreenTools.defaultFontPixelWidth
496 anchors.top: orientationCalAreaHelpText.bottom
497 anchors.bottom: parent.bottom
498 anchors.left: parent.left
499 anchors.right: parent.right
500 spacing: ScreenTools.defaultFontPixelWidth / 2
501
502 property real indicatorWidth: (width / 3) - (spacing * 2)
503 property real indicatorHeight: (height / 2) - spacing
504
505 VehicleRotationCal {
506 width: parent.indicatorWidth
507 height: parent.indicatorHeight
508 visible: controller.orientationCalDownSideVisible
509 calValid: controller.orientationCalDownSideDone
510 calInProgress: controller.orientationCalDownSideInProgress
511 calInProgressText: controller.orientationCalDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
512 imageSource: controller.orientationCalDownSideRotate ? "qrc:///qmlimages/VehicleDownRotate.png" : "qrc:///qmlimages/VehicleDown.png"
513 }
514 VehicleRotationCal {
515 width: parent.indicatorWidth
516 height: parent.indicatorHeight
517 visible: controller.orientationCalUpsideDownSideVisible
518 calValid: controller.orientationCalUpsideDownSideDone
519 calInProgress: controller.orientationCalUpsideDownSideInProgress
520 calInProgressText: controller.orientationCalUpsideDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
521 imageSource: controller.orientationCalUpsideDownSideRotate ? "qrc:///qmlimages/VehicleUpsideDownRotate.png" : "qrc:///qmlimages/VehicleUpsideDown.png"
522 }
523 VehicleRotationCal {
524 width: parent.indicatorWidth
525 height: parent.indicatorHeight
526 visible: controller.orientationCalNoseDownSideVisible
527 calValid: controller.orientationCalNoseDownSideDone
528 calInProgress: controller.orientationCalNoseDownSideInProgress
529 calInProgressText: controller.orientationCalNoseDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
530 imageSource: controller.orientationCalNoseDownSideRotate ? "qrc:///qmlimages/VehicleNoseDownRotate.png" : "qrc:///qmlimages/VehicleNoseDown.png"
531 }
532 VehicleRotationCal {
533 width: parent.indicatorWidth
534 height: parent.indicatorHeight
535 visible: controller.orientationCalTailDownSideVisible
536 calValid: controller.orientationCalTailDownSideDone
537 calInProgress: controller.orientationCalTailDownSideInProgress
538 calInProgressText: controller.orientationCalTailDownSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
539 imageSource: controller.orientationCalTailDownSideRotate ? "qrc:///qmlimages/VehicleTailDownRotate.png" : "qrc:///qmlimages/VehicleTailDown.png"
540 }
541 VehicleRotationCal {
542 width: parent.indicatorWidth
543 height: parent.indicatorHeight
544 visible: controller.orientationCalLeftSideVisible
545 calValid: controller.orientationCalLeftSideDone
546 calInProgress: controller.orientationCalLeftSideInProgress
547 calInProgressText: controller.orientationCalLeftSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
548 imageSource: controller.orientationCalLeftSideRotate ? "qrc:///qmlimages/VehicleLeftRotate.png" : "qrc:///qmlimages/VehicleLeft.png"
549 }
550 VehicleRotationCal {
551 width: parent.indicatorWidth
552 height: parent.indicatorHeight
553 visible: controller.orientationCalRightSideVisible
554 calValid: controller.orientationCalRightSideDone
555 calInProgress: controller.orientationCalRightSideInProgress
556 calInProgressText: controller.orientationCalRightSideRotate ? qsTr("Rotate") : qsTr("Hold Still")
557 imageSource: controller.orientationCalRightSideRotate ? "qrc:///qmlimages/VehicleRightRotate.png" : "qrc:///qmlimages/VehicleRight.png"
558 }
559 }
560 }
561
562 QGCButton {
563 text: qsTr("Factory reset")
564 width: _buttonWidth
565
566 anchors {
567 right: orientationCalArea.left
568 rightMargin: ScreenTools.defaultFontPixelWidth/2
569 bottom: orientationCalArea.bottom
570 }
571
572 onClicked: {
573 controller.resetFactoryParameters()
574 }
575 }
576 }
577 }
578}