From 32ed1ec009fdf67c004b292058bb81008a4f18c5 Mon Sep 17 00:00:00 2001 From: Gus Grubba Date: Sun, 18 Feb 2018 15:51:32 -0500 Subject: [PATCH] Make all argument to AirMap queries based on what the screen shows (bounding rectangle and/or radius), respecting the limits imposed by AirMap. --- qgroundcontrol.pro | 2 + src/Airmap/AirMapAdvisoryManager.cc | 17 ++-- src/Airmap/AirMapAdvisoryManager.h | 19 ++--- src/Airmap/AirMapFlightPlanManager.cc | 12 +-- src/Airmap/AirMapManager.cc | 4 +- src/Airmap/AirMapRestrictionManager.cc | 31 ++++--- src/Airmap/AirMapRestrictionManager.h | 8 +- src/Airmap/AirMapRulesetsManager.cc | 12 ++- src/Airmap/AirMapRulesetsManager.h | 4 +- src/Airmap/AirMapWeatherInfoManager.cc | 10 +-- src/Airmap/AirMapWeatherInfoManager.h | 3 +- src/Airmap/AirspaceControl.qml | 15 +++- .../AirspaceAdvisoryProvider.h | 3 +- src/AirspaceManagement/AirspaceManager.cc | 17 ++-- src/AirspaceManagement/AirspaceManager.h | 8 +- .../AirspaceRestrictionProvider.h | 3 +- .../AirspaceRulesetsProvider.h | 3 +- .../AirspaceWeatherInfoProvider.h | 3 +- src/FlightDisplay/FlightDisplayViewMap.qml | 20 ++++- .../FlightDisplayViewWidgets.qml | 2 +- src/MissionManager/MissionController.h | 2 +- src/PlanView/PlanView.qml | 19 +++-- src/QGCApplication.cc | 3 + src/QGCGeo.cc | 7 -- src/QGCGeo.h | 42 ---------- src/QmlControls/QGCGeoBoundingCube.cc | 83 +++++++++++++++++++ src/QmlControls/QGCGeoBoundingCube.h | 77 +++++++++++++++++ 27 files changed, 297 insertions(+), 132 deletions(-) create mode 100644 src/QmlControls/QGCGeoBoundingCube.cc create mode 100644 src/QmlControls/QGCGeoBoundingCube.h diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 0d088431c..a6ef69da8 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -573,6 +573,7 @@ HEADERS += \ src/QmlControls/QGCImageProvider.h \ src/QmlControls/QGroundControlQmlGlobal.h \ src/QmlControls/QmlObjectListModel.h \ + src/QmlControls/QGCGeoBoundingCube.h \ src/QmlControls/RCChannelMonitorController.h \ src/QmlControls/ScreenToolsController.h \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.h \ @@ -766,6 +767,7 @@ SOURCES += \ src/QmlControls/QGCImageProvider.cc \ src/QmlControls/QGroundControlQmlGlobal.cc \ src/QmlControls/QmlObjectListModel.cc \ + src/QmlControls/QGCGeoBoundingCube.cc \ src/QmlControls/RCChannelMonitorController.cc \ src/QmlControls/ScreenToolsController.cc \ src/QtLocationPlugin/QMLControl/QGCMapEngineManager.cc \ diff --git a/src/Airmap/AirMapAdvisoryManager.cc b/src/Airmap/AirMapAdvisoryManager.cc index c2f6e59ea..40d09c982 100644 --- a/src/Airmap/AirMapAdvisoryManager.cc +++ b/src/Airmap/AirMapAdvisoryManager.cc @@ -22,7 +22,6 @@ using namespace airmap; //----------------------------------------------------------------------------- AirMapAdvisory::AirMapAdvisory(QObject* parent) : AirspaceAdvisory(parent) - , _radius(0.0) { } @@ -30,19 +29,17 @@ AirMapAdvisory::AirMapAdvisory(QObject* parent) AirMapAdvisoryManager::AirMapAdvisoryManager(AirMapSharedState& shared, QObject *parent) : AirspaceAdvisoryProvider(parent) , _valid(false) - , _lastRadius(0.0) , _shared(shared) { } //----------------------------------------------------------------------------- void -AirMapAdvisoryManager::setROI(const QGeoCoordinate& center, double radiusMeters) +AirMapAdvisoryManager::setROI(const QGCGeoBoundingCube& roi) { //-- If first time or we've moved more than ADVISORY_UPDATE_DISTANCE, ask for updates. - if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(center) > ADVISORY_UPDATE_DISTANCE || _lastRadius != radiusMeters) { - _lastRadius = radiusMeters; - _lastRoiCenter = center; + if(!_lastROI.isValid() || _lastROI.pointNW.distanceTo(roi.pointNW) > ADVISORY_UPDATE_DISTANCE || _lastROI.pointSE.distanceTo(roi.pointSE) > ADVISORY_UPDATE_DISTANCE) { + _lastROI = roi; _requestAdvisories(); } } @@ -71,11 +68,13 @@ AirMapAdvisoryManager::_requestAdvisories() _valid = false; _advisories.clearAndDeleteContents(); Status::GetStatus::Parameters params; - params.longitude = _lastRoiCenter.longitude(); - params.latitude = _lastRoiCenter.latitude(); + params.longitude = _lastROI.center().longitude(); + params.latitude = _lastROI.center().latitude(); params.types = Airspace::Type::all; params.weather = false; - params.buffer = _lastRadius; + double diagonal = _lastROI.pointNW.distanceTo(_lastROI.pointSE); + params.buffer = fmax(fmin(diagonal, 10000.0), 500.0); + params.flight_date_time = Clock::universal_time(); std::weak_ptr isAlive(_instance); _shared.client()->status().get_status_by_point(params, [this, isAlive](const Status::GetStatus::Result& result) { if (!isAlive.lock()) return; diff --git a/src/Airmap/AirMapAdvisoryManager.h b/src/Airmap/AirMapAdvisoryManager.h index 4e668f4fd..38fcb0163 100644 --- a/src/Airmap/AirMapAdvisoryManager.h +++ b/src/Airmap/AirMapAdvisoryManager.h @@ -16,7 +16,7 @@ #include "AirspaceAdvisoryProvider.h" #include "AirMapSharedState.h" -#include +#include "QGCGeoBoundingCube.h" #include "airmap/status.h" @@ -53,20 +53,19 @@ class AirMapAdvisoryManager : public AirspaceAdvisoryProvider, public LifetimeCh { Q_OBJECT public: - AirMapAdvisoryManager (AirMapSharedState &shared, QObject *parent = nullptr); - bool valid () override { return _valid; } - AdvisoryColor airspaceColor () override { return _airspaceColor; } - QmlObjectListModel* advisories () override { return &_advisories; } - void setROI (const QGeoCoordinate& center, double radiusMeters) override; + AirMapAdvisoryManager (AirMapSharedState &shared, QObject *parent = nullptr); + bool valid () override { return _valid; } + AdvisoryColor airspaceColor () override { return _airspaceColor; } + QmlObjectListModel* advisories () override { return &_advisories; } + void setROI (const QGCGeoBoundingCube& roi) override; signals: - void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); + void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); private: - void _requestAdvisories(); + void _requestAdvisories (); private: bool _valid; - double _lastRadius; AirMapSharedState& _shared; - QGeoCoordinate _lastRoiCenter; + QGCGeoBoundingCube _lastROI; QmlObjectListModel _advisories; AdvisoryColor _airspaceColor; }; diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index e409188ac..9c4b56bbd 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -106,12 +106,7 @@ AirMapFlightPlanManager::_createFlightPlan() QGCGeoBoundingCube bc = _controller->travelBoundingCube(); _flight.maxAltitude = fmax(bc.pointNW.altitude(), bc.pointSE.altitude()); _flight.takeoffCoord = _controller->takeoffCoordinate(); - _flight.coords.append(QGeoCoordinate(bc.pointNW.latitude(), bc.pointNW.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointNW.latitude(), bc.pointSE.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointSE.latitude(), bc.pointSE.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointSE.latitude(), bc.pointNW.longitude(), _flight.maxAltitude)); - _flight.coords.append(QGeoCoordinate(bc.pointNW.latitude(), bc.pointNW.longitude(), _flight.maxAltitude)); - + _flight.coords = bc.polygon2D(); if(_flightStartTime.isNull() || _flightStartTime < QDateTime::currentDateTime()) { _flightStartTime = QDateTime::currentDateTime().addSecs(5 * 60); emit flightStartTimeChanged(); @@ -382,6 +377,11 @@ AirMapFlightPlanManager::_pollBriefing() //-- Iterate Rules for (const auto& rule : ruleset.rules) { AirMapRule* pRule = new AirMapRule(rule, this); + //-- Iterate Rule Features + for (const auto& feature : rule.features) { + AirMapRuleFeature* pFeature = new AirMapRuleFeature(feature, this); + pRule->_features.append(pFeature); + } pRuleSet->_rules.append(pRule); } //-- Sort rules by relevance order diff --git a/src/Airmap/AirMapManager.cc b/src/Airmap/AirMapManager.cc index f5aeeea8e..a995f2769 100644 --- a/src/Airmap/AirMapManager.cc +++ b/src/Airmap/AirMapManager.cc @@ -37,8 +37,8 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox) { _logger = std::make_shared(); qt::register_types(); // TODO: still needed? - _logger->logging_category().setEnabled(QtDebugMsg, false); - _logger->logging_category().setEnabled(QtInfoMsg, false); + _logger->logging_category().setEnabled(QtDebugMsg, false); + _logger->logging_category().setEnabled(QtInfoMsg, false); _logger->logging_category().setEnabled(QtWarningMsg, true); _dispatchingLogger = std::make_shared(_logger); connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error); diff --git a/src/Airmap/AirMapRestrictionManager.cc b/src/Airmap/AirMapRestrictionManager.cc index 777f61160..2bf78c598 100644 --- a/src/Airmap/AirMapRestrictionManager.cc +++ b/src/Airmap/AirMapRestrictionManager.cc @@ -20,25 +20,26 @@ using namespace airmap; //----------------------------------------------------------------------------- AirMapRestrictionManager::AirMapRestrictionManager(AirMapSharedState& shared) : _shared(shared) - , _lastRadius(0.0) { } //----------------------------------------------------------------------------- void -AirMapRestrictionManager::setROI(const QGeoCoordinate& center, double radiusMeters) +AirMapRestrictionManager::setROI(const QGCGeoBoundingCube& roi) { - //-- If first time or we've moved more than ADVISORY_UPDATE_DISTANCE, ask for updates. - if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(center) > RESTRICTION_UPDATE_DISTANCE || _lastRadius != radiusMeters) { - _lastRadius = radiusMeters; - _lastRoiCenter = center; - _requestRestrictions(center, radiusMeters); + //-- If first time or we've moved more than RESTRICTION_UPDATE_DISTANCE, ask for updates. + if(!_lastROI.isValid() || _lastROI.pointNW.distanceTo(roi.pointNW) > RESTRICTION_UPDATE_DISTANCE || _lastROI.pointSE.distanceTo(roi.pointSE) > RESTRICTION_UPDATE_DISTANCE) { + //-- No more than 40000 km^2 + if(roi.area() < 40000.0) { + _lastROI = roi; + _requestRestrictions(roi); + } } } //----------------------------------------------------------------------------- void -AirMapRestrictionManager::_requestRestrictions(const QGeoCoordinate& center, double radiusMeters) +AirMapRestrictionManager::_requestRestrictions(const QGCGeoBoundingCube& roi) { if (!_shared.client()) { qCDebug(AirMapManagerLog) << "No AirMap client instance. Not updating Airspace"; @@ -48,14 +49,22 @@ AirMapRestrictionManager::_requestRestrictions(const QGeoCoordinate& center, dou qCWarning(AirMapManagerLog) << "AirMapRestrictionManager::updateROI: state not idle"; return; } - qCDebug(AirMapManagerLog) << "setting ROI"; + qCDebug(AirMapManagerLog) << "Setting Restriction Manager ROI"; _polygons.clear(); _circles.clear(); _state = State::RetrieveItems; Airspaces::Search::Parameters params; - params.geometry = Geometry::point(center.latitude(), center.longitude()); - params.buffer = radiusMeters; params.full = true; + params.date_time = Clock::universal_time(); + //-- Geometry: Polygon + Geometry::Polygon polygon; + for (const auto& qcoord : roi.polygon2D()) { + Geometry::Coordinate coord; + coord.latitude = qcoord.latitude(); + coord.longitude = qcoord.longitude(); + polygon.outer_ring.coordinates.push_back(coord); + } + params.geometry = Geometry(polygon); std::weak_ptr isAlive(_instance); _shared.client()->airspaces().search(params, [this, isAlive](const Airspaces::Search::Result& result) { diff --git a/src/Airmap/AirMapRestrictionManager.h b/src/Airmap/AirMapRestrictionManager.h index cc4fc8979..849bbe3d2 100644 --- a/src/Airmap/AirMapRestrictionManager.h +++ b/src/Airmap/AirMapRestrictionManager.h @@ -12,6 +12,7 @@ #include "LifetimeChecker.h" #include "AirspaceRestrictionProvider.h" #include "AirMapSharedState.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -30,13 +31,13 @@ public: AirMapRestrictionManager (AirMapSharedState& shared); QmlObjectListModel* polygons () override { return &_polygons; } QmlObjectListModel* circles () override { return &_circles; } - void setROI (const QGeoCoordinate& center, double radiusMeters) override; + void setROI (const QGCGeoBoundingCube &roi) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); private: - void _requestRestrictions(const QGeoCoordinate& center, double radiusMeters); + void _requestRestrictions(const QGCGeoBoundingCube& roi); void _addPolygonToList (const airmap::Geometry::Polygon& polygon); enum class State { @@ -45,8 +46,7 @@ private: }; AirMapSharedState& _shared; - double _lastRadius; - QGeoCoordinate _lastRoiCenter; + QGCGeoBoundingCube _lastROI; State _state = State::Idle; QmlObjectListModel _polygons; QmlObjectListModel _circles; diff --git a/src/Airmap/AirMapRulesetsManager.cc b/src/Airmap/AirMapRulesetsManager.cc index 0e44f8c91..e8de64098 100644 --- a/src/Airmap/AirMapRulesetsManager.cc +++ b/src/Airmap/AirMapRulesetsManager.cc @@ -177,7 +177,7 @@ rules_sort(QObject* a, QObject* b) } //----------------------------------------------------------------------------- -void AirMapRulesetsManager::setROI(const QGeoCoordinate& center) +void AirMapRulesetsManager::setROI(const QGCGeoBoundingCube& roi) { if (!_shared.client()) { qCDebug(AirMapManagerLog) << "No AirMap client instance. Not updating Airspace"; @@ -192,7 +192,15 @@ void AirMapRulesetsManager::setROI(const QGeoCoordinate& center) _ruleSets.clearAndDeleteContents(); _state = State::RetrieveItems; RuleSets::Search::Parameters params; - params.geometry = Geometry::point(center.latitude(), center.longitude()); + //-- Geometry: Polygon + Geometry::Polygon polygon; + for (const auto& qcoord : roi.polygon2D()) { + Geometry::Coordinate coord; + coord.latitude = qcoord.latitude(); + coord.longitude = qcoord.longitude(); + polygon.outer_ring.coordinates.push_back(coord); + } + params.geometry = Geometry(polygon); std::weak_ptr isAlive(_instance); _shared.client()->rulesets().search(params, [this, isAlive](const RuleSets::Search::Result& result) { diff --git a/src/Airmap/AirMapRulesetsManager.h b/src/Airmap/AirMapRulesetsManager.h index 8540dc276..4d5ec4799 100644 --- a/src/Airmap/AirMapRulesetsManager.h +++ b/src/Airmap/AirMapRulesetsManager.h @@ -12,6 +12,7 @@ #include "LifetimeChecker.h" #include "AirspaceRulesetsProvider.h" #include "AirMapSharedState.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -50,6 +51,7 @@ class AirMapRule : public AirspaceRule { Q_OBJECT friend class AirMapRulesetsManager; + friend class AirMapFlightPlanManager; public: AirMapRule (QObject* parent = NULL); @@ -107,7 +109,7 @@ public: QmlObjectListModel* ruleSets () override { return &_ruleSets; } QString selectedRuleSets() override; - void setROI (const QGeoCoordinate& center) override; + void setROI (const QGCGeoBoundingCube& roi) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); diff --git a/src/Airmap/AirMapWeatherInfoManager.cc b/src/Airmap/AirMapWeatherInfoManager.cc index d309a8c70..8c2c51af7 100644 --- a/src/Airmap/AirMapWeatherInfoManager.cc +++ b/src/Airmap/AirMapWeatherInfoManager.cc @@ -23,17 +23,17 @@ AirMapWeatherInfoManager::AirMapWeatherInfoManager(AirMapSharedState& shared, QO } void -AirMapWeatherInfoManager::setROI(const QGeoCoordinate& center) +AirMapWeatherInfoManager::setROI(const QGCGeoBoundingCube& roi) { //-- If first time or we've moved more than WEATHER_UPDATE_DISTANCE, ask for weather updates. - if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(center) > WEATHER_UPDATE_DISTANCE) { - _lastRoiCenter = center; - _requestWeatherUpdate(center); + if(!_lastRoiCenter.isValid() || _lastRoiCenter.distanceTo(roi.center()) > WEATHER_UPDATE_DISTANCE) { + _lastRoiCenter = roi.center(); + _requestWeatherUpdate(_lastRoiCenter); _weatherTime.start(); } else { //-- Check weather once every WEATHER_UPDATE_TIME if(_weatherTime.elapsed() > WEATHER_UPDATE_TIME) { - _requestWeatherUpdate(center); + _requestWeatherUpdate(roi.center()); _weatherTime.start(); } } diff --git a/src/Airmap/AirMapWeatherInfoManager.h b/src/Airmap/AirMapWeatherInfoManager.h index d078e2db0..9f7a34104 100644 --- a/src/Airmap/AirMapWeatherInfoManager.h +++ b/src/Airmap/AirMapWeatherInfoManager.h @@ -13,6 +13,7 @@ #include "AirspaceWeatherInfoProvider.h" #include "AirMapSharedState.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -41,7 +42,7 @@ public: quint32 visibility () override { return _weather.visibility; } quint32 precipitation () override { return _weather.precipitation; } - void setROI (const QGeoCoordinate& center) override; + void setROI (const QGCGeoBoundingCube& roi) override; signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); diff --git a/src/Airmap/AirspaceControl.qml b/src/Airmap/AirspaceControl.qml index 7643c2fb9..8f7a601df 100644 --- a/src/Airmap/AirspaceControl.qml +++ b/src/Airmap/AirspaceControl.qml @@ -86,10 +86,19 @@ Item { color: _textColor anchors.verticalCenter: parent.verticalCenter } - QGCLabel { - text: qsTr("Airspace") - color: _textColor + Column { + spacing: 0 anchors.verticalCenter: parent.verticalCenter + QGCLabel { + text: qsTr("Airspace") + color: _textColor + } + QGCLabel { + text: _validAdvisories ? QGroundControl.airspaceManager.advisories.advisories.count + qsTr(" Advisories") : "" + color: _textColor + visible: _validAdvisories + font.pointSize: ScreenTools.smallFontPointSize + } } Item { width: ScreenTools.defaultFontPixelWidth diff --git a/src/AirspaceManagement/AirspaceAdvisoryProvider.h b/src/AirspaceManagement/AirspaceAdvisoryProvider.h index 4946a4c0e..300def805 100644 --- a/src/AirspaceManagement/AirspaceAdvisoryProvider.h +++ b/src/AirspaceManagement/AirspaceAdvisoryProvider.h @@ -15,6 +15,7 @@ */ #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -49,7 +50,7 @@ public: * Set region of interest that should be queried. When finished, the advisoryChanged() signal will be emmited. * @param center Center coordinate for ROI */ - virtual void setROI (const QGeoCoordinate& center, double radiusMeters) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; signals: void advisoryChanged (); diff --git a/src/AirspaceManagement/AirspaceManager.cc b/src/AirspaceManagement/AirspaceManager.cc index a90306339..27cdbc8d0 100644 --- a/src/AirspaceManagement/AirspaceManager.cc +++ b/src/AirspaceManagement/AirspaceManager.cc @@ -70,30 +70,29 @@ void AirspaceManager::setToolbox(QGCToolbox* toolbox) _flightPlan = _instantiateAirspaceFlightPlanProvider(); } -void AirspaceManager::setROI(QGeoCoordinate center, double radiusMeters) +void AirspaceManager::setROI(const QGeoCoordinate& pointNW, const QGeoCoordinate& pointSE) { - _setROI(center, radiusMeters); + _setROI(QGCGeoBoundingCube(pointNW, pointSE)); } -void AirspaceManager::_setROI(const QGeoCoordinate& center, double radiusMeters) +void AirspaceManager::_setROI(const QGCGeoBoundingCube& roi) { - _roiCenter = center; - _roiRadius = radiusMeters; + _roi = roi; _roiUpdateTimer.start(); } void AirspaceManager::_updateToROI() { if(_airspaces) { - _airspaces->setROI(_roiCenter, _roiRadius); + _airspaces->setROI(_roi); } if(_ruleSetsProvider) { - _ruleSetsProvider->setROI(_roiCenter); + _ruleSetsProvider->setROI(_roi); } if(_weatherProvider) { - _weatherProvider->setROI(_roiCenter); + _weatherProvider->setROI(_roi); } if (_advisories) { - _advisories->setROI(_roiCenter, _roiRadius); + _advisories->setROI(_roi); } } diff --git a/src/AirspaceManagement/AirspaceManager.h b/src/AirspaceManagement/AirspaceManager.h index c0f470b96..d99e8a65f 100644 --- a/src/AirspaceManagement/AirspaceManager.h +++ b/src/AirspaceManagement/AirspaceManager.h @@ -26,6 +26,7 @@ #include "QGCToolbox.h" #include "QGCLoggingCategory.h" #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -63,7 +64,7 @@ public: Q_PROPERTY(AirspaceFlightPlanProvider* flightPlan READ flightPlan CONSTANT) Q_PROPERTY(bool airspaceVisible READ airspaceVisible WRITE setAirspaceVisible NOTIFY airspaceVisibleChanged) - Q_INVOKABLE void setROI (QGeoCoordinate center, double radius); + Q_INVOKABLE void setROI (const QGeoCoordinate& pointNW, const QGeoCoordinate& pointSE); AirspaceWeatherInfoProvider* weatherInfo () { return _weatherProvider; } AirspaceAdvisoryProvider* advisories () { return _advisories; } @@ -92,7 +93,7 @@ protected: * @param center Center coordinate for ROI * @param radiusMeters Radius in meters around center which is of interest */ - virtual void _setROI (const QGeoCoordinate& center, double radiusMeters); + virtual void _setROI (const QGCGeoBoundingCube& roi); /** * Factory methods @@ -111,8 +112,7 @@ protected: AirspaceRestrictionProvider* _airspaces = nullptr; ///< Airspace info AirspaceFlightPlanProvider* _flightPlan = nullptr; ///< Flight plan management QTimer _roiUpdateTimer; - QGeoCoordinate _roiCenter; - double _roiRadius; + QGCGeoBoundingCube _roi; private: void _updateToROI (); diff --git a/src/AirspaceManagement/AirspaceRestrictionProvider.h b/src/AirspaceManagement/AirspaceRestrictionProvider.h index 2b627ec8e..723a78ace 100644 --- a/src/AirspaceManagement/AirspaceRestrictionProvider.h +++ b/src/AirspaceManagement/AirspaceRestrictionProvider.h @@ -15,6 +15,7 @@ */ #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -37,7 +38,7 @@ public: * @param center Center coordinate for ROI * @param radiusMeters Radius in meters around center which is of interest */ - virtual void setROI (const QGeoCoordinate& center, double radiusMeters) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; virtual QmlObjectListModel* polygons () = 0; ///< List of AirspacePolygonRestriction objects virtual QmlObjectListModel* circles () = 0; ///< List of AirspaceCircularRestriction objects diff --git a/src/AirspaceManagement/AirspaceRulesetsProvider.h b/src/AirspaceManagement/AirspaceRulesetsProvider.h index 91777f80e..834b8f8ec 100644 --- a/src/AirspaceManagement/AirspaceRulesetsProvider.h +++ b/src/AirspaceManagement/AirspaceRulesetsProvider.h @@ -16,6 +16,7 @@ */ #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include #include @@ -161,7 +162,7 @@ public: * Set region of interest that should be queried. When finished, the rulesChanged() signal will be emmited. * @param center Center coordinate for ROI */ - virtual void setROI (const QGeoCoordinate& center) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; signals: void ruleSetsChanged (); diff --git a/src/AirspaceManagement/AirspaceWeatherInfoProvider.h b/src/AirspaceManagement/AirspaceWeatherInfoProvider.h index a8f99bf0a..5e0de6660 100644 --- a/src/AirspaceManagement/AirspaceWeatherInfoProvider.h +++ b/src/AirspaceManagement/AirspaceWeatherInfoProvider.h @@ -14,6 +14,7 @@ * Weather information provided by the Airspace Managemement */ +#include "QGCGeoBoundingCube.h" #include #include @@ -50,7 +51,7 @@ public: * Set region of interest that should be queried. When finished, the weatherChanged() signal will be emmited. * @param center Center coordinate for ROI */ - virtual void setROI (const QGeoCoordinate& center) = 0; + virtual void setROI (const QGCGeoBoundingCube& roi) = 0; signals: void weatherChanged (); diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index 6c5b9dd65..c8affbe72 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -57,13 +57,25 @@ FlightMap { property bool _disableVehicleTracking: false property bool _keepVehicleCentered: _mainIsMap ? false : true - // Track last known map position and zoom from Fly view in settings - onZoomLevelChanged: QGroundControl.flightMapZoom = zoomLevel - onCenterChanged: { + function updateAirspace() { if(_airspaceEnabled) { - QGroundControl.airspaceManager.setROI(center, 1000) + var coordinateNW = flightMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */) + var coordinateSE = flightMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */) + if(coordinateNW.isValid && coordinateSE.isValid) { + QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE) + } } + } + + // Track last known map position and zoom from Fly view in settings + + onZoomLevelChanged: { + QGroundControl.flightMapZoom = zoomLevel + updateAirspace() + } + onCenterChanged: { QGroundControl.flightMapPosition = center + updateAirspace() } // When the user pans the map we stop responding to vehicle coordinate updates until the panRecenterTimer fires diff --git a/src/FlightDisplay/FlightDisplayViewWidgets.qml b/src/FlightDisplay/FlightDisplayViewWidgets.qml index 1641001b2..0a58861a8 100644 --- a/src/FlightDisplay/FlightDisplayViewWidgets.qml +++ b/src/FlightDisplay/FlightDisplayViewWidgets.qml @@ -30,7 +30,7 @@ Item { property var qgcView property bool useLightColors property var missionController - property bool showValues: QGroundControl.airspaceManager.airspaceVisible + property bool showValues: !QGroundControl.airspaceManager.airspaceVisible property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _isSatellite: _mainIsMap ? (_flightMap ? _flightMap.isSatelliteMap : true) : true diff --git a/src/MissionManager/MissionController.h b/src/MissionManager/MissionController.h index 0f0b37439..9fc75cf80 100644 --- a/src/MissionManager/MissionController.h +++ b/src/MissionManager/MissionController.h @@ -16,7 +16,7 @@ #include "Vehicle.h" #include "QGCLoggingCategory.h" #include "MavlinkQmlSingleton.h" -#include "QGCGeo.h" +#include "QGCGeoBoundingCube.h" #include diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 42f5c4451..753875713 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -84,6 +84,16 @@ QGCView { _missionController.setCurrentPlanViewIndex(sequenceNumber, true) } + function updateAirspace() { + if(_airspaceEnabled) { + var coordinateNW = editorMap.toCoordinate(Qt.point(0,0), false /* clipToViewPort */) + var coordinateSE = editorMap.toCoordinate(Qt.point(width,height), false /* clipToViewPort */) + if(coordinateNW.isValid && coordinateSE.isValid) { + QGroundControl.airspaceManager.setROI(coordinateNW, coordinateSE) + } + } + } + property bool _firstMissionLoadComplete: false property bool _firstFenceLoadComplete: false property bool _firstRallyLoadComplete: false @@ -347,11 +357,8 @@ QGCView { QGCMapPalette { id: mapPal; lightColors: editorMap.isSatelliteMap } - onCenterChanged: { - if(_airspaceEnabled) { - QGroundControl.airspaceManager.setROI(center, 5000) - } - } + onZoomLevelChanged: updateAirspace() + onCenterChanged: updateAirspace() MouseArea { //-- It's a whole lot faster to just fill parent and deal with top offset below @@ -542,7 +549,7 @@ QGCView { height: ScreenTools.availableHeight width: _rightPanelWidth color: qgcPal.window - opacity: 0.2 + opacity: planExpanded.visible ? 0.2 : 0 anchors.bottom: parent.bottom anchors.right: parent.right anchors.rightMargin: ScreenTools.defaultFontPixelWidth diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 9dbfcd0fe..9f8be2da7 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -61,6 +61,7 @@ #include "JoystickConfigController.h" #include "JoystickManager.h" #include "QmlObjectListModel.h" +#include "QGCGeoBoundingCube.h" #include "MissionManager.h" #include "QGroundControlQmlGlobal.h" #include "FlightMapSettings.h" @@ -381,6 +382,8 @@ void QGCApplication::_initCommon(void) qmlRegisterUncreatableType("QGroundControl.Controllers", 1, 0, "RallyPointController", "Reference only"); qmlRegisterUncreatableType ("QGroundControl.Controllers", 1, 0, "VisualMissionItem", "Reference only"); + qmlRegisterType ("QGroundControl", 1, 0, "QGCGeoBoundingCube"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ParameterEditorController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ScreenToolsController"); diff --git a/src/QGCGeo.cc b/src/QGCGeo.cc index 0160e4f23..0c27941cb 100644 --- a/src/QGCGeo.cc +++ b/src/QGCGeo.cc @@ -102,10 +102,3 @@ void convertUTMToGeo(double easting, double northing, int zone, bool southhemi, coord.setLatitude(RadToDeg(latRadians)); coord.setLongitude(RadToDeg(lonRadians)); } - -double QGCGeoBoundingCube::MaxAlt = 1000000.0; -double QGCGeoBoundingCube::MinAlt = -1000000.0; -double QGCGeoBoundingCube::MaxNorth = 90.0; -double QGCGeoBoundingCube::MaxSouth = -90.0; -double QGCGeoBoundingCube::MaxWest = -180.0; -double QGCGeoBoundingCube::MaxEast = 180.0; diff --git a/src/QGCGeo.h b/src/QGCGeo.h index f4a4638e9..18f91ed2c 100644 --- a/src/QGCGeo.h +++ b/src/QGCGeo.h @@ -81,46 +81,4 @@ int convertGeoToUTM(const QGeoCoordinate& coord, double& easting, double& northi // The function does not return a value. void convertUTMToGeo(double easting, double northing, int zone, bool southhemi, QGeoCoordinate& coord); -// A bounding cube -class QGCGeoBoundingCube { -public: - QGCGeoBoundingCube() - : pointNW(QGeoCoordinate(MaxSouth, MaxEast, MaxAlt)) - , pointSE(QGeoCoordinate(MaxNorth, MaxWest, MinAlt)) - { - } - QGCGeoBoundingCube(QGeoCoordinate p1, QGeoCoordinate p2) - : pointNW(p1) - , pointSE(p2) - { - } - QGeoCoordinate pointNW; - QGeoCoordinate pointSE; - inline bool operator ==(const QGCGeoBoundingCube& other) - { - return pointNW == other.pointNW && pointSE == other.pointSE; - } - inline bool operator !=(const QGCGeoBoundingCube& other) - { - return !(*this == other); - } - inline QGCGeoBoundingCube operator =(const QGCGeoBoundingCube& other) - { - pointNW = other.pointNW; - pointSE = other.pointSE; - return *this; - } - inline bool isValid() - { - return pointNW.isValid() && pointSE.isValid() && pointNW.latitude() != MaxSouth && pointSE.latitude() != MaxNorth && \ - pointNW.longitude() != MaxEast && pointSE.longitude() != MaxWest && pointNW.altitude() < MaxAlt and pointSE.altitude() > MinAlt; - } - static double MaxAlt; - static double MinAlt; - static double MaxNorth; - static double MaxSouth; - static double MaxWest; - static double MaxEast; -}; - #endif // QGCGEO_H diff --git a/src/QmlControls/QGCGeoBoundingCube.cc b/src/QmlControls/QGCGeoBoundingCube.cc new file mode 100644 index 000000000..7fe03d0ff --- /dev/null +++ b/src/QmlControls/QGCGeoBoundingCube.cc @@ -0,0 +1,83 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +#include "QGCGeoBoundingCube.h" +#include + +double QGCGeoBoundingCube::MaxAlt = 1000000.0; +double QGCGeoBoundingCube::MinAlt = -1000000.0; +double QGCGeoBoundingCube::MaxNorth = 90.0; +double QGCGeoBoundingCube::MaxSouth = -90.0; +double QGCGeoBoundingCube::MaxWest = -180.0; +double QGCGeoBoundingCube::MaxEast = 180.0; + +//----------------------------------------------------------------------------- +bool +QGCGeoBoundingCube::isValid() const +{ + return pointNW.isValid() && pointSE.isValid() && pointNW.latitude() != MaxSouth && pointSE.latitude() != MaxNorth && \ + pointNW.longitude() != MaxEast && pointSE.longitude() != MaxWest && pointNW.altitude() < MaxAlt and pointSE.altitude() > MinAlt; +} + +//----------------------------------------------------------------------------- +QGeoCoordinate +QGCGeoBoundingCube::center() const +{ + double lat = (((pointNW.latitude() + 90.0) + (pointSE.latitude() + 90.0)) / 2.0) - 90.0; + double lon = (((pointNW.longitude() + 180.0) + (pointSE.longitude() + 180.0)) / 2.0) - 180.0; + double alt = (pointNW.altitude() + pointSE.altitude()) / 2.0; + //qDebug() << pointNW << pointSE << QGeoCoordinate(lat, lon, alt); + return QGeoCoordinate(lat, lon, alt); +} + +//----------------------------------------------------------------------------- +QList +QGCGeoBoundingCube::polygon2D() const +{ + QList coords; + coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointNW.latitude(), pointSE.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointSE.latitude(), pointSE.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointSE.latitude(), pointNW.longitude(), pointSE.altitude())); + coords.append(QGeoCoordinate(pointNW.latitude(), pointNW.longitude(), pointSE.altitude())); + return coords; +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::width() const +{ + QGeoCoordinate ne = QGeoCoordinate(pointNW.latitude(), pointSE.longitude()); + return pointNW.distanceTo(ne); +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::height() const +{ + QGeoCoordinate sw = QGeoCoordinate(pointSE.latitude(), pointNW.longitude()); + return pointNW.distanceTo(sw); +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::area() const +{ + // Area in km^2 + double a = (height() / 1000.0) * (width() / 1000.0); + //qDebug() << "Area:" << a; + return a; +} + +//----------------------------------------------------------------------------- +double +QGCGeoBoundingCube::radius() const +{ + return pointNW.distanceTo(pointSE) / 2.0; +} diff --git a/src/QmlControls/QGCGeoBoundingCube.h b/src/QmlControls/QGCGeoBoundingCube.h new file mode 100644 index 000000000..225f3072c --- /dev/null +++ b/src/QmlControls/QGCGeoBoundingCube.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#pragma once + +#include +#include + +// A bounding "cube" for small surface areas (doesn't take in consideration earth's curvature) +// Coordinate system makes NW Up Left Bottom (0,0,0) and SE Bottom Right Top (y,x,z) +class QGCGeoBoundingCube : public QObject { + Q_OBJECT +public: + QGCGeoBoundingCube(const QGCGeoBoundingCube& other) + { + pointNW = other.pointNW; + pointSE = other.pointSE; + } + + QGCGeoBoundingCube() + : pointNW(QGeoCoordinate(MaxSouth, MaxEast, MaxAlt)) + , pointSE(QGeoCoordinate(MaxNorth, MaxWest, MinAlt)) + { + } + + QGCGeoBoundingCube(QGeoCoordinate p1, QGeoCoordinate p2) + : pointNW(p1) + , pointSE(p2) + { + } + + Q_PROPERTY(QGeoCoordinate pointNW MEMBER pointNW CONSTANT) + Q_PROPERTY(QGeoCoordinate pointSE MEMBER pointNW CONSTANT) + + Q_INVOKABLE bool isValid() const; + Q_INVOKABLE QGeoCoordinate center() const; + + inline bool operator ==(const QGCGeoBoundingCube& other) + { + return pointNW == other.pointNW && pointSE == other.pointSE; + } + + inline bool operator !=(const QGCGeoBoundingCube& other) + { + return !(*this == other); + } + + inline const QGCGeoBoundingCube& operator =(const QGCGeoBoundingCube& other) + { + pointNW = other.pointNW; + pointSE = other.pointSE; + return *this; + } + + //-- 2D + QList polygon2D() const; + double width () const; + double height () const; + double area () const; + double radius () const; + + QGeoCoordinate pointNW; + QGeoCoordinate pointSE; + static double MaxAlt; + static double MinAlt; + static double MaxNorth; + static double MaxSouth; + static double MaxWest; + static double MaxEast; +}; -- 2.22.0