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; }
......
This diff is collapsed.
......@@ -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