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
27#include "GlobalObject.h"
28#include "positioning/PositionInfoSource_Satellite.h"
29
30
31namespace Positioning {
32
48
49class PositionProvider : public QObject
50{
51 Q_OBJECT
52 QML_ELEMENT
53 QML_SINGLETON
54
55
56public:
61 explicit PositionProvider(QObject* parent = nullptr);
62
63 // No default constructor, important for QML singleton
64 explicit PositionProvider() = delete;
65
68
69
70 // factory function for QML singleton
71 static Positioning::PositionProvider* create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/)
72 {
74 }
75
76
77 //
78 // PROPERTIES
79 //
80
87
88
95 Q_PROPERTY(QString icon READ icon BINDABLE bindableIcon)
96
105
113 Q_PROPERTY(QGeoCoordinate mapCenter READ mapCenter WRITE setMapCenter BINDABLE bindableMapCenter NOTIFY mapCenterChanged)
114
121 Q_PROPERTY(Units::Angle lastValidTT READ lastValidTT BINDABLE bindableLastValidTT)
122
130 Q_PROPERTY(Positioning::PositionInfo positionInfo READ positionInfo BINDABLE bindablePositionInfo NOTIFY positionInfoChanged)
131
141
159 Q_PROPERTY(bool pressureAltitudeImplausible READ pressureAltitudeImplausible BINDABLE bindablePressureAltitudeImplausible NOTIFY pressureAltitudeImplausibleChanged)
160
168
175 Q_PROPERTY(QString statusString READ statusString BINDABLE bindableStatusString)
176
177
178 //
179 // Getter Methods
180 //
181
186 [[nodiscard]] QGeoCoordinate approximateLastValidCoordinate() const {return m_approximateLastValidCoordinate.value();}
187
192 [[nodiscard]] QBindable<QGeoCoordinate> bindableApproximateLastValidCoordinate() const {return &m_approximateLastValidCoordinate;}
193
198 [[nodiscard]] QString icon() const {return m_icon.value();}
199
204 [[nodiscard]] QBindable<QString> bindableIcon() const {return &m_icon;}
205
210 [[nodiscard]] static QGeoCoordinate lastValidCoordinate();
211
216 [[nodiscard]] QBindable<QGeoCoordinate> bindableLastValidCoordinate() {return &m_lastValidCoordinate;}
217
222 [[nodiscard]] static Units::Angle lastValidTT();
223
228 [[nodiscard]] QBindable<Units::Angle> bindableLastValidTT() {return &m_lastValidTT;}
229
234 [[nodiscard]] QGeoCoordinate mapCenter() const {return m_mapCenter.value();}
235
240 [[nodiscard]] QBindable<QGeoCoordinate> bindableMapCenter() {return &m_mapCenter;}
241
246 void setMapCenter(const QGeoCoordinate& newMapCenter) {m_mapCenter = newMapCenter;}
247
252 [[nodiscard]] Positioning::PositionInfo positionInfo() const {return m_positionInfo.value();}
253
258 [[nodiscard]] QBindable<Positioning::PositionInfo> bindablePositionInfo() const {return &m_positionInfo;}
259
264 [[nodiscard]] Units::Distance pressureAltitude() const {return m_pressureAltitude.value();}
265
270 [[nodiscard]] QBindable<Units::Distance> bindablePressureAltitude() const {return &m_pressureAltitude;}
271
276 [[nodiscard]] bool pressureAltitudeImplausible() const {return m_pressureAltitudeImplausible.value();}
277
282 [[nodiscard]] QBindable<bool> bindablePressureAltitudeImplausible() const {return &m_pressureAltitudeImplausible;}
283
288 [[nodiscard]] bool receivingPositionInfo() const {return m_receivingPositionInfo.value();}
289
294 [[nodiscard]] QBindable<bool> bindableReceivingPositionInfo() {return &m_receivingPositionInfo;}
295
300 [[nodiscard]] QString statusString() const {return m_statusString.value();}
301
306 [[nodiscard]] QBindable<QString> bindableStatusString() const {return &m_statusString;}
307
308
309 //
310 // Constants
311 //
312
320
321
322 //
323 // Methods
324 //
325
332 Q_INVOKABLE void startUpdates() { satelliteSource.startUpdates(); }
333
334signals:
335 // Notifier signal
336 void approximateLastValidCoordinateChanged();
337
338 // Notifier signal
339 void mapCenterChanged();
340
341 // Notifier signal
342 void positionInfoChanged(const Positioning::PositionInfo& info);
343
344 // Notifier signal
345 void pressureAltitudeImplausibleChanged();
346
347 // Notifier signal
348 void receivingPositionInfoChanged(bool);
349
350private slots:
351 // Intializations that are moved out of the constructor, in order to avoid
352 // nested uses of constructors in Global.
353 void deferredInitialization();
354
355 // Saves last valid position and track
356 void savePositionAndTrack();
357
358private:
359 Q_DISABLE_COPY_MOVE(PositionProvider)
360
361 // Computation method for property with the same name
362 QString computeStatusString();
363
364 // Aircraft is considered flying if speed is at least this high
365 static constexpr double minFlightSpeedInKT = 30.0;
366 // Hysteresis for flight speed
367 static constexpr double flightSpeedHysteresis = 5.0;
368
369 // Coordinates of EDTF airfield
370 static constexpr double EDTF_lat = 48.022653;
371 static constexpr double EDTF_lon = 7.832583;
372 static constexpr double EDTF_ele = 244;
373
374 PositionInfoSource_Satellite satelliteSource;
375
376 // The incoming position info is set by a binding that monitors
377 // the satelliteSource and the TrafficDataSource
378 QProperty<Positioning::PositionInfo> m_incomingPositionInfo;
379 Positioning::PositionInfo computeIncomingPositionInfo();
380
381 // This method updates m_approximateLastValidCoordinate, m_lastValidCoordinate and m_lastValidTT
382 // whenever m_incomingPositionInfo changes.
383 void onIncomingPositionInfoUpdated();
384 QPropertyNotifier m_incomingPositionInfoNotifier;
385
386 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, Positioning::PositionInfo, m_positionInfo, &Positioning::PositionProvider::positionInfoChanged);
387 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, QGeoCoordinate, m_approximateLastValidCoordinate, &Positioning::PositionProvider::approximateLastValidCoordinateChanged);
388 QProperty<QGeoCoordinate> m_lastValidCoordinate {QGeoCoordinate(EDTF_lat, EDTF_lon, EDTF_ele)};
389 QProperty<Units::Angle> m_lastValidTT;
390 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, QGeoCoordinate, m_mapCenter, &Positioning::PositionProvider::mapCenterChanged);
391
392 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, bool, m_receivingPositionInfo, &Positioning::PositionProvider::receivingPositionInfoChanged);
393 QProperty<QString> m_icon;
394 QProperty<QString> m_statusString;
395
396 QProperty<Units::Distance> m_pressureAltitude;
397 static Units::Distance computePressureAltitude();
398
399 // This method updates m_pressureAltitudeImplausible. It is called whenever
400 // m_positionInfo or m_pressureAltitude change.
401 void updatePressureAltitudeImplausible();
402 QPropertyNotifier m_pressureAltitudeNotifier;
403
404 // Hysteresis for the pressure altitude plausibility check: once the warning
405 // is active, it clears only when the difference drops below this value.
406 static constexpr Units::Distance pressureAltitudePlausibleThreshold = Units::Distance::fromFT(3000.0);
407 // The difference must persist for at least this long before the warning is raised.
408 static constexpr qint64 pressureAltitudeImplausibleDwellTime_ms = 30*1000;
409 // Measures for how long pressure altitude and geometric altitude have been
410 // differing by more than pressureAltitudeImplausibleThreshold.
411 QElapsedTimer m_pressureAltitudeDivergenceTimer;
412 Q_OBJECT_BINDABLE_PROPERTY(Positioning::PositionProvider, bool, m_pressureAltitudeImplausible, &Positioning::PositionProvider::pressureAltitudeImplausibleChanged);
413};
414
415} // 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.
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.
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