Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
ee46c6b5
Unverified
Commit
ee46c6b5
authored
Jan 31, 2018
by
Don Gagne
Committed by
GitHub
Jan 31, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6076 from DonLakeFlyer/BatchTerrainStable
Batch terrain requests
parents
b5f3955c
cf2d2aca
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
158 additions
and
65 deletions
+158
-65
MissionSettingsItem.cc
src/MissionManager/MissionSettingsItem.cc
+0
-6
VisualMissionItem.h
src/MissionManager/VisualMissionItem.h
+1
-5
Terrain.cc
src/Terrain.cc
+107
-29
Terrain.h
src/Terrain.h
+50
-25
No files found.
src/MissionManager/MissionSettingsItem.cc
View file @
ee46c6b5
...
@@ -57,7 +57,6 @@ MissionSettingsItem::MissionSettingsItem(Vehicle* vehicle, QObject* parent)
...
@@ -57,7 +57,6 @@ MissionSettingsItem::MissionSettingsItem(Vehicle* vehicle, QObject* parent)
connect
(
this
,
&
MissionSettingsItem
::
terrainAltitudeChanged
,
this
,
&
MissionSettingsItem
::
_setHomeAltFromTerrain
);
connect
(
this
,
&
MissionSettingsItem
::
terrainAltitudeChanged
,
this
,
&
MissionSettingsItem
::
_setHomeAltFromTerrain
);
connect
(
&
_plannedHomePositionAltitudeFact
,
&
Fact
::
valueChanged
,
this
,
&
MissionSettingsItem
::
_setDirty
);
connect
(
&
_plannedHomePositionAltitudeFact
,
&
Fact
::
valueChanged
,
this
,
&
MissionSettingsItem
::
_updateAltitudeInCoordinate
);
connect
(
&
_plannedHomePositionAltitudeFact
,
&
Fact
::
valueChanged
,
this
,
&
MissionSettingsItem
::
_updateAltitudeInCoordinate
);
connect
(
&
_cameraSection
,
&
CameraSection
::
dirtyChanged
,
this
,
&
MissionSettingsItem
::
_sectionDirtyChanged
);
connect
(
&
_cameraSection
,
&
CameraSection
::
dirtyChanged
,
this
,
&
MissionSettingsItem
::
_sectionDirtyChanged
);
...
@@ -297,11 +296,6 @@ void MissionSettingsItem::setMissionEndRTL(bool missionEndRTL)
...
@@ -297,11 +296,6 @@ void MissionSettingsItem::setMissionEndRTL(bool missionEndRTL)
void
MissionSettingsItem
::
_setHomeAltFromTerrain
(
double
terrainAltitude
)
void
MissionSettingsItem
::
_setHomeAltFromTerrain
(
double
terrainAltitude
)
{
{
if
(
!
_plannedHomePositionFromVehicle
)
{
if
(
!
_plannedHomePositionFromVehicle
)
{
// We need to stop this from signalling, Otherwise the dirty but get set on a delay
// which then marks the Plan view as incorrectly dirty
_plannedHomePositionAltitudeFact
.
setSendValueChangedSignals
(
false
);
_plannedHomePositionAltitudeFact
.
setRawValue
(
terrainAltitude
);
_plannedHomePositionAltitudeFact
.
setRawValue
(
terrainAltitude
);
_plannedHomePositionAltitudeFact
.
clearDeferredValueChangeSignal
();
_plannedHomePositionAltitudeFact
.
setSendValueChangedSignals
(
true
);
}
}
}
}
src/MissionManager/VisualMissionItem.h
View file @
ee46c6b5
...
@@ -7,9 +7,7 @@
...
@@ -7,9 +7,7 @@
*
*
****************************************************************************/
****************************************************************************/
#pragma once
#ifndef VisualMissionItem_H
#define VisualMissionItem_H
#include <QObject>
#include <QObject>
#include <QString>
#include <QString>
...
@@ -215,5 +213,3 @@ private:
...
@@ -215,5 +213,3 @@ private:
double
_lastLatTerrainQuery
;
double
_lastLatTerrainQuery
;
double
_lastLonTerrainQuery
;
double
_lastLonTerrainQuery
;
};
};
#endif
src/Terrain.cc
View file @
ee46c6b5
...
@@ -17,27 +17,63 @@
...
@@ -17,27 +17,63 @@
#include <QJsonDocument>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonArray>
#include <QTimer>
ElevationProvider
::
ElevationProvider
(
QObject
*
parent
)
QGC_LOGGING_CATEGORY
(
ElevationProviderLog
,
"ElevationProviderLog"
)
:
QObject
(
parent
)
Q_GLOBAL_STATIC
(
TerrainBatchManager
,
_terrainBatchManager
)
TerrainBatchManager
::
TerrainBatchManager
(
void
)
{
{
_batchTimer
.
setSingleShot
(
true
);
_batchTimer
.
setInterval
(
_batchTimeout
);
connect
(
&
_batchTimer
,
&
QTimer
::
timeout
,
this
,
&
TerrainBatchManager
::
_sendNextBatch
);
}
void
TerrainBatchManager
::
addQuery
(
ElevationProvider
*
elevationProvider
,
const
QList
<
QGeoCoordinate
>&
coordinates
)
{
if
(
coordinates
.
length
()
>
0
)
{
QueuedRequestInfo_t
queuedRequestInfo
=
{
elevationProvider
,
coordinates
};
_requestQueue
.
append
(
queuedRequestInfo
);
if
(
!
_batchTimer
.
isActive
())
{
_batchTimer
.
start
();
}
}
}
}
bool
ElevationProvider
::
queryTerrainData
(
const
QList
<
QGeoCoordinate
>&
coordinates
)
void
TerrainBatchManager
::
_sendNextBatch
(
void
)
{
{
if
(
_state
!=
State
::
Idle
||
coordinates
.
length
()
==
0
)
{
qCDebug
(
ElevationProviderLog
)
<<
"_sendNextBatch _state:_requestQueue.count"
<<
(
int
)
_state
<<
_requestQueue
.
count
();
return
false
;
if
(
_state
!=
State
::
Idle
)
{
// Waiting for last download the complete, wait some more
_batchTimer
.
start
();
return
;
}
}
QUrlQuery
query
;
if
(
_requestQueue
.
count
()
==
0
)
{
QString
points
=
""
;
return
;
for
(
const
auto
&
coordinate
:
coordinates
)
{
points
+=
QString
::
number
(
coordinate
.
latitude
(),
'f'
,
10
)
+
","
+
QString
::
number
(
coordinate
.
longitude
(),
'f'
,
10
)
+
","
;
}
}
points
=
points
.
mid
(
0
,
points
.
length
()
-
1
);
// remove the last ','
_sentRequests
.
clear
();
// Convert coordinates to point strings for json query
QString
points
;
foreach
(
const
QueuedRequestInfo_t
&
requestInfo
,
_requestQueue
)
{
SentRequestInfo_t
sentRequestInfo
=
{
requestInfo
.
elevationProvider
,
requestInfo
.
coordinates
.
count
()
};
qCDebug
(
ElevationProviderLog
)
<<
"Building request: coordinate count"
<<
requestInfo
.
coordinates
.
count
();
_sentRequests
.
append
(
sentRequestInfo
);
foreach
(
const
QGeoCoordinate
&
coord
,
requestInfo
.
coordinates
)
{
points
+=
QString
::
number
(
coord
.
latitude
(),
'f'
,
10
)
+
","
+
QString
::
number
(
coord
.
longitude
(),
'f'
,
10
)
+
","
;
}
}
points
=
points
.
mid
(
0
,
points
.
length
()
-
1
);
// remove the last ',' from string
_requestQueue
.
clear
();
QUrlQuery
query
;
query
.
addQueryItem
(
QStringLiteral
(
"points"
),
points
);
query
.
addQueryItem
(
QStringLiteral
(
"points"
),
points
);
QUrl
url
(
QStringLiteral
(
"https://api.airmap.com/elevation/stage/srtm1/ele"
));
QUrl
url
(
QStringLiteral
(
"https://api.airmap.com/elevation/stage/srtm1/ele"
));
url
.
setQuery
(
query
);
url
.
setQuery
(
query
);
...
@@ -50,28 +86,36 @@ bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinate
...
@@ -50,28 +86,36 @@ bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinate
QNetworkReply
*
networkReply
=
_networkManager
.
get
(
request
);
QNetworkReply
*
networkReply
=
_networkManager
.
get
(
request
);
if
(
!
networkReply
)
{
if
(
!
networkReply
)
{
return
false
;
_batchFailed
();
return
;
}
}
connect
(
networkReply
,
&
QNetworkReply
::
finished
,
this
,
&
ElevationProvid
er
::
_requestFinished
);
connect
(
networkReply
,
&
QNetworkReply
::
finished
,
this
,
&
TerrainBatchManag
er
::
_requestFinished
);
_state
=
State
::
Downloading
;
_state
=
State
::
Downloading
;
return
true
;
}
}
void
ElevationProvider
::
_requestFinished
()
void
TerrainBatchManager
::
_batchFailed
(
void
)
{
QList
<
float
>
noAltitudes
;
foreach
(
const
SentRequestInfo_t
&
sentRequestInfo
,
_sentRequests
)
{
sentRequestInfo
.
elevationProvider
->
_signalTerrainData
(
false
,
noAltitudes
);
}
_sentRequests
.
clear
();
}
void
TerrainBatchManager
::
_requestFinished
()
{
{
qCDebug
(
ElevationProviderLog
)
<<
"_requestFinished"
;
QNetworkReply
*
reply
=
qobject_cast
<
QNetworkReply
*>
(
QObject
::
sender
());
QNetworkReply
*
reply
=
qobject_cast
<
QNetworkReply
*>
(
QObject
::
sender
());
QList
<
float
>
altitudes
;
_state
=
State
::
Idle
;
_state
=
State
::
Idle
;
// When an error occurs we still end up here
// When an error occurs we still end up here
if
(
reply
->
error
()
!=
QNetworkReply
::
NoError
)
{
if
(
reply
->
error
()
!=
QNetworkReply
::
NoError
)
{
QByteArray
responseBytes
=
reply
->
readAll
();
_batchFailed
();
reply
->
deleteLater
();
QJsonParseError
parseError
;
QJsonDocument
responseJson
=
QJsonDocument
::
fromJson
(
responseBytes
,
&
parseError
);
emit
terrainData
(
false
,
altitudes
);
return
;
return
;
}
}
...
@@ -80,18 +124,52 @@ void ElevationProvider::_requestFinished()
...
@@ -80,18 +124,52 @@ void ElevationProvider::_requestFinished()
QJsonParseError
parseError
;
QJsonParseError
parseError
;
QJsonDocument
responseJson
=
QJsonDocument
::
fromJson
(
responseBytes
,
&
parseError
);
QJsonDocument
responseJson
=
QJsonDocument
::
fromJson
(
responseBytes
,
&
parseError
);
if
(
parseError
.
error
!=
QJsonParseError
::
NoError
)
{
if
(
parseError
.
error
!=
QJsonParseError
::
NoError
)
{
emit
terrainData
(
false
,
altitudes
);
_batchFailed
();
reply
->
deleteLater
();
return
;
return
;
}
}
QJsonObject
rootObject
=
responseJson
.
object
();
QJsonObject
rootObject
=
responseJson
.
object
();
QString
status
=
rootObject
[
"status"
].
toString
();
QString
status
=
rootObject
[
"status"
].
toString
();
if
(
status
=
=
"success"
)
{
if
(
status
!
=
"success"
)
{
const
QJsonArray
&
dataArray
=
rootObject
[
"data"
].
toArray
();
_batchFailed
();
for
(
int
i
=
0
;
i
<
dataArray
.
count
();
i
++
)
{
reply
->
deleteLater
();
altitudes
.
push_back
(
dataArray
[
i
].
toDouble
())
;
return
;
}
}
emit
terrainData
(
true
,
altitudes
);
QList
<
float
>
altitudes
;
const
QJsonArray
&
dataArray
=
rootObject
[
"data"
].
toArray
();
for
(
int
i
=
0
;
i
<
dataArray
.
count
();
i
++
)
{
altitudes
.
push_back
(
dataArray
[
i
].
toDouble
());
}
int
currentIndex
=
0
;
foreach
(
const
SentRequestInfo_t
&
sentRequestInfo
,
_sentRequests
)
{
QList
<
float
>
requestAltitudes
=
altitudes
.
mid
(
currentIndex
,
sentRequestInfo
.
cCoord
);
sentRequestInfo
.
elevationProvider
->
_signalTerrainData
(
true
,
requestAltitudes
);
currentIndex
+=
sentRequestInfo
.
cCoord
;
}
}
emit
terrainData
(
false
,
altitudes
);
_sentRequests
.
clear
();
reply
->
deleteLater
();
}
ElevationProvider
::
ElevationProvider
(
QObject
*
parent
)
:
QObject
(
parent
)
{
}
void
ElevationProvider
::
queryTerrainData
(
const
QList
<
QGeoCoordinate
>&
coordinates
)
{
qCDebug
(
ElevationProviderLog
)
<<
"queryTerrainData: coordinate count"
<<
coordinates
.
count
();
if
(
coordinates
.
length
()
==
0
)
{
return
;
}
_terrainBatchManager
->
addQuery
(
this
,
coordinates
);
}
void
ElevationProvider
::
_signalTerrainData
(
bool
success
,
QList
<
float
>&
altitudes
)
{
emit
terrainData
(
success
,
altitudes
);
}
}
src/Terrain.h
View file @
ee46c6b5
...
@@ -9,47 +9,72 @@
...
@@ -9,47 +9,72 @@
#pragma once
#pragma once
#include "QGCLoggingCategory.h"
#include <QObject>
#include <QObject>
#include <QGeoCoordinate>
#include <QGeoCoordinate>
#include <QNetworkAccessManager>
#include <QNetworkAccessManager>
#include <QTimer>
/* usage example:
Q_DECLARE_LOGGING_CATEGORY
(
ElevationProviderLog
)
ElevationProvider *p = new ElevationProvider();
QList<QGeoCoordinate> coordinates;
QGeoCoordinate c(47.379243, 8.548265);
coordinates.push_back(c);
c.setLatitude(c.latitude()+0.01);
coordinates.push_back(c);
p->queryTerrainData(coordinates);
*/
class
ElevationProvider
;
class
ElevationProvider
:
public
QObject
/// Used internally by ElevationProvider to batch requests together
{
class
TerrainBatchManager
:
public
QObject
{
Q_OBJECT
Q_OBJECT
public:
ElevationProvider
(
QObject
*
parent
=
NULL
);
/**
public:
* Async elevation query for a list of lon,lat coordinates. When the query is done, the terrainData() signal
TerrainBatchManager
(
void
);
* is emitted.
* @param coordinates
* @return true on success
*/
bool
queryTerrainData
(
const
QList
<
QGeoCoordinate
>&
coordinates
);
signals:
void
addQuery
(
ElevationProvider
*
elevationProvider
,
const
QList
<
QGeoCoordinate
>&
coordinates
);
void
terrainData
(
bool
success
,
QList
<
float
>
altitudes
);
private
slots
:
private
slots
:
void
_requestFinished
();
void
_sendNextBatch
(
void
);
void
_requestFinished
(
void
);
private:
private:
typedef
struct
{
ElevationProvider
*
elevationProvider
;
QList
<
QGeoCoordinate
>
coordinates
;
}
QueuedRequestInfo_t
;
typedef
struct
{
ElevationProvider
*
elevationProvider
;
int
cCoord
;
}
SentRequestInfo_t
;
enum
class
State
{
enum
class
State
{
Idle
,
Idle
,
Downloading
,
Downloading
,
};
};
State
_state
=
State
::
Idle
;
void
_batchFailed
(
void
);
QNetworkAccessManager
_networkManager
;
QList
<
QueuedRequestInfo_t
>
_requestQueue
;
QList
<
SentRequestInfo_t
>
_sentRequests
;
State
_state
=
State
::
Idle
;
QNetworkAccessManager
_networkManager
;
const
int
_batchTimeout
=
500
;
QTimer
_batchTimer
;
};
/// NOTE: ElevationProvider is not thread safe. All instances/calls to ElevationProvider must be on main thread.
class
ElevationProvider
:
public
QObject
{
Q_OBJECT
public:
ElevationProvider
(
QObject
*
parent
=
NULL
);
/// Async elevation query for a list of lon,lat coordinates. When the query is done, the terrainData() signal
/// is emitted.
/// @param coordinates to query
void
queryTerrainData
(
const
QList
<
QGeoCoordinate
>&
coordinates
);
// Internal method
void
_signalTerrainData
(
bool
success
,
QList
<
float
>&
altitudes
);
signals:
void
terrainData
(
bool
success
,
QList
<
float
>
altitudes
);
};
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment