QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GimbalIndicator.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Layouts
4
5import QGroundControl
6import QGroundControl.Controls
7import QGroundControl.FactControls
8
9Item {
10 id: control
11 objectName: "toolbar_gimbalIndicator"
12 anchors.top: parent.top
13 anchors.bottom: parent.bottom
14 width: gimbalIndicatorRow.width
15
16 property bool showIndicator: gimbalController.gimbals.count
17
18 property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle
19 property var gimbalController: activeVehicle.gimbalController
20 property var gimbals: gimbalController.gimbals
21 property var activeGimbal: gimbalController.activeGimbal
22 property var multiGimbalSetup: gimbalController.gimbals.count > 1
23 property bool joystickButtonsAvailable: activeVehicle ? joystickManager.activeJoystickEnabledForActiveVehicle : false
24 property bool showAzimuth: QGroundControl.settingsManager.gimbalControllerSettings.toolbarIndicatorShowAzimuth.rawValue
25
26 property var margins: ScreenTools.defaultFontPixelWidth
27 property var panelRadius: ScreenTools.defaultFontPixelWidth * 0.5
28 property var buttonHeight: height * 1.6
29 property var squareButtonPadding: ScreenTools.defaultFontPixelWidth
30 property var separatorHeight: buttonHeight * 0.9
31 property var settingsPanelVisible: false
32
33 property var _gimbalControllerSettings: QGroundControl.settingsManager.gimbalControllerSettings
34
35 /// Names a gimbal as "<manager compid>-<device id>", e.g. "154-1", so that gimbals
36 /// belonging to different managers can be told apart.
37 function gimbalName(gimbal) {
38 return gimbal ? (gimbal.managerCompid.valueString + "-" + gimbal.deviceId.valueString) : ""
39 }
40
41 QGCPalette { id: qgcPal }
42
43 Row {
44 id: gimbalIndicatorRow
45 anchors.top: parent.top
46 anchors.bottom: parent.bottom
47 spacing: ScreenTools.defaultFontPixelWidth / 2
48
49 Column {
50 anchors.top: parent.top
51 anchors.bottom: parent.bottom
52 spacing: 0
53
54 QGCColoredImage {
55 id: gimbalIndicatorIcon
56 anchors.horizontalCenter: parent.horizontalCenter
57 width: height
58 height: multiGimbalSetup ? parent.height - gimbalIdLabel.contentHeight : parent.height
59 source: "/res/CameraGimbal.png"
60 fillMode: Image.PreserveAspectFit
61 sourceSize.height: height
62 color: qgcPal.text
63
64 }
65
66 QGCLabel {
67 id: gimbalIdLabel
68 anchors.horizontalCenter: parent.horizontalCenter
69 font.pointSize: ScreenTools.smallFontPointSize
70 text: control.gimbalName(activeGimbal)
71 color: qgcPal.text
72 visible: multiGimbalSetup
73 }
74 }
75
76 // Telemetry and status indicator
77 GridLayout {
78 anchors.verticalCenter: parent.verticalCenter
79 columns: 2
80 rows: 2
81 rowSpacing: 0
82 columnSpacing: margins / 2
83
84 QGCLabel {
85 id: statusLabel
86 font.pointSize: ScreenTools.smallFontPointSize
87 text: activeGimbal && activeGimbal.retracted ?
88 qsTr("Retracted") :
89 (activeGimbal && activeGimbal.yawLock ? qsTr("Yaw locked") : qsTr("Yaw follow"))
90 color: qgcPal.text
91 Layout.columnSpan: 2
92 Layout.alignment: Qt.AlignHCenter
93 }
94 QGCLabel {
95 id: pitchLabel
96 font.pointSize: ScreenTools.smallFontPointSize
97 text: activeGimbal ? qsTr("P: ") + activeGimbal.absolutePitch.valueString : ""
98 color: qgcPal.text
99 }
100 QGCLabel {
101 id: panLabel
102 font.pointSize: ScreenTools.smallFontPointSize
103 text: activeGimbal ?
104 (showAzimuth ?
105 (qsTr("Az: ") + activeGimbal.absoluteYaw.valueString) :
106 (qsTr("Y: ") + activeGimbal.bodyYaw.valueString)) :
107 ""
108 color: qgcPal.text
109 }
110 }
111 }
112
113 MouseArea {
114 anchors.fill: parent
115 onClicked: mainWindow.showIndicatorDrawer(gimbalPopup, control)
116 }
117
118 Component {
119 id: gimbalPopup
120
121 ToolIndicatorPage {
122 showExpand: true
123 waitForParameters: false
124 contentComponent: gimbalContentComponent
125 expandedComponent: gimbalExpandedComponent
126 }
127 }
128
129 Component {
130 id: gimbalContentComponent
131
132 ColumnLayout {
133 spacing: ScreenTools.defaultFontPixelWidth / 2
134
135 SettingsGroupLayout {
136 heading: qsTr("Active Gimbal")
137 visible: multiGimbalSetup
138
139 QGCComboBox {
140 id: gimbalSelectorCombo
141 Layout.fillWidth: true
142 visible: multiGimbalSetup
143 onCurrentIndexChanged: gimbalController.activeGimbal = gimbalController.gimbals.get(currentIndex)
144
145 function _updateComboModel() {
146 let gimbalModel = []
147 let activeIndex = -1
148 for (var i = 0; i < gimbals.count; i++) {
149 var gimbal = gimbals.get(i)
150 gimbalModel.push(gimbal.deviceName ?
151 qsTr("%1 (%2)").arg(gimbal.deviceName).arg(control.gimbalName(gimbal)) :
152 qsTr("Gimbal %1").arg(control.gimbalName(gimbal)))
153 if (gimbal === activeGimbal) {
154 activeIndex = i
155 }
156 }
157 gimbalSelectorCombo.model = gimbalModel
158 gimbalSelectorCombo.currentIndex = activeIndex
159 }
160
161 Component.onCompleted: _updateComboModel()
162 Connections {
163 target: gimbals
164 function onCountChanged(count) { _updateComboModel() }
165 }
166 Instantiator {
167 model: gimbals
168 delegate: Connections {
169 target: object
170 function onDeviceNameChanged() { gimbalSelectorCombo._updateComboModel() }
171 }
172 }
173 }
174 }
175
176 SettingsGroupLayout {
177 heading: qsTr("Commands")
178 showDividers: false
179
180 QGCButton {
181 Layout.fillWidth: true
182 text: activeGimbal.yawLock ? qsTr("Yaw Follow") : qsTr("Yaw Lock")
183 visible: activeGimbal.supportsYawLock
184 onClicked: {
185 gimbalController.setGimbalYawLock(!activeGimbal.yawLock)
186 mainWindow.closeIndicatorDrawer()
187 }
188 }
189
190 QGCButton {
191 Layout.fillWidth: true
192 text: qsTr("Center")
193 onClicked: {
194 gimbalController.centerGimbal()
195 mainWindow.closeIndicatorDrawer()
196 }
197 }
198
199 QGCButton {
200 Layout.fillWidth: true
201 text: qsTr("Tilt 90")
202 onClicked: {
203 gimbalController.sendPitchBodyYaw(-90, 0)
204 mainWindow.closeIndicatorDrawer()
205 }
206 }
207
208 QGCButton {
209 Layout.fillWidth: true
210 text: qsTr("Point Home")
211 onClicked: {
212 activeVehicle.guidedModeROI(activeVehicle.homePosition, 0)
213 mainWindow.closeIndicatorDrawer()
214 }
215 }
216
217 QGCButton {
218 Layout.fillWidth: true
219 text: qsTr("Retract")
220 visible: activeGimbal.supportsRetract
221 onClicked: {
222 gimbalController.setGimbalRetract(true)
223 mainWindow.closeIndicatorDrawer()
224 }
225 }
226
227 QGCButton {
228 Layout.fillWidth: true
229 text: activeGimbal.gimbalHaveControl ? qsTr("Release Control") : qsTr("Acquire Control")
230 visible: _gimbalControllerSettings.toolbarIndicatorShowAcquireReleaseControl.rawValue
231 onClicked: {
232 activeGimbal.gimbalHaveControl ? gimbalController.releaseGimbalControl() : gimbalController.acquireGimbalControl()
233 mainWindow.closeIndicatorDrawer()
234 }
235 }
236 }
237 }
238 }
239
240 Component {
241 id: gimbalExpandedComponent
242
243 ColumnLayout {
244 spacing: ScreenTools.defaultFontPixelWidth / 2
245
246 SettingsGroupLayout {
247 heading: qsTr("On-Screen Control")
248 showDividers: false
249
250 FactCheckBoxSlider {
251 id: enableOnScreenControlCheckbox
252 Layout.fillWidth: true
253 text: qsTr("Enabled")
254 fact: _gimbalControllerSettings.enableOnScreenControl
255 }
256
257 FactCheckBoxSlider {
258 Layout.fillWidth: true
259 text: qsTr("Click and drag")
260 fact: _gimbalControllerSettings.clickAndDrag
261 visible: enableOnScreenControlCheckbox.checked
262 }
263
264 LabelledFactTextField {
265 label: qsTr("Horizontal FOV")
266 fact: _gimbalControllerSettings.cameraHFov
267 visible: enableOnScreenControlCheckbox.checked && !_gimbalControllerSettings.clickAndDrag.rawValue
268 }
269
270 LabelledFactTextField {
271 label: qsTr("Vertical FOV")
272 fact: _gimbalControllerSettings.cameraVFov
273 visible: enableOnScreenControlCheckbox.checked && !_gimbalControllerSettings.clickAndDrag.rawValue
274 }
275
276 LabelledFactTextField {
277 label: qsTr("Max speed")
278 fact: _gimbalControllerSettings.cameraSlideSpeed
279 visible: enableOnScreenControlCheckbox.checked && _gimbalControllerSettings.clickAndDrag.rawValue
280 }
281 }
282
283 SettingsGroupLayout {
284 heading: qsTr("Zoom speed")
285 showDividers: false
286
287 LabelledFactTextField {
288 label: qsTr("Max speed (min zoom)")
289 fact: _gimbalControllerSettings.zoomMaxSpeed
290 }
291
292 LabelledFactTextField {
293 label: qsTr("Min speed (max zoom)")
294 fact: _gimbalControllerSettings.zoomMinSpeed
295 }
296
297 }
298
299 SettingsGroupLayout {
300 LabelledFactTextField {
301 label: qsTr("Joystick buttons speed:")
302 fact: _gimbalControllerSettings.joystickButtonsSpeed
303 enabled: joystickButtonsAvailable && _gimbalControllerSettings.userVisible
304 }
305
306 FactCheckBoxSlider {
307 Layout.fillWidth: true
308 text: qsTr("Show gimbal Azimuth indicator in map")
309 fact: _gimbalControllerSettings.showAzimuthIndicatorOnMap
310 }
311
312 FactCheckBoxSlider {
313 Layout.fillWidth: true
314 text: qsTr("Use Azimuth instead of local yaw on top toolbar indicator")
315 fact: _gimbalControllerSettings.toolbarIndicatorShowAzimuth
316 }
317
318 FactCheckBoxSlider {
319 Layout.fillWidth: true
320 text: qsTr("Show Acquire/Release control button")
321 fact: _gimbalControllerSettings.toolbarIndicatorShowAcquireReleaseControl
322 }
323 }
324 }
325 }
326
327 Connections {
328 id: acquirePopupConnection
329 property bool isPopupOpen: false
330 target: gimbalController
331 function onShowAcquireGimbalControlPopup() {
332 if(!acquirePopupConnection.isPopupOpen){
333 acquirePopupConnection.isPopupOpen = true;
334 QGroundControl.showMessageDialog(
335 control,
336 qsTr("Request Gimbal Control?"),
337 qsTr("Command not sent. Another user has control of the gimbal."),
338 Dialog.Yes | Dialog.No,
339 gimbalController.acquireGimbalControl,
340 function() { acquirePopupConnection.isPopupOpen = false }
341 )
342 }
343 }
344 }
345}