8#include <QtCore/QApplicationStatic>
9#include <QtCore/QPermissions>
10#include <QtPositioning/QNmeaPositionInfoSource>
19 qCDebug(QGCPositionManagerLog) <<
this;
24 qCDebug(QGCPositionManagerLog) <<
this;
29 return _positionManager();
36 _setPositionSource(QGCPositionSource::Simulated);
42void QGCPositionManager::_setupPositionSources()
46 _usingPluginSource =
true;
48 qCDebug(QGCPositionManagerLog) << Q_FUNC_INFO << QGeoPositionInfoSource::availableSources();
50 _defaultSource = QGeoPositionInfoSource::createDefaultSource(
this);
51 if (!_defaultSource) {
52 qCWarning(QGCPositionManagerLog) << Q_FUNC_INFO <<
"No default source available";
57 _setPositionSource(QGCPositionSource::InternalGPS);
60void QGCPositionManager::_handlePermissionStatus(Qt::PermissionStatus permissionStatus)
62 if (permissionStatus == Qt::PermissionStatus::Granted) {
63 _setupPositionSources();
65 qCWarning(QGCPositionManagerLog) << Q_FUNC_INFO <<
"Location Permission Denied";
69void QGCPositionManager::_checkPermission()
71 QLocationPermission locationPermission;
72 locationPermission.setAccuracy(QLocationPermission::Precise);
74 const Qt::PermissionStatus permissionStatus = QCoreApplication::instance()->checkPermission(locationPermission);
75 if (permissionStatus == Qt::PermissionStatus::Undetermined) {
76 QCoreApplication::instance()->requestPermission(locationPermission,
this, [
this](
const QPermission &permission) {
77 _handlePermissionStatus(permission.status());
80 _handlePermissionStatus(permissionStatus);
87 _nmeaSource->stopUpdates();
88 (void) _nmeaSource->disconnect(
this);
90 if (_currentSource == _nmeaSource) {
91 _currentSource =
nullptr;
95 _nmeaSource =
nullptr;
98 _nmeaSource =
new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode,
this);
99 _nmeaSource->setDevice(device);
100 _nmeaSource->setUserEquivalentRangeError(5.1);
101 _setPositionSource(QGCPositionManager::NmeaGPS);
110 if (_currentSource == _nmeaSource) {
114 _setPositionSource(QGCPositionManager::InternalGPS);
116 _nmeaSource->stopUpdates();
117 (void) _nmeaSource->disconnect(
this);
121 _nmeaSource =
nullptr;
124void QGCPositionManager::_positionUpdated(
const QGeoPositionInfo &update)
126 _geoPositionInfo = update;
127 _gcsPositioningError = QGeoPositionInfoSource::NoError;
129 QGeoCoordinate newGCSPosition(_gcsPosition);
131 if (update.hasAttribute(QGeoPositionInfo::HorizontalAccuracy)) {
132 if ((qAbs(update.coordinate().latitude()) > 0.001) && (qAbs(update.coordinate().longitude()) > 0.001)) {
133 _gcsPositionHorizontalAccuracy = update.attribute(QGeoPositionInfo::HorizontalAccuracy);
134 if (_gcsPositionHorizontalAccuracy <= kMinHorizonalAccuracyMeters) {
135 newGCSPosition.setLatitude(update.coordinate().latitude());
136 newGCSPosition.setLongitude(update.coordinate().longitude());
140 _gcsPositionTimestamp = QDateTime::currentDateTimeUtc();
146 if (update.hasAttribute(QGeoPositionInfo::VerticalAccuracy)) {
147 _gcsPositionVerticalAccuracy = update.attribute(QGeoPositionInfo::VerticalAccuracy);
148 if (_gcsPositionVerticalAccuracy <= kMinVerticalAccuracyMeters) {
149 newGCSPosition.setAltitude(update.coordinate().altitude());
153 _gcsPositionAccuracy = sqrt(pow(_gcsPositionHorizontalAccuracy, 2) + pow(_gcsPositionVerticalAccuracy, 2));
155 _setGCSPosition(newGCSPosition);
157 if (update.hasAttribute(QGeoPositionInfo::DirectionAccuracy)) {
158 _gcsDirectionAccuracy = update.attribute(QGeoPositionInfo::DirectionAccuracy);
159 if (_gcsDirectionAccuracy <= kMinDirectionAccuracyDegrees) {
160 _setGCSHeading(update.attribute(QGeoPositionInfo::Direction));
162 }
else if (_usingPluginSource) {
163 _setGCSHeading(update.attribute(QGeoPositionInfo::Direction));
169void QGCPositionManager::_positionError(QGeoPositionInfoSource::Error gcsPositioningError)
171 qCWarning(QGCPositionManagerLog) << Q_FUNC_INFO <<
"Positioning error:" <<
gcsPositioningError;
175void QGCPositionManager::_setGCSHeading(qreal newGCSHeading)
177 if (newGCSHeading != _gcsHeading) {
178 _gcsHeading = newGCSHeading;
183void QGCPositionManager::_setGCSPosition(
const QGeoCoordinate& newGCSPosition)
185 if (newGCSPosition != _gcsPosition) {
186 _gcsPosition = newGCSPosition;
191void QGCPositionManager::_setPositionSource(QGCPositionSource source)
193 if (_currentSource !=
nullptr) {
194 _currentSource->stopUpdates();
198 (void) _currentSource->disconnect(
this);
200 _geoPositionInfo = QGeoPositionInfo();
203 _setGCSPosition(QGeoCoordinate());
204 _gcsPositionTimestamp = QDateTime();
206 _setGCSHeading(qQNaN());
208 _gcsPositionHorizontalAccuracy = std::numeric_limits<qreal>::infinity();
213 case QGCPositionManager::Log:
215 case QGCPositionManager::Simulated:
216 _currentSource = _simulatedSource;
218 case QGCPositionManager::NmeaGPS:
219 _currentSource = _nmeaSource;
221 case QGCPositionManager::InternalGPS:
222 _currentSource = _defaultSource;
224 case QGCPositionManager::ExternalGPS:
227 _currentSource = _defaultSource;
231 if (_currentSource !=
nullptr) {
232 _currentSource->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
233 _updateInterval = _currentSource->minimumUpdateInterval();
234 #if !defined(Q_OS_DARWIN) && !defined(Q_OS_IOS)
235 _currentSource->setUpdateInterval(_updateInterval);
238 (void) connect(_currentSource, &QGeoPositionInfoSource::positionUpdated,
this, &QGCPositionManager::_positionUpdated);
239 (void) connect(_currentSource, &QGeoPositionInfoSource::errorOccurred,
this, &QGCPositionManager::_positionError);
243 _currentSource->startUpdates();
Q_APPLICATION_STATIC(QGCPositionManager, _positionManager)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
virtual QGeoPositionInfoSource * createPositionSource(QObject *parent)
static QGCCorePlugin * instance()
void resetNmeaSourceDevice()
static QGCPositionManager * instance()
void gcsPositionChanged(QGeoCoordinate gcsPosition)
QGeoPositionInfoSource::Error gcsPositioningError() const
void setNmeaSourceDevice(QIODevice *device)
void gcsPositionHorizontalAccuracyChanged(qreal gcsPositionHorizontalAccuracy)
void positionInfoUpdated(QGeoPositionInfo update)
void gcsHeadingChanged(qreal gcsHeading)