diff --git a/src/Airmap/AirMapAdvisoryManager.cc b/src/Airmap/AirMapAdvisoryManager.cc index 36d081c..7db453e 100644 --- a/src/Airmap/AirMapAdvisoryManager.cc +++ b/src/Airmap/AirMapAdvisoryManager.cc @@ -9,12 +9,16 @@ #include "AirMapAdvisoryManager.h" #include "AirspaceRestriction.h" +#include "AirMapRulesetsManager.h" #include "AirMapManager.h" +#include "QGCApplication.h" #include #include +#include #include "airmap/airspaces.h" +#include "airmap/advisory.h" #define ADVISORY_UPDATE_DISTANCE 500 //-- 500m threshold for updates @@ -68,27 +72,53 @@ AirMapAdvisoryManager::_requestAdvisories() } _valid = false; _advisories.clearAndDeleteContents(); - Status::GetStatus::Parameters params; - params.longitude = static_cast(_lastROI.center().longitude()); - params.latitude = static_cast(_lastROI.center().latitude()); - params.types = Airspace::Type::all; - params.weather = false; - double diagonal = _lastROI.pointNW.distanceTo(_lastROI.pointSE); - params.buffer = static_cast(std::fmax(std::fmin(diagonal, 10000.0), 500.0)); - params.flight_date_time = Clock::universal_time(); + Advisory::Search::Parameters params; + //-- Geometry + Geometry::Polygon polygon; + for (const auto& qcoord : _lastROI.polygon2D()) { + Geometry::Coordinate coord; + coord.latitude = qcoord.latitude(); + coord.longitude = qcoord.longitude(); + polygon.outer_ring.coordinates.push_back(coord); + } + params.geometry = Geometry(polygon); + //-- Rulesets + AirMapRulesetsManager* pRulesMgr = dynamic_cast(qgcApp()->toolbox()->airspaceManager()->ruleSets()); + QString ruleIDs; + if(pRulesMgr) { + for(int rs = 0; rs < pRulesMgr->ruleSets()->count(); rs++) { + AirMapRuleSet* ruleSet = qobject_cast(pRulesMgr->ruleSets()->get(rs)); + //-- If this ruleset is selected + if(ruleSet && ruleSet->selected()) { + ruleIDs = ruleIDs + ruleSet->id(); + //-- Separate rules with commas + if(rs < pRulesMgr->ruleSets()->count() - 1) { + ruleIDs = ruleIDs + ","; + } + } + } + } + params.rulesets = ruleIDs.toStdString(); + //-- Time + quint64 start = static_cast(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch()); + quint64 end = start + 60 * 30 * 1000; + params.start = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast(start))); + params.end = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast(end))); std::weak_ptr isAlive(_instance); - _shared.client()->status().get_status_by_point(params, [this, isAlive](const Status::GetStatus::Result& result) { + _shared.client()->advisory().search(params, [this, isAlive](const Advisory::Search::Result& result) { if (!isAlive.lock()) return; if (result) { - qCDebug(AirMapManagerLog) << "Successful advisory search. Items:" << result.value().advisories.size(); - _airspaceColor = (AirspaceAdvisoryProvider::AdvisoryColor)(int)result.value().advisory_color; - const std::vector advisories = result.value().advisories; - for (const auto& advisory : advisories) { + qCDebug(AirMapManagerLog) << "Successful advisory search. Items:" << result.value().size(); + _airspaceColor = AirspaceAdvisoryProvider::Green; + for (const auto& advisory : result.value()) { AirMapAdvisory* pAdvisory = new AirMapAdvisory(this); - pAdvisory->_id = QString::fromStdString(advisory.airspace.id()); - pAdvisory->_name = QString::fromStdString(advisory.airspace.name()); - pAdvisory->_type = (AirspaceAdvisory::AdvisoryType)(int)advisory.airspace.type(); - pAdvisory->_color = (AirspaceAdvisoryProvider::AdvisoryColor)(int)advisory.color; + pAdvisory->_id = QString::fromStdString(advisory.advisory.airspace.id()); + pAdvisory->_name = QString::fromStdString(advisory.advisory.airspace.name()); + pAdvisory->_type = static_cast(advisory.advisory.airspace.type()); + pAdvisory->_color = static_cast(advisory.color); + if(pAdvisory->_color > _airspaceColor) { + _airspaceColor = pAdvisory->_color; + } _advisories.append(pAdvisory); qCDebug(AirMapManagerLog) << "Adding advisory" << pAdvisory->name(); } diff --git a/src/Airmap/AirMapAdvisoryManager.h b/src/Airmap/AirMapAdvisoryManager.h index 63a2610..bbbfbae 100644 --- a/src/Airmap/AirMapAdvisoryManager.h +++ b/src/Airmap/AirMapAdvisoryManager.h @@ -32,7 +32,7 @@ class AirMapAdvisory : public AirspaceAdvisory friend class AirMapAdvisoryManager; friend class AirMapFlightPlanManager; public: - AirMapAdvisory (QObject* parent = NULL); + AirMapAdvisory (QObject* parent = nullptr); QString id () override { return _id; } QString name () override { return _name; } AdvisoryType type () override { return _type; } diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index 1dd088d..4e226de 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -76,28 +76,28 @@ AirMapFlightInfo::AirMapFlightInfo(const airmap::Flight& flight, QObject *parent QString AirMapFlightInfo::createdTime() { - return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.created_at)).toString("yyyy MM dd - hh:mm:ss"); + return QDateTime::fromMSecsSinceEpoch(static_cast(airmap::milliseconds_since_epoch(_flight.created_at))).toString("yyyy MM dd - hh:mm:ss"); } //----------------------------------------------------------------------------- QString AirMapFlightInfo::startTime() { - return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.start_time)).toString("yyyy MM dd - hh:mm:ss"); + return QDateTime::fromMSecsSinceEpoch(static_cast(airmap::milliseconds_since_epoch(_flight.start_time))).toString("yyyy MM dd - hh:mm:ss"); } //----------------------------------------------------------------------------- QDateTime AirMapFlightInfo::qStartTime() { - return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.start_time)); + return QDateTime::fromMSecsSinceEpoch(static_cast(airmap::milliseconds_since_epoch(_flight.start_time))); } //----------------------------------------------------------------------------- bool AirMapFlightInfo::active() { - QDateTime end = QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.end_time)); + QDateTime end = QDateTime::fromMSecsSinceEpoch(static_cast(airmap::milliseconds_since_epoch(_flight.end_time))); QDateTime now = QDateTime::currentDateTime(); return end > now; } @@ -114,7 +114,7 @@ AirMapFlightInfo::setEndFlight(DateTime end) QString AirMapFlightInfo::endTime() { - return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flight.end_time)).toString("yyyy MM dd - hh:mm:ss"); + return QDateTime::fromMSecsSinceEpoch(static_cast(airmap::milliseconds_since_epoch(_flight.end_time))).toString("yyyy MM dd - hh:mm:ss"); } //----------------------------------------------------------------------------- @@ -123,6 +123,8 @@ AirMapFlightPlanManager::AirMapFlightPlanManager(AirMapSharedState& shared, QObj , _shared(shared) { connect(&_pollTimer, &QTimer::timeout, this, &AirMapFlightPlanManager::_pollBriefing); + _flightStartTime = QDateTime::currentDateTime().addSecs(60); + _flightEndTime = _flightStartTime.addSecs(30 * 60); } //----------------------------------------------------------------------------- @@ -136,30 +138,31 @@ AirMapFlightPlanManager::~AirMapFlightPlanManager() void AirMapFlightPlanManager::setFlightStartTime(QDateTime start) { - quint64 startt = start.toUTC().toMSecsSinceEpoch(); - if(_flightPlan.start_time != airmap::from_milliseconds_since_epoch(airmap::milliseconds((long long)startt))) { - //-- Can't start in the past - if(start < QDateTime::currentDateTime()) { - start = QDateTime::currentDateTime().addSecs(5 * 60); - startt = start.toUTC().toMSecsSinceEpoch(); - } - _flightPlan.start_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds((long long)startt)); + if(start < QDateTime::currentDateTime()) { + start = QDateTime::currentDateTime().addSecs(60); + } + if(_flightStartTime != start) { + _flightStartTime = start; emit flightStartTimeChanged(); } + //-- End has to be after start + if(_flightEndTime < _flightStartTime) { + _flightEndTime = _flightStartTime.addSecs(30 * 60); + emit flightEndTimeChanged(); + } + qCDebug(AirMapManagerLog) << "Set time" << _flightStartTime << _flightEndTime; } //----------------------------------------------------------------------------- void AirMapFlightPlanManager::setFlightEndTime(QDateTime end) { - quint64 endt = end.toUTC().toMSecsSinceEpoch(); - if(_flightPlan.end_time != airmap::from_milliseconds_since_epoch(airmap::milliseconds((long long)endt))) { - //-- End has to be after start - if(end < flightStartTime()) { - end = flightStartTime().addSecs(30 * 60); - endt = end.toUTC().toMSecsSinceEpoch(); - } - _flightPlan.end_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds((long long)endt)); + //-- End has to be after start + if(end < _flightStartTime) { + end = _flightStartTime.addSecs(30 * 60); + } + if(_flightEndTime != end) { + _flightEndTime = end; emit flightEndTimeChanged(); } } @@ -168,14 +171,14 @@ AirMapFlightPlanManager::setFlightEndTime(QDateTime end) QDateTime AirMapFlightPlanManager::flightStartTime() const { - return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flightPlan.start_time)); + return _flightStartTime; } //----------------------------------------------------------------------------- QDateTime AirMapFlightPlanManager::flightEndTime() const { - return QDateTime::fromMSecsSinceEpoch((quint64)airmap::milliseconds_since_epoch(_flightPlan.end_time)); + return _flightEndTime; } //----------------------------------------------------------------------------- @@ -205,6 +208,8 @@ AirMapFlightPlanManager::startFlightPlanning(PlanMasterController *planControlle //-- Get notified of mission changes connect(planController->missionController(), &MissionController::missionBoundingCubeChanged, this, &AirMapFlightPlanManager::_missionChanged); } + //-- Set initial flight start time + setFlightStartTime(QDateTime::currentDateTime().addSecs(5 * 60)); } //----------------------------------------------------------------------------- @@ -216,6 +221,7 @@ AirMapFlightPlanManager::submitFlightPlan() return; } _flightId.clear(); + emit flightIDChanged(_flightId); _state = State::FlightSubmit; FlightPlans::Submit::Parameters params; params.authorization = _shared.loginToken().toStdString(); @@ -229,6 +235,7 @@ AirMapFlightPlanManager::submitFlightPlan() _flightId = QString::fromStdString(_flightPlan.flight_id.get()); _state = State::Idle; _pollBriefing(); + emit flightIDChanged(_flightId); } else { QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : ""); emit error("Failed to submit Flight Plan", @@ -301,7 +308,7 @@ AirMapFlightPlanManager::_endFlight() qCDebug(AirMapManagerLog) << "End non existing flight"; return; } - qCDebug(AirMapManagerLog) << "End Flight. State:" << (int)_state; + qCDebug(AirMapManagerLog) << "End Flight. State:" << static_cast(_state); if(_state != State::Idle) { QTimer::singleShot(100, this, &AirMapFlightPlanManager::_endFlight); return; @@ -343,12 +350,12 @@ AirMapFlightPlanManager::_collectFlightDtata() } //-- Get flight bounding cube and prepare (box) polygon QGCGeoBoundingCube bc = *_planController->missionController()->travelBoundingCube(); - if(!bc.isValid() || !bc.area()) { + if(!bc.isValid() || (fabs(bc.area()) < 0.0001)) { //-- TODO: If single point, we need to set a point and a radius instead qCDebug(AirMapManagerLog) << "Not enough points for a flight plan."; return false; } - _flight.maxAltitude = fmax(bc.pointNW.altitude(), bc.pointSE.altitude()); + _flight.maxAltitude = static_cast(fmax(bc.pointNW.altitude(), bc.pointSE.altitude())); _flight.takeoffCoord = _planController->missionController()->takeoffCoordinate(); _flight.coords = bc.polygon2D(); _flight.bc = bc; @@ -443,7 +450,7 @@ AirMapFlightPlanManager::_updateRulesAndFeatures(std::vector& rules case AirspaceRuleFeature::Float: //-- Sanity check for floats if(std::isfinite(feature->value().toFloat())) { - features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toFloat()); + features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toDouble()); } break; case AirspaceRuleFeature::String: @@ -467,9 +474,29 @@ AirMapFlightPlanManager::_updateRulesAndFeatures(std::vector& rules //----------------------------------------------------------------------------- void +AirMapFlightPlanManager::_updateFlightStartEndTime(DateTime& start_time, DateTime& end_time) +{ + if(_flightStartTime < QDateTime::currentDateTime()) { + //-- Can't start in the past + _flightStartTime = QDateTime::currentDateTime(); + emit flightStartTimeChanged(); + } + quint64 startt = static_cast(_flightStartTime.toUTC().toMSecsSinceEpoch()); + start_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast(startt))); + //-- End has to be after start + if(_flightEndTime < _flightStartTime) { + _flightEndTime = _flightStartTime.addSecs(30 * 60); + emit flightEndTimeChanged(); + } + quint64 endt = static_cast(_flightEndTime.toUTC().toMSecsSinceEpoch()); + end_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast(endt))); +} + +//----------------------------------------------------------------------------- +void AirMapFlightPlanManager::_uploadFlightPlan() { - qCDebug(AirMapManagerLog) << "Uploading flight plan. State:" << (int)_state; + qCDebug(AirMapManagerLog) << "Uploading flight plan. State:" << static_cast(_state); if(_state != State::Idle) { QTimer::singleShot(100, this, &AirMapFlightPlanManager::_uploadFlightPlan); return; @@ -482,14 +509,12 @@ AirMapFlightPlanManager::_uploadFlightPlan() FlightPlans::Create::Parameters params; params.max_altitude = _flight.maxAltitude; params.min_altitude = 0.0; - params.buffer = 2.f; - params.latitude = _flight.takeoffCoord.latitude(); - params.longitude = _flight.takeoffCoord.longitude(); + params.buffer = 0.f; + params.latitude = static_cast(_flight.takeoffCoord.latitude()); + params.longitude = static_cast(_flight.takeoffCoord.longitude()); params.pilot.id = _pilotID.toStdString(); - quint64 start = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(); - quint64 end = start + 60 * 30 * 1000; - params.start_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds((long long)start)); - params.end_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds((long long)end)); + //-- Handle flight start/end + _updateFlightStartEndTime(params.start_time, params.end_time); //-- Rules & Features _updateRulesAndFeatures(params.rulesets, params.features); //-- Geometry: polygon @@ -530,7 +555,7 @@ AirMapFlightPlanManager::_updateFlightPlanOnTimer() void AirMapFlightPlanManager::_updateFlightPlan(bool interactive) { - qCDebug(AirMapManagerLog) << "Updating flight plan. State:" << (int)_state; + qCDebug(AirMapManagerLog) << "Updating flight plan. State:" << static_cast(_state); if(_state != State::Idle) { QTimer::singleShot(100, this, &AirMapFlightPlanManager::_updateFlightPlanOnTimer); @@ -541,22 +566,19 @@ AirMapFlightPlanManager::_updateFlightPlan(bool interactive) return; } - qCDebug(AirMapManagerLog) << "Takeoff: " << _flight.takeoffCoord; - qCDebug(AirMapManagerLog) << "Bounding box:" << _flight.bc.pointNW << _flight.bc.pointSE; - qCDebug(AirMapManagerLog) << "Flight Start:" << flightStartTime().toString(); - qCDebug(AirMapManagerLog) << "Flight End: " << flightEndTime().toString(); - //-- Update local instance of the flight plan _flightPlan.altitude_agl.max = _flight.maxAltitude; _flightPlan.altitude_agl.min = 0.0f; _flightPlan.buffer = 2.f; - _flightPlan.takeoff.latitude = _flight.takeoffCoord.latitude(); - _flightPlan.takeoff.longitude = _flight.takeoffCoord.longitude(); + _flightPlan.takeoff.latitude = static_cast(_flight.takeoffCoord.latitude()); + _flightPlan.takeoff.longitude = static_cast(_flight.takeoffCoord.longitude()); //-- Rules & Features _flightPlan.rulesets.clear(); _flightPlan.features.clear(); //-- If interactive, we collect features otherwise we don't _updateRulesAndFeatures(_flightPlan.rulesets, _flightPlan.features, interactive); + //-- Handle flight start/end + _updateFlightStartEndTime(_flightPlan.start_time, _flightPlan.end_time); //-- Geometry: polygon Geometry::Polygon polygon; for (const auto& qcoord : _flight.coords) { @@ -566,6 +588,12 @@ AirMapFlightPlanManager::_updateFlightPlan(bool interactive) polygon.outer_ring.coordinates.push_back(coord); } _flightPlan.geometry = Geometry(polygon); + + qCDebug(AirMapManagerLog) << "Takeoff: " << _flight.takeoffCoord; + qCDebug(AirMapManagerLog) << "Bounding box:" << _flight.bc.pointNW << _flight.bc.pointSE; + qCDebug(AirMapManagerLog) << "Flight Start:" << flightStartTime().toString(); + qCDebug(AirMapManagerLog) << "Flight End: " << flightEndTime().toString(); + _state = State::FlightUpdate; std::weak_ptr isAlive(_instance); _shared.doRequestWithLogin([this, isAlive](const QString& login_token) { @@ -647,13 +675,13 @@ AirMapFlightPlanManager::_pollBriefing() _valid = false; _advisories.clearAndDeleteContents(); const std::vector advisories = briefing.airspace.advisories; - _airspaceColor = (AirspaceAdvisoryProvider::AdvisoryColor)(int)briefing.airspace.color; + _airspaceColor = static_cast(briefing.airspace.color); for (const auto& advisory : advisories) { AirMapAdvisory* pAdvisory = new AirMapAdvisory(this); pAdvisory->_id = QString::fromStdString(advisory.airspace.id()); pAdvisory->_name = QString::fromStdString(advisory.airspace.name()); - pAdvisory->_type = (AirspaceAdvisory::AdvisoryType)(int)advisory.airspace.type(); - pAdvisory->_color = (AirspaceAdvisoryProvider::AdvisoryColor)(int)advisory.color; + pAdvisory->_type = static_cast(advisory.airspace.type()); + pAdvisory->_color = static_cast(advisory.color); _advisories.append(pAdvisory); qCDebug(AirMapManagerLog) << "Adding briefing advisory" << pAdvisory->name(); } @@ -682,12 +710,18 @@ AirMapFlightPlanManager::_pollBriefing() if(rule.status == RuleSet::Rule::Status::missing_info) { if(!_findBriefFeature(pFeature->name())) { _briefFeatures.append(pFeature); + _importantFeatures.append(pFeature); qCDebug(AirMapManagerLog) << "Adding briefing feature" << pFeature->name() << pFeature->description() << pFeature->type(); } else { qCDebug(AirMapManagerLog) << "Skipping briefing feature duplicate" << pFeature->name() << pFeature->description() << pFeature->type(); } } } + for(const auto& feature : _importantFeatures) { + if(!_findBriefFeature(feature->name())) { + _briefFeatures.append(feature); + } + } pRuleSet->_rules.append(pRule); //-- Rules separated by status for presentation switch(rule.status) { @@ -734,10 +768,6 @@ AirMapFlightPlanManager::_pollBriefing() case Evaluation::Authorization::Status::pending: pending = true; break; - //-- If we don't know, accept it - default: - accepted = true; - break; } } if (briefing.evaluation.authorizations.size() == 0) { diff --git a/src/Airmap/AirMapFlightPlanManager.h b/src/Airmap/AirMapFlightPlanManager.h index 589f106..ee5ca4a 100644 --- a/src/Airmap/AirMapFlightPlanManager.h +++ b/src/Airmap/AirMapFlightPlanManager.h @@ -22,6 +22,7 @@ #include "airmap/flight_plan.h" #include "airmap/ruleset.h" +class AirMapRuleFeature; class PlanMasterController; //----------------------------------------------------------------------------- @@ -52,7 +53,7 @@ public: QString startTime () override; QString endTime () override; QDateTime qStartTime () override; - QGeoCoordinate takeOff () override { return QGeoCoordinate(_flight.latitude, _flight.longitude);} + QGeoCoordinate takeOff () override { return QGeoCoordinate(static_cast(_flight.latitude), static_cast(_flight.longitude));} QVariantList boundingBox () override { return _boundingBox; } bool active () override; void setEndFlight (airmap::DateTime end); @@ -68,7 +69,7 @@ class AirMapFlightPlanManager : public AirspaceFlightPlanProvider, public Lifeti Q_OBJECT public: AirMapFlightPlanManager (AirMapSharedState& shared, QObject *parent = nullptr); - ~AirMapFlightPlanManager (); + ~AirMapFlightPlanManager () override; PermitStatus flightPermitStatus () const override { return _flightPermitStatus; } QDateTime flightStartTime () const override; @@ -102,6 +103,7 @@ public: signals: void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails); + void flightIDChanged (QString flightID); private slots: void _pollBriefing (); @@ -116,6 +118,7 @@ private: bool _collectFlightDtata (); void _updateFlightPlan (bool interactive = false); bool _findBriefFeature (const QString& name); + void _updateFlightStartEndTime (airmap::DateTime& start_time, airmap::DateTime& end_time); void _updateRulesAndFeatures (std::vector& rulesets, std::unordered_map& features, bool updateFeatures = false); private: @@ -164,6 +167,10 @@ private: QDateTime _rangeStart; QDateTime _rangeEnd; airmap::FlightPlan _flightPlan; + QDateTime _flightStartTime; + QDateTime _flightEndTime; + + QList _importantFeatures; AirspaceAdvisoryProvider::AdvisoryColor _airspaceColor; AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone; diff --git a/src/Airmap/AirMapManager.cc b/src/Airmap/AirMapManager.cc index b2361fb..44795e1 100644 --- a/src/Airmap/AirMapManager.cc +++ b/src/Airmap/AirMapManager.cc @@ -43,9 +43,9 @@ 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(QtWarningMsg, false); + _logger->logging_category().setEnabled(QtDebugMsg, true); + _logger->logging_category().setEnabled(QtInfoMsg, true); + _logger->logging_category().setEnabled(QtWarningMsg, true); _dispatchingLogger = std::make_shared(_logger); connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error); connect(&_shared, &AirMapSharedState::authStatus, this, &AirMapManager::_authStatusChanged); diff --git a/src/Airmap/AirMapRulesetsManager.cc b/src/Airmap/AirMapRulesetsManager.cc index af54be6..4d43d55 100644 --- a/src/Airmap/AirMapRulesetsManager.cc +++ b/src/Airmap/AirMapRulesetsManager.cc @@ -197,13 +197,11 @@ AirMapRuleSet::setSelected(bool sel) if(_selected != sel) { _selected = sel; emit selectedChanged(); - qgcApp()->toolbox()->airspaceManager()->setUpdate(); } } else { if(!_selected) { _selected = true; emit selectedChanged(); - qgcApp()->toolbox()->airspaceManager()->setUpdate(); } } } diff --git a/src/Airmap/AirMapTelemetry.cc b/src/Airmap/AirMapTelemetry.cc index 02b455b..5357cf7 100644 --- a/src/Airmap/AirMapTelemetry.cc +++ b/src/Airmap/AirMapTelemetry.cc @@ -77,11 +77,11 @@ AirMapTelemetry::_handleGlobalPositionInt(const mavlink_message_t& message) mavlink_msg_global_position_int_decode(&message, &globalPosition); Telemetry::Position position{ milliseconds_since_epoch(Clock::universal_time()), - (double) globalPosition.lat / 1e7, - (double) globalPosition.lon / 1e7, - (float) globalPosition.alt / 1000.f, - (float) globalPosition.relative_alt / 1000.f, - _lastHdop + static_cast(globalPosition.lat / 1e7), + static_cast(globalPosition.lon / 1e7), + static_cast(globalPosition.alt) / 1000.0, + static_cast(globalPosition.relative_alt) / 1000.0, + static_cast(_lastHdop) }; Telemetry::Speed speed{ milliseconds_since_epoch(Clock::universal_time()), @@ -102,7 +102,7 @@ void AirMapTelemetry::startTelemetryStream(const QString& flightID) { if (_state != State::Idle) { - qCWarning(AirMapManagerLog) << "Not starting telemetry: not in idle state:" << (int)_state; + qCWarning(AirMapManagerLog) << "Not starting telemetry: not in idle state:" << static_cast(_state); return; } if(flightID.isEmpty()) { diff --git a/src/Airmap/AirMapTrafficMonitor.cc b/src/Airmap/AirMapTrafficMonitor.cc index 56d96ac..c09cd5c 100644 --- a/src/Airmap/AirMapTrafficMonitor.cc +++ b/src/Airmap/AirMapTrafficMonitor.cc @@ -28,7 +28,11 @@ AirMapTrafficMonitor::~AirMapTrafficMonitor() void AirMapTrafficMonitor::startConnection(const QString& flightID) { + if(flightID.isEmpty() || _flightID == flightID) { + return; + } _flightID = flightID; + qCDebug(AirMapManagerLog) << "Traffic update started for" << flightID; std::weak_ptr isAlive(_instance); auto handler = [this, isAlive](const Traffic::Monitor::Result& result) { if (!isAlive.lock()) return; @@ -58,7 +62,7 @@ AirMapTrafficMonitor::_update(Traffic::Update::Type type, const std::vector(traffic.heading)); } } diff --git a/src/Airmap/AirMapVehicleManager.cc b/src/Airmap/AirMapVehicleManager.cc index feb4a59..935ed73 100644 --- a/src/Airmap/AirMapVehicleManager.cc +++ b/src/Airmap/AirMapVehicleManager.cc @@ -14,6 +14,8 @@ #include "QGCApplication.h" #include "Vehicle.h" +#include "QGCApplication.h" +#include "SettingsManager.h" //----------------------------------------------------------------------------- AirMapVehicleManager::AirMapVehicleManager(AirMapSharedState& shared, const Vehicle& vehicle) @@ -27,17 +29,24 @@ AirMapVehicleManager::AirMapVehicleManager(AirMapSharedState& shared, const Vehi connect(&_telemetry, &AirMapTelemetry::error, this, &AirMapVehicleManager::error); connect(&_trafficMonitor, &AirMapTrafficMonitor::error, this, &AirMapVehicleManager::error); connect(&_trafficMonitor, &AirMapTrafficMonitor::trafficUpdate, this, &AirspaceVehicleManager::trafficUpdate); + AirMapFlightPlanManager* planMgr = qobject_cast(qgcApp()->toolbox()->airspaceManager()->flightPlan()); + if(planMgr) { + connect(planMgr, &AirMapFlightPlanManager::flightIDChanged, this, &AirMapVehicleManager::_flightIDChanged); + } } //----------------------------------------------------------------------------- void AirMapVehicleManager::startTelemetryStream() { - AirMapFlightPlanManager* planMgr = (AirMapFlightPlanManager*)qgcApp()->toolbox()->airspaceManager()->flightPlan(); + AirMapFlightPlanManager* planMgr = qobject_cast(qgcApp()->toolbox()->airspaceManager()->flightPlan()); if (!planMgr->flightID().isEmpty()) { - //-- TODO: This will start telemetry using the current flight ID in memory (current flight in AirMapFlightPlanManager) - qCDebug(AirMapManagerLog) << "AirMap telemetry stream enabled"; - _telemetry.startTelemetryStream(planMgr->flightID()); + //-- Is telemetry enabled? + if(qgcApp()->toolbox()->settingsManager()->airMapSettings()->enableTelemetry()->rawValue().toBool()) { + //-- TODO: This will start telemetry using the current flight ID in memory (current flight in AirMapFlightPlanManager) + qCDebug(AirMapManagerLog) << "AirMap telemetry stream enabled"; + _telemetry.startTelemetryStream(planMgr->flightID()); + } } else { qCDebug(AirMapManagerLog) << "AirMap telemetry stream not possible (No Flight ID)"; } @@ -61,7 +70,7 @@ AirMapVehicleManager::isTelemetryStreaming() void AirMapVehicleManager::endFlight() { - AirMapFlightPlanManager* planMgr = (AirMapFlightPlanManager*)qgcApp()->toolbox()->airspaceManager()->flightPlan(); + AirMapFlightPlanManager* planMgr = qobject_cast(qgcApp()->toolbox()->airspaceManager()->flightPlan()); if (!planMgr->flightID().isEmpty()) { _flightManager.endFlight(planMgr->flightID()); } @@ -76,3 +85,16 @@ AirMapVehicleManager::vehicleMavlinkMessageReceived(const mavlink_message_t& mes _telemetry.vehicleMessageReceived(message); } } + +//----------------------------------------------------------------------------- +void +AirMapVehicleManager::_flightIDChanged(QString flightID) +{ + qCDebug(AirMapManagerLog) << "Flight ID Changed:" << flightID; + //-- Handle traffic monitor + if(flightID.isEmpty()) { + _trafficMonitor.stop(); + } else { + _trafficMonitor.startConnection(flightID); + } +} diff --git a/src/Airmap/AirMapVehicleManager.h b/src/Airmap/AirMapVehicleManager.h index 87a962f..84813f2 100644 --- a/src/Airmap/AirMapVehicleManager.h +++ b/src/Airmap/AirMapVehicleManager.h @@ -23,7 +23,7 @@ class AirMapVehicleManager : public AirspaceVehicleManager Q_OBJECT public: AirMapVehicleManager (AirMapSharedState& shared, const Vehicle& vehicle); - ~AirMapVehicleManager () = default; + ~AirMapVehicleManager () override = default; void startTelemetryStream () override; void stopTelemetryStream () override; @@ -36,7 +36,10 @@ public slots: void endFlight () override; protected slots: - virtual void vehicleMavlinkMessageReceived(const mavlink_message_t& message) override; + void vehicleMavlinkMessageReceived(const mavlink_message_t& message) override; + +private slots: + void _flightIDChanged (QString flightID); private: AirMapSharedState& _shared; diff --git a/src/Airmap/FlightBrief.qml b/src/Airmap/FlightBrief.qml index 3a7e4b8..64f8498 100644 --- a/src/Airmap/FlightBrief.qml +++ b/src/Airmap/FlightBrief.qml @@ -200,6 +200,7 @@ Item { visible: planView width: ScreenTools.defaultFontPixelWidth * 12 onClicked: { + _dirty = false QGroundControl.airspaceManager.flightPlan.updateFlightPlan() } } diff --git a/src/Airmap/FlightDetails.qml b/src/Airmap/FlightDetails.qml index fda70b3..e4935c7 100644 --- a/src/Airmap/FlightDetails.qml +++ b/src/Airmap/FlightDetails.qml @@ -2,6 +2,7 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.2 import QtQml 2.2 import QGroundControl 1.0 @@ -62,21 +63,34 @@ Item { anchors.right: parent.right anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter - QGCButton { - text: { - var today = new Date(); - if(datePicker.selectedDate.setHours(0,0,0,0) === today.setHours(0,0,0,0)) { - return qsTr("Today") - } else { - return datePicker.selectedDate.toLocaleDateString(Qt.locale()) - } - } - iconSource: "qrc:/airmap/expand.svg" + RowLayout { + spacing: ScreenTools.defaultFontPixelWidth * 0.5 anchors.right: parent.right anchors.left: parent.left - onClicked: { - _dirty = true - datePicker.visible = true + QGCButton { + text: qsTr("Now") + onClicked: { + _dirty = true + var today = new Date() + QGroundControl.airspaceManager.flightPlan.flightStartTime = today + timeSlider.updateTime() + } + } + QGCButton { + text: { + var today = QGroundControl.airspaceManager.flightPlan.flightStartTime + if(datePicker.selectedDate.setHours(0,0,0,0) === today.setHours(0,0,0,0)) { + return qsTr("Today") + } else { + return datePicker.selectedDate.toLocaleDateString(Qt.locale()) + } + } + Layout.fillWidth: true + iconSource: "qrc:/airmap/expand.svg" + onClicked: { + _dirty = true + datePicker.visible = true + } } } Item { @@ -102,12 +116,20 @@ Item { anchors.verticalCenter: parent.verticalCenter onValueChanged: { _dirty = true + var today = QGroundControl.airspaceManager.flightPlan.flightStartTime + today.setHours(Math.floor(timeSlider.value * 0.25)) + today.setMinutes((timeSlider.value * 15) % 60) + today.setSeconds(0) + QGroundControl.airspaceManager.flightPlan.flightStartTime = today } Component.onCompleted: { - var today = new Date() + updateTime() + } + function updateTime() { + var today = QGroundControl.airspaceManager.flightPlan.flightStartTime var val = (((today.getHours() * 60) + today.getMinutes()) * (96/1440)) + 1 if(val > 95) val = 95 - value = Math.ceil(val) + timeSlider.value = Math.ceil(val) } } } @@ -133,12 +155,11 @@ Item { } Calendar { id: datePicker - anchors.centerIn: parent - visible: false; - minimumDate: { - return new Date() - } + anchors.centerIn: parent + visible: false; + minimumDate: QGroundControl.airspaceManager.flightPlan.flightStartTime onClicked: { + QGroundControl.airspaceManager.flightPlan.flightStartTime = datePicker.selectedDate visible = false; } } diff --git a/src/AirspaceManagement/AirspaceManager.cc b/src/AirspaceManagement/AirspaceManager.cc index 33e4b44..e612421 100644 --- a/src/AirspaceManagement/AirspaceManager.cc +++ b/src/AirspaceManagement/AirspaceManager.cc @@ -27,12 +27,12 @@ AirspaceManager::AirspaceManager(QGCApplication* app, QGCToolbox* toolbox) : QGCTool(app, toolbox) , _airspaceVisible(false) { - _roiUpdateTimer.setInterval(2000); - _roiUpdateTimer.setSingleShot(true); + _ruleUpdateTimer.setInterval(2000); + _ruleUpdateTimer.setSingleShot(true); _updateTimer.setInterval(1000); _updateTimer.setSingleShot(true); - connect(&_roiUpdateTimer, &QTimer::timeout, this, &AirspaceManager::_updateToROITimeout); - connect(&_updateTimer, &QTimer::timeout, this, &AirspaceManager::_updateTimeout); + connect(&_ruleUpdateTimer, &QTimer::timeout, this, &AirspaceManager::_updateRulesTimeout); + connect(&_updateTimer, &QTimer::timeout, this, &AirspaceManager::_updateTimeout); qmlRegisterUncreatableType ("QGroundControl.Airspace", 1, 0, "AirspaceAdvisoryProvider", "Reference only"); qmlRegisterUncreatableType ("QGroundControl.Airspace", 1, 0, "AirspaceFlightPlanProvider", "Reference only"); qmlRegisterUncreatableType ("QGroundControl.Airspace", 1, 0, "AirspaceManager", "Reference only"); @@ -77,6 +77,10 @@ AirspaceManager::setToolbox(QGCToolbox* toolbox) _advisories = _instatiateAirspaceAdvisoryProvider(); _airspaces = _instantiateAirspaceRestrictionProvider(); _flightPlan = _instantiateAirspaceFlightPlanProvider(); + //-- Keep track of rule changes + if(_ruleSetsProvider) { + connect(_ruleSetsProvider, &AirspaceRulesetsProvider::selectedRuleSetsChanged, this, &AirspaceManager::_rulesChanged); + } } //----------------------------------------------------------------------------- @@ -107,21 +111,13 @@ AirspaceManager::setROI(const QGeoCoordinate& pointNW, const QGeoCoordinate& poi } } - -//----------------------------------------------------------------------------- -void -AirspaceManager::setUpdate() -{ - _updateTimer.start(); -} - //----------------------------------------------------------------------------- void AirspaceManager::_setROI(const QGCGeoBoundingCube& roi) { if(_roi != roi) { _roi = roi; - _roiUpdateTimer.start(); + _ruleUpdateTimer.start(); } } @@ -129,9 +125,6 @@ AirspaceManager::_setROI(const QGCGeoBoundingCube& roi) void AirspaceManager::_updateToROI(bool reset) { - if(reset) { - _updateTimer.stop(); - } if(_airspaces) { _airspaces->setROI(_roi, reset); } @@ -141,21 +134,28 @@ AirspaceManager::_updateToROI(bool reset) if(_weatherProvider) { _weatherProvider->setROI(_roi, reset); } - if (_advisories) { - _advisories->setROI(_roi, reset); - } } + //----------------------------------------------------------------------------- void -AirspaceManager::_updateToROITimeout() +AirspaceManager::_updateTimeout() { _updateToROI(false); } //----------------------------------------------------------------------------- void -AirspaceManager::_updateTimeout() +AirspaceManager::_rulesChanged() { - emit update(); + _ruleUpdateTimer.start(); +} + +//----------------------------------------------------------------------------- +void +AirspaceManager::_updateRulesTimeout() +{ + if (_advisories) { + _advisories->setROI(_roi, true); + } } diff --git a/src/AirspaceManagement/AirspaceManager.h b/src/AirspaceManagement/AirspaceManager.h index 7d3ffa4..f196e29 100644 --- a/src/AirspaceManagement/AirspaceManager.h +++ b/src/AirspaceManagement/AirspaceManager.h @@ -93,7 +93,6 @@ public: virtual void setAirspaceVisible (bool set) { _airspaceVisible = set; emit airspaceVisibleChanged(); } virtual bool connected () const = 0; virtual QString connectStatus () const { return QString(); } - virtual void setUpdate (); virtual AirspaceManager::AuthStatus authStatus () const { return Anonymous; } @@ -107,7 +106,6 @@ signals: void connectedChanged (); void connectStatusChanged (); void authStatusChanged (); - void update (); protected: /** @@ -133,13 +131,14 @@ protected: AirspaceAdvisoryProvider* _advisories = nullptr; ///< Advisory info AirspaceRestrictionProvider* _airspaces = nullptr; ///< Airspace info AirspaceFlightPlanProvider* _flightPlan = nullptr; ///< Flight plan management - QTimer _roiUpdateTimer; + QTimer _ruleUpdateTimer; QTimer _updateTimer; QGCGeoBoundingCube _roi; private slots: - void _updateToROITimeout (); + void _updateRulesTimeout (); void _updateTimeout (); + void _rulesChanged (); private: void _updateToROI (bool reset = false); diff --git a/src/FlightDisplay/FlightDisplayViewMap.qml b/src/FlightDisplay/FlightDisplayViewMap.qml index 66a6e92..d00415f 100644 --- a/src/FlightDisplay/FlightDisplayViewMap.qml +++ b/src/FlightDisplay/FlightDisplayViewMap.qml @@ -167,13 +167,6 @@ FlightMap { QGCMapPalette { id: mapPal; lightColors: isSatelliteMap } Connections { - target: QGroundControl.airspaceManager - onUpdate: { - updateAirspace(true) - } - } - - Connections { target: _missionController onNewItemsFromVehicle: { diff --git a/src/PlanView/PlanView.qml b/src/PlanView/PlanView.qml index 0adead5..d55b34a 100644 --- a/src/PlanView/PlanView.qml +++ b/src/PlanView/PlanView.qml @@ -185,9 +185,6 @@ QGCView { onAirspaceVisibleChanged: { planControlColapsed = QGroundControl.airspaceManager.airspaceVisible } - onUpdate: { - updateAirspace(true) - } } Component {