Commit e67ba35d authored by Gus Grubba's avatar Gus Grubba

Switch advisory API

Handle flight start/end time
Handle start/stop traffic monitor
Only start telemetry if enabled
Added a "Now" button for the flight start time
Collect advisories only when the rules change
parent 467c4eb5
......@@ -9,12 +9,16 @@
#include "AirMapAdvisoryManager.h"
#include "AirspaceRestriction.h"
#include "AirMapRulesetsManager.h"
#include "AirMapManager.h"
#include "QGCApplication.h"
#include <cmath>
#include <QTimer>
#include <QDateTime>
#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<float>(_lastROI.center().longitude());
params.latitude = static_cast<float>(_lastROI.center().latitude());
params.types = Airspace::Type::all;
params.weather = false;
double diagonal = _lastROI.pointNW.distanceTo(_lastROI.pointSE);
params.buffer = static_cast<std::uint32_t>(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<AirMapRulesetsManager*>(qgcApp()->toolbox()->airspaceManager()->ruleSets());
QString ruleIDs;
if(pRulesMgr) {
for(int rs = 0; rs < pRulesMgr->ruleSets()->count(); rs++) {
AirMapRuleSet* ruleSet = qobject_cast<AirMapRuleSet*>(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<quint64>(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch());
quint64 end = start + 60 * 30 * 1000;
params.start = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast<qint64>(start)));
params.end = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast<qint64>(end)));
std::weak_ptr<LifetimeChecker> 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<Status::Advisory> 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<AirspaceAdvisory::AdvisoryType>(advisory.advisory.airspace.type());
pAdvisory->_color = static_cast<AirspaceAdvisoryProvider::AdvisoryColor>(advisory.color);
if(pAdvisory->_color > _airspaceColor) {
_airspaceColor = pAdvisory->_color;
}
_advisories.append(pAdvisory);
qCDebug(AirMapManagerLog) << "Adding advisory" << pAdvisory->name();
}
......
......@@ -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; }
......
......@@ -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<qint64>(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<qint64>(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<qint64>(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<qint64>(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<qint64>(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<int>(_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<float>(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<RuleSet::Id>& 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:
......@@ -465,11 +472,31 @@ AirMapFlightPlanManager::_updateRulesAndFeatures(std::vector<RuleSet::Id>& 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<quint64>(_flightStartTime.toUTC().toMSecsSinceEpoch());
start_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast<qint64>(startt)));
//-- End has to be after start
if(_flightEndTime < _flightStartTime) {
_flightEndTime = _flightStartTime.addSecs(30 * 60);
emit flightEndTimeChanged();
}
quint64 endt = static_cast<quint64>(_flightEndTime.toUTC().toMSecsSinceEpoch());
end_time = airmap::from_milliseconds_since_epoch(airmap::milliseconds(static_cast<qint64>(endt)));
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::_uploadFlightPlan()
{
qCDebug(AirMapManagerLog) << "Uploading flight plan. State:" << (int)_state;
qCDebug(AirMapManagerLog) << "Uploading flight plan. State:" << static_cast<int>(_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<float>(_flight.takeoffCoord.latitude());
params.longitude = static_cast<float>(_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<int>(_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<float>(_flight.takeoffCoord.latitude());
_flightPlan.takeoff.longitude = static_cast<float>(_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<LifetimeChecker> isAlive(_instance);
_shared.doRequestWithLogin([this, isAlive](const QString& login_token) {
......@@ -647,13 +675,13 @@ AirMapFlightPlanManager::_pollBriefing()
_valid = false;
_advisories.clearAndDeleteContents();
const std::vector<Status::Advisory> advisories = briefing.airspace.advisories;
_airspaceColor = (AirspaceAdvisoryProvider::AdvisoryColor)(int)briefing.airspace.color;
_airspaceColor = static_cast<AirspaceAdvisoryProvider::AdvisoryColor>(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<AirspaceAdvisory::AdvisoryType>(advisory.airspace.type());
pAdvisory->_color = static_cast<AirspaceAdvisoryProvider::AdvisoryColor>(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) {
......
......@@ -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<double>(_flight.latitude), static_cast<double>(_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<airmap::RuleSet::Id>& rulesets, std::unordered_map<std::string, airmap::RuleSet::Feature::Value>& features, bool updateFeatures = false);
private:
......@@ -164,6 +167,10 @@ private:
QDateTime _rangeStart;
QDateTime _rangeEnd;
airmap::FlightPlan _flightPlan;
QDateTime _flightStartTime;
QDateTime _flightEndTime;
QList<AirMapRuleFeature*> _importantFeatures;
AirspaceAdvisoryProvider::AdvisoryColor _airspaceColor;
AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone;
......
......@@ -43,9 +43,9 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox)
{
_logger = std::make_shared<qt::Logger>();
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<qt::DispatchingLogger>(_logger);
connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error);
connect(&_shared, &AirMapSharedState::authStatus, this, &AirMapManager::_authStatusChanged);
......
......@@ -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();
}
}
}
......
......@@ -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<double>(globalPosition.lat / 1e7),
static_cast<double>(globalPosition.lon / 1e7),
static_cast<double>(globalPosition.alt) / 1000.0,
static_cast<double>(globalPosition.relative_alt) / 1000.0,
static_cast<double>(_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<int>(_state);
return;
}
if(flightID.isEmpty()) {
......
......@@ -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<LifetimeChecker> 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<Traf
QString traffic_id = QString::fromStdString(traffic.id);
QString vehicle_id = QString::fromStdString(traffic.aircraft_id);
emit trafficUpdate(type == Traffic::Update::Type::alert, traffic_id, vehicle_id,
QGeoCoordinate(traffic.latitude, traffic.longitude, traffic.altitude), traffic.heading);
QGeoCoordinate(traffic.latitude, traffic.longitude, traffic.altitude), static_cast<float>(traffic.heading));
}
}
......
......@@ -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<AirMapFlightPlanManager*>(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<AirMapFlightPlanManager*>(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<AirMapFlightPlanManager*>(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);
}
}
......@@ -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;
......
......@@ -200,6 +200,7 @@ Item {
visible: planView
width: ScreenTools.defaultFontPixelWidth * 12
onClicked: {
_dirty = false
QGroundControl.airspaceManager.flightPlan.updateFlightPlan()
}
}
......
......@@ -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;
}
}
......
......@@ -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<AirspaceAdvisoryProvider> ("QGroundControl.Airspace", 1, 0, "AirspaceAdvisoryProvider", "Reference only");
qmlRegisterUncreatableType<AirspaceFlightPlanProvider> ("QGroundControl.Airspace", 1, 0, "AirspaceFlightPlanProvider", "Reference only");
qmlRegisterUncreatableType<AirspaceManager> ("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);
}
}
......@@ -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);
......
......@@ -166,13 +166,6 @@ FlightMap {
QGCPalette { id: qgcPal; colorGroupEnabled: true }
QGCMapPalette { id: mapPal; lightColors: isSatelliteMap }
Connections {
target: QGroundControl.airspaceManager
onUpdate: {
updateAirspace(true)
}
}
Connections {
target: _missionController
......
......@@ -185,9 +185,6 @@ QGCView {
onAirspaceVisibleChanged: {
planControlColapsed = QGroundControl.airspaceManager.airspaceVisible
}
onUpdate: {
updateAirspace(true)
}
}
Component {
......
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