QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GPSRtk.cc
Go to the documentation of this file.
1#include "GPSRtk.h"
2
3#include "GPSProvider.h"
4#include "GPSRTKFactGroup.h"
5#include "GPSType.h"
6#include "NTRIPManager.h"
8#include "RTCMMavlink.h"
9#include "RTKSettings.h"
10#include "SettingsManager.h"
11
12QGC_LOGGING_CATEGORY(GPSRtkLog, "GPS.GPSRtk")
13
14namespace {
15struct GPSTypeEntry
16{
17 QLatin1StringView key;
18 GPSType type;
19 int manufacturerId; // RTKSettings::baseReceiverManufacturers enum value
20};
21
22constexpr GPSTypeEntry kGPSTypeTable[] = {
23 {QLatin1StringView("trimble"), GPSType::trimble, 1},
24 {QLatin1StringView("septentrio"), GPSType::septentrio, 2},
25 {QLatin1StringView("femtomes"), GPSType::femto, 3},
26 {QLatin1StringView("blox"), GPSType::u_blox, 4},
27};
28} // namespace
29
30GPSRtk::GPSRtk(QObject* parent) : QObject(parent), _gpsRtkFactGroup(new GPSRTKFactGroup(this))
31{
32 qCDebug(GPSRtkLog) << this;
33
34 (void) qRegisterMetaType<satellite_info_s>("satellite_info_s");
35 (void) qRegisterMetaType<sensor_gps_s>("sensor_gps_s");
36 (void) qRegisterMetaType<GPSConnectionError>("GPSConnectionError");
37 (void) qRegisterMetaType<GPSSurveyInStatus>("GPSSurveyInStatus");
38}
39
41{
43
44 qCDebug(GPSRtkLog) << this;
45}
46
47void GPSRtk::_onGPSConnect()
48{
49 _gpsRtkFactGroup->connected()->setRawValue(true);
50}
51
52void GPSRtk::_onGPSDisconnect()
53{
54 _gpsRtkFactGroup->connected()->setRawValue(false);
55}
56
57void GPSRtk::_onGPSConnectionError(GPSConnectionError error)
58{
59 switch (error) {
61 qCWarning(GPSRtkLog) << "Failed to open GPS serial device";
62 break;
64 qCWarning(GPSRtkLog) << "GPS receiver did not accept configuration";
65 break;
67 qCWarning(GPSRtkLog) << "GPS device error, connection lost";
68 break;
70 break;
71 }
72
73 _gpsRtkFactGroup->lastError()->setRawValue(static_cast<int>(error));
74}
75
76void GPSRtk::_onGPSSurveyInStatus(const GPSSurveyInStatus& status)
77{
78 _gpsRtkFactGroup->currentDuration()->setRawValue(status.durationSecs);
79 _gpsRtkFactGroup->currentAccuracy()->setRawValue(static_cast<double>(status.meanAccuracyMM) / 1000.0);
80 _gpsRtkFactGroup->currentLatitude()->setRawValue(status.latitude);
81 _gpsRtkFactGroup->currentLongitude()->setRawValue(status.longitude);
82 _gpsRtkFactGroup->currentAltitude()->setRawValue(status.altitude);
83 _gpsRtkFactGroup->valid()->setRawValue(status.valid);
84 _gpsRtkFactGroup->active()->setRawValue(status.active);
85}
86
87void GPSRtk::connectGPS(const QString& device, QStringView gps_type)
88{
89 RTKSettings* const rtkSettings = SettingsManager::instance()->rtkSettings();
90
92 int manufacturerId = 4; // u-blox by default
93 for (const GPSTypeEntry& entry : kGPSTypeTable) {
94 if (gps_type.contains(entry.key, Qt::CaseInsensitive)) {
95 type = entry.type;
96 manufacturerId = entry.manufacturerId;
97 break;
98 }
99 }
100 rtkSettings->baseReceiverManufacturers()->setRawValue(manufacturerId);
101 qCDebug(GPSRtkLog) << "Connecting GPS device" << gps_type << "manufacturer id" << manufacturerId;
102
104
105 _requestGpsStop = false;
106 _gpsRtkFactGroup->lastError()->setRawValue(static_cast<int>(GPSConnectionError::None));
107 const bool useFixedBase =
108 static_cast<BaseModeDefinition::Mode>(rtkSettings->useFixedBasePosition()->rawValue().toInt()) ==
110 const GPSReceiverConfig rtkConfig = {
111 .useFixedBase = useFixedBase,
112 .surveyInAccMeters = rtkSettings->surveyInAccuracyLimit()->rawValue().toDouble(),
113 .surveyInDurationSecs = rtkSettings->surveyInMinObservationDuration()->rawValue().toInt(),
114 .fixedBaseLatitude = rtkSettings->fixedBasePositionLatitude()->rawValue().toDouble(),
115 .fixedBaseLongitude = rtkSettings->fixedBasePositionLongitude()->rawValue().toDouble(),
116 .fixedBaseAltitudeMeters = rtkSettings->fixedBasePositionAltitude()->rawValue().toFloat(),
117 .fixedBaseAccuracyMeters = rtkSettings->fixedBasePositionAccuracy()->rawValue().toFloat(),
118 };
119 _gpsProvider = new GPSProvider(device, type, rtkConfig, _requestGpsStop, this);
120 // Forward serial-RTK corrections through NTRIPManager's shared RTCMMavlink so
121 // serial and NTRIP sources share one GPS_RTCM_DATA sequence-id domain.
122 RTCMMavlink* const rtcmMavlink = NTRIPManager::instance()->rtcmMavlink();
123 if (rtcmMavlink) {
124 (void) connect(_gpsProvider, &GPSProvider::RTCMDataUpdate, rtcmMavlink, &RTCMMavlink::RTCMDataUpdate);
125 } else {
126 qCWarning(GPSRtkLog) << "Shared RTCMMavlink unavailable; serial RTK corrections will not be forwarded";
127 }
128 (void) connect(_gpsProvider, &GPSProvider::satelliteInfoUpdate, this, &GPSRtk::_satelliteInfoUpdate);
129 (void) connect(_gpsProvider, &GPSProvider::sensorGpsUpdate, this, &GPSRtk::_sensorGpsUpdate);
130 (void) connect(_gpsProvider, &GPSProvider::surveyInStatus, this, &GPSRtk::_onGPSSurveyInStatus);
131 (void) connect(_gpsProvider, &GPSProvider::connectionError, this, &GPSRtk::_onGPSConnectionError);
132 (void) connect(_gpsProvider, &GPSProvider::finished, this, &GPSRtk::_onGPSDisconnect);
133
134 _onGPSConnect();
135
136 // Start the thread only after every signal is wired, so no early emission is lost.
137 (void) QMetaObject::invokeMethod(_gpsProvider, "start", Qt::AutoConnection);
138}
139
141{
142 if (_gpsProvider) {
143 _requestGpsStop = true;
144 if (_gpsProvider->wait(kGPSThreadDisconnectTimeout)) {
145 _gpsProvider->deleteLater();
146 } else {
147 qCWarning(GPSRtkLog) << "GPS thread did not exit in time; deferring cleanup to finished()";
148 (void) _gpsProvider->disconnect(this); // stale signals must not flip facts after reconnect
149 (void) connect(_gpsProvider, &QThread::finished, _gpsProvider, &QObject::deleteLater);
150 }
151 _gpsProvider = nullptr;
152 }
153}
154
156{
157 return (_gpsProvider ? _gpsProvider->isRunning() : false);
158}
159
161{
162 return _gpsRtkFactGroup;
163}
164
166{
167 SatelliteCounts counts;
169 for (uint8_t i = 0; i < counts.inView; ++i) {
170 if (msg.used[i]) {
171 ++counts.used;
172 }
173 }
174 return counts;
175}
176
177void GPSRtk::_satelliteInfoUpdate(const satellite_info_s& msg)
178{
179 const SatelliteCounts counts = countSatellites(msg);
180 qCDebug(GPSRtkLog) << Q_FUNC_INFO << QStringLiteral("%1 in view, %2 used").arg(counts.inView).arg(counts.used);
181 _gpsRtkFactGroup->numSatellites()->setRawValue(counts.inView);
182 _gpsRtkFactGroup->numSatellitesUsed()->setRawValue(counts.used);
183}
184
185void GPSRtk::_sensorGpsUpdate(const sensor_gps_s& msg)
186{
187 qCDebug(GPSRtkLog) << Q_FUNC_INFO
188 << QStringLiteral("alt=%1, long=%2, lat=%3")
189 .arg(msg.altitude_msl_m)
190 .arg(msg.longitude_deg)
191 .arg(msg.latitude_deg);
192}
GPSConnectionError
Definition GPSProvider.h:16
@ ConfigFailed
receiver did not accept configuration
@ DeviceError
fatal serial error after a working connection
@ OpenFailed
serial device could not be opened
GPSType
Receiver families QGC can drive via the px4-gpsdrivers library.
Definition GPSType.h:5
Error error
#define QGC_LOGGING_CATEGORY(name, categoryStr)
Used to group Facts together into an object hierarachy.
Definition FactGroup.h:16
void setRawValue(const QVariant &value)
Definition Fact.cc:134
void RTCMDataUpdate(const QByteArray &message)
void sensorGpsUpdate(const sensor_gps_s &message)
void satelliteInfoUpdate(const satellite_info_s &message)
void surveyInStatus(const GPSSurveyInStatus &status)
void connectionError(GPSConnectionError error)
Fact * currentLongitude()
Fact * currentAccuracy()
Fact * currentDuration()
Fact * currentLatitude()
Fact * numSatellitesUsed()
Fact * currentAltitude()
void disconnectGPS()
Definition GPSRtk.cc:140
static SatelliteCounts countSatellites(const satellite_info_s &msg)
Clamp count to the array bound and tally used-in-solution satellites.
Definition GPSRtk.cc:165
~GPSRtk()
Definition GPSRtk.cc:40
void connectGPS(const QString &device, QStringView gps_type)
Definition GPSRtk.cc:87
FactGroup * gpsRtkFactGroup()
Definition GPSRtk.cc:160
bool connected() const
Definition GPSRtk.cc:155
GPSRtk(QObject *parent=nullptr)
Definition GPSRtk.cc:30
static NTRIPManager * instance()
RTCMMavlink * rtcmMavlink() const
RTKSettings * rtkSettings() const
static SettingsManager * instance()
RTK base-station configuration, decoupled from QGC settings types.
Definition GPSDriver.h:19
Survey-in progress, translated from the px4 SurveyInStatus.
Definition GPSDriver.h:32
uint32_t meanAccuracyMM
Definition GPSDriver.h:36
uint32_t durationSecs
Definition GPSDriver.h:37
static constexpr uint8_t SAT_INFO_MAX_SATELLITES
uint8_t used[SAT_INFO_MAX_SATELLITES]
double latitude_deg
Definition sensor_gps.h:16
double altitude_msl_m
Definition sensor_gps.h:18
double longitude_deg
Definition sensor_gps.h:17