7import QGroundControl.FactControls
8import QGroundControl.Controls
10/// Base class for Remote Control Calibration (supports both RC and Joystick)
12 required property var controller
13 property Component additionalSetupComponent
14 property Component additionalMonitorComponent
16 // Controllers need access to these UI elements
17 property alias statusText: statusText
18 property alias cancelButton: cancelButton
19 property alias nextButton: nextButton
22 spacing: ScreenTools.defaultFontPixelHeight
24 property bool useDeadband: false
26 property real _channelValueDisplayWidth: ScreenTools.defaultFontPixelWidth * 30
27 property bool _deadbandActive: useDeadband
29 QGCPalette { id: qgcPal; colorGroupEnabled: root.enabled }
32 // Left Column - Attitude Controls display
34 Layout.alignment: Qt.AlignTop
35 spacing: ScreenTools.defaultFontPixelHeight
38 id: attitudeControlsLayout
39 Layout.fillWidth: true
40 spacing: ScreenTools.defaultFontPixelHeight
42 QGCLabel { text: qsTr("Attitude Controls") }
46 { name: qsTr("Pitch"), mapped: controller.pitchChannelMapped, value: controller.adjustedPitchChannelValue, deadband: controller.pitchDeadband },
47 { name: qsTr("Roll"), mapped: controller.rollChannelMapped, value: controller.adjustedRollChannelValue, deadband: controller.rollDeadband },
48 { name: qsTr("Yaw"), mapped: controller.yawChannelMapped, value: controller.adjustedYawChannelValue, deadband: controller.yawDeadband },
49 { name: qsTr("Throttle"), mapped: controller.throttleChannelMapped, value: controller.adjustedThrottleChannelValue, deadband: controller.throttleDeadband }
53 Layout.fillWidth: true
56 Layout.fillWidth: true
60 RemoteControlChannelValueDisplay {
61 Layout.preferredWidth: root._channelValueDisplayWidth
62 mode: RemoteControlChannelValueDisplay.MappedValue
63 channelValueMin: controller.channelValueMin
64 channelValueMax: controller.channelValueMax
65 channelMapped: modelData.mapped
66 channelValue: modelData.value
67 deadbandValue: modelData.deadband
68 deadbandEnabled: root._deadbandActive
74 text: qsTr("Aux Extensions")
75 visible: controller.pitchExtensionEnabled || controller.rollExtensionEnabled
80 { name: qsTr("Pitch"), extensionEnabled: controller.pitchExtensionEnabled, mapped: controller.pitchExtensionChannelMapped, value: controller.adjustedPitchExtensionChannelValue, deadband: controller.pitchExtensionDeadband },
81 { name: qsTr("Roll"), extensionEnabled: controller.rollExtensionEnabled, mapped: controller.rollExtensionChannelMapped, value: controller.adjustedRollExtensionChannelValue, deadband: controller.rollExtensionDeadband },
85 Layout.fillWidth: true
86 visible: modelData.extensionEnabled
89 Layout.fillWidth: true
93 RemoteControlChannelValueDisplay {
94 Layout.preferredWidth: root._channelValueDisplayWidth
95 mode: RemoteControlChannelValueDisplay.MappedValue
96 channelValueMin: controller.channelValueMin
97 channelValueMax: controller.channelValueMax
98 channelMapped: modelData.mapped
99 channelValue: modelData.value
100 deadbandValue: modelData.deadband
101 deadbandEnabled: root._deadbandActive
107 text: qsTr("Additional Axes")
108 visible: controller.additionalAxis1Enabled || controller.additionalAxis2Enabled || controller.additionalAxis3Enabled ||
109 controller.additionalAxis4Enabled || controller.additionalAxis5Enabled || controller.additionalAxis6Enabled
114 { name: qsTr("Aux 1"), extensionEnabled: controller.additionalAxis1Enabled, mapped: controller.additionalAxis1ChannelMapped, value: controller.adjustedAdditionalAxis1ChannelValue, deadband: controller.additionalAxis1Deadband },
115 { name: qsTr("Aux 2"), extensionEnabled: controller.additionalAxis2Enabled, mapped: controller.additionalAxis2ChannelMapped, value: controller.adjustedAdditionalAxis2ChannelValue, deadband: controller.additionalAxis2Deadband },
116 { name: qsTr("Aux 3"), extensionEnabled: controller.additionalAxis3Enabled, mapped: controller.additionalAxis3ChannelMapped, value: controller.adjustedAdditionalAxis3ChannelValue, deadband: controller.additionalAxis3Deadband },
117 { name: qsTr("Aux 4"), extensionEnabled: controller.additionalAxis4Enabled, mapped: controller.additionalAxis4ChannelMapped, value: controller.adjustedAdditionalAxis4ChannelValue, deadband: controller.additionalAxis4Deadband },
118 { name: qsTr("Aux 5"), extensionEnabled: controller.additionalAxis5Enabled, mapped: controller.additionalAxis5ChannelMapped, value: controller.adjustedAdditionalAxis5ChannelValue, deadband: controller.additionalAxis5Deadband },
119 { name: qsTr("Aux 6"), extensionEnabled: controller.additionalAxis6Enabled, mapped: controller.additionalAxis6ChannelMapped, value: controller.adjustedAdditionalAxis6ChannelValue, deadband: controller.additionalAxis6Deadband }
123 Layout.fillWidth: true
124 visible: modelData.extensionEnabled
127 Layout.fillWidth: true
131 RemoteControlChannelValueDisplay {
132 Layout.preferredWidth: root._channelValueDisplayWidth
133 mode: RemoteControlChannelValueDisplay.MappedValue
134 channelValueMin: controller.channelValueMin
135 channelValueMax: controller.channelValueMax
136 channelMapped: modelData.mapped
137 channelValue: modelData.value
138 deadbandValue: modelData.deadband
139 deadbandEnabled: root._deadbandActive
146 // Right Column - Stick Display
148 Layout.alignment: Qt.AlignTop
149 spacing: ScreenTools.defaultFontPixelHeight / 2
152 id: stickDisplayContainer
153 implicitWidth: stickDisplayLayout.width + _margins * 2
154 implicitHeight: stickDisplayLayout.height + _margins * 2
155 border.color: qgcPal.text
158 radius: ScreenTools.defaultBorderRadius
160 property real _margins: ScreenTools.defaultFontPixelHeight / 2
161 property real _stickAdjust: leftStickDisplay.width / 2 - _margins * 1.25
164 id: stickDisplayLayout
165 anchors.leftMargin: stickDisplayContainer._margins
166 anchors.topMargin: stickDisplayContainer._margins
167 anchors.left: parent.left
168 anchors.top: parent.top
169 spacing: stickDisplayContainer._margins
172 spacing: ScreenTools.defaultFontPixelWidth * 2
175 id: transmitterModeComboBox
176 model: [ qsTr("Mode 1"), qsTr("Mode 2"), qsTr("Mode 3"), qsTr("Mode 4") ]
177 enabled: !controller.calibrating
179 onActivated: (index) => controller.transmitterMode = index + 1
181 Component.onCompleted: currentIndex = controller.transmitterMode - 1
185 id: centeredThrottleCheckBox
186 text: qsTr("Centered Throttle")
187 checked: controller.centeredThrottle
188 enabled: !controller.calibrating
189 visible: !controller.joystickMode
191 onClicked: controller.centeredThrottle = checked
197 Layout.fillWidth: true
198 spacing: stickDisplayContainer._margins * 2
200 property color stickColor: controller.calibrating ? stickPal.buttonHighlight : stickPal.text
202 QGCPalette { id: stickPal; colorGroupEnabled: controller.calibrating }
206 Layout.alignment: Qt.AlignLeft
207 implicitWidth: ScreenTools.defaultFontPixelHeight * 5
208 implicitHeight: implicitWidth
209 radius: implicitWidth / 2
210 border.color: stickDisplayRow.stickColor
215 x: parent.width / 2 + stickDisplayContainer._stickAdjust * controller.stickDisplayPositions[0] - width / 2
216 y: parent.height / 2 + stickDisplayContainer._stickAdjust * -controller.stickDisplayPositions[1] - height / 2
217 width: ScreenTools.defaultFontPixelHeight
220 color: stickDisplayRow.stickColor
225 Layout.alignment: Qt.AlignRight
226 implicitWidth: leftStickDisplay.implicitWidth
227 implicitHeight: implicitWidth
228 radius: implicitWidth / 2
229 border.color: stickDisplayRow.stickColor
232 visible: !controller.singleStickDisplay
235 x: parent.width / 2 + stickDisplayContainer._stickAdjust * controller.stickDisplayPositions[2] - width / 2
236 y: parent.height / 2 + stickDisplayContainer._stickAdjust * -controller.stickDisplayPositions[3] - height / 2
237 width: ScreenTools.defaultFontPixelHeight
240 color: stickDisplayRow.stickColor
249 // Command Buttons and Status Text
251 Layout.preferredWidth: parent.width
252 spacing: ScreenTools.defaultFontPixelWidth
257 onClicked: controller.cancelButtonClicked()
261 text: qsTr("One-Sided")
262 visible: controller.oneSidedButtonVisible
263 onClicked: controller.oneSidedButtonClicked()
269 text: qsTr("Calibrate")
272 if (text === qsTr("Calibrate")) {
273 if (controller.channelCount < controller.minChannelCount) {
274 let errorMessage = ""
276 if (controller.joystickMode) {
277 title = qsTr("Joystick Not Ready")
278 errorMessage = qsTr("%1 axes or more are needed to fly. Joystick is reporting %2 axes.").arg(controller.minChannelCount).arg(controller.channelCount)
280 title = qsTr("Not Ready")
281 errorMessage = controller.channelCount === 0 ? qsTr("Please turn on RC transmitter.") : qsTr("%1 channels or more are needed to fly.").arg(controller.minChannelCount)
283 QGroundControl.showMessageDialog(root, title, errorMessage)
285 } else if (!controller.joystickMode) {
286 QGroundControl.showMessageDialog(root, qsTr("Zero Trims"),
287 qsTr("Before calibrating you should zero all your trims and subtrims. Click Ok to start Calibration.\n\n%1").arg(
288 (QGroundControl.multiVehicleManager.activeVehicle.px4Firmware ? "" : qsTr("Please ensure all motor power is disconnected AND all props are removed from the vehicle."))),
290 function() { controller.nextButtonClicked() })
294 controller.nextButtonClicked()
300 Layout.fillWidth: true
301 wrapMode: Text.WordWrap
307 Layout.fillWidth: true
312 // Additional Setup + Channel Monitor
314 Layout.fillWidth: true
315 spacing: ScreenTools.defaultFontPixelHeight
319 Layout.fillWidth: true
321 visible: additionalSetupComponent === undefined
325 id: additionalSetupLoader
326 Layout.alignment: Qt.AlignTop
327 sourceComponent: additionalSetupComponent
331 Layout.alignment: Qt.AlignTop
332 Layout.fillWidth: true
333 spacing: ScreenTools.defaultFontPixelHeight
335 RemoteControlChannelMonitor {
337 Layout.fillWidth: true
339 channelCount: controller.channelCount
340 channelValueMin: controller.channelValueMin
341 channelValueMax: controller.channelValueMax
345 onRawChannelValueChanged: (channel, channelValue) => channelMonitor.rawChannelValueChanged(channel, channelValue)
350 id: additionalMonitorLoader
351 Layout.preferredWidth: parent.width
352 sourceComponent: additionalMonitorComponent