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 "QGCMath.h"
4#include "TerrainQuery.h"
5
6QGC_LOGGING_CATEGORY(FlightPathSegmentLog, "Plan.FlightPathSegment")
7
8FlightPathSegment::FlightPathSegment(SegmentType segmentType, const QGeoCoordinate& coord1, double amslCoord1Alt, const QGeoCoordinate& coord2, double amslCoord2Alt, bool queryTerrainData, QObject* parent)
9 : QObject (parent)
10 , _coord1 (coord1)
11 , _coord2 (coord2)
12 , _coord1AMSLAlt (amslCoord1Alt)
13 , _coord2AMSLAlt (amslCoord2Alt)
14 , _queryTerrainData (queryTerrainData)
15 , _segmentType (segmentType)
16{
17 _delayedTerrainPathQueryTimer.setSingleShot(true);
18 _delayedTerrainPathQueryTimer.setInterval(200);
19 _delayedTerrainPathQueryTimer.callOnTimeout(this, &FlightPathSegment::_sendTerrainPathQuery);
20 _updateTotalDistance();
21
22 qCDebug(FlightPathSegmentLog) << this << "new" << coord1 << coord2 << amslCoord1Alt << amslCoord2Alt << _totalDistance;
23
24 _sendTerrainPathQuery();
25}
26
27void FlightPathSegment::setCoordinate1(const QGeoCoordinate &coordinate)
28{
29 if (_coord1 != coordinate) {
30 _coord1 = coordinate;
31 emit coordinate1Changed(_coord1);
32 _delayedTerrainPathQueryTimer.start();
33 _updateTotalDistance();
34 }
35}
36
37void FlightPathSegment::setCoordinate2(const QGeoCoordinate &coordinate)
38{
39 if (_coord2 != coordinate) {
40 _coord2 = coordinate;
41 emit coordinate2Changed(_coord2);
42 _delayedTerrainPathQueryTimer.start();
43 _updateTotalDistance();
44 }
45}
46
48{
49 if (!QGC::fuzzyCompare(alt, _coord1AMSLAlt)) {
50 _coord1AMSLAlt = alt;
52 _updateTerrainCollision();
53 }
54}
55
57{
58 if (!QGC::fuzzyCompare(alt, _coord2AMSLAlt)) {
59 _coord2AMSLAlt = alt;
61 _updateTerrainCollision();
62 }
63}
64
66{
67 if (_specialVisual != specialVisual) {
68 _specialVisual = specialVisual;
70 }
71}
72
73void FlightPathSegment::_sendTerrainPathQuery(void)
74{
75 if (_queryTerrainData && _coord1.isValid() && _coord2.isValid()) {
76 qCDebug(FlightPathSegmentLog) << this << "_sendTerrainPathQuery";
77 // Clear any previous query
78 if (_currentTerrainPathQuery) {
79 // We are already waiting on another query. We don't care about those results any more.
80 disconnect(_currentTerrainPathQuery, &TerrainPathQuery::terrainDataReceived, this, &FlightPathSegment::_terrainDataReceived);
81 _currentTerrainPathQuery = nullptr;
82 }
83
84 // Clear old terrain data
85 _amslTerrainHeights.clear();
86 _distanceBetween = 0;
87 _finalDistanceBetween = 0;
91
92 _currentTerrainPathQuery = new TerrainPathQuery(true /* autoDelete */);
93 connect(_currentTerrainPathQuery, &TerrainPathQuery::terrainDataReceived, this, &FlightPathSegment::_terrainDataReceived);
94 _currentTerrainPathQuery->requestData(_coord1, _coord2);
95 }
96}
97
98void FlightPathSegment::_terrainDataReceived(bool success, const TerrainPathHeightInfo& pathHeightInfo)
99{
100 qCDebug(FlightPathSegmentLog) << this << "_terrainDataReceived" << success << pathHeightInfo.heights.count();
101 if (success) {
102 if (!QGC::fuzzyCompare(pathHeightInfo.distanceBetween, _distanceBetween)) {
103 _distanceBetween = pathHeightInfo.distanceBetween;
104 emit distanceBetweenChanged(_distanceBetween);
105 }
106 if (!QGC::fuzzyCompare(pathHeightInfo.finalDistanceBetween, _finalDistanceBetween)) {
107 _finalDistanceBetween = pathHeightInfo.finalDistanceBetween;
108 emit finalDistanceBetweenChanged(_finalDistanceBetween);
109 }
110
111 _amslTerrainHeights.clear();
112 for (const double& amslTerrainHeight: pathHeightInfo.heights) {
113 _amslTerrainHeights.append(amslTerrainHeight);
114 }
116 }
117
118 _currentTerrainPathQuery->deleteLater();
119 _currentTerrainPathQuery = nullptr;
120
121 _updateTerrainCollision();
122}
123
124void FlightPathSegment::_updateTotalDistance(void)
125{
126 double newTotalDistance = 0;
127 if (_coord1.isValid() && _coord2.isValid()) {
128 newTotalDistance = _coord1.distanceTo(_coord2);
129 }
130
131 if (!QGC::fuzzyCompare(newTotalDistance, _totalDistance)) {
132 _totalDistance = newTotalDistance;
133 emit totalDistanceChanged(_totalDistance);
134 }
135}
136
137void FlightPathSegment::_updateTerrainCollision(void)
138{
139 bool newTerrainCollision = false;
140
141 if (_segmentType != SegmentTypeTerrainFrame) {
142 double slope = (_coord2AMSLAlt - _coord1AMSLAlt) / _totalDistance;
143 double yIntercept = _coord1AMSLAlt;
144
145 double x = 0;
146 for (int i=0; i<_amslTerrainHeights.count(); i++) {
147 bool ignoreCollision = false;
148 if (_segmentType == SegmentTypeTakeoff && x < _collisionIgnoreMeters) {
149 ignoreCollision = true;
150 } else if (_segmentType == SegmentTypeLand && x > _totalDistance - _collisionIgnoreMeters) {
151 ignoreCollision = true;
152 }
153
154 if (!ignoreCollision) {
155 double y = _amslTerrainHeights[i].value<double>();
156 if (y > (slope * x) + yIntercept) {
157 newTerrainCollision = true;
158 break;
159 }
160 }
161
162 if (i == _amslTerrainHeights.count() - 2) {
163 x += _finalDistanceBetween;
164 } else {
165 x += _distanceBetween;
166 }
167 }
168 }
169
170 qCDebug(FlightPathSegmentLog) << this << "_updateTerrainCollision new:old" << newTerrainCollision << _terrainCollision;
171
172 if (newTerrainCollision != _terrainCollision) {
173 _terrainCollision = newTerrainCollision;
174 emit terrainCollisionChanged(_terrainCollision);
175 }
176}
#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 coordinate1Changed(QGeoCoordinate coordinate)
void coord1AMSLAltChanged(void)
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 QGCMath.cc:109
double finalDistanceBetween
Distance between final two height values.
QList< double > heights
Terrain heights along path.
double distanceBetween
Distance between each height value.