Enroute Flight Navigation
A navigation app for VFR pilots
PositionProvider.h
1/***************************************************************************
2 * Copyright (C) 2019-2025 by Stefan Kebekus *
3 * stefan.kebekus@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 3 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#pragma once
22
23#include <QBindable>
24#include <QElapsedTimer>
25#include <QQmlEngine>
26#include <QSet>
27
28#include "GlobalObject.h"
29#include "positioning/PositionInfoSource_Satellite.h"
30
31
32namespace Positioning {
33
49
50class PositionProvider : public QObject
51{
52 Q_OBJECT
53 QML_ELEMENT
54 QML_SINGLETON
55
56
57public:
62 explicit PositionProvider(QObject* parent = nullptr);
63
64 // No default constructor, important for QML singleton
65 explicit PositionProvider() = delete;
66
69
70
71 // factory function for QML singleton
72 static Positioning::PositionProvider* create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/)
73 {
75 }
76
77
78 //
79 // PROPERTIES
80 //
81
88
89
96 Q_PROPERTY(QString icon READ icon BINDABLE bindableIcon)
97
106
114 Q_PROPERTY(QGeoCoordinate mapCenter READ mapCenter WRITE setMapCenter BINDABLE bindableMapCenter NOTIFY mapCenterChanged)
115
122 Q_PROPERTY(Units::Angle lastValidTT READ lastValidTT BINDABLE bindableLastValidTT)
123
131 Q_PROPERTY(Positioning::PositionInfo positionInfo READ positionInfo BINDABLE bindablePositionInfo NOTIFY positionInfoChanged)
132
142
160 Q_PROPERTY(bool pressureAltitudeImplausible READ pressureAltitudeImplausible BINDABLE bindablePressureAltitudeImplausible NOTIFY pressureAltitudeImplausibleChanged)
161
169
176 Q_PROPERTY(QString statusString READ statusString BINDABLE bindableStatusString)
177
178
179 //
180 // Getter Methods
181 //
182
187 [[nodiscard]] QGeoCoordinate approximateLastValidCoordinate() const {return m_approximateLastValidCoordinate.value();}
188
193 [[nodiscard]] QBindable<QGeoCoordinate> bindableApproximateLastValidCoordinate() const {return &m_approximateLastValidCoordinate;}
194
199 [[nodiscard]] QString icon() const {return m_icon.value();}
200
205 [[nodiscard]] QBindable<QString> bindableIcon() const {return &m_icon;}
206
211 [[nodiscard]] static QGeoCoordinate lastValidCoordinate();
212
217 [[nodiscard]] QBindable<QGeoCoordinate> bindableLastValidCoordinate() {return &m_lastValidCoordinate;}
218
223 [[nodiscard]] static Units::Angle lastValidTT();
224
229 [[nodiscard]] QBindable<Units::Angle> bindableLastValidTT() {return &m_lastValidTT;}
230
235 [[nodiscard]] QGeoCoordinate mapCenter() const {return m_mapCenter.value();}
236
241 [[nodiscard]] QBindable<QGeoCoordinate> bindableMapCenter() {return &m_mapCenter;}
242
247 void setMapCenter(const QGeoCoordinate& newMapCenter) {m_mapCenter = newMapCenter;}
248
253 [[nodiscard]] Positioning::PositionInfo positionInfo() const {return m_positionInfo.value();}
254
259 [[nodiscard]] QBindable<Positioning::PositionInfo> bindablePositionInfo() const {return &m_positionInfo;}
260
265 [[nodiscard]] Units::Distance pressureAltitude() const {return m_pressureAltitude.value();}
266
271 [[nodiscard]] QBindable<Units::Distance> bindablePressureAltitude() const {return &m_pressureAltitude;}
272
277 [[nodiscard]] bool pressureAltitudeImplausible() const {return m_pressureAltitudeImplausible.value();}
278
283 [[nodiscard]] QBindable<bool> bindablePressureAltitudeImplausible() const {return &m_pressureAltitudeImplausible;}
284
289 [[nodiscard]] bool receivingPositionInfo() const {return m_receivingPositionInfo.value();}
290
295 [[nodiscard]] QBindable<bool> bindableReceivingPositionInfo() {return &m_receivingPositionInfo;}
296
301 [[nodiscard]] QString statusString() const {return m_statusString.value();}
302
307 [[nodiscard]] QBindable<QString> bindableStatusString() const {return &m_statusString;}
308
309
310 //
311 // Constants
312 //
313
321
322
323 //
324 // Methods
325 //
326
333 Q_INVOKABLE void startUpdates() { satelliteSource.startUpdates(); }
334
345 Q_INVOKABLE void setBackgroundUpdates(const QString& caller, bool enable);
346
347signals:
348 // Notifier signal
349 void approximateLastValidCoordinateChanged();
350
351 // Notifier signal
352 void mapCenterChanged();
353
354 // Notifier signal
355 void positionInfoChanged(const Positioning::PositionInfo& info);
356
357 // Notifier signal
358 void pressureAltitudeImplausibleChanged();
359
360 // Notifier signal
361 void receivingPositionInfoChanged(bool);
362
371
372private slots:
373 // Intializations that are moved out of the constructor, in order to avoid
374 // nested uses of constructors in Global.
375 void deferredInitialization();
376
377 // Saves last valid position and track
378 void savePositionAndTrack();
379
380private:
381 Q_DISABLE_COPY_MOVE(PositionProvider)
382
383#ifdef Q_OS_IOS
384 QSet<QString> m_backgroundUpdateCallers;
385 void updateBackgroundLocation();
386#endif
387
388 // Computation method for property with the same name
389 QString computeStatusString();
390
391 // Aircraft is considered flying if speed is at least this high
392 static constexpr double minFlightSpeedInKT = 30.0;
393 // Hysteresis for flight speed
394 static constexpr double flightSpeedHysteresis = 5.0;
395
396 // Coordinates of EDTF airfield
397 static constexpr double EDTF_lat = 48.022653;
398 static constexpr double EDTF_lon = 7.832583;
399 static constexpr double EDTF_ele = 244;
400
401 PositionInfoSource_Satellite satelliteSource;
402
403 // The incoming position info is set by a binding that monitors
404 // the satelliteSource and the TrafficDataSource
405 QProperty<Positioning::PositionInfo> m_incomingPositionInfo;
406 Positioning::PositionInfo computeIncomingPositionInfo();
407
408 // This method updates m_approximateLastValidCoordinate, m_lastValidCoordinate and m_lastValidTT
409 // whenever m_incomingPositionInfo changes.
410 void onIncomingPositionInfoUpdated();
411 QPropertyNotifier m_incomingPositionInfoNotifier;
412
413 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, Positioning::PositionInfo, m_positionInfo, &Positioning::PositionProvider::positionInfoChanged);
414 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, QGeoCoordinate, m_approximateLastValidCoordinate, &Positioning::PositionProvider::approximateLastValidCoordinateChanged);
415 QProperty<QGeoCoordinate> m_lastValidCoordinate {QGeoCoordinate(EDTF_lat, EDTF_lon, EDTF_ele)};
416 QProperty<Units::Angle> m_lastValidTT;
417 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, QGeoCoordinate, m_mapCenter, &Positioning::PositionProvider::mapCenterChanged);
418
419 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, bool, m_receivingPositionInfo, &Positioning::PositionProvider::receivingPositionInfoChanged);
420 QProperty<QString> m_icon;
421 QProperty<QString> m_statusString;
422
423 QProperty<Units::Distance> m_pressureAltitude;
424 static Units::Distance computePressureAltitude();
425
426 // This method updates m_pressureAltitudeImplausible. It is called whenever
427 // m_positionInfo or m_pressureAltitude change.
428 void updatePressureAltitudeImplausible();
429 QPropertyNotifier m_pressureAltitudeNotifier;
430
431 // Hysteresis for the pressure altitude plausibility check: once the warning
432 // is active, it clears only when the difference drops below this value.
433 static constexpr Units::Distance pressureAltitudePlausibleThreshold = Units::Distance::fromFT(3000.0);
434 // The difference must persist for at least this long before the warning is raised.
435 static constexpr qint64 pressureAltitudeImplausibleDwellTime_ms = 30LL*1000;
436 // Measures for how long pressure altitude and geometric altitude have been
437 // differing by more than pressureAltitudeImplausibleThreshold.
438 QElapsedTimer m_pressureAltitudeDivergenceTimer;
439 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, bool, m_pressureAltitudeImplausible, &Positioning::PositionProvider::pressureAltitudeImplausibleChanged);
440};
441
442} // namespace Positioning
static Q_INVOKABLE Positioning::PositionProvider * positionProvider()
Pointer to appplication-wide static PositionProvider instance.
Geographic position.
Central Position Provider.
QBindable< Positioning::PositionInfo > bindablePositionInfo() const
Getter method for property with the same name.
PositionProvider(QObject *parent=nullptr)
Standard constructor.
void backgroundLocationUnavailable()
Emitted when background location was requested but iOS did not grant (or has not yet granted) "Always...
Units::Distance pressureAltitude
Pressure altitude.
Positioning::PositionInfo positionInfo() const
Getter method for property with the same name.
QString statusString() const
Getter method for property with the same name.
QBindable< QGeoCoordinate > bindableLastValidCoordinate()
Getter function for the property with the same name.
Units::Angle lastValidTT
Last valid true track.
QBindable< QGeoCoordinate > bindableMapCenter()
Getter function for the property with the same name.
Q_INVOKABLE void setBackgroundUpdates(const QString &caller, bool enable)
Request or release background location updates (iOS only).
Units::Distance pressureAltitude() const
Getter method for property with the same name.
QBindable< bool > bindablePressureAltitudeImplausible() const
Getter method for property with the same name.
QGeoCoordinate mapCenter() const
Getter function for the property with the same name.
QBindable< Units::Angle > bindableLastValidTT()
Getter function for the property with the same name.
static QGeoCoordinate lastValidCoordinate()
Getter function for the property with the same name.
QGeoCoordinate mapCenter
Map center coordinate.
QGeoCoordinate lastValidCoordinate
Last valid coordinate reading.
QBindable< Units::Distance > bindablePressureAltitude() const
Getter method for property with the same name.
QBindable< QString > bindableStatusString() const
Getter method for property with the same name.
QGeoCoordinate approximateLastValidCoordinate
Approximate last valid coordinate.
Positioning::PositionInfo positionInfo
Position information.
static Units::Angle lastValidTT()
Getter function for the property with the same name.
QString statusString
Source status.
QBindable< bool > bindableReceivingPositionInfo()
Getter method for property with the same name.
bool receivingPositionInfo() const
Getter method for property with the same name.
QBindable< QGeoCoordinate > bindableApproximateLastValidCoordinate() const
Getter function for the property with the same name.
static constexpr Units::Distance pressureAltitudeImplausibleThreshold
Threshold for the pressure altitude plausibility check.
Q_INVOKABLE void startUpdates()
startUpdates
QString icon() const
Getter function for the property with the same name.
QBindable< QString > bindableIcon() const
Getter function for the property with the same name.
bool pressureAltitudeImplausible() const
Getter method for property with the same name.
~PositionProvider() override
Standard destructor.
void setMapCenter(const QGeoCoordinate &newMapCenter)
Setter function for the property with the same name.
bool receivingPositionInfo
Indicator that position information is being received.
bool pressureAltitudeImplausible
Indicator that pressure altitude and geometric altitude are inconsistent.
Convenience class for angle computations.
Definition Angle.h:41
Convenience class for distance computations.
Definition Distance.h:35
static Q_INVOKABLE constexpr Units::Distance fromFT(double distanceInFT)
Constructs a distance.
Definition Distance.h:108
Conversion between units used in aviation.
Definition Angle.h:34