5import QGroundControl.FactControls
6import QGroundControl.Controls
7import QGroundControl.AutoPilotPlugins.APM
10 property int instance: 1
11 property real verticalSpacing: ScreenTools.defaultFontPixelHeight / 2
12 property real horizontalSpacing: ScreenTools.defaultFontPixelWidth * 2
16 property real _sliderWidth: ScreenTools.defaultFontPixelWidth * 20
17 property var _controller: gimbalParams.controller
18 property var _rcRateFact: gimbalParams.rcRateFact
20 function _servoChannelCount() {
22 while (_controller.parameterExists(-1, "SERVO" + servoIndex + "_FUNCTION")) {
28 function _rcChannelCount() {
30 while (_controller.parameterExists(-1, "RC" + rcIndex + "_OPTION")) {
36 function _servoChannelModel() {
37 let model = [ qsTr("Disabled") ]
38 let channelCount = _servoChannelCount()
39 for (let i = 1; i <= channelCount; i++) {
40 model.push(qsTr("Channel ") + i)
45 function _rcChannelModel() {
46 let model = [ qsTr("Disabled") ]
47 let channelCount = _rcChannelCount()
48 for (let i = 1; i <= channelCount; i++) {
49 model.push(qsTr("Channel ") + i)
54 APMGimbalParams { id: gimbalParams; instance: control.instance }
57 Layout.fillWidth: false
58 spacing: horizontalSpacing
59 visible: gimbalParams.instanceCount > 0
61 LabelledFactComboBox {
62 label: qsTr("Gimbal Type")
63 fact: gimbalParams.typeFact
65 comboBoxPreferredWidth: ScreenTools.defaultFontPixelWidth * 30
68 LabelledFactComboBox {
69 label: qsTr("Default Mode")
70 fact: gimbalParams.defaultModeFact
72 comboBoxPreferredWidth: ScreenTools.defaultFontPixelWidth * 30
73 visible: fact !== null
78 sourceComponent: gimbalParams.paramsAvailable ? configComponent : rebootRequiredComponent
85 spacing: verticalSpacing
88 heading: qsTr("Neutral Position")
91 spacing: horizontalSpacing
93 LabelledFactTextField {
94 Layout.fillWidth: true
96 fact: gimbalParams.neutralYFact
99 LabelledFactTextField {
100 Layout.fillWidth: true
102 fact: gimbalParams.neutralZFact
105 LabelledFactTextField {
106 Layout.fillWidth: true
108 fact: gimbalParams.neutralXFact
113 SettingsGroupLayout {
114 heading: qsTr("Retracted Position")
117 spacing: horizontalSpacing
119 LabelledFactTextField {
120 Layout.fillWidth: true
122 fact: gimbalParams.retractYFact
125 LabelledFactTextField {
126 Layout.fillWidth: true
128 fact: gimbalParams.retractZFact
131 LabelledFactTextField {
132 Layout.fillWidth: true
134 fact: gimbalParams.retractXFact
139 SettingsGroupLayout {
140 heading: qsTr("Axis Constraints")
145 axisLabel: qsTr("Pitch"),
146 minFact: gimbalParams.pitchMinFact,
147 maxFact: gimbalParams.pitchMaxFact
150 axisLabel: qsTr("Yaw"),
151 minFact: gimbalParams.yawMinFact,
152 maxFact: gimbalParams.yawMaxFact
155 axisLabel: qsTr("Roll"),
156 minFact: gimbalParams.rollMinFact,
157 maxFact: gimbalParams.rollMaxFact
162 spacing: verticalSpacing
165 text: modelData.axisLabel
169 spacing: horizontalSpacing
171 LabelledFactTextField {
172 Layout.fillWidth: true
173 label: qsTr("Min Angle")
174 fact: modelData.minFact
177 LabelledFactTextField {
178 Layout.fillWidth: true
179 label: qsTr("Max Angle")
180 fact: modelData.maxFact
187 SettingsGroupLayout {
188 heading: qsTr("RC Targetting")
191 spacing: horizontalSpacing
195 { comboLabel: qsTr("Pitch"), optionValue: 213 },
196 { comboLabel: qsTr("Yaw"), optionValue: 214 },
197 { comboLabel: qsTr("Roll"), optionValue: 212 }
201 id: outputChannelCombo
202 label: modelData.comboLabel
203 comboBoxPreferredWidth: ScreenTools.defaultFontPixelWidth * 30
204 model: _rcChannelModel()
206 Component.onCompleted: {
207 let maxRcChannel = _rcChannelCount()
208 for (let rcIndex = 1; rcIndex <= maxRcChannel; rcIndex++) {
209 let parameterName = "RC" + rcIndex + "_OPTION"
210 let functionFact = _controller.getParameterFact(-1, parameterName)
211 if (functionFact.value == modelData.optionValue) {
212 currentIndex = rcIndex
220 if (currentIndex == 0) {
222 let maxRcChannel = _rcChannelCount()
223 for (let rcIndex = 1; rcIndex <= maxRcChannel; rcIndex++) {
224 let parameterName = "RC" + rcIndex + "_OPTION"
225 let functionFact = _controller.getParameterFact(-1, parameterName)
226 if (functionFact.value == modelData.optionValue) {
227 functionFact.rawValue = 0
233 let rcIndex = currentIndex
234 let parameterName = "RC" + rcIndex + "_OPTION"
235 _controller.getParameterFact(-1, parameterName).rawValue = modelData.optionValue
245 spacing: horizontalSpacing
248 text: qsTr("Angle Control")
249 checked: !(_rcRateFact.rawValue > 0)
250 onClicked: _rcRateFact.rawValue = 0
254 text: qsTr("Rate Control")
255 checked: _rcRateFact.rawValue > 0
256 onClicked: _rcRateFact.rawValue = 90
259 LabelledFactTextField {
260 Layout.fillWidth: true
268 SettingsGroupLayout {
269 heading: qsTr("Servo Controlled Gimbal")
270 visible: gimbalParams.typeFact.rawValue === 1
274 { axisLabel: qsTr("Pitch"), functionValue: 7, stabilizeFact: gimbalParams.pitchLeadFact },
275 { axisLabel: qsTr("Yaw"), functionValue: 6, stabilizeFact: null },
276 { axisLabel: qsTr("Roll"), functionValue: 8, stabilizeFact: gimbalParams.rollLeadFact }
280 spacing: verticalSpacing
282 property bool servoChannelValid: outputChannelCombo.currentIndex > 0
283 property int validServoChannel: servoChannelValid ? outputChannelCombo.currentIndex : 1
284 property string servoPrefix: "SERVO" + validServoChannel + "_"
285 property bool hasStabilizeParam: modelData.stabilizeFact !== null
288 Layout.fillWidth: false
289 spacing: horizontalSpacing
292 text: modelData.axisLabel
296 text: qsTr("Servo Reversed")
297 fact: _controller.getParameterFact(-1, servoPrefix + "REVERSED")
298 enabled: servoChannelValid
303 Layout.fillWidth: hasStabilizeParam
304 spacing: horizontalSpacing
307 Layout.fillWidth: hasStabilizeParam
308 id: outputChannelCombo
309 label: qsTr("Output Channel")
310 comboBoxPreferredWidth: ScreenTools.defaultFontPixelWidth * 30
311 model: _servoChannelModel()
313 Component.onCompleted: {
314 let maxServoChannel = _servoChannelCount()
315 for (let servoIndex = 1; servoIndex <= maxServoChannel; servoIndex++) {
316 let parameterName = "SERVO" + servoIndex + "_FUNCTION"
317 let functionFact = _controller.getParameterFact(-1, parameterName)
318 if (functionFact.value == modelData.functionValue) {
319 currentIndex = servoIndex
327 if (currentIndex == 0) {
329 let maxServoChannel = _servoChannelCount()
330 for (let servoIndex = 1; servoIndex <= maxServoChannel; servoIndex++) {
331 let parameterName = "SERVO" + servoIndex + "_FUNCTION"
332 let functionFact = _controller.getParameterFact(-1, parameterName)
333 if (functionFact.value == modelData.functionValue) {
334 functionFact.rawValue = 0
340 let servoIndex = currentIndex
341 let parameterName = "SERVO" + servoIndex + "_FUNCTION"
342 _controller.getParameterFact(-1, parameterName).rawValue = modelData.functionValue
346 LabelledFactTextField {
347 Layout.fillWidth: true
348 label: qsTr("Stabilization Lead")
349 fact: modelData.stabilizeFact
350 visible: hasStabilizeParam
351 enabled: servoChannelValid
356 Layout.alignment: Qt.AlignHCenter
357 Layout.fillWidth: true
358 spacing: horizontalSpacing
359 enabled: servoChannelValid
361 LabelledFactTextField {
362 Layout.fillWidth: true
363 label: qsTr("Min PWM")
364 fact: _controller.getParameterFact(-1, servoPrefix + "MIN")
367 LabelledFactTextField {
368 Layout.fillWidth: true
369 label: qsTr("Max PWM")
370 fact: _controller.getParameterFact(-1, servoPrefix + "MAX")
380 id: rebootRequiredComponent
383 text: qsTr("Gimbal settings will be available after rebooting the vehicle.")
384 visible: gimbalParams.typeFact.rawValue !== 0