Commit e33c30c5 authored by Andreas Bircher's avatar Andreas Bircher

Merge branch 'pull_upstream' into feature/offlineElevationData

Conflicts:
	qgroundcontrol.pro
	src/Terrain.cc
	src/Terrain.h
parents 32a35ac9 32b4b1da
...@@ -41,7 +41,7 @@ You **need to install Qt as described below** instead of using pre-built package ...@@ -41,7 +41,7 @@ You **need to install Qt as described below** instead of using pre-built package
* Windows: Make sure to install VS 2015 32 bit package. * Windows: Make sure to install VS 2015 32 bit package.
###### Install additional packages: ###### Install additional packages:
* Ubuntu: sudo apt-get install speech-dispatcher libudev-dev libsdl2-dev libgstreamer1.0-0 gstreamer1.0-plugins-base libgstreamer-plugins-base1.0-dev gstreamer1.0* * Ubuntu: sudo apt-get install speech-dispatcher libudev-dev libsdl2-dev
* Fedora: sudo dnf install speech-dispatcher SDL2-devel SDL2 systemd-devel * Fedora: sudo dnf install speech-dispatcher SDL2-devel SDL2 systemd-devel
* Arch Linux: pacman -Sy speech-dispatcher * Arch Linux: pacman -Sy speech-dispatcher
* Windows: [USB Driver](http://www.pixhawk.org/firmware/downloads) to connect to Pixhawk/PX4Flow/3DR Radio * Windows: [USB Driver](http://www.pixhawk.org/firmware/downloads) to connect to Pixhawk/PX4Flow/3DR Radio
......
...@@ -346,6 +346,7 @@ INCLUDEPATH += \ ...@@ -346,6 +346,7 @@ INCLUDEPATH += \
src/QtLocationPlugin \ src/QtLocationPlugin \
src/QtLocationPlugin/QMLControl \ src/QtLocationPlugin/QMLControl \
src/Settings \ src/Settings \
src/Terrain \
src/VehicleSetup \ src/VehicleSetup \
src/ViewWidgets \ src/ViewWidgets \
src/Audio \ src/Audio \
...@@ -586,7 +587,7 @@ HEADERS += \ ...@@ -586,7 +587,7 @@ HEADERS += \
src/Settings/SettingsManager.h \ src/Settings/SettingsManager.h \
src/Settings/UnitsSettings.h \ src/Settings/UnitsSettings.h \
src/Settings/VideoSettings.h \ src/Settings/VideoSettings.h \
src/Terrain.h \ src/Terrain/TerrainQuery.h \
src/TerrainTile.h \ src/TerrainTile.h \
src/Vehicle/MAVLinkLogManager.h \ src/Vehicle/MAVLinkLogManager.h \
src/VehicleSetup/JoystickConfigController.h \ src/VehicleSetup/JoystickConfigController.h \
...@@ -779,7 +780,7 @@ SOURCES += \ ...@@ -779,7 +780,7 @@ SOURCES += \
src/Settings/SettingsManager.cc \ src/Settings/SettingsManager.cc \
src/Settings/UnitsSettings.cc \ src/Settings/UnitsSettings.cc \
src/Settings/VideoSettings.cc \ src/Settings/VideoSettings.cc \
src/Terrain.cc \ src/Terrain/TerrainQuery.cc \
src/TerrainTile.cc\ src/TerrainTile.cc\
src/Vehicle/MAVLinkLogManager.cc \ src/Vehicle/MAVLinkLogManager.cc \
src/VehicleSetup/JoystickConfigController.cc \ src/VehicleSetup/JoystickConfigController.cc \
......
...@@ -36,17 +36,18 @@ public: ...@@ -36,17 +36,18 @@ public:
Q_INVOKABLE void rotateEntryPoint(void); Q_INVOKABLE void rotateEntryPoint(void);
// Overrides from ComplexMissionItem // Overrides from ComplexMissionItem
int lastSequenceNumber (void) const final;
int lastSequenceNumber (void) const final; bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final;
bool load (const QJsonObject& complexObject, int sequenceNumber, QString& errorString) final; QString mapVisualQML (void) const final { return QStringLiteral("CorridorScanMapVisual.qml"); }
QString mapVisualQML (void) const final { return QStringLiteral("CorridorScanMapVisual.qml"); }
// Overrides from TransectStyleComplexItem // Overrides from TransectStyleComplexItem
void save (QJsonArray& planItems) final;
bool specifiesCoordinate (void) const final;
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final;
void save (QJsonArray& missionItems) final; // Overrides from VisualMissionionItem
bool specifiesCoordinate (void) const final; bool readyForSave (void) const;
void appendMissionItems (QList<MissionItem*>& items, QObject* missionItemParent) final;
void applyNewAltitude (double newAltitude) final;
static const char* jsonComplexItemTypeValue; static const char* jsonComplexItemTypeValue;
...@@ -54,17 +55,19 @@ public: ...@@ -54,17 +55,19 @@ public:
static const char* corridorWidthName; static const char* corridorWidthName;
private slots: private slots:
void _polylineDirtyChanged (bool dirty); void _polylineDirtyChanged (bool dirty);
void _polylineCountChanged (int count); void _polylineCountChanged (int count);
void _rebuildCorridor (void); void _rebuildCorridor (void);
// Overrides from TransectStyleComplexItem // Overrides from TransectStyleComplexItem
virtual void _rebuildTransects (void) final; void _rebuildTransectsPhase1 (void) final;
void _rebuildTransectsPhase2 (void) final;
private: private:
int _transectCount (void) const; int _transectCount (void) const;
void _rebuildCorridorPolygon(void); void _rebuildCorridorPolygon (void);
void _buildAndAppendMissionItems(QList<MissionItem*>& items, QObject* missionItemParent);
void _appendLoadedMissionItems (QList<MissionItem*>& items, QObject* missionItemParent);
QGCMapPolyline _corridorPolyline; QGCMapPolyline _corridorPolyline;
QList<QList<QGeoCoordinate>> _transectSegments; ///< Internal transect segments including grid exit, turnaround and internal camera points QList<QList<QGeoCoordinate>> _transectSegments; ///< Internal transect segments including grid exit, turnaround and internal camera points
...@@ -75,5 +78,5 @@ private: ...@@ -75,5 +78,5 @@ private:
QMap<QString, FactMetaData*> _metaDataMap; QMap<QString, FactMetaData*> _metaDataMap;
SettingsFact _corridorWidthFact; SettingsFact _corridorWidthFact;
static const char* _entryPointName; static const char* _jsonEntryPointKey;
}; };
...@@ -134,13 +134,26 @@ void CorridorScanComplexItemTest::_testItemCount(void) ...@@ -134,13 +134,26 @@ void CorridorScanComplexItemTest::_testItemCount(void)
{ {
QList<MissionItem*> items; QList<MissionItem*> items;
_corridorItem->turnAroundDistance()->setRawValue(20);
_corridorItem->turnAroundDistance()->setRawValue(0);
_corridorItem->cameraTriggerInTurnAround()->setRawValue(false); _corridorItem->cameraTriggerInTurnAround()->setRawValue(false);
_corridorItem->appendMissionItems(items, this); _corridorItem->appendMissionItems(items, this);
QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber()); QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber());
items.clear(); items.clear();
_corridorItem->turnAroundDistance()->setRawValue(0);
_corridorItem->cameraTriggerInTurnAround()->setRawValue(true);
_corridorItem->appendMissionItems(items, this);
QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber());
items.clear();
_corridorItem->turnAroundDistance()->setRawValue(20);
_corridorItem->cameraTriggerInTurnAround()->setRawValue(false);
_corridorItem->appendMissionItems(items, this);
QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber());
items.clear();
_corridorItem->turnAroundDistance()->setRawValue(20);
_corridorItem->cameraTriggerInTurnAround()->setRawValue(true); _corridorItem->cameraTriggerInTurnAround()->setRawValue(true);
_corridorItem->appendMissionItems(items, this); _corridorItem->appendMissionItems(items, this);
QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber()); QCOMPARE(items.count() - 1, _corridorItem->lastSequenceNumber());
......
...@@ -277,7 +277,7 @@ void MissionController::convertToKMLDocument(QDomDocument& document) ...@@ -277,7 +277,7 @@ void MissionController::convertToKMLDocument(QDomDocument& document)
return; return;
} }
float altitude = missionJson[_jsonPlannedHomePositionKey].toArray()[2].toDouble(); float homeAltitude = missionJson[_jsonPlannedHomePositionKey].toArray()[2].toDouble();
QString coord; QString coord;
QStringList coords; QStringList coords;
...@@ -292,11 +292,12 @@ void MissionController::convertToKMLDocument(QDomDocument& document) ...@@ -292,11 +292,12 @@ void MissionController::convertToKMLDocument(QDomDocument& document)
qgcApp()->toolbox()->missionCommandTree()->getUIInfo(_controllerVehicle, item->command()); qgcApp()->toolbox()->missionCommandTree()->getUIInfo(_controllerVehicle, item->command());
if (uiInfo && uiInfo->specifiesCoordinate() && !uiInfo->isStandaloneCoordinate()) { if (uiInfo && uiInfo->specifiesCoordinate() && !uiInfo->isStandaloneCoordinate()) {
double amslAltitude = item->param7() + (item->frame() == MAV_FRAME_GLOBAL ? 0 : homeAltitude);
coord = QString::number(item->param6(),'f',7) \ coord = QString::number(item->param6(),'f',7) \
+ "," \ + "," \
+ QString::number(item->param5(),'f',7) \ + QString::number(item->param5(),'f',7) \
+ "," \ + "," \
+ QString::number(item->param7() + altitude,'f',2); + QString::number(amslAltitude,'f',2);
coords.append(coord); coords.append(coord);
} }
} }
......
...@@ -34,5 +34,32 @@ ...@@ -34,5 +34,32 @@
"shortDescription": "Refly the pattern at a 90 degree angle", "shortDescription": "Refly the pattern at a 90 degree angle",
"type": "bool", "type": "bool",
"defaultValue": false "defaultValue": false
},
{
"name": "TerrainAdjustTolerance",
"shortDescription": "TerrainAdjustTolerance",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m",
"defaultValue": 10
},
{
"name": "TerrainAdjustMaxClimbRate",
"shortDescription": "TerrainAdjustMaxClimbRate",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m/s",
"defaultValue": 0
},
{
"name": "TerrainAdjustMaxDescentRate",
"shortDescription": "TerrainAdjustMaxDescentRate",
"type": "double",
"decimalPlaces": 2,
"min": 0,
"units": "m/s",
"defaultValue": 0
} }
] ]
...@@ -174,7 +174,12 @@ TransectStyleItem::TransectStyleItem(Vehicle* vehicle, QObject* parent) ...@@ -174,7 +174,12 @@ TransectStyleItem::TransectStyleItem(Vehicle* vehicle, QObject* parent)
} }
void TransectStyleItem::_rebuildTransects(void) void TransectStyleItem::_rebuildTransectsPhase1(void)
{ {
rebuildTransectsCalled = true; rebuildTransectsCalled = true;
} }
void TransectStyleItem::_rebuildTransectsPhase2(void)
{
}
...@@ -101,5 +101,6 @@ public: ...@@ -101,5 +101,6 @@ public:
private slots: private slots:
// Overrides from TransectStyleComplexItem // Overrides from TransectStyleComplexItem
void _rebuildTransects (void) final; void _rebuildTransectsPhase1(void) final;
void _rebuildTransectsPhase2(void) final;
}; };
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include "FirmwarePluginManager.h" #include "FirmwarePluginManager.h"
#include "QGCApplication.h" #include "QGCApplication.h"
#include "JsonHelper.h" #include "JsonHelper.h"
#include "Terrain.h" #include "TerrainQuery.h"
const char* VisualMissionItem::jsonTypeKey = "type"; const char* VisualMissionItem::jsonTypeKey = "type";
const char* VisualMissionItem::jsonTypeSimpleItemValue = "SimpleItem"; const char* VisualMissionItem::jsonTypeSimpleItemValue = "SimpleItem";
...@@ -172,18 +172,18 @@ void VisualMissionItem::_reallyUpdateTerrainAltitude(void) ...@@ -172,18 +172,18 @@ void VisualMissionItem::_reallyUpdateTerrainAltitude(void)
if (coord.isValid() && (qIsNaN(_terrainAltitude) || !qFuzzyCompare(_lastLatTerrainQuery, coord.latitude()) || qFuzzyCompare(_lastLonTerrainQuery, coord.longitude()))) { if (coord.isValid() && (qIsNaN(_terrainAltitude) || !qFuzzyCompare(_lastLatTerrainQuery, coord.latitude()) || qFuzzyCompare(_lastLonTerrainQuery, coord.longitude()))) {
_lastLatTerrainQuery = coord.latitude(); _lastLatTerrainQuery = coord.latitude();
_lastLonTerrainQuery = coord.longitude(); _lastLonTerrainQuery = coord.longitude();
ElevationProvider* terrain = new ElevationProvider(this); TerrainAtCoordinateQuery* terrain = new TerrainAtCoordinateQuery(this);
connect(terrain, &ElevationProvider::terrainData, this, &VisualMissionItem::_terrainDataReceived); connect(terrain, &TerrainAtCoordinateQuery::terrainData, this, &VisualMissionItem::_terrainDataReceived);
QList<QGeoCoordinate> rgCoord; QList<QGeoCoordinate> rgCoord;
rgCoord.append(coordinate()); rgCoord.append(coordinate());
terrain->queryTerrainData(rgCoord); terrain->requestData(rgCoord);
} }
} }
void VisualMissionItem::_terrainDataReceived(bool success, QList<float> altitudes) void VisualMissionItem::_terrainDataReceived(bool success, QList<double> heights)
{ {
if (success) { if (success) {
_terrainAltitude = altitudes[0]; _terrainAltitude = heights[0];
emit terrainAltitudeChanged(_terrainAltitude); emit terrainAltitudeChanged(_terrainAltitude);
sender()->deleteLater(); sender()->deleteLater();
} }
......
...@@ -211,7 +211,7 @@ protected: ...@@ -211,7 +211,7 @@ protected:
private slots: private slots:
void _updateTerrainAltitude (void); void _updateTerrainAltitude (void);
void _reallyUpdateTerrainAltitude (void); void _reallyUpdateTerrainAltitude (void);
void _terrainDataReceived (bool success, QList<float> altitudes); void _terrainDataReceived (bool success, QList<double> heights);
private: private:
QTimer _updateTerrainTimer; QTimer _updateTerrainTimer;
......
...@@ -56,6 +56,11 @@ Rectangle { ...@@ -56,6 +56,11 @@ Rectangle {
anchors.right: parent.right anchors.right: parent.right
spacing: _margin spacing: _margin
QGCLabel {
text: "WIP: Careful!"
color: qgcPal.warningText
}
QGCLabel { QGCLabel {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
...@@ -126,6 +131,59 @@ Rectangle { ...@@ -126,6 +131,59 @@ Rectangle {
onClicked: missionItem.rotateEntryPoint() onClicked: missionItem.rotateEntryPoint()
} }
SectionHeader {
id: terrainHeader
text: qsTr("Terrain")
checked: false
}
ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: _margin
visible: terrainHeader.checked
QGCCheckBox {
id: followsTerrainCheckBox
text: qsTr("Vehicle follows terrain")
checked: missionItem.followTerrain
onClicked: missionItem.followTerrain = checked
}
GridLayout {
anchors.left: parent.left
anchors.right: parent.right
columnSpacing: _margin
rowSpacing: _margin
columns: 2
visible: followsTerrainCheckBox.checked
QGCLabel {
text: "WIP: Careful!"
color: qgcPal.warningText
Layout.columnSpan: 2
}
QGCLabel { text: qsTr("Tolerance") }
FactTextField {
fact: missionItem.terrainAdjustTolerance
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Max Climb Rate") }
FactTextField {
fact: missionItem.terrainAdjustMaxClimbRate
Layout.fillWidth: true
}
QGCLabel { text: qsTr("Max Descent Rate") }
FactTextField {
fact: missionItem.terrainAdjustMaxDescentRate
Layout.fillWidth: true
}
}
}
SectionHeader { SectionHeader {
id: statsHeader id: statsHeader
text: qsTr("Statistics") text: qsTr("Statistics")
......
/****************************************************************************
*
* (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.
*
****************************************************************************/
#include "Terrain.h"
#include "QGCMapEngine.h"
#include "QGeoMapReplyQGC.h"
#include <QUrl>
#include <QUrlQuery>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTimer>
#include <QtLocation/private/qgeotilespec_p.h>
QGC_LOGGING_CATEGORY(ElevationProviderLog, "ElevationProviderLog")
Q_GLOBAL_STATIC(TerrainBatchManager, _terrainBatchManager)
TerrainBatchManager::TerrainBatchManager(void)
{
}
void TerrainBatchManager::addQuery(ElevationProvider* elevationProvider, const QList<QGeoCoordinate>& coordinates)
{
if (coordinates.length() > 0) {
QList<float> altitudes;
if (!_getAltitudesForCoordinates(coordinates, altitudes)) {
QueuedRequestInfo_t queuedRequestInfo = { elevationProvider, coordinates };
_requestQueue.append(queuedRequestInfo);
return;
}
qCDebug(ElevationProviderLog) << "All altitudes taken from cached data";
elevationProvider->_signalTerrainData(coordinates.count() == altitudes.count(), altitudes);
}
}
bool TerrainBatchManager::_getAltitudesForCoordinates(const QList<QGeoCoordinate>& coordinates, QList<float>& altitudes)
{
foreach (const QGeoCoordinate& coordinate, coordinates) {
QString tileHash = _getTileHash(coordinate);
_tilesMutex.lock();
if (!_tiles.contains(tileHash)) {
qCDebug(ElevationProviderLog) << "Need to download tile " << tileHash;
// Schedule the fetch task
if (_state != State::Downloading) {
QNetworkRequest request = getQGCMapEngine()->urlFactory()->getTileURL(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1, &_networkManager);
QGeoTileSpec spec;
spec.setX(QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1));
spec.setY(QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1));
spec.setZoom(1);
spec.setMapId(UrlFactory::AirmapElevation);
QGeoTiledMapReplyQGC* reply = new QGeoTiledMapReplyQGC(&_networkManager, request, spec);
connect(reply, &QGeoTiledMapReplyQGC::finished, this, &TerrainBatchManager::_fetchedTile);
connect(reply, &QGeoTiledMapReplyQGC::aborted, this, &TerrainBatchManager::_fetchedTile);
_state = State::Downloading;
}
_tilesMutex.unlock();
return false;
} else {
if (_tiles[tileHash].isIn(coordinate)) {
altitudes.push_back(_tiles[tileHash].elevation(coordinate));
} else {
qCDebug(ElevationProviderLog) << "Error: coordinate not in tile region";
altitudes.push_back(-1.0);
}
}
_tilesMutex.unlock();
}
return true;
}
void TerrainBatchManager::_tileFailed(void)
{
QList<float> noAltitudes;
foreach (const QueuedRequestInfo_t& requestInfo, _requestQueue) {
requestInfo.elevationProvider->_signalTerrainData(false, noAltitudes);
}
_requestQueue.clear();
}
void TerrainBatchManager::_fetchedTile()
{
QGeoTiledMapReplyQGC* reply = qobject_cast<QGeoTiledMapReplyQGC*>(QObject::sender());
_state = State::Idle;
if (!reply) {
qCDebug(ElevationProviderLog) << "Elevation tile fetched but invalid reply data type.";
return;
}
// remove from download queue
QGeoTileSpec spec = reply->tileSpec();
QString hash = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, spec.x(), spec.y(), spec.zoom());
// handle potential errors
if (reply->error() != QGeoTiledMapReply::NoError) {
if (reply->error() == QGeoTiledMapReply::CommunicationError) {
qCDebug(ElevationProviderLog) << "Elevation tile fetching returned communication error. " << reply->errorString();
} else {
qCDebug(ElevationProviderLog) << "Elevation tile fetching returned error. " << reply->errorString();
}
_tileFailed();
reply->deleteLater();
return;
}
if (!reply->isFinished()) {
qCDebug(ElevationProviderLog) << "Error in fetching elevation tile. Not finished. " << reply->errorString();
_tileFailed();
reply->deleteLater();
return;
}
// parse received data and insert into hash table
QByteArray responseBytes = reply->mapImageData();
QJsonParseError parseError;
QJsonDocument responseJson = QJsonDocument::fromJson(responseBytes, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qCDebug(ElevationProviderLog) << "Could not parse terrain tile " << parseError.errorString();
qCDebug(ElevationProviderLog) << responseBytes;
_tileFailed();
reply->deleteLater();
return;
}
TerrainTile* terrainTile = new TerrainTile(responseJson);
if (terrainTile->isValid()) {
_tilesMutex.lock();
if (!_tiles.contains(hash)) {
_tiles.insert(hash, *terrainTile);
} else {
delete terrainTile;
}
_tilesMutex.unlock();
} else {
qCDebug(ElevationProviderLog) << "Received invalid tile";
}
reply->deleteLater();
// now try to query the data again
for (int i = _requestQueue.count() - 1; i >= 0; i--) {
QList<float> altitudes;
if (_getAltitudesForCoordinates(_requestQueue[i].coordinates, altitudes)) {
_requestQueue[i].elevationProvider->_signalTerrainData(_requestQueue[i].coordinates.count() == altitudes.count(), altitudes);
_requestQueue.removeAt(i);
}
}
}
QString TerrainBatchManager::_getTileHash(const QGeoCoordinate& coordinate)
{
QString ret = QGCMapEngine::getTileHash(UrlFactory::AirmapElevation, QGCMapEngine::long2elevationTileX(coordinate.longitude(), 1), QGCMapEngine::lat2elevationTileY(coordinate.latitude(), 1), 1);
qCDebug(ElevationProviderLog) << "Computing unique tile hash for " << coordinate << ret;
return ret;
}
ElevationProvider::ElevationProvider(QObject* parent)
: QObject(parent)
{
}
bool ElevationProvider::queryTerrainData(const QList<QGeoCoordinate>& coordinates)
{
if (coordinates.length() == 0) {
return false;
}
_terrainBatchManager->addQuery(this, coordinates);
return false;
}
void ElevationProvider::_signalTerrainData(bool success, QList<float>& altitudes)
{
emit terrainData(success, altitudes);
}
/****************************************************************************
*
* (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 "TerrainTile.h"
#include "QGCMapEngineData.h"
#include "QGCLoggingCategory.h"
#include <QObject>
#include <QGeoCoordinate>
#include <QNetworkAccessManager>
#include <QHash>
#include <QMutex>
#include <QtLocation/private/qgeotiledmapreply_p.h>
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 _fetchedTile (void); /// slot to handle fetched elevation tiles
private:
typedef struct {
ElevationProvider* elevationProvider;
QList<QGeoCoordinate> coordinates;
} QueuedRequestInfo_t;
enum class State {
Idle,
Downloading,
};
void _tileFailed(void);
bool _getAltitudesForCoordinates(const QList<QGeoCoordinate>& coordinates, QList<float>& altitudes);
QString _getTileHash(const QGeoCoordinate& coordinate); /// Method to create a unique string for each tile
QList<QueuedRequestInfo_t> _requestQueue;
State _state = State::Idle;
QNetworkAccessManager _networkManager;
QMutex _tilesMutex;
QHash<QString, TerrainTile> _tiles;
};
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. This call caches local elevation tables for faster lookup in the future.
* @param coordinates
* @return true on success
*/
bool queryTerrainData(const QList<QGeoCoordinate>& coordinates);
/// Internal method
void _signalTerrainData(bool success, QList<float>& altitudes);
signals:
/// signal returning requested elevation data
void terrainData(bool success, QList<float> altitudes);
};
This diff is collapsed.
This diff is collapsed.
...@@ -40,6 +40,9 @@ list=$(apt-cache --names-only search ^gstreamer1.0-* | awk '{ print $1 }' | grep ...@@ -40,6 +40,9 @@ list=$(apt-cache --names-only search ^gstreamer1.0-* | awk '{ print $1 }' | grep
``` ```
sudo apt-get install $list sudo apt-get install $list
``` ```
```
sudo apt-get install libgstreamer-plugins-base1.0-dev
```
The build system is setup to use pkgconfig and it will find the necessary headers and libraries automatically. The build system is setup to use pkgconfig and it will find the necessary headers and libraries automatically.
......
...@@ -181,24 +181,7 @@ VideoEnabled { ...@@ -181,24 +181,7 @@ VideoEnabled {
} else { } else {
LinuxBuild|MacBuild|iOSBuild|WindowsBuild|AndroidBuild { LinuxBuild|MacBuild|iOSBuild|WindowsBuild|AndroidBuild {
message("Skipping support for video streaming (GStreamer libraries not installed)") message("Skipping support for video streaming (GStreamer libraries not installed)")
MacBuild { message("Installation instructions here: https://github.com/mavlink/qgroundcontrol/blob/master/src/VideoStreaming/README.md")
message(" You can download it from http://gstreamer.freedesktop.org/data/pkg/osx/")
message(" Select the devel package and install it (gstreamer-1.0-devel-1.x.x-x86_64.pkg)")
message(" It will be installed in /Libraries/Frameworks")
}
LinuxBuild {
message(" You can install it using apt-get")
message(" sudo apt-get install gstreamer1.0*")
}
WindowsBuild {
message(" You can download it from http://gstreamer.freedesktop.org/data/pkg/windows/")
message(" Select the devel AND runtime packages and install them (x86, not the 64-Bit)")
message(" It will be installed in C:/gstreamer. You need to update you PATH to point to the bin directory.")
}
AndroidBuild {
message(" You can download it from http://gstreamer.freedesktop.org/data/pkg/android/")
message(" Uncompress the archive into the qgc root source directory (same directory where qgroundcontrol.pro is found.")
}
} else { } else {
message("Skipping support for video streaming (Unsupported platform)") message("Skipping support for video streaming (Unsupported platform)")
} }
......
...@@ -35,9 +35,15 @@ QGC_LOGGING_CATEGORY(MockLinkVerboseLog, "MockLinkVerboseLog") ...@@ -35,9 +35,15 @@ QGC_LOGGING_CATEGORY(MockLinkVerboseLog, "MockLinkVerboseLog")
// Vehicle position is set close to default Gazebo vehicle location. This allows for multi-vehicle // Vehicle position is set close to default Gazebo vehicle location. This allows for multi-vehicle
// testing of a gazebo vehicle and a mocklink vehicle // testing of a gazebo vehicle and a mocklink vehicle
double MockLink::_defaultVehicleLatitude = 47.397f; #if 1
double MockLink::_defaultVehicleLongitude = 8.5455f; double MockLink::_defaultVehicleLatitude = 47.397;
double MockLink::_defaultVehicleAltitude = 488.056f; double MockLink::_defaultVehicleLongitude = 8.5455;
double MockLink::_defaultVehicleAltitude = 488.056;
#else
double MockLink::_defaultVehicleLatitude = 47.6333022928789;
double MockLink::_defaultVehicleLongitude = -122.08833157994995;
double MockLink::_defaultVehicleAltitude = 19.0;
#endif
int MockLink::_nextVehicleSystemId = 128; int MockLink::_nextVehicleSystemId = 128;
const char* MockLink::_failParam = "COM_FLTMODE6"; const char* MockLink::_failParam = "COM_FLTMODE6";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment