QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
FlightPathSegment.cc
Go to the documentation of this file.
1#include "FlightPathSegment.h"
2#include "QGC.h"
4
5QGC_LOGGING_CATEGORY(FlightPathSegmentLog, "Plan.FlightPathSegment")
6
7FlightPathSegment::FlightPathSegment(SegmentType segmentType, const QGeoCoordinate& coord1, double amslCoord1Alt, const QGeoCoordinate& coord2, double amslCoord2Alt, bool queryTerrainData, QObject* parent)
8 : QObject (parent)
9 , _coord1 (coord1)
10 , _coord2 (coord2)
11 , _coord1AMSLAlt (amslCoord1Alt)
12 , _coord2AMSLAlt (amslCoord2Alt)
13 , _queryTerrainData (queryTerrainData)
14 , _segmentType (segmentType)
15{
16 _delayedTerrainPathQueryTimer.setSingleShot(true);
17 _delayedTerrainPathQueryTimer.setInterval(200);
18 _delayedTerrainPathQueryTimer.callOnTimeout(this, &FlightPathSegment::_sendTerrainPathQuery);
19 _updateTotalDistance();
20
21 qCDebug(FlightPathSegmentLog) << this << "new" << coord1 << coord2 << amslCoord1Alt << amslCoord2Alt << _totalDistance;
22
23 _sendTerrainPathQuery();
24}
25
26void FlightPathSegment::setCoordinate1(const QGeoCoordinate &coordinate)
27{
28 if (_coord1 != coordinate) {
29 _coord1 = coordinate;
30 emit coordinate1Changed(_coord1);
31 _delayedTerrainPathQueryTimer.start();
32 _updateTotalDistance();
33 }
34}
35
36void FlightPathSegment::setCoordinate2(const QGeoCoordinate &coordinate)
37{
38 if (_coord2 != coordinate) {
39 _coord2 = coordinate;
40 emit coordinate2Changed(_coord2);
41 _delayedTerrainPathQueryTimer.start();
42 _updateTotalDistance();
43 }
44}
45
47{
48 if (!QGC::fuzzyCompare(alt, _coord1AMSLAlt)) {
49 _coord1AMSLAlt = alt;
51 _updateTerrainCollision();
52 }
53}
54
56{
57 if (!QGC::fuzzyCompare(alt, _coord2AMSLAlt)) {
58 _coord2AMSLAlt = alt;
60 _updateTerrainCollision();
61 }
62}
63
65{
66 if (_specialVisual != specialVisual) {
67 _specialVisual = specialVisual;
69 }
70}
71
72void FlightPathSegment::_sendTerrainPathQuery(void)
73{
74 if (_queryTerrainData && _coord1.isValid() && _coord2.isValid()) {
75 qCDebug(FlightPathSegmentLog) << this << "_sendTerrainPathQuery";
76 // Clear any previous query
77 if (_currentTerrainPathQuery) {
78 // We are already waiting on another query. We don't care about those results any more.
79 disconnect(_currentTerrainPathQuery, &TerrainPathQuery::terrainDataReceived, this, &FlightPathSegment::_terrainDataReceived);
80 _currentTerrainPathQuery = nullptr;
81 }
82
83 // Clear old terrain data
84 _amslTerrainHeights.clear();
85 _distanceBetween = 0;
86 _finalDistanceBetween = 0;
90
91 _currentTerrainPathQuery = new TerrainPathQuery(true /* autoDelete */);
92 connect(_currentTerrainPathQuery, &TerrainPathQuery::terrainDataReceived, this, &FlightPathSegment::_terrainDataReceived);
93 _currentTerrainPathQuery->requestData(_coord1, _coord2);
94 }
95}
96
97void FlightPathSegment::_terrainDataReceived(bool success, const TerrainPathQuery::PathHeightInfo_t& pathHeightInfo)
98{
99 qCDebug(FlightPathSegmentLog) << this << "_terrainDataReceived" << success << pathHeightInfo.heights.count();
100 if (success) {
101 if (!QGC::fuzzyCompare(pathHeightInfo.distanceBetween, _distanceBetween)) {
102 _distanceBetween = pathHeightInfo.distanceBetween;
103 emit distanceBetweenChanged(_distanceBetween);
104 }
105 if (!QGC::fuzzyCompare(pathHeightInfo.finalDistanceBetween, _finalDistanceBetween)) {
106 _finalDistanceBetween = pathHeightInfo.finalDistanceBetween;
107 emit finalDistanceBetweenChanged(_finalDistanceBetween);
108 }
109
110 _amslTerrainHeights.clear();
111 for (const double& amslTerrainHeight: pathHeightInfo.heights) {
112 _amslTerrainHeights.append(amslTerrainHeight);
113 }
115 }
116
117 _currentTerrainPathQuery->deleteLater();
118 _currentTerrainPathQuery = nullptr;
119
120 _updateTerrainCollision();
121}
122
123void FlightPathSegment::_updateTotalDistance(void)
124{
125 double newTotalDistance = 0;
126 if (_coord1.isValid() && _coord2.isValid()) {
127 newTotalDistance = _coord1.distanceTo(_coord2);
128 }
129
130 if (!QGC::fuzzyCompare(newTotalDistance, _totalDistance)) {
131 _totalDistance = newTotalDistance;
132 emit totalDistanceChanged(_totalDistance);
133 }
134}
135
136void FlightPathSegment::_updateTerrainCollision(void)
137{
138 bool newTerrainCollision = false;
139
140 if (_segmentType != SegmentTypeTerrainFrame) {
141 double slope = (_coord2AMSLAlt - _coord1AMSLAlt) / _totalDistance;
142 double yIntercept = _coord1AMSLAlt;
143
144 double x = 0;
145 for (int i=0; i<_amslTerrainHeights.count(); i++) {
146 bool ignoreCollision = false;
147 if (_segmentType == SegmentTypeTakeoff && x < _collisionIgnoreMeters) {
148 ignoreCollision = true;
149 } else if (_segmentType == SegmentTypeLand && x > _totalDistance - _collisionIgnoreMeters) {
150 ignoreCollision = true;
151 }
152
153 if (!ignoreCollision) {
154 double y = _amslTerrainHeights[i].value<double>();
155 if (y > (slope * x) + yIntercept) {
156 newTerrainCollision = true;
157 break;
158 }
159 }
160
161 if (i == _amslTerrainHeights.count() - 2) {
162 x += _finalDistanceBetween;
163 } else {
164 x += _distanceBetween;
165 }
166 }
167 }
168
169 qCDebug(FlightPathSegmentLog) << this << "_updateTerrainCollision new:old" << newTerrainCollision << _terrainCollision;
170
171 if (newTerrainCollision != _terrainCollision) {
172 _terrainCollision = newTerrainCollision;
173 emit terrainCollisionChanged(_terrainCollision);
174 }
175}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void terrainCollisionChanged(bool terrainCollision)
void totalDistanceChanged(double totalDistance)
void setCoordinate2(const QGeoCoordinate &coordinate)
void coord2AMSLAltChanged(void)
void finalDistanceBetweenChanged(double finalDistanceBetween)
void coord1AMSLAltChanged(void)
QGeoCoordinate coordinate1 MEMBER _coord1 NOTIFY coordinate1Changed(QGeoCoordinate coordinate2 MEMBER _coord2 NOTIFY coordinate2Changed) 1(double coord1AMSLAlt MEMBER _coord1AMSLAlt NOTIFY coord1AMSLAltChanged) 1(double coord2AMSLAlt MEMBER _coord2AMSLAlt NOTIFY coord2AMSLAltChanged) 1(bool specialVisual READ specialVisual WRITE setSpecialVisual NOTIFY specialVisualChanged) 1(QVariantList amslTerrainHeights MEMBER _amslTerrainHeights NOTIFY amslTerrainHeightsChanged) 1(double distanceBetween MEMBER _distanceBetween NOTIFY distanceBetweenChanged) 1(double final DistanceBetween MEMBER _finalDistanceBetween NOTIFY final DistanceBetweenChanged) 1(double totalDistance MEMBER _totalDistance NOTIFY totalDistanceChanged) 1(bool terrainCollision MEMBER _terrainCollision NOTIFY terrainCollisionChanged) 1(SegmentType segmentType MEMBER _segmentType CONSTANT) QGeoCoordinate coordinate1(void) const
void setSpecialVisual(bool specialVisual)
void amslTerrainHeightsChanged(void)
bool specialVisual(void) const
void specialVisualChanged(bool specialVisual)
void coordinate2Changed(QGeoCoordinate coordinate)
void setCoord2AMSLAlt(double alt)
void distanceBetweenChanged(double distanceBetween)
void setCoord1AMSLAlt(double alt)
void setCoordinate1(const QGeoCoordinate &coordinate)
void terrainDataReceived(bool success, const TerrainPathQuery::PathHeightInfo_t &pathHeightInfo)
Signalled when terrain data comes back from server.
void requestData(const QGeoCoordinate &fromCoord, const QGeoCoordinate &toCoord)
bool fuzzyCompare(double value1, double value2)
Returns true if the two values are equal or close. Correctly handles 0 and NaN values.
Definition QGC.cc:106
double distanceBetween
Distance between each height value.
double finalDistanceBetween
Distance between final two height values.
QList< double > heights
Terrain heights along path.