8#include <QtCore/QApplicationStatic>
9#include <QtCore/QPermissions>
10#include <QtPositioning/QGeoPositionInfoSource>
11#include <QtPositioning/private/qgeopositioninfosource_p.h>
12#include <QtPositioning/QNmeaPositionInfoSource>
21 qCDebug(QGCPositionManagerLog) <<
this;
24QGCPositionManager::~QGCPositionManager()
26 qCDebug(QGCPositionManagerLog) <<
this;
31 return _positionManager();
34void QGCPositionManager::init()
36 if (
qgcApp()->runningUnitTests()) {
38 _setPositionSource(QGCPositionSource::Simulated);
44void QGCPositionManager::_setupPositionSources()
46 _defaultSource = QGCCorePlugin::instance()->createPositionSource(
this);
48 _usingPluginSource =
true;
50 qCDebug(QGCPositionManagerLog) << Q_FUNC_INFO << QGeoPositionInfoSource::availableSources();
52 _defaultSource = QGeoPositionInfoSource::createDefaultSource(
this);
53 if (!_defaultSource) {
54 qCWarning(QGCPositionManagerLog) << Q_FUNC_INFO <<
"No default source available";
59 _setPositionSource(QGCPositionSource::InternalGPS);
62void QGCPositionManager::_handlePermissionStatus(Qt::PermissionStatus permissionStatus)
64 if (permissionStatus == Qt::PermissionStatus::Granted) {
65 _setupPositionSources();
67 qCWarning(QGCPositionManagerLog) << Q_FUNC_INFO <<
"Location Permission Denied";
71void QGCPositionManager::_checkPermission()
73 QLocationPermission locationPermission;
74 locationPermission.setAccuracy(QLocationPermission::Precise);
76 const Qt::PermissionStatus permissionStatus = QCoreApplication::instance()->checkPermission(locationPermission);
77 if (permissionStatus == Qt::PermissionStatus::Undetermined) {
78 QCoreApplication::instance()->requestPermission(locationPermission,
this, [
this](
const QPermission &permission) {
79 _handlePermissionStatus(permission.status());
82 _handlePermissionStatus(permissionStatus);
86void QGCPositionManager::setNmeaSourceDevice(QIODevice *device)
89 _nmeaSource->stopUpdates();
90 (void) disconnect(_nmeaSource);
92 if (_currentSource == _nmeaSource) {
93 _currentSource =
nullptr;
97 _nmeaSource =
nullptr;
100 _nmeaSource =
new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode,
this);
101 _nmeaSource->setDevice(device);
102 _nmeaSource->setUserEquivalentRangeError(5.1);
103 _setPositionSource(QGCPositionManager::NmeaGPS);
106void QGCPositionManager::_positionUpdated(
const QGeoPositionInfo &update)
108 _geoPositionInfo = update;
110 QGeoCoordinate newGCSPosition(_gcsPosition);
112 if (update.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) {
113 if ((qAbs(update.coordinate().latitude()) > 0.001) && (qAbs(update.coordinate().longitude()) > 0.001)) {
114 _gcsPositionHorizontalAccuracy = update.attribute(QGeoPositionInfo::HorizontalAccuracy);
115 if (_gcsPositionHorizontalAccuracy <= kMinHorizonalAccuracyMeters) {
116 newGCSPosition.setLatitude(update.coordinate().latitude());
117 newGCSPosition.setLongitude(update.coordinate().longitude());
123 if (update.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) {
124 _gcsPositionVerticalAccuracy = update.attribute(QGeoPositionInfo::VerticalAccuracy);
125 if (_gcsPositionVerticalAccuracy <= kMinVerticalAccuracyMeters) {
126 newGCSPosition.setAltitude(update.coordinate().altitude());
130 _gcsPositionAccuracy = sqrt(pow(_gcsPositionHorizontalAccuracy, 2) + pow(_gcsPositionVerticalAccuracy, 2));
132 _setGCSPosition(newGCSPosition);
134 if (update.hasAttribute(QGeoPositionInfo::DirectionAccuracy)) {
135 _gcsDirectionAccuracy = update.attribute(QGeoPositionInfo::DirectionAccuracy);
136 if (_gcsDirectionAccuracy <= kMinDirectionAccuracyDegrees) {
137 _setGCSHeading(update.attribute(QGeoPositionInfo::Direction));
139 }
else if (_usingPluginSource) {
140 _setGCSHeading(update.attribute(QGeoPositionInfo::Direction));
146void QGCPositionManager::_setGCSHeading(qreal newGCSHeading)
148 if (newGCSHeading != _gcsHeading) {
149 _gcsHeading = newGCSHeading;
154void QGCPositionManager::_setGCSPosition(
const QGeoCoordinate& newGCSPosition)
156 if (newGCSPosition != _gcsPosition) {
157 _gcsPosition = newGCSPosition;
162void QGCPositionManager::_setPositionSource(QGCPositionSource source)
164 if (_currentSource !=
nullptr) {
165 _currentSource->stopUpdates();
166 (void) disconnect(_currentSource);
168 _geoPositionInfo = QGeoPositionInfo();
171 _setGCSPosition(QGeoCoordinate());
173 _setGCSHeading(qQNaN());
175 _gcsPositionHorizontalAccuracy = std::numeric_limits<qreal>::infinity();
180 case QGCPositionManager::Log:
182 case QGCPositionManager::Simulated:
183 _currentSource = _simulatedSource;
185 case QGCPositionManager::NmeaGPS:
186 _currentSource = _nmeaSource;
188 case QGCPositionManager::InternalGPS:
189 _currentSource = _defaultSource;
191 case QGCPositionManager::ExternalGPS:
194 _currentSource = _defaultSource;
198 if (_currentSource !=
nullptr) {
199 _currentSource->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
200 _updateInterval = _currentSource->minimumUpdateInterval();
201 #if !defined(Q_OS_DARWIN) && !defined(Q_OS_IOS)
202 _currentSource->setUpdateInterval(_updateInterval);
204 (void) connect(_currentSource, &QGeoPositionInfoSource::positionUpdated,
this, &QGCPositionManager::_positionUpdated);
205 (void) connect(_currentSource, &QGeoPositionInfoSource::errorOccurred,
this, [](QGeoPositionInfoSource::Error positioningError) {
206 qCWarning(QGCPositionManagerLog) << Q_FUNC_INFO << positioningError;
211 _currentSource->startUpdates();
Q_APPLICATION_STATIC(QGCPositionManager, _positionManager)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void gcsPositionChanged(QGeoCoordinate gcsPosition)
void gcsPositionHorizontalAccuracyChanged(qreal gcsPositionHorizontalAccuracy)
void positionInfoUpdated(QGeoPositionInfo update)
void gcsHeadingChanged(qreal gcsHeading)