QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GPSReceiverSettings.qml
Go to the documentation of this file.
1pragma ComponentBehavior: Bound
2
3import QtQuick
4import QtQuick.Layouts
5
6import QGroundControl
7import QGroundControl.Controls
8import QGroundControl.FactControls
9import QGroundControl.GPS
10
11SettingsGroupLayout {
12 id: root
13
14 property GPSReceiver receiver: QGroundControl.gpsManager.receiver
15 property RTKSettings settings: QGroundControl.settingsManager.rtkSettings
16 property SettingsFact autoConnectFact: settings.autoConnect as SettingsFact
17 property list<gpsSerialPortEntry> serialPorts: root.receiver.serialPortEntries
18 property list<int> serialBaudRates: root.receiver.serialBaudRates
19 /// Hosts that already show receiver errors elsewhere can hide the inline message.
20 property bool showErrorMessage: true
21
22 readonly property int role: settings.receiverRole.rawValue
23 readonly property bool configuredBase: role === RTKSettings.ConfiguredBase
24 readonly property int manufacturer: settings.baseReceiverManufacturers.rawValue
25 readonly property int baseMode: settings.useFixedBasePosition.rawValue
26 readonly property gpsReceiverPresentation presentation: receiver.capabilitiesFor(role, manufacturer)
27 // A pending automatic reconnect keeps the saved connection; stop it before editing.
28 readonly property bool _active: receiver.hasReceiver || receiver.reconnecting
29 readonly property bool _editable: !_active
30 readonly property int _connection: settings.connectionType.rawValue
31 readonly property bool _udp: receiver.effectiveConnectionType === RTKSettings.Udp
32 readonly property bool _tcp: receiver.effectiveConnectionType === RTKSettings.Tcp
33 readonly property bool _serial: receiver.effectiveConnectionType === RTKSettings.Serial
34 readonly property bool _connectionSupported: receiver.connectionSupported
35 readonly property list<string> _baseModeNames: settings.useFixedBasePosition.enumStrings
36 // Automatic detection words the Quectel notes for a receiver that may not be one.
37 readonly property string _quectelOnly: presentation.automatic
38 ? qsTr("Applies only if a Quectel receiver is identified.") + " " : ""
39
40 heading: qsTr("GNSS Receiver")
41
42 component Field: GPSField {
43 required property Fact fact
44 /// Shows the field when the setting itself is visible.
45 property bool shown: true
46 readonly property SettingsFact _setting: fact as SettingsFact
47
48 label: fact.label
49 visible: shown && (!_setting || _setting.userVisible)
50 }
51
52 component SettingField: Field {
53 id: textField
54 FactTextField {
55 Layout.fillWidth: true
56 Layout.minimumWidth: 0
57 fact: textField.fact
58 }
59 }
60
61 component ComboField: Field {
62 id: comboField
63 property alias comboBox: combo
64 FactComboBox {
65 id: combo
66 Layout.fillWidth: true
67 Layout.minimumWidth: 0
68 fact: comboField.fact
69 }
70 }
71
72 component SwitchField: Field {
73 id: switchField
74 property alias toggle: slider
75 FactCheckBoxSlider {
76 id: slider
77 text: ""
78 Accessible.name: switchField.fact.label
79 fact: switchField.fact
80 }
81 }
82
83 component ModeButton: QGCRadioButton {
84 Layout.fillWidth: true
85 Layout.minimumWidth: 0
86 focusPolicy: Qt.StrongFocus
87 wrapMode: Text.Wrap
88 }
89
90 ComboField {
91 fact: root.settings.receiverRole
92 comboBox.objectName: "rtkReceiverRole"
93 comboBox.enabled: root._editable
94 note: root.configuredBase
95 ? qsTr("QGroundControl configures a supported receiver as an RTK base station and forwards its RTCM corrections to vehicles.")
96 : qsTr("QGroundControl never configures this receiver. Its NMEA, u-blox UBX or Septentrio SBF position output provides the ground station position. Configure the receiver's output externally and select its existing baud rate. No survey-in status is inferred.")
97 }
98
99 SwitchField {
100 fact: root.settings.forwardReceiverRtcm
101 note: root.settings.forwardReceiverRtcm.shortDescription
102 shown: !root.configuredBase
103 toggle.objectName: "rtkForwardReceiverRtcm"
104 toggle.enabled: root._editable
105 }
106
107 ComboField {
108 fact: root.settings.baseReceiverManufacturers
109 shown: root.configuredBase
110 comboBox.objectName: "rtkManufacturer"
111 comboBox.enabled: root._editable
112
113 GPSNoteLabel {
114 objectName: "rtkAutomaticExplanation"
115 visible: root.presentation.automatic
116 text: root.settings.baseReceiverManufacturers.shortDescription
117 }
118 }
119
120 ComboField {
121 fact: root.settings.connectionType
122 comboBox.objectName: "rtkConnectionType"
123 comboBox.enabled: root._editable
124
125 GPSNoteLabel {
126 objectName: "rtkTcpOnly"
127 visible: !root.receiver.serialSupported && root._connection === RTKSettings.Serial
128 text: qsTr("Serial receivers are not supported on this platform, so the receiver connects over TCP.")
129 }
130 }
131
132 SettingField {
133 objectName: "rtkTcpHost"
134 fact: root.settings.tcpHost
135 enabled: root._editable
136 shown: root._tcp
137 }
138
139 SettingField {
140 objectName: "rtkTcpPort"
141 fact: root.settings.tcpPort
142 enabled: root._editable
143 shown: root._tcp
144 note: qsTr("Connect to a receiver's TCP port or a serial-to-TCP bridge. A bridge must already run the receiver link at 115200 baud; QGroundControl cannot change a bridge's rate.")
145 }
146
147 SettingField {
148 objectName: "rtkUdpPort"
149 fact: root.settings.udpPort
150 enabled: root._editable
151 shown: root._udp
152
153 GPSNoteLabel {
154 objectName: "rtkUdpExplanation"
155 warning: !root._connectionSupported
156 text: root._connectionSupported ? root.settings.udpPort.shortDescription
157 : qsTr("A configured base needs a serial or TCP connection. UDP only receives data.")
158 }
159 }
160
161 GPSReceiverSerialPort {
162 Layout.minimumWidth: 0
163 visible: root.receiver.serialSupported && root._serial
164 deviceFact: root.settings.serialDevice
165 baudFact: root.settings.serialBaudRate
166 serialPorts: root.serialPorts
167 serialBaudRates: root.serialBaudRates
168 anyDeviceLabel: root.configuredBase && root.autoConnectFact.rawValue ? qsTr("Any RTK receiver on USB") : ""
169 allowAutoBaud: !root.presentation.passive
170 editable: root._editable
171 }
172
173 GPSNoteLabel {
174 visible: root._editable && root.configuredBase
175 text: root.presentation.automatic
176 ? qsTr("If the identified receiver does not support the selected base mode, connecting fails and names the receiver. Auto baud tries every rate the supported receivers use.")
177 : !root.presentation.specificReceiver
178 ? qsTr("Select a receiver type and its connection to connect manually. Auto baud detects the rate of configurable receivers.")
179 : qsTr("Connect only the selected receiver; automatic connections configure it too. A USB adapter's identity only decides which USB ports are tried, not the GNSS manufacturer.")
180 }
181
182 GPSNoteLabel {
183 objectName: "rtkPersistentConfigurationWarning"
184 visible: root.presentation.restartOnConnect
185 text: root._quectelOnly + qsTr("Without permission to save, Quectel role and base settings must already match settings saved externally. The receiver restarts on connection. Survey-In counts accepted 1 Hz observations; its accuracy limit filters each observation and does not guarantee final position accuracy.")
186 }
187
188 GPSNoteLabel {
189 objectName: "rtkSurveySavesPosition"
190 visible: root.presentation.surveyMaySavePosition && root.baseMode === BaseModeDefinition.BaseSurveyIn
191 text: root._quectelOnly + qsTr("The Quectel receiver may automatically store the completed survey position in its own memory.")
192 }
193
194 ColumnLayout {
195 Layout.minimumWidth: 0
196 visible: root.presentation.rtkBase
197 enabled: root._editable
198
199 ModeButton {
200 objectName: "rtkSurveyMode"
201 text: root._baseModeNames[BaseModeDefinition.BaseSurveyIn]
202 checked: root.baseMode === BaseModeDefinition.BaseSurveyIn
203 onClicked: root.settings.useFixedBasePosition.rawValue = BaseModeDefinition.BaseSurveyIn
204 visible: root.presentation.surveyIn
205 }
206 ModeButton {
207 objectName: "rtkFixedMode"
208 text: root._baseModeNames[BaseModeDefinition.BaseFixed]
209 checked: root.baseMode === BaseModeDefinition.BaseFixed
210 onClicked: root.settings.useFixedBasePosition.rawValue = BaseModeDefinition.BaseFixed
211 }
212 ModeButton {
213 text: root._baseModeNames[BaseModeDefinition.BaseReceiverAveraging]
214 checked: root.baseMode === BaseModeDefinition.BaseReceiverAveraging
215 onClicked: root.settings.useFixedBasePosition.rawValue = BaseModeDefinition.BaseReceiverAveraging
216 visible: root.presentation.receiverAveraging
217 }
218 }
219
220 GPSNoteLabel {
221 visible: !root.receiver.baseModeSupported
222 text: qsTr("The selected base mode is not supported by this receiver. Choose a supported mode explicitly.")
223 }
224
225 SettingField {
226 fact: root.settings.receiverAveragingDuration
227 shown: root.presentation.receiverAveraging && root.baseMode === BaseModeDefinition.BaseReceiverAveraging
228 enabled: root._editable
229 note: root.settings.receiverAveragingDuration.shortDescription
230 }
231
232 ColumnLayout {
233 Layout.minimumWidth: 0
234 spacing: ScreenTools.defaultFontPixelHeight / 2
235 visible: root.baseMode === BaseModeDefinition.BaseSurveyIn
236 && (root.presentation.surveyAccuracy || root.presentation.surveyDuration)
237 enabled: root._editable
238
239 FactSlider {
240 Layout.fillWidth: true
241 Layout.minimumWidth: 0
242 label: root.presentation.observationAccuracyFilter ? qsTr("Observation accuracy limit")
243 : root.settings.surveyInAccuracyLimit.label
244 fact: root.settings.surveyInAccuracyLimit
245 majorTickStepSize: 0.1
246 visible: root.presentation.surveyAccuracy && (root.settings.surveyInAccuracyLimit as SettingsFact).userVisible
247 }
248
249 FactSlider {
250 Layout.fillWidth: true
251 Layout.minimumWidth: 0
252 label: root.presentation.acceptedObservationTime ? qsTr("Accepted observation time")
253 : root.settings.surveyInMinObservationDuration.label
254 fact: root.settings.surveyInMinObservationDuration
255 majorTickStepSize: 10
256 visible: root.presentation.surveyDuration
257 && (root.settings.surveyInMinObservationDuration as SettingsFact).userVisible
258 }
259 }
260
261 // The fixed base position reads as one value, so its coordinates are not divided.
262 ColumnLayout {
263 Layout.minimumWidth: 0
264 spacing: ScreenTools.defaultFontPixelHeight / 2
265 visible: root.baseMode === BaseModeDefinition.BaseFixed && root.presentation.rtkBase
266 enabled: root._editable
267
268 SettingField { fact: root.settings.fixedBasePositionLatitude }
269 SettingField { fact: root.settings.fixedBasePositionLongitude }
270 SettingField { fact: root.settings.fixedBasePositionAltitude }
271 SettingField {
272 fact: root.settings.fixedBasePositionAccuracy
273 shown: root.presentation.fixedBaseAccuracy
274 }
275 }
276
277 SwitchField {
278 fact: root.settings.compactRtcmCorrections
279 note: root.settings.compactRtcmCorrections.shortDescription
280 shown: root.configuredBase && root.presentation.compactObservations
281 toggle.objectName: "rtkCompactRtcm"
282 toggle.enabled: root._editable
283 }
284
285 ColumnLayout {
286 Layout.minimumWidth: 0
287 spacing: ScreenTools.defaultFontPixelHeight / 4
288 visible: root.presentation.persistentConfiguration
289
290 QGCCheckBox {
291 objectName: "rtkPersistentChangesCheckBox"
292 Layout.fillWidth: true
293 Layout.minimumWidth: 0
294 text: root.presentation.automatic ? qsTr("Allow flash save and restart if a Quectel receiver is identified")
295 : qsTr("Allow flash save and restart")
296 focusPolicy: Qt.StrongFocus
297 wrapMode: Text.Wrap
298 enabled: root._editable
299 checked: root.receiver.persistentChangesAllowed
300 onClicked: root.receiver.persistentChangesAllowed = checked
301 }
302
303 GPSNoteLabel {
304 objectName: "rtkPersistentConsentWarning"
305 text: root._quectelOnly + qsTr("For this connection only, allow QGroundControl to write requested base role or base-setting changes to receiver flash and restart it. Changes may remain saved even if reconnecting fails. No factory reset is performed. Permission is cleared after each attempt and is never used by automatic connections. To use the receiver as a rover again, restore its role with Quectel QGNSS or $PQTMCFGRCVRMODE,W,1 followed by $PQTMSAVEPAR.")
306 }
307 }
308
309 SwitchField {
310 fact: root.autoConnectFact
311 note: root.autoConnectFact.rawValue ? root.autoConnectFact.shortDescription : ""
312 toggle.objectName: "rtkAutoConnect"
313 }
314
315 QGCButton {
316 objectName: "rtkConnectButton"
317 Layout.fillWidth: true
318 Layout.minimumWidth: 0
319 wrapMode: Text.Wrap
320 focusPolicy: Qt.StrongFocus
321 text: root._active ? qsTr("Disconnect") : qsTr("Connect")
322 enabled: root._active || root.receiver.canConnect
323 onClicked: {
324 if (root._active) {
325 root.receiver.disconnectReceiver()
326 } else {
327 root.receiver.connectReceiver()
328 }
329 }
330 }
331
332 GPSNoteLabel {
333 objectName: "rtkErrorMessage"
334 visible: root.showErrorMessage && text.length > 0
335 text: root.receiver.errorMessage || ""
336 }
337
338 // The permission is for the configuration shown here, so leaving the page withdraws it.
339 Component.onDestruction: {
340 if (receiver) {
341 receiver.persistentChangesAllowed = false
342 }
343 }
344}