PositionManager.cpp 5.01 KB
Newer Older
1
2
3
4
5
6
7
8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
Jimmy Johnson's avatar
Jimmy Johnson committed
9
10

#include "PositionManager.h"
11
12
#include "QGCApplication.h"
#include "QGCCorePlugin.h"
Jimmy Johnson's avatar
Jimmy Johnson committed
13

14
QGCPositionManager::QGCPositionManager(QGCApplication* app, QGCToolbox* toolbox)
Don Gagne's avatar
Don Gagne committed
15
    : QGCTool           (app, toolbox)
Jimmy Johnson's avatar
Jimmy Johnson committed
16
17
18
19
20
21
22
{

}

QGCPositionManager::~QGCPositionManager()
{
    delete(_simulatedSource);
23
    delete(_nmeaSource);
Jimmy Johnson's avatar
Jimmy Johnson committed
24
25
}

26
void QGCPositionManager::setToolbox(QGCToolbox *toolbox)
Jimmy Johnson's avatar
Jimmy Johnson committed
27
{
28
29
30
   QGCTool::setToolbox(toolbox);
   //-- First see if plugin provides a position source
   _defaultSource = toolbox->corePlugin()->createPositionSource(this);
DoinLakeFlyer's avatar
   
DoinLakeFlyer committed
31
32
33
   if (_defaultSource) {
       _usingPluginSource = true;
   }
Don Gagne's avatar
   
Don Gagne committed
34
35
36
37
38
39
40

   if (qgcApp()->runningUnitTests()) {
       // Units test on travis fail due to lack of position source
       return;
   }

   if (!_defaultSource) {
41
42
43
44
       //-- Otherwise, create a default one
       _defaultSource = QGeoPositionInfoSource::createDefaultSource(this);
   }
   _simulatedSource = new SimulatedPosition();
Jimmy Johnson's avatar
Jimmy Johnson committed
45

DonLakeFlyer's avatar
   
DonLakeFlyer committed
46
#if 1
47
   setPositionSource(QGCPositionSource::InternalGPS);
Don Gagne's avatar
   
Don Gagne committed
48
49
50
#else
   setPositionSource(QGCPositionManager::Simulated);
#endif
51
52
53
54
}

void QGCPositionManager::setNmeaSourceDevice(QIODevice* device)
{
55
    // stop and release _nmeaSource
56
    if (_nmeaSource) {
57
58
59
60
61
62
63
64
        _nmeaSource->stopUpdates();
        disconnect(_nmeaSource);

        // if _currentSource is pointing there, point to null
        if (_currentSource == _nmeaSource){
            _currentSource = nullptr;
        }

65
        delete _nmeaSource;
66
67
        _nmeaSource = nullptr;

68
69
70
71
    }
    _nmeaSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode, this);
    _nmeaSource->setDevice(device);
    setPositionSource(QGCPositionManager::NmeaGPS);
72
}
Jimmy Johnson's avatar
Jimmy Johnson committed
73

DonLakeFlyer's avatar
DonLakeFlyer committed
74
void QGCPositionManager::_positionUpdated(const QGeoPositionInfo &update)
75
{
Don Gagne's avatar
   
Don Gagne committed
76
77
    _geoPositionInfo = update;

Don Gagne's avatar
   
Don Gagne committed
78
    QGeoCoordinate newGCSPosition = QGeoCoordinate();
79
    qreal newGCSHeading = update.attribute(QGeoPositionInfo::Direction);
Don Gagne's avatar
   
Don Gagne committed
80
81
82
83
84
85
86
87
88
89
90

    if (update.isValid()) {
        // Note that gcsPosition filters out possible crap values
        if (qAbs(update.coordinate().latitude()) > 0.001 && qAbs(update.coordinate().longitude()) > 0.001) {
            newGCSPosition = update.coordinate();
        }
    }
    if (newGCSPosition != _gcsPosition) {
        _gcsPosition = newGCSPosition;
        emit gcsPositionChanged(_gcsPosition);
    }
DoinLakeFlyer's avatar
   
DoinLakeFlyer committed
91
92
93
94
95
96
97
98

    // At this point only plugins support gcs heading. The reason is that the quality of heading information from a local
    // position device (not a compass) is unknown. In many cases it can only be trusted if the GCS location is moving above
    // a certain rate of speed. When it is not, or the gcs is standing still the heading is just random. We don't want these
    // random heading to be shown on the fly view. So until we can get a true compass based heading or some smarted heading quality
    // information which takes into account the speed of movement we normally don't set a heading. We do use the heading though
    // if the plugin overrides the position source. In that case we assume that it hopefully know what it is doing.
    if (_usingPluginSource && newGCSHeading != _gcsHeading) {
99
100
101
        _gcsHeading = newGCSHeading;
        emit gcsHeadingChanged(_gcsHeading);
    }
Don Gagne's avatar
   
Don Gagne committed
102

Jimmy Johnson's avatar
Jimmy Johnson committed
103
104
105
106
107
108
109
110
111
112
    emit positionInfoUpdated(update);
}

int QGCPositionManager::updateInterval() const
{
    return _updateInterval;
}

void QGCPositionManager::setPositionSource(QGCPositionManager::QGCPositionSource source)
{
113
    if (_currentSource != nullptr) {
Jimmy Johnson's avatar
Jimmy Johnson committed
114
        _currentSource->stopUpdates();
DonLakeFlyer's avatar
DonLakeFlyer committed
115
        disconnect(_currentSource);
Jimmy Johnson's avatar
Jimmy Johnson committed
116
117
    }

118
119
120
121
122
    if (qgcApp()->runningUnitTests()) {
        // Units test on travis fail due to lack of position source
        return;
    }

Jimmy Johnson's avatar
Jimmy Johnson committed
123
124
125
126
127
128
    switch(source) {
    case QGCPositionManager::Log:
        break;
    case QGCPositionManager::Simulated:
        _currentSource = _simulatedSource;
        break;
129
130
131
132
    case QGCPositionManager::NmeaGPS:
        _currentSource = _nmeaSource;
        break;
    case QGCPositionManager::InternalGPS:
Jimmy Johnson's avatar
Jimmy Johnson committed
133
134
135
136
137
    default:        
        _currentSource = _defaultSource;
        break;
    }

138
139
140
141
    if (_currentSource != nullptr) {
        _updateInterval = _currentSource->minimumUpdateInterval();
        _currentSource->setPreferredPositioningMethods(QGeoPositionInfoSource::SatellitePositioningMethods);
        _currentSource->setUpdateInterval(_updateInterval);
DonLakeFlyer's avatar
DonLakeFlyer committed
142
143
        connect(_currentSource, &QGeoPositionInfoSource::positionUpdated,       this, &QGCPositionManager::_positionUpdated);
        connect(_currentSource, SIGNAL(error(QGeoPositionInfoSource::Error)),   this, SLOT(_error(QGeoPositionInfoSource::Error)));
144
        _currentSource->startUpdates();
145
    }
Jimmy Johnson's avatar
Jimmy Johnson committed
146
147
}

DonLakeFlyer's avatar
DonLakeFlyer committed
148
149
void QGCPositionManager::_error(QGeoPositionInfoSource::Error positioningError)
{
Don Gagne's avatar
   
Don Gagne committed
150
    qWarning() << "QGCPositionManager error" << positioningError;
DonLakeFlyer's avatar
DonLakeFlyer committed
151
}