6#include <QtCore/QDateTime>
7#include <QtPositioning/QGeoCoordinate>
14#include "development/mavlink_msg_gnss_integrity.h"
17 :
FactGroup(1000, QStringLiteral(
":/json/Vehicle/GPSFact.json"), parent)
20 , _rtkStatusExpiry(_scheduler, this)
21 , _integrityExpiry(_scheduler, this)
41 _addFact(&_postProcessingQualityFact);
47 for (
Fact* fact : {&_spoofingStateFact, &_jammingStateFact, &_authenticationStateFact}) {
51 _latFact.
setRawValue(std::numeric_limits<float>::quiet_NaN());
52 _lonFact.
setRawValue(std::numeric_limits<float>::quiet_NaN());
54 _hdopFact.
setRawValue(std::numeric_limits<float>::quiet_NaN());
55 _vdopFact.
setRawValue(std::numeric_limits<float>::quiet_NaN());
58 _courseOverGroundFact.
setRawValue(std::numeric_limits<float>::quiet_NaN());
68 switch (message.msgid) {
69 case MAVLINK_MSG_ID_GPS_RAW_INT:
71 _handleGpsRaw(message);
74 case MAVLINK_MSG_ID_GPS2_RAW:
76 _handleGpsRaw(message);
79 case MAVLINK_MSG_ID_HIGH_LATENCY:
81 _handleHighLatency(message);
84 case MAVLINK_MSG_ID_HIGH_LATENCY2:
86 _handleHighLatency2(message);
89 case MAVLINK_MSG_ID_GNSS_INTEGRITY:
90 _handleGnssIntegrity(message);
92 case MAVLINK_MSG_ID_GPS_RTK:
94 _handleGpsRtk(message);
97 case MAVLINK_MSG_ID_GPS2_RTK:
99 _handleGpsRtk(message);
107void VehicleGPSFactGroup::_updateFix(
int fixType,
int satellitesVisible,
double hdopValue,
double vdopValue,
108 double courseValue,
double yawValue)
110 count()->
setRawValue(satellitesVisible == UINT8_MAX ? 0 : satellitesVisible);
118void VehicleGPSFactGroup::_reportPosition(QGeoPositionInfo position,
int fixType)
120 position.setTimestamp(QDateTime::currentDateTimeUtc());
133 const auto update = [
this](
const auto& raw) {
135 position.setCoordinate(QGeoCoordinate(raw.lat * 1e-7, raw.lon * 1e-7, raw.alt / 1000.0));
136 if (raw.h_acc != 0) {
137 position.setAttribute(QGeoPositionInfo::HorizontalAccuracy, raw.h_acc / 1000.0);
139 if (raw.v_acc != 0) {
140 position.setAttribute(QGeoPositionInfo::VerticalAccuracy, raw.v_acc / 1000.0);
142 if (raw.cog < 36000) {
143 position.setAttribute(QGeoPositionInfo::Direction, raw.cog / 100.0);
145 const double hdopValue = raw.eph == UINT16_MAX ? qQNaN() : raw.eph / 100.0;
146 const double vdopValue = raw.epv == UINT16_MAX ? qQNaN() : raw.epv / 100.0;
147 const double yawValue = raw.yaw > 0 && raw.yaw <= 36000 ? (raw.yaw % 36000) / 100.0 : qQNaN();
148 _updateFix(raw.fix_type, raw.satellites_visible, hdopValue, vdopValue,
149 position.attribute(QGeoPositionInfo::Direction), yawValue);
150 _reportPosition(position, raw.fix_type);
152 if (message.msgid == MAVLINK_MSG_ID_GPS_RAW_INT) {
153 mavlink_gps_raw_int_t raw{};
154 mavlink_msg_gps_raw_int_decode(&message, &raw);
157 mavlink_gps2_raw_t raw{};
158 mavlink_msg_gps2_raw_decode(&message, &raw);
165 mavlink_high_latency_t highLatency{};
166 mavlink_msg_high_latency_decode(&message, &highLatency);
170 QGeoCoordinate(highLatency.latitude * 1e-7, highLatency.longitude * 1e-7, highLatency.altitude_amsl));
171 _updateFix(highLatency.gps_fix_type, highLatency.gps_nsat, qQNaN(), qQNaN(), qQNaN(), qQNaN());
172 _reportPosition(position, highLatency.gps_fix_type);
178 mavlink_msg_high_latency2_decode(&message, &highLatency2);
182 QGeoCoordinate(highLatency2.latitude * 1e-7, highLatency2.longitude * 1e-7, highLatency2.altitude));
183 if (highLatency2.eph != UINT8_MAX) {
184 position.setAttribute(QGeoPositionInfo::HorizontalAccuracy, highLatency2.eph / 10.0);
186 if (highLatency2.epv != UINT8_MAX) {
187 position.setAttribute(QGeoPositionInfo::VerticalAccuracy, highLatency2.epv / 10.0);
191 _reportPosition(position, GPS_FIX_TYPE_NO_GPS);
196 mavlink_gnss_integrity_t gnssIntegrity;
197 mavlink_msg_gnss_integrity_decode(&message, &gnssIntegrity);
199 if (gnssIntegrity.id !=
static_cast<uint8_t
>(_receiver)) {
214void VehicleGPSFactGroup::_clearIntegrity()
217 for (
Fact* fact : {&_spoofingStateFact, &_jammingStateFact, &_authenticationStateFact, &_correctionsQualityFact,
218 &_systemQualityFact, &_gnssSignalQualityFact, &_postProcessingQualityFact}) {
225 const auto apply = [
this](
const auto& rtk) {
227 const double a = rtk.baseline_a_mm;
228 const double b = rtk.baseline_b_mm;
229 const double c = rtk.baseline_c_mm;
234 if (message.msgid == MAVLINK_MSG_ID_GPS2_RTK) {
235 mavlink_gps2_rtk_t rtk;
236 mavlink_msg_gps2_rtk_decode(&message, &rtk);
239 mavlink_gps_rtk_t rtk;
240 mavlink_msg_gps_rtk_decode(&message, &rtk);
246void VehicleGPSFactGroup::_clearRtkStatus()
256 static constexpr const char* ERROR_NAMES[] = {
257 QT_TR_NOOP(
"Incoming correction"),
258 QT_TR_NOOP(
"Configuration"),
259 QT_TR_NOOP(
"Software"),
260 QT_TR_NOOP(
"Antenna"),
261 QT_TR_NOOP(
"Event congestion"),
262 QT_TR_NOOP(
"CPU overload"),
263 QT_TR_NOOP(
"Output congestion"),
265 const quint32 errors = _systemErrorsFact.
rawValue().toUInt();
268 for (quint32 bit = 0; bit < std::size(ERROR_NAMES); ++bit) {
270 if (errors & (1u << bit)) {
271 names.append(tr(ERROR_NAMES[bit]));
274 if (errors & ~known) {
275 names.append(tr(
"Other (0x%1)").arg(errors & ~known, 0, 16));
277 return names.join(QStringLiteral(
", "));
297 const int spoofing = _spoofingStateFact.
rawValue().toInt();
298 const int jamming = _jammingStateFact.
rawValue().toInt();
299 return (std::max) (
reported(spoofing) ? spoofing : 0,
reported(jamming) ? jamming : 0);
struct __mavlink_message mavlink_message_t
Geographic coordinate conversion utilities using GeographicLib.
struct __mavlink_high_latency2_t mavlink_high_latency2_t
Used to group Facts together into an object hierarachy.
void _setTelemetryAvailable(bool telemetryAvailable)
void _addFact(Fact *fact, const QString &name)
A Fact is used to hold a single value within the system.
void rawValueChanged(const QVariant &value)
void setRawValue(const QVariant &value)
QVariant rawValue() const
bool schedule(std::chrono::microseconds delay, RuntimeScheduler::Callback callback)
bool spoofingReported() const
Fact * authenticationState()
bool authenticationReported() const
int authenticationSeverity() const
Fact * rtkBaseline()
GPS_RTK (primary) or GPS2_RTK (secondary); cleared when the vehicle stops reporting them.
static constexpr std::chrono::seconds GNSS_INTEGRITY_TIMEOUT
The GNSS_INTEGRITY facts return to unreported when the vehicle stops sending it for this long.
bool jammingReported() const
Fact * postProcessingQuality()
int interferenceState() const
void handleMessage(Vehicle *vehicle, const mavlink_message_t &message) override
Allows a FactGroup to parse incoming messages and fill in values.
static constexpr int NOT_REPORTED
The value of a state the vehicle has not reported.
Fact * correctionsQuality()
Fact * gnssSignalQuality()
QString systemErrorText() const
The receiver's reported system errors, comma separated; empty when there are none.
ReceiverIndex
The worse of the reported spoofing and jamming states, or 0 when neither is reported.
static constexpr bool reported(int state)
A state other than Unknown or NOT_REPORTED.
Fact * horizontalAccuracy()
AuthenticationState
MAVLink GPS_AUTHENTICATION_STATE.
void systemErrorTextChanged()
void positionReported(const QGeoPositionInfo &position, int fixType)
Fact * courseOverGround()
static constexpr std::chrono::seconds RTK_STATUS_TIMEOUT
Fact * verticalAccuracy()
VehicleGPSFactGroup(QObject *parent=nullptr, RuntimeScheduler *scheduler=nullptr, ReceiverIndex receiver=ReceiverIndex::Primary)
GPSPositionReport position(const GPSDecodedPosition &source, const GPSIntegrityReport &diagnostic, uint64_t nowUs)
std::optional< double > coordinate(std::string_view field, std::string_view hemisphere, bool latitude)
QString convertGeoToMGRS(const QGeoCoordinate &coord)