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(qsTr("Gimbal %1").arg(control.gimbalName(gimbal)))
151 if (gimbal === activeGimbal) {
152 activeIndex = i
153 }
154 }
155 gimbalSelectorCombo.model = gimbalModel
156 gimbalSelectorCombo.currentIndex = activeIndex
157 }
158
159 Component.onCompleted: _updateComboModel()
160 Connections {
161 target: gimbals
162 function onCountChanged(count) { _updateComboModel() }
163 }
164 }
165 }
166
167 SettingsGroupLayout {
168 heading: qsTr("Commands")
169 showDividers: false
170
171 QGCButton {
172 Layout.fillWidth: true
173 text: activeGimbal.yawLock ? qsTr("Yaw Follow") : qsTr("Yaw Lock")
174 visible: activeGimbal.supportsYawLock
175 onClicked: {
176 gimbalController.setGimbalYawLock(!activeGimbal.yawLock)
177 mainWindow.closeIndicatorDrawer()
178 }
179 }
180
181 QGCButton {
182 Layout.fillWidth: true
183 text: qsTr("Center")
184 onClicked: {
185 gimbalController.centerGimbal()
186 mainWindow.closeIndicatorDrawer()
187 }
188 }
189
190 QGCButton {
191 Layout.fillWidth: true
192 text: qsTr("Tilt 90")
193 onClicked: {
194 gimbalController.sendPitchBodyYaw(-90, 0)
195 mainWindow.closeIndicatorDrawer()
196 }
197 }
198
199 QGCButton {
200 Layout.fillWidth: true
201 text: qsTr("Point Home")
202 onClicked: {
203 activeVehicle.guidedModeROI(activeVehicle.homePosition)
204 mainWindow.closeIndicatorDrawer()
205 }
206 }
207
208 QGCButton {
209 Layout.fillWidth: true
210 text: qsTr("Retract")
211 visible: activeGimbal.supportsRetract
212 onClicked: {
213 gimbalController.setGimbalRetract(true)
214 mainWindow.closeIndicatorDrawer()
215 }
216 }
217
218 QGCButton {
219 Layout.fillWidth: true
220 text: activeGimbal.gimbalHaveControl ? qsTr("Release Control") : qsTr("Acquire Control")
221 visible: _gimbalControllerSettings.toolbarIndicatorShowAcquireReleaseControl.rawValue
222 onClicked: {
223 activeGimbal.gimbalHaveControl ? gimbalController.releaseGimbalControl() : gimbalController.acquireGimbalControl()
224 mainWindow.closeIndicatorDrawer()
225 }
226 }
227 }
228 }
229 }
230
231 Component {
232 id: gimbalExpandedComponent
233
234 ColumnLayout {
235 spacing: ScreenTools.defaultFontPixelWidth / 2
236
237 SettingsGroupLayout {
238 heading: qsTr("On-Screen Control")
239 showDividers: false
240
241 FactCheckBoxSlider {
242 id: enableOnScreenControlCheckbox
243 Layout.fillWidth: true
244 text: qsTr("Enabled")
245 fact: _gimbalControllerSettings.enableOnScreenControl
246 }
247
248 FactCheckBoxSlider {
249 Layout.fillWidth: true
250 text: qsTr("Click and drag")
251 fact: _gimbalControllerSettings.clickAndDrag
252 visible: enableOnScreenControlCheckbox.checked
253 }
254
255 LabelledFactTextField {
256 label: qsTr("Horizontal FOV")
257 fact: _gimbalControllerSettings.cameraHFov
258 visible: enableOnScreenControlCheckbox.checked && !_gimbalControllerSettings.clickAndDrag.rawValue
259 }
260
261 LabelledFactTextField {
262 label: qsTr("Vertical FOV")
263 fact: _gimbalControllerSettings.cameraVFov
264 visible: enableOnScreenControlCheckbox.checked && !_gimbalControllerSettings.clickAndDrag.rawValue
265 }
266
267 LabelledFactTextField {
268 label: qsTr("Max speed")
269 fact: _gimbalControllerSettings.cameraSlideSpeed
270 visible: enableOnScreenControlCheckbox.checked && _gimbalControllerSettings.clickAndDrag.rawValue
271 }
272 }
273
274 SettingsGroupLayout {
275 heading: qsTr("Zoom speed")
276 showDividers: false
277
278 LabelledFactTextField {
279 label: qsTr("Max speed (min zoom)")
280 fact: _gimbalControllerSettings.zoomMaxSpeed
281 }
282
283 LabelledFactTextField {
284 label: qsTr("Min speed (max zoom)")
285 fact: _gimbalControllerSettings.zoomMinSpeed
286 }
287
288 }
289
290 SettingsGroupLayout {
291 LabelledFactTextField {
292 label: qsTr("Joystick buttons speed:")
293 fact: _gimbalControllerSettings.joystickButtonsSpeed
294 enabled: joystickButtonsAvailable && _gimbalControllerSettings.userVisible
295 }
296
297 FactCheckBoxSlider {
298 Layout.fillWidth: true
299 text: qsTr("Show gimbal Azimuth indicator in map")
300 fact: _gimbalControllerSettings.showAzimuthIndicatorOnMap
301 }
302
303 FactCheckBoxSlider {
304 Layout.fillWidth: true
305 text: qsTr("Use Azimuth instead of local yaw on top toolbar indicator")
306 fact: _gimbalControllerSettings.toolbarIndicatorShowAzimuth
307 }
308
309 FactCheckBoxSlider {
310 Layout.fillWidth: true
311 text: qsTr("Show Acquire/Release control button")
312 fact: _gimbalControllerSettings.toolbarIndicatorShowAcquireReleaseControl
313 }
314 }
315 }
316 }
317
318 Connections {
319 id: acquirePopupConnection
320 property bool isPopupOpen: false
321 target: gimbalController
322 function onShowAcquireGimbalControlPopup() {
323 if(!acquirePopupConnection.isPopupOpen){
324 acquirePopupConnection.isPopupOpen = true;
325 QGroundControl.showMessageDialog(
326 control,
327 "Request Gimbal Control?",
328 "Command not sent. Another user has control of the gimbal.",
329 Dialog.Yes | Dialog.No,
330 gimbalController.acquireGimbalControl,
331 function() { acquirePopupConnection.isPopupOpen = false }
332 )
333 }
334 }
335 }
336}