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
12241e62
Commit
12241e62
authored
Mar 16, 2018
by
DonLakeFlyer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Restructure terrain query to support path query as well
parent
c7f4ac3d
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
480 additions
and
89 deletions
+480
-89
qgroundcontrol.pro
qgroundcontrol.pro
+3
-2
VisualMissionItem.cc
src/MissionManager/VisualMissionItem.cc
+4
-4
Terrain.h
src/Terrain.h
+0
-83
TerrainQuery.cc
src/Terrain/TerrainQuery.cc
+331
-0
TerrainQuery.h
src/Terrain/TerrainQuery.h
+142
-0
No files found.
qgroundcontrol.pro
View file @
12241e62
...
...
@@ -346,6 +346,7 @@ INCLUDEPATH += \
src
/
QtLocationPlugin
\
src
/
QtLocationPlugin
/
QMLControl
\
src
/
Settings
\
src
/
Terrain
\
src
/
VehicleSetup
\
src
/
ViewWidgets
\
src
/
Audio
\
...
...
@@ -586,7 +587,7 @@ HEADERS += \
src
/
Settings
/
SettingsManager
.
h
\
src
/
Settings
/
UnitsSettings
.
h
\
src
/
Settings
/
VideoSettings
.
h
\
src
/
Terrain
.
h
\
src
/
Terrain
/
TerrainQuery
.
h
\
src
/
Vehicle
/
MAVLinkLogManager
.
h
\
src
/
VehicleSetup
/
JoystickConfigController
.
h
\
src
/
comm
/
LinkConfiguration
.
h
\
...
...
@@ -778,7 +779,7 @@ SOURCES += \
src
/
Settings
/
SettingsManager
.
cc
\
src
/
Settings
/
UnitsSettings
.
cc
\
src
/
Settings
/
VideoSettings
.
cc
\
src
/
Terrain
.
cc
\
src
/
Terrain
/
TerrainQuery
.
cc
\
src
/
Vehicle
/
MAVLinkLogManager
.
cc
\
src
/
VehicleSetup
/
JoystickConfigController
.
cc
\
src
/
comm
/
LinkConfiguration
.
cc
\
...
...
src/MissionManager/VisualMissionItem.cc
View file @
12241e62
...
...
@@ -15,7 +15,7 @@
#include "FirmwarePluginManager.h"
#include "QGCApplication.h"
#include "JsonHelper.h"
#include "Terrain.h"
#include "Terrain
Query
.h"
const
char
*
VisualMissionItem
::
jsonTypeKey
=
"type"
;
const
char
*
VisualMissionItem
::
jsonTypeSimpleItemValue
=
"SimpleItem"
;
...
...
@@ -172,11 +172,11 @@ void VisualMissionItem::_reallyUpdateTerrainAltitude(void)
if
(
coord
.
isValid
()
&&
(
qIsNaN
(
_terrainAltitude
)
||
!
qFuzzyCompare
(
_lastLatTerrainQuery
,
coord
.
latitude
())
||
qFuzzyCompare
(
_lastLonTerrainQuery
,
coord
.
longitude
())))
{
_lastLatTerrainQuery
=
coord
.
latitude
();
_lastLonTerrainQuery
=
coord
.
longitude
();
ElevationProvider
*
terrain
=
new
ElevationProvider
(
this
);
connect
(
terrain
,
&
ElevationProvider
::
terrainData
,
this
,
&
VisualMissionItem
::
_terrainDataReceived
);
TerrainAtCoordinateQuery
*
terrain
=
new
TerrainAtCoordinateQuery
(
this
);
connect
(
terrain
,
&
TerrainAtCoordinateQuery
::
terrainData
,
this
,
&
VisualMissionItem
::
_terrainDataReceived
);
QList
<
QGeoCoordinate
>
rgCoord
;
rgCoord
.
append
(
coordinate
());
terrain
->
queryTerrain
Data
(
rgCoord
);
terrain
->
request
Data
(
rgCoord
);
}
}
...
...
src/Terrain.h
deleted
100644 → 0
View file @
c7f4ac3d
/****************************************************************************
*
* (c) 2017 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.
*
****************************************************************************/
#pragma once
#include "QGCLoggingCategory.h"
#include <QObject>
#include <QGeoCoordinate>
#include <QNetworkAccessManager>
#include <QTimer>
Q_DECLARE_LOGGING_CATEGORY
(
ElevationProviderLog
)
class
ElevationProvider
;
/// Used internally by ElevationProvider to batch requests together
class
TerrainBatchManager
:
public
QObject
{
Q_OBJECT
public:
TerrainBatchManager
(
void
);
void
addQuery
(
ElevationProvider
*
elevationProvider
,
const
QList
<
QGeoCoordinate
>&
coordinates
);
private
slots
:
void
_sendNextBatch
(
void
);
void
_requestFinished
(
void
);
void
_elevationProviderDestroyed
(
QObject
*
elevationProvider
);
private:
typedef
struct
{
ElevationProvider
*
elevationProvider
;
QList
<
QGeoCoordinate
>
coordinates
;
}
QueuedRequestInfo_t
;
typedef
struct
{
ElevationProvider
*
elevationProvider
;
bool
providerDestroyed
;
int
cCoord
;
}
SentRequestInfo_t
;
enum
class
State
{
Idle
,
Downloading
,
};
void
_batchFailed
(
void
);
QString
_stateToString
(
State
state
);
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
);
};
src/Terrain.cc
→
src/Terrain
/TerrainQuery
.cc
View file @
12241e62
...
...
@@ -7,7 +7,7 @@
*
****************************************************************************/
#include "Terrain.h"
#include "Terrain
Query
.h"
#include <QUrl>
#include <QUrlQuery>
...
...
@@ -19,23 +19,85 @@
#include <QJsonArray>
#include <QTimer>
QGC_LOGGING_CATEGORY
(
ElevationProviderLog
,
"ElevationProvider
Log"
)
QGC_LOGGING_CATEGORY
(
TerrainQueryLog
,
"TerrainQuery
Log"
)
Q_GLOBAL_STATIC
(
Terrain
BatchManager
,
_terrain
BatchManager
)
Q_GLOBAL_STATIC
(
Terrain
AtCoordinateBatchManager
,
_TerrainAtCoordinate
BatchManager
)
TerrainBatchManager
::
TerrainBatchManager
(
void
)
TerrainQuery
::
TerrainQuery
(
QObject
*
parent
)
:
QObject
(
parent
)
{
}
void
TerrainQuery
::
_sendQuery
(
const
QString
&
path
,
const
QUrlQuery
&
urlQuery
)
{
QUrl
url
(
QStringLiteral
(
"https://api.airmap.com/elevation/v1/ele"
)
+
path
);
url
.
setQuery
(
urlQuery
);
QNetworkRequest
request
(
url
);
QNetworkProxy
tProxy
;
tProxy
.
setType
(
QNetworkProxy
::
DefaultProxy
);
_networkManager
.
setProxy
(
tProxy
);
QNetworkReply
*
networkReply
=
_networkManager
.
get
(
request
);
if
(
!
networkReply
)
{
_getNetworkReplyFailed
();
return
;
}
connect
(
networkReply
,
&
QNetworkReply
::
finished
,
this
,
&
TerrainQuery
::
_requestFinished
);
}
void
TerrainQuery
::
_requestFinished
(
void
)
{
QNetworkReply
*
reply
=
qobject_cast
<
QNetworkReply
*>
(
QObject
::
sender
());
if
(
reply
->
error
()
!=
QNetworkReply
::
NoError
)
{
qCDebug
(
TerrainQueryLog
)
<<
"_requestFinished error:"
<<
reply
->
error
();
_requestFailed
(
reply
->
error
());
reply
->
deleteLater
();
return
;
}
QByteArray
responseBytes
=
reply
->
readAll
();
reply
->
deleteLater
();
// Convert the response to Json
QJsonParseError
parseError
;
QJsonDocument
responseJson
=
QJsonDocument
::
fromJson
(
responseBytes
,
&
parseError
);
if
(
parseError
.
error
!=
QJsonParseError
::
NoError
)
{
qCDebug
(
TerrainQueryLog
)
<<
"_requestFinished unable to parse json:"
<<
parseError
.
errorString
();
_requestJsonParseFailed
(
parseError
.
errorString
());
return
;
}
// Check airmap reponse status
QJsonObject
rootObject
=
responseJson
.
object
();
QString
status
=
rootObject
[
"status"
].
toString
();
if
(
status
!=
"success"
)
{
qCDebug
(
TerrainQueryLog
)
<<
"_requestFinished status != success:"
<<
status
;
_requestAirmapStatusFailed
(
status
);
return
;
}
// Send back data
_requestSucess
(
rootObject
[
"data"
]);
}
TerrainAtCoordinateBatchManager
::
TerrainAtCoordinateBatchManager
(
void
)
{
_batchTimer
.
setSingleShot
(
true
);
_batchTimer
.
setInterval
(
_batchTimeout
);
connect
(
&
_batchTimer
,
&
QTimer
::
timeout
,
this
,
&
TerrainBatchManager
::
_sendNextBatch
);
connect
(
&
_batchTimer
,
&
QTimer
::
timeout
,
this
,
&
Terrain
AtCoordinate
BatchManager
::
_sendNextBatch
);
}
void
Terrain
BatchManager
::
addQuery
(
ElevationProvider
*
elevationProvider
,
const
QList
<
QGeoCoordinate
>&
coordinates
)
void
Terrain
AtCoordinateBatchManager
::
addQuery
(
TerrainAtCoordinateQuery
*
terrainAtCoordinateQuery
,
const
QList
<
QGeoCoordinate
>&
coordinates
)
{
if
(
coordinates
.
length
()
>
0
)
{
qCDebug
(
ElevationProviderLog
)
<<
"addQuery: elevationProvider:coordinates.count"
<<
elevationProvider
<<
coordinates
.
count
();
connect
(
elevationProvider
,
&
ElevationProvider
::
destroyed
,
this
,
&
TerrainBatchManager
::
_elevationProvider
Destroyed
);
QueuedRequestInfo_t
queuedRequestInfo
=
{
elevationProvider
,
coordinates
};
qCDebug
(
TerrainQueryLog
)
<<
"addQuery: TerrainAtCoordinateQuery:coordinates.count"
<<
terrainAtCoordinateQuery
<<
coordinates
.
count
();
connect
(
terrainAtCoordinateQuery
,
&
TerrainAtCoordinateQuery
::
destroyed
,
this
,
&
TerrainAtCoordinateBatchManager
::
_queryObject
Destroyed
);
QueuedRequestInfo_t
queuedRequestInfo
=
{
terrainAtCoordinateQuery
,
coordinates
};
_requestQueue
.
append
(
queuedRequestInfo
);
if
(
!
_batchTimer
.
isActive
())
{
_batchTimer
.
start
();
...
...
@@ -43,9 +105,9 @@ void TerrainBatchManager::addQuery(ElevationProvider* elevationProvider, const Q
}
}
void
TerrainBatchManager
::
_sendNextBatch
(
void
)
void
Terrain
AtCoordinate
BatchManager
::
_sendNextBatch
(
void
)
{
qCDebug
(
ElevationProvider
Log
)
<<
"_sendNextBatch _state:_requestQueue.count:_sentRequests.count"
<<
_stateToString
(
_state
)
<<
_requestQueue
.
count
()
<<
_sentRequests
.
count
();
qCDebug
(
TerrainQuery
Log
)
<<
"_sendNextBatch _state:_requestQueue.count:_sentRequests.count"
<<
_stateToString
(
_state
)
<<
_requestQueue
.
count
()
<<
_sentRequests
.
count
();
if
(
_state
!=
State
::
Idle
)
{
// Waiting for last download the complete, wait some more
...
...
@@ -62,8 +124,8 @@ void TerrainBatchManager::_sendNextBatch(void)
// Convert coordinates to point strings for json query
QString
points
;
foreach
(
const
QueuedRequestInfo_t
&
requestInfo
,
_requestQueue
)
{
SentRequestInfo_t
sentRequestInfo
=
{
requestInfo
.
elevationProvider
,
false
,
requestInfo
.
coordinates
.
count
()
};
qCDebug
(
ElevationProvider
Log
)
<<
"Building request: coordinate count"
<<
requestInfo
.
coordinates
.
count
();
SentRequestInfo_t
sentRequestInfo
=
{
requestInfo
.
terrainAtCoordinateQuery
,
false
,
requestInfo
.
coordinates
.
count
()
};
qCDebug
(
TerrainQuery
Log
)
<<
"Building request: coordinate count"
<<
requestInfo
.
coordinates
.
count
();
_sentRequests
.
append
(
sentRequestInfo
);
foreach
(
const
QGeoCoordinate
&
coord
,
requestInfo
.
coordinates
)
{
...
...
@@ -77,104 +139,34 @@ void TerrainBatchManager::_sendNextBatch(void)
QUrlQuery
query
;
query
.
addQueryItem
(
QStringLiteral
(
"points"
),
points
);
QUrl
url
(
QStringLiteral
(
"https://api.airmap.com/elevation/v1/ele"
));
url
.
setQuery
(
query
);
QNetworkRequest
request
(
url
);
QNetworkProxy
tProxy
;
tProxy
.
setType
(
QNetworkProxy
::
DefaultProxy
);
_networkManager
.
setProxy
(
tProxy
);
QNetworkReply
*
networkReply
=
_networkManager
.
get
(
request
);
if
(
!
networkReply
)
{
_batchFailed
();
return
;
}
connect
(
networkReply
,
&
QNetworkReply
::
finished
,
this
,
&
TerrainBatchManager
::
_requestFinished
);
_sendQuery
(
QString
()
/* path */
,
query
);
_state
=
State
::
Downloading
;
}
void
TerrainBatchManager
::
_batchFailed
(
void
)
void
Terrain
AtCoordinate
BatchManager
::
_batchFailed
(
void
)
{
QList
<
float
>
noAltitudes
;
foreach
(
const
SentRequestInfo_t
&
sentRequestInfo
,
_sentRequests
)
{
if
(
!
sentRequestInfo
.
providerDestroyed
)
{
disconnect
(
sentRequestInfo
.
elevationProvider
,
&
ElevationProvider
::
destroyed
,
this
,
&
TerrainBatchManager
::
_elevationProviderDestroyed
);
sentRequestInfo
.
elevationProvider
->
_signalTerrainData
(
false
,
noAltitudes
);
}
}
_sentRequests
.
clear
();
}
void
TerrainBatchManager
::
_requestFinished
()
{
QNetworkReply
*
reply
=
qobject_cast
<
QNetworkReply
*>
(
QObject
::
sender
());
_state
=
State
::
Idle
;
// When an error occurs we still end up here
if
(
reply
->
error
()
!=
QNetworkReply
::
NoError
)
{
qCDebug
(
ElevationProviderLog
)
<<
"_requestFinished error:"
<<
reply
->
error
();
_batchFailed
();
reply
->
deleteLater
();
return
;
}
QByteArray
responseBytes
=
reply
->
readAll
();
QJsonParseError
parseError
;
QJsonDocument
responseJson
=
QJsonDocument
::
fromJson
(
responseBytes
,
&
parseError
);
if
(
parseError
.
error
!=
QJsonParseError
::
NoError
)
{
qCDebug
(
ElevationProviderLog
)
<<
"_requestFinished unable to parse json:"
<<
parseError
.
errorString
();
_batchFailed
();
reply
->
deleteLater
();
return
;
}
QJsonObject
rootObject
=
responseJson
.
object
();
QString
status
=
rootObject
[
"status"
].
toString
();
if
(
status
!=
"success"
)
{
qCDebug
(
ElevationProviderLog
)
<<
"_requestFinished status != success:"
<<
status
;
_batchFailed
();
reply
->
deleteLater
();
return
;
}
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
)
{
if
(
!
sentRequestInfo
.
providerDestroyed
)
{
disconnect
(
sentRequestInfo
.
elevationProvider
,
&
ElevationProvider
::
destroyed
,
this
,
&
TerrainBatchManager
::
_elevationProviderDestroyed
);
QList
<
float
>
requestAltitudes
=
altitudes
.
mid
(
currentIndex
,
sentRequestInfo
.
cCoord
);
sentRequestInfo
.
elevationProvider
->
_signalTerrainData
(
true
,
requestAltitudes
);
currentIndex
+=
sentRequestInfo
.
cCoord
;
if
(
!
sentRequestInfo
.
queryObjectDestroyed
)
{
disconnect
(
sentRequestInfo
.
terrainAtCoordinateQuery
,
&
TerrainAtCoordinateQuery
::
destroyed
,
this
,
&
TerrainAtCoordinateBatchManager
::
_queryObjectDestroyed
);
sentRequestInfo
.
terrainAtCoordinateQuery
->
_signalTerrainData
(
false
,
noAltitudes
);
}
}
_sentRequests
.
clear
();
reply
->
deleteLater
();
}
void
Terrain
BatchManager
::
_elevationProviderDestroyed
(
QObject
*
elevationProvider
)
void
Terrain
AtCoordinateBatchManager
::
_queryObjectDestroyed
(
QObject
*
terrainAtCoordinateQuery
)
{
// Remove/Mark deleted objects queries from queues
qCDebug
(
ElevationProviderLog
)
<<
"_elevationProviderDestroyed elevationProvider"
<<
elevationProvider
;
qCDebug
(
TerrainQueryLog
)
<<
"_TerrainAtCoordinateQueryDestroyed TerrainAtCoordinateQuery"
<<
terrainAtCoordinateQuery
;
int
i
=
0
;
while
(
i
<
_requestQueue
.
count
())
{
const
QueuedRequestInfo_t
&
requestInfo
=
_requestQueue
[
i
];
if
(
requestInfo
.
elevationProvider
==
elevationProvider
)
{
qCDebug
(
ElevationProviderLog
)
<<
"Removing deleted provider from _requestQueue index:elevationProvider"
<<
i
<<
requestInfo
.
elevationProvider
;
if
(
requestInfo
.
terrainAtCoordinateQuery
==
terrainAtCoordinateQuery
)
{
qCDebug
(
TerrainQueryLog
)
<<
"Removing deleted provider from _requestQueue index:terrainAtCoordinateQuery"
<<
i
<<
requestInfo
.
terrainAtCoordinateQuery
;
_requestQueue
.
removeAt
(
i
);
}
else
{
i
++
;
...
...
@@ -183,14 +175,14 @@ void TerrainBatchManager::_elevationProviderDestroyed(QObject* elevationProvider
for
(
int
i
=
0
;
i
<
_sentRequests
.
count
();
i
++
)
{
SentRequestInfo_t
&
sentRequestInfo
=
_sentRequests
[
i
];
if
(
sentRequestInfo
.
elevationProvider
==
elevationProvider
)
{
qCDebug
(
ElevationProviderLog
)
<<
"Zombieing deleted provider from _sentRequests index:elevatationProvider"
<<
sentRequestInfo
.
elevationProvider
;
sentRequestInfo
.
provider
Destroyed
=
true
;
if
(
sentRequestInfo
.
terrainAtCoordinateQuery
==
terrainAtCoordinateQuery
)
{
qCDebug
(
TerrainQueryLog
)
<<
"Zombieing deleted provider from _sentRequests index:terrainAtCoordinateQuery"
<<
sentRequestInfo
.
terrainAtCoordinateQuery
;
sentRequestInfo
.
queryObject
Destroyed
=
true
;
}
}
}
QString
TerrainBatchManager
::
_stateToString
(
State
state
)
QString
Terrain
AtCoordinate
BatchManager
::
_stateToString
(
State
state
)
{
switch
(
state
)
{
case
State
:
:
Idle
:
...
...
@@ -202,21 +194,138 @@ QString TerrainBatchManager::_stateToString(State state)
return
QStringLiteral
(
"State unknown"
);
}
ElevationProvider
::
ElevationProvider
(
QObject
*
parent
)
void
TerrainAtCoordinateBatchManager
::
_getNetworkReplyFailed
(
void
)
{
_batchFailed
();
}
void
TerrainAtCoordinateBatchManager
::
_requestFailed
(
QNetworkReply
::
NetworkError
error
)
{
Q_UNUSED
(
error
);
_state
=
State
::
Idle
;
_batchFailed
();
}
void
TerrainAtCoordinateBatchManager
::
_requestJsonParseFailed
(
const
QString
&
errorString
)
{
Q_UNUSED
(
errorString
);
_state
=
State
::
Idle
;
_batchFailed
();
}
void
TerrainAtCoordinateBatchManager
::
_requestAirmapStatusFailed
(
const
QString
&
status
)
{
Q_UNUSED
(
status
);
_state
=
State
::
Idle
;
_batchFailed
();
}
void
TerrainAtCoordinateBatchManager
::
_requestSucess
(
const
QJsonValue
&
dataJsonValue
)
{
_state
=
State
::
Idle
;
QList
<
float
>
altitudes
;
const
QJsonArray
&
dataArray
=
dataJsonValue
.
toArray
();
for
(
int
i
=
0
;
i
<
dataArray
.
count
();
i
++
)
{
altitudes
.
push_back
(
dataArray
[
i
].
toDouble
());
}
int
currentIndex
=
0
;
foreach
(
const
SentRequestInfo_t
&
sentRequestInfo
,
_sentRequests
)
{
if
(
!
sentRequestInfo
.
queryObjectDestroyed
)
{
disconnect
(
sentRequestInfo
.
terrainAtCoordinateQuery
,
&
TerrainAtCoordinateQuery
::
destroyed
,
this
,
&
TerrainAtCoordinateBatchManager
::
_queryObjectDestroyed
);
QList
<
float
>
requestAltitudes
=
altitudes
.
mid
(
currentIndex
,
sentRequestInfo
.
cCoord
);
sentRequestInfo
.
terrainAtCoordinateQuery
->
_signalTerrainData
(
true
,
requestAltitudes
);
currentIndex
+=
sentRequestInfo
.
cCoord
;
}
}
_sentRequests
.
clear
();
}
TerrainAtCoordinateQuery
::
TerrainAtCoordinateQuery
(
QObject
*
parent
)
:
QObject
(
parent
)
{
}
void
ElevationProvider
::
queryTerrain
Data
(
const
QList
<
QGeoCoordinate
>&
coordinates
)
void
TerrainAtCoordinateQuery
::
request
Data
(
const
QList
<
QGeoCoordinate
>&
coordinates
)
{
if
(
coordinates
.
length
()
==
0
)
{
return
;
}
_
terrain
BatchManager
->
addQuery
(
this
,
coordinates
);
_
TerrainAtCoordinate
BatchManager
->
addQuery
(
this
,
coordinates
);
}
void
ElevationProvider
::
_signalTerrainData
(
bool
success
,
QList
<
float
>&
altitudes
)
void
TerrainAtCoordinateQuery
::
_signalTerrainData
(
bool
success
,
QList
<
float
>&
altitudes
)
{
emit
terrainData
(
success
,
altitudes
);
}
TerrainPathQuery
::
TerrainPathQuery
(
QObject
*
parent
)
:
TerrainQuery
(
parent
)
{
}
void
TerrainPathQuery
::
requestData
(
const
QGeoCoordinate
&
fromCoord
,
const
QGeoCoordinate
&
toCoord
)
{
if
(
!
fromCoord
.
isValid
()
||
!
toCoord
.
isValid
())
{
return
;
}
QString
points
;
points
+=
QString
::
number
(
fromCoord
.
latitude
(),
'f'
,
10
)
+
","
+
QString
::
number
(
fromCoord
.
longitude
(),
'f'
,
10
)
+
","
;
points
+=
QString
::
number
(
toCoord
.
latitude
(),
'f'
,
10
)
+
","
+
QString
::
number
(
toCoord
.
longitude
(),
'f'
,
10
);
QUrlQuery
query
;
query
.
addQueryItem
(
QStringLiteral
(
"points"
),
points
);
_sendQuery
(
QStringLiteral
(
"/path"
),
query
);
}
void
TerrainPathQuery
::
_getNetworkReplyFailed
(
void
)
{
QList
<
double
>
altitudes
;
emit
terrainData
(
false
,
0
,
0
,
altitudes
);
}
void
TerrainPathQuery
::
_requestFailed
(
QNetworkReply
::
NetworkError
error
)
{
Q_UNUSED
(
error
);
QList
<
double
>
altitudes
;
emit
terrainData
(
false
,
0
,
0
,
altitudes
);
}
void
TerrainPathQuery
::
_requestJsonParseFailed
(
const
QString
&
errorString
)
{
Q_UNUSED
(
errorString
);
QList
<
double
>
altitudes
;
emit
terrainData
(
false
,
0
,
0
,
altitudes
);
}
void
TerrainPathQuery
::
_requestAirmapStatusFailed
(
const
QString
&
status
)
{
Q_UNUSED
(
status
);
QList
<
double
>
altitudes
;
emit
terrainData
(
false
,
0
,
0
,
altitudes
);
}
void
TerrainPathQuery
::
_requestSucess
(
const
QJsonValue
&
dataJsonValue
)
{
QJsonObject
jsonObject
=
dataJsonValue
.
toArray
()[
0
].
toObject
();
QJsonArray
stepArray
=
jsonObject
[
"step"
].
toArray
();
QJsonArray
profileArray
=
jsonObject
[
"profile"
].
toArray
();
QList
<
double
>
rgProfile
;
foreach
(
const
QJsonValue
&
profileValue
,
profileArray
)
{
rgProfile
.
append
(
profileValue
.
toDouble
());
}
emit
terrainData
(
true
,
// success
stepArray
[
0
].
toDouble
(),
// lat step
stepArray
[
1
].
toDouble
(),
// lon step
rgProfile
);
}
src/Terrain/TerrainQuery.h
0 → 100644
View file @
12241e62
/****************************************************************************
*
* (c) 2017 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.
*
****************************************************************************/
#pragma once
#include "QGCLoggingCategory.h"
#include <QObject>
#include <QGeoCoordinate>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QTimer>
Q_DECLARE_LOGGING_CATEGORY
(
TerrainQueryLog
)
class
TerrainAtCoordinateQuery
;
// Base class for all terrain query objects
class
TerrainQuery
:
public
QObject
{
Q_OBJECT
public:
TerrainQuery
(
QObject
*
parent
=
NULL
);
protected:
// Send a query to AirMap terrain servers. Data and errors are returned back from super class virtual implementations.
// @param path Additional path to add to url
// @param urlQuery Query to send
void
_sendQuery
(
const
QString
&
path
,
const
QUrlQuery
&
urlQuery
);
virtual
void
_getNetworkReplyFailed
(
void
)
=
0
;
///< QNetworkManager::get failed to return QNetworkReplay object
virtual
void
_requestFailed
(
QNetworkReply
::
NetworkError
error
)
=
0
;
///< QNetworkReply::finished returned error
virtual
void
_requestJsonParseFailed
(
const
QString
&
errorString
)
=
0
;
///< Parsing of returned json failed
virtual
void
_requestAirmapStatusFailed
(
const
QString
&
status
)
=
0
;
///< AirMap status was not "success"
virtual
void
_requestSucess
(
const
QJsonValue
&
dataJsonValue
)
=
0
;
///< Successful reqest, data returned
private
slots
:
void
_requestFinished
(
void
);
private:
QNetworkAccessManager
_networkManager
;
};
/// Used internally by TerrainAtCoordinateQuery to batch coordinate requests together
class
TerrainAtCoordinateBatchManager
:
public
TerrainQuery
{
Q_OBJECT
public:
TerrainAtCoordinateBatchManager
(
void
);
void
addQuery
(
TerrainAtCoordinateQuery
*
terrainAtCoordinateQuery
,
const
QList
<
QGeoCoordinate
>&
coordinates
);
protected:
void
_getNetworkReplyFailed
(
void
)
final
;
void
_requestFailed
(
QNetworkReply
::
NetworkError
error
)
final
;
void
_requestJsonParseFailed
(
const
QString
&
errorString
)
final
;
void
_requestAirmapStatusFailed
(
const
QString
&
status
)
final
;
void
_requestSucess
(
const
QJsonValue
&
dataJsonValue
)
final
;
private
slots
:
void
_sendNextBatch
(
void
);
void
_queryObjectDestroyed
(
QObject
*
elevationProvider
);
private:
typedef
struct
{
TerrainAtCoordinateQuery
*
terrainAtCoordinateQuery
;
QList
<
QGeoCoordinate
>
coordinates
;
}
QueuedRequestInfo_t
;
typedef
struct
{
TerrainAtCoordinateQuery
*
terrainAtCoordinateQuery
;
bool
queryObjectDestroyed
;
int
cCoord
;
}
SentRequestInfo_t
;
enum
class
State
{
Idle
,
Downloading
,
};
void
_batchFailed
(
void
);
QString
_stateToString
(
State
state
);
QList
<
QueuedRequestInfo_t
>
_requestQueue
;
QList
<
SentRequestInfo_t
>
_sentRequests
;
State
_state
=
State
::
Idle
;
const
int
_batchTimeout
=
500
;
QTimer
_batchTimer
;
};
/// NOTE: TerrainAtCoordinateQuery is not thread safe. All instances/calls to ElevationProvider must be on main thread.
class
TerrainAtCoordinateQuery
:
public
QObject
{
Q_OBJECT
public:
TerrainAtCoordinateQuery
(
QObject
*
parent
=
NULL
);
/// Async terrain query for a list of lon,lat coordinates. When the query is done, the terrainData() signal
/// is emitted.
/// @param coordinates to query
void
requestData
(
const
QList
<
QGeoCoordinate
>&
coordinates
);
// Internal method
void
_signalTerrainData
(
bool
success
,
QList
<
float
>&
altitudes
);
signals:
void
terrainData
(
bool
success
,
QList
<
float
>
altitudes
);
};
class
TerrainPathQuery
:
public
TerrainQuery
{
Q_OBJECT
public:
TerrainPathQuery
(
QObject
*
parent
=
NULL
);
/// Async terrain query for terrain heights between two lat/lon coordinates. When the query is done, the terrainData() signal
/// is emitted.
/// @param coordinates to query
void
requestData
(
const
QGeoCoordinate
&
fromCoord
,
const
QGeoCoordinate
&
toCoord
);
protected:
void
_getNetworkReplyFailed
(
void
)
final
;
void
_requestFailed
(
QNetworkReply
::
NetworkError
error
)
final
;
void
_requestJsonParseFailed
(
const
QString
&
errorString
)
final
;
void
_requestAirmapStatusFailed
(
const
QString
&
status
)
final
;
void
_requestSucess
(
const
QJsonValue
&
dataJsonValue
)
final
;
signals:
/// Signalled when terrain data comes back from server
/// @param latStep Amount of latitudinal distance between each returned height
/// @param lonStep Amount of longitudinal distance between each returned height
/// @param altitudes Altitudes along specified path
void
terrainData
(
bool
success
,
double
latStep
,
double
lonStep
,
QList
<
double
>
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