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
67 LabelledFactComboBox {
68 label: qsTr("Default Mode")
69 fact: gimbalParams.defaultModeFact
71 visible: fact !== null
76 sourceComponent: gimbalParams.paramsAvailable ? configComponent : rebootRequiredComponent
83 spacing: verticalSpacing
86 heading: qsTr("Neutral Position")
89 spacing: horizontalSpacing
91 LabelledFactTextField {
92 Layout.fillWidth: true
94 fact: gimbalParams.neutralYFact
97 LabelledFactTextField {
98 Layout.fillWidth: true
100 fact: gimbalParams.neutralZFact
103 LabelledFactTextField {
104 Layout.fillWidth: true
106 fact: gimbalParams.neutralXFact
111 SettingsGroupLayout {
112 heading: qsTr("Retracted Position")
115 spacing: horizontalSpacing
117 LabelledFactTextField {
118 Layout.fillWidth: true
120 fact: gimbalParams.retractYFact
123 LabelledFactTextField {
124 Layout.fillWidth: true
126 fact: gimbalParams.retractZFact
129 LabelledFactTextField {
130 Layout.fillWidth: true
132 fact: gimbalParams.retractXFact
137 SettingsGroupLayout {
138 heading: qsTr("Axis Constraints")
143 axisLabel: qsTr("Pitch"),
144 minFact: gimbalParams.pitchMinFact,
145 maxFact: gimbalParams.pitchMaxFact
148 axisLabel: qsTr("Yaw"),
149 minFact: gimbalParams.yawMinFact,
150 maxFact: gimbalParams.yawMaxFact
153 axisLabel: qsTr("Roll"),
154 minFact: gimbalParams.rollMinFact,
155 maxFact: gimbalParams.rollMaxFact
160 spacing: verticalSpacing
163 text: modelData.axisLabel
167 spacing: horizontalSpacing
169 LabelledFactTextField {
170 Layout.fillWidth: true
171 label: qsTr("Min Angle")
172 fact: modelData.minFact
175 LabelledFactTextField {
176 Layout.fillWidth: true
177 label: qsTr("Max Angle")
178 fact: modelData.maxFact
185 SettingsGroupLayout {
186 heading: qsTr("RC Targetting")
189 spacing: horizontalSpacing
193 { comboLabel: qsTr("Pitch"), optionValue: 213 },
194 { comboLabel: qsTr("Yaw"), optionValue: 214 },
195 { comboLabel: qsTr("Roll"), optionValue: 212 }
199 id: outputChannelCombo
200 label: modelData.comboLabel
201 model: _rcChannelModel()
203 Component.onCompleted: {
204 let maxRcChannel = _rcChannelCount()
205 for (var rcIndex = 1; rcIndex <= maxRcChannel; rcIndex++) {
206 var parameterName = "RC" + rcIndex + "_OPTION"
207 var functionFact = _controller.getParameterFact(-1, parameterName)
208 if (functionFact.value == modelData.optionValue) {
209 currentIndex = rcIndex
217 if (currentIndex == 0) {
219 let maxRcChannel = _rcChannelCount()
220 for (let rcIndex = 1; rcIndex <= maxRcChannel; rcIndex++) {
221 let parameterName = "RC" + rcIndex + "_OPTION"
222 let functionFact = _controller.getParameterFact(-1, parameterName)
223 if (functionFact.value == modelData.optionValue) {
224 functionFact.rawValue = 0
230 let rcIndex = currentIndex
231 let parameterName = "RC" + rcIndex + "_OPTION"
232 _controller.getParameterFact(-1, parameterName).rawValue = modelData.optionValue
242 spacing: horizontalSpacing
245 text: qsTr("Angle Control")
246 checked: !(_rcRateFact.rawValue > 0)
247 onClicked: _rcRateFact.rawValue = 0
251 text: qsTr("Rate Control")
252 checked: _rcRateFact.rawValue > 0
253 onClicked: _rcRateFact.rawValue = 90
256 LabelledFactTextField {
257 Layout.fillWidth: true
265 SettingsGroupLayout {
266 heading: qsTr("Servo Controlled Gimbal")
267 visible: gimbalParams.typeFact.rawValue === 1
271 { axisLabel: qsTr("Pitch"), functionValue: 7, stabilizeFact: gimbalParams.pitchLeadFact },
272 { axisLabel: qsTr("Yaw"), functionValue: 6, stabilizeFact: null },
273 { axisLabel: qsTr("Roll"), functionValue: 8, stabilizeFact: gimbalParams.rollLeadFact }
277 spacing: verticalSpacing
279 property bool servoChannelValid: outputChannelCombo.currentIndex > 0
280 property int validServoChannel: servoChannelValid ? outputChannelCombo.currentIndex : 1
281 property string servoPrefix: "SERVO" + validServoChannel + "_"
282 property bool hasStabilizeParam: modelData.stabilizeFact !== null
285 Layout.fillWidth: false
286 spacing: horizontalSpacing
289 text: modelData.axisLabel
293 text: qsTr("Servo Reversed")
294 fact: _controller.getParameterFact(-1, servoPrefix + "REVERSED")
295 enabled: servoChannelValid
300 Layout.fillWidth: hasStabilizeParam
301 spacing: horizontalSpacing
304 Layout.fillWidth: hasStabilizeParam
305 id: outputChannelCombo
306 label: qsTr("Output Channel")
307 model: _servoChannelModel()
309 Component.onCompleted: {
310 let maxServoChannel = _servoChannelCount()
311 for (var servoIndex = 1; servoIndex <= maxServoChannel; servoIndex++) {
312 var parameterName = "SERVO" + servoIndex + "_FUNCTION"
313 var functionFact = _controller.getParameterFact(-1, parameterName)
314 if (functionFact.value == modelData.functionValue) {
315 currentIndex = servoIndex
323 if (currentIndex == 0) {
325 let maxServoChannel = _servoChannelCount()
326 for (let servoIndex = 1; servoIndex <= maxServoChannel; servoIndex++) {
327 let parameterName = "SERVO" + servoIndex + "_FUNCTION"
328 let functionFact = _controller.getParameterFact(-1, parameterName)
329 if (functionFact.value == modelData.functionValue) {
330 functionFact.rawValue = 0
336 let servoIndex = currentIndex
337 let parameterName = "SERVO" + servoIndex + "_FUNCTION"
338 _controller.getParameterFact(-1, parameterName).rawValue = modelData.functionValue
342 LabelledFactTextField {
343 Layout.fillWidth: true
344 label: qsTr("Stabilization Lead")
345 fact: modelData.stabilizeFact
346 visible: hasStabilizeParam
347 enabled: servoChannelValid
352 Layout.alignment: Qt.AlignHCenter
353 Layout.fillWidth: true
354 spacing: horizontalSpacing
355 enabled: servoChannelValid
357 LabelledFactTextField {
358 Layout.fillWidth: true
359 label: qsTr("Min PWM")
360 fact: _controller.getParameterFact(-1, servoPrefix + "MIN")
363 LabelledFactTextField {
364 Layout.fillWidth: true
365 label: qsTr("Max PWM")
366 fact: _controller.getParameterFact(-1, servoPrefix + "MAX")
376 id: rebootRequiredComponent
379 text: qsTr("Gimbal settings will be available after rebooting the vehicle.")
380 visible: gimbalParams.typeFact.rawValue !== 0