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
196 Layout.fillWidth: true
197 spacing: stickDisplayContainer._margins * 2
201 Layout.alignment: Qt.AlignLeft
202 implicitWidth: ScreenTools.defaultFontPixelHeight * 5
203 implicitHeight: implicitWidth
204 radius: implicitWidth / 2
205 border.color: qgcPal.buttonHighlight
210 x: parent.width / 2 + stickDisplayContainer._stickAdjust * controller.stickDisplayPositions[0] - width / 2
211 y: parent.height / 2 + stickDisplayContainer._stickAdjust * -controller.stickDisplayPositions[1] - height / 2
212 width: ScreenTools.defaultFontPixelHeight
215 color: qgcPal.buttonHighlight
220 Layout.alignment: Qt.AlignRight
221 implicitWidth: leftStickDisplay.implicitWidth
222 implicitHeight: implicitWidth
223 radius: implicitWidth / 2
224 border.color: qgcPal.buttonHighlight
227 visible: !controller.singleStickDisplay
230 x: parent.width / 2 + stickDisplayContainer._stickAdjust * controller.stickDisplayPositions[2] - width / 2
231 y: parent.height / 2 + stickDisplayContainer._stickAdjust * -controller.stickDisplayPositions[3] - height / 2
232 width: ScreenTools.defaultFontPixelHeight
235 color: qgcPal.buttonHighlight
244 // Command Buttons and Status Text
246 Layout.preferredWidth: parent.width
247 spacing: ScreenTools.defaultFontPixelWidth
252 onClicked: controller.cancelButtonClicked()
256 text: qsTr("One-Sided")
257 visible: controller.oneSidedButtonVisible
258 onClicked: controller.oneSidedButtonClicked()
264 text: qsTr("Calibrate")
267 if (text === qsTr("Calibrate")) {
268 if (controller.channelCount < controller.minChannelCount) {
269 let errorMessage = ""
271 if (controller.joystickMode) {
272 title = qsTr("Joystick Not Ready")
273 errorMessage = qsTr("%1 axes or more are needed to fly. Joystick is reporting %2 axes.").arg(controller.minChannelCount).arg(controller.channelCount)
275 title = qsTr("Not Ready")
276 errorMessage = controller.channelCount === 0 ? qsTr("Please turn on RC transmitter.") : qsTr("%1 channels or more are needed to fly.").arg(controller.minChannelCount)
278 QGroundControl.showMessageDialog(root, title, errorMessage)
280 } else if (!controller.joystickMode) {
281 QGroundControl.showMessageDialog(root, qsTr("Zero Trims"),
282 qsTr("Before calibrating you should zero all your trims and subtrims. Click Ok to start Calibration.\n\n%1").arg(
283 (QGroundControl.multiVehicleManager.activeVehicle.px4Firmware ? "" : qsTr("Please ensure all motor power is disconnected AND all props are removed from the vehicle."))),
285 function() { controller.nextButtonClicked() })
289 controller.nextButtonClicked()
295 Layout.fillWidth: true
296 wrapMode: Text.WordWrap
302 Layout.fillWidth: true
307 // Additional Setup + Channel Monitor
309 Layout.fillWidth: true
310 spacing: ScreenTools.defaultFontPixelHeight
314 Layout.fillWidth: true
316 visible: additionalSetupComponent === undefined
320 id: additionalSetupLoader
321 Layout.alignment: Qt.AlignTop
322 sourceComponent: additionalSetupComponent
326 Layout.alignment: Qt.AlignTop
327 Layout.fillWidth: true
328 spacing: ScreenTools.defaultFontPixelHeight
330 RemoteControlChannelMonitor {
332 Layout.fillWidth: true
334 channelCount: controller.channelCount
335 channelValueMin: controller.channelValueMin
336 channelValueMax: controller.channelValueMax
340 onRawChannelValueChanged: (channel, channelValue) => channelMonitor.rawChannelValueChanged(channel, channelValue)
345 id: additionalMonitorLoader
346 Layout.preferredWidth: parent.width
347 sourceComponent: additionalMonitorComponent