Commit 9359c154 authored by Gus Grubba's avatar Gus Grubba

Cleaning up old vehicle manager and getting it ready to actually provide...

Cleaning up old vehicle manager and getting it ready to actually provide services for a vehicle (flight management)
Added submit flight plan
Added update flight plan
Disable flight features as these don't seem to be quite working (values must be initialized and validated before submission as backend doesn't validate and the objects don't initialize their members)
parent 96792c7b
......@@ -97,7 +97,8 @@ AirMapAdvisoryManager::_requestAdvisories()
_advisories.endReset();
_valid = true;
} else {
qCDebug(AirMapManagerLog) << "Advisories Request Failed";
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
qCDebug(AirMapManagerLog) << "Advisories Request Failed" << QString::fromStdString(result.error().message()) << description;
}
emit advisoryChanged();
});
......
This diff is collapsed.
......@@ -18,19 +18,7 @@
#include <QList>
#include <QGeoCoordinate>
class MissionItem;
/*
* TODO: This is here for reference. It will have to modifed quite a bit before it
* can be used. This was the original file that combined both the creation of a
* flight plan and immediate submission of a flight. The flight plan is now handled
* by its own class. This now needs to be made into a proper "Flight Manager".
*/
//-- TODO: This is not even WIP yet. Just a skeleton of what's to come.
//-----------------------------------------------------------------------------
/// class to upload a flight
......@@ -38,79 +26,28 @@ class AirMapFlightManager : public QObject, public LifetimeChecker
{
Q_OBJECT
public:
AirMapFlightManager(AirMapSharedState& shared);
/// Send flight path to AirMap
void createFlight(const QList<MissionItem*>& missionItems);
AirspaceFlightPlanProvider::PermitStatus flightPermitStatus() const { return _flightPermitStatus; }
const QString& flightID() const { return _currentFlightId; }
AirMapFlightManager (AirMapSharedState& shared);
public slots:
void endFlight();
void findFlight (const QGCGeoBoundingCube& bc);
void endFlight (const QString& id);
QString flightID () { return _flightID; }
signals:
void error(const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
void flightPermitStatusChanged();
private slots:
void _pollBriefing();
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
void flightIDChanged ();
private:
/**
* upload flight stored in _flight
*/
void _uploadFlight();
/**
* query the active flights and end the first one (because only a single flight can be active at a time).
*/
void _endFirstFlight();
/**
* implementation of endFlight()
*/
void _endFlight(const QString& flightID);
/**
* check if the briefing response is valid and call _submitPendingFlightPlan() if it is.
*/
void _checkForValidBriefing();
void _submitPendingFlightPlan();
enum class State {
Idle,
GetPilotID,
FlightUpload,
FlightBrief,
FlightSubmit,
FlightPolling, // poll & check for approval
FetchFlights,
FlightEnd,
EndFirstFlight, // get a list of open flights & end the first one (because there can only be 1 active at a time)
};
struct Flight {
QList<QGeoCoordinate> coords;
QGeoCoordinate takeoffCoord;
float maxAltitude = 0;
void reset() {
coords.clear();
maxAltitude = 0;
}
};
Flight _flight; ///< flight pending to be uploaded
State _state = State::Idle;
AirMapSharedState& _shared;
QString _currentFlightId; ///< Flight ID, empty if there is none
QString _pendingFlightId; ///< current flight ID, not necessarily accepted yet (once accepted, it's equal to _currentFlightId)
QString _pendingFlightPlan; ///< current flight plan, waiting to be submitted
AirspaceFlightPlanProvider::PermitStatus _flightPermitStatus = AirspaceFlightPlanProvider::PermitNone;
QString _flightID;
QString _pilotID; ///< Pilot ID in the form "auth0|abc123"
bool _noFlightCreatedYet = true;
QTimer _pollTimer; ///< timer to poll for approval check
};
......@@ -86,6 +86,13 @@ AirMapFlightPlanManager::startFlightPlanning(PlanMasterController *planControlle
}
//-- TODO: Check if there is an ongoing flight plan and do something about it (Delete it?)
/*
* if(!_flightPlan.isEmpty()) {
* do something;
* }
*/
if(!_planController) {
_planController = planController;
//-- Get notified of mission changes
......@@ -93,6 +100,52 @@ AirMapFlightPlanManager::startFlightPlanning(PlanMasterController *planControlle
}
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::submitFlightPlan()
{
if(_flightPlan.isEmpty()) {
qCWarning(AirMapManagerLog) << "Submit flight with no flight plan.";
return;
}
_state = State::FlightSubmit;
FlightPlans::Submit::Parameters params;
params.authorization = _shared.loginToken().toStdString();
params.id = _flightPlan.toStdString();
std::weak_ptr<LifetimeChecker> isAlive(_instance);
_shared.client()->flight_plans().submit(params, [this, isAlive](const FlightPlans::Submit::Result& result) {
if (!isAlive.lock()) return;
if (_state != State::FlightSubmit) return;
if (result) {
_flightId = QString::fromStdString(result.value().flight_id.get());
_state = State::FlightPolling;
_pollBriefing();
} else {
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Failed to submit Flight Plan",
QString::fromStdString(result.error().message()), description);
_state = State::Idle;
}
});
}
//-----------------------------------------------------------------------------
void
AirMapFlightPlanManager::updateFlightPlan()
{
//-- Are we enabled?
if(!qgcApp()->toolbox()->settingsManager()->airMapSettings()->enableAirMap()->rawValue().toBool()) {
return;
}
//-- Do we have a license?
if(!_shared.hasAPIKey()) {
return;
}
_flightPermitStatus = AirspaceFlightPlanProvider::PermitPending;
emit flightPermitStatusChanged();
_updateFlightPlan();
}
//-----------------------------------------------------------------------------
bool
AirMapFlightPlanManager::_collectFlightDtata()
......@@ -215,6 +268,7 @@ AirMapFlightPlanManager::_uploadFlightPlan()
if(ruleSet && ruleSet->selected()) {
params.rulesets.push_back(ruleSet->id().toStdString());
//-- Features within each rule
/*
for(int r = 0; r < ruleSet->rules()->count(); r++) {
AirMapRule* rule = qobject_cast<AirMapRule*>(ruleSet->rules()->get(r));
if(rule) {
......@@ -238,6 +292,7 @@ AirMapFlightPlanManager::_uploadFlightPlan()
}
}
}
*/
}
}
}
......@@ -258,12 +313,12 @@ AirMapFlightPlanManager::_uploadFlightPlan()
if (result) {
_flightPlan = QString::fromStdString(result.value().id);
qCDebug(AirMapManagerLog) << "Flight plan created:" << _flightPlan;
_state = State::Idle;
_state = State::FlightPlanPolling;
_pollBriefing();
} else {
_state = State::Idle;
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
emit error("Flight Plan creation failed", QString::fromStdString(result.error().message()), description);
emit error("Flight Plan update failed", QString::fromStdString(result.error().message()), description);
}
});
});
......@@ -293,12 +348,13 @@ AirMapFlightPlanManager::_updateFlightPlan()
_shared.doRequestWithLogin([this, isAlive](const QString& login_token) {
if (!isAlive.lock()) return;
if (_state != State::FlightUpdate) return;
FlightPlans::Update::Parameters params;
params.authorization = login_token.toStdString();
params.flight_plan.id = _flightPlan.toStdString();
params.flight_plan.pilot.id = _pilotID.toStdString();
params.flight_plan.altitude_agl.max = _flight.maxAltitude;
params.flight_plan.buffer = 2.f;
FlightPlans::Update::Parameters params = {};
params.authorization = login_token.toStdString();
params.flight_plan.id = _flightPlan.toStdString();
params.flight_plan.pilot.id = _pilotID.toStdString();
params.flight_plan.altitude_agl.max = _flight.maxAltitude;
params.flight_plan.altitude_agl.min = 0.0f;
params.flight_plan.buffer = 2.f;
params.flight_plan.takeoff.latitude = _flight.takeoffCoord.latitude();
params.flight_plan.takeoff.longitude = _flight.takeoffCoord.longitude();
/*
......@@ -309,8 +365,8 @@ AirMapFlightPlanManager::_updateFlightPlan()
quint64 end = _flightEndTime.toUTC().toMSecsSinceEpoch();
*/
params.flight_plan.start_time = Clock::universal_time() + Minutes{5};
params.flight_plan.end_time = Clock::universal_time() + Hours{2};
params.flight_plan.start_time = Clock::universal_time() + Minutes{5};
params.flight_plan.end_time = Clock::universal_time() + Hours{2};
//-- Rules
/*
AirMapRulesetsManager* pRulesMgr = dynamic_cast<AirMapRulesetsManager*>(qgcApp()->toolbox()->airspaceManager()->ruleSets());
......@@ -334,7 +390,7 @@ AirMapFlightPlanManager::_updateFlightPlan()
if (!isAlive.lock()) return;
if (_state != State::FlightUpdate) return;
if (result) {
_state = State::Idle;
_state = State::FlightPlanPolling;
qCDebug(AirMapManagerLog) << "Flight plan updated:" << _flightPlan;
_pollBriefing();
} else {
......@@ -370,19 +426,16 @@ rules_sort(QObject* a, QObject* b)
void
AirMapFlightPlanManager::_pollBriefing()
{
if (_state != State::Idle) {
qCWarning(AirMapManagerLog) << "AirMapFlightPlanManager::_pollBriefing: not idle" << (int)_state;
_pollTimer.start(500);
if (_state != State::FlightPlanPolling && _state != State::FlightPolling) {
return;
}
_state = State::FlightPolling;
FlightPlans::RenderBriefing::Parameters params;
params.authorization = _shared.loginToken().toStdString();
params.id = _flightPlan.toStdString();
params.id = _flightPlan.toStdString();
std::weak_ptr<LifetimeChecker> isAlive(_instance);
_shared.client()->flight_plans().render_briefing(params, [this, isAlive](const FlightPlans::RenderBriefing::Result& result) {
if (!isAlive.lock()) return;
if (_state != State::FlightPolling) return;
if (_state != State::FlightPlanPolling && _state != State::FlightPolling) return;
if (result) {
const FlightPlan::Briefing& briefing = result.value();
qCDebug(AirMapManagerLog) << "Flight polling/briefing response";
......@@ -486,11 +539,10 @@ AirMapFlightPlanManager::_pollBriefing()
}
emit flightPermitStatusChanged();
_state = State::Idle;
} else if(pending) {
//-- Wait until we send the next polling request
_state = State::Idle;
} else {
//-- Pending. Try again.
_pollTimer.setSingleShot(true);
_pollTimer.start(2000);
_pollTimer.start(1000);
}
} else {
_state = State::Idle;
......@@ -549,7 +601,7 @@ AirMapFlightPlanManager::_missionChanged()
_createFlightPlan();
} else {
//-- Plan is being modified
//_updateFlightPlan();
_updateFlightPlan();
}
}
}
......@@ -26,18 +26,19 @@ class AirMapFlightPlanManager : public AirspaceFlightPlanProvider, public Lifeti
{
Q_OBJECT
public:
AirMapFlightPlanManager (AirMapSharedState& shared, QObject *parent = nullptr);
~AirMapFlightPlanManager ();
AirMapFlightPlanManager (AirMapSharedState& shared, QObject *parent = nullptr);
~AirMapFlightPlanManager ();
PermitStatus flightPermitStatus () const override { return _flightPermitStatus; }
QString flightID () { return _flightPlan; }
QDateTime flightStartTime () const override { return _flightStartTime; }
QDateTime flightEndTime () const override { return _flightEndTime; }
bool valid () override { return _valid; }
QmlObjectListModel* advisories () override { return &_advisories; }
QmlObjectListModel* ruleSets () override { return &_rulesets; }
QGCGeoBoundingCube* missionArea () override { return &_flight.bc; }
AirspaceAdvisoryProvider::AdvisoryColor airspaceColor () override { return _airspaceColor; }
AirspaceAdvisoryProvider::AdvisoryColor
airspaceColor () override { return _airspaceColor; }
QmlObjectListModel* rulesViolation () override { return &_rulesViolation; }
QmlObjectListModel* rulesInfo () override { return &_rulesInfo; }
......@@ -45,23 +46,25 @@ public:
QmlObjectListModel* rulesFollowing () override { return &_rulesFollowing; }
QmlObjectListModel* briefFeatures () override { return &_briefFeatures; }
void startFlightPlanning (PlanMasterController* planController) override;
void setFlightStartTime (QDateTime start) override;
void setFlightEndTime (QDateTime end) override;
void updateFlightPlan () override;
void startFlightPlanning (PlanMasterController* planController) override;
void setFlightStartTime (QDateTime start) override;
void setFlightEndTime (QDateTime end) override;
void submitFlightPlan () override;
signals:
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
private slots:
void _pollBriefing ();
void _missionChanged ();
void _pollBriefing ();
void _missionChanged ();
private:
void _uploadFlightPlan ();
void _updateFlightPlan ();
void _createFlightPlan ();
void _deleteFlightPlan ();
bool _collectFlightDtata ();
void _uploadFlightPlan ();
void _updateFlightPlan ();
void _createFlightPlan ();
void _deleteFlightPlan ();
bool _collectFlightDtata ();
private:
enum class State {
......@@ -69,8 +72,10 @@ private:
GetPilotID,
FlightUpload,
FlightUpdate,
FlightPlanPolling,
FlightDelete,
FlightSubmit,
FlightPolling,
FlightDelete
};
struct Flight {
......@@ -90,6 +95,7 @@ private:
AirMapSharedState& _shared;
QTimer _pollTimer; ///< timer to poll for approval check
QString _flightPlan; ///< Current flight plan
QString _flightId; ///< Current flight ID, not necessarily accepted yet
QString _pilotID; ///< Pilot ID in the form "auth0|abc123"
PlanMasterController* _planController = nullptr;
bool _valid = false;
......
......@@ -95,7 +95,7 @@ AirMapManager::_settingsChanged()
qCDebug(AirMapManagerLog) << "Creating AirMap client";
auto credentials = Credentials{};
credentials.api_key = _shared.settings().apiKey.toStdString();
auto configuration = Client::default_staging_configuration(credentials);
auto configuration = Client::default_production_configuration(credentials);
qt::Client::create(configuration, _dispatchingLogger, this, [this, ap](const qt::Client::CreateResult& result) {
if (result) {
qCDebug(AirMapManagerLog) << "Successfully created airmap::qt::Client instance";
......@@ -114,7 +114,7 @@ AirMapManager::_settingsChanged()
AirspaceVehicleManager*
AirMapManager::instantiateVehicle(const Vehicle& vehicle)
{
AirMapVehicleManager* manager = new AirMapVehicleManager(_shared, vehicle, *_toolbox);
AirMapVehicleManager* manager = new AirMapVehicleManager(_shared, vehicle);
connect(manager, &AirMapVehicleManager::error, this, &AirMapManager::_error);
return manager;
}
......
......@@ -29,7 +29,19 @@ AirMapRuleFeature::AirMapRuleFeature(airmap::RuleSet::Feature feature, QObject*
//-- Restore persisted value (if it exists)
QSettings settings;
settings.beginGroup(kAirMapFeatureGroup);
_value = settings.value(name());
switch(_feature.type) {
case RuleSet::Feature::Type::boolean:
_value = settings.value(name(), false);
break;;
case RuleSet::Feature::Type::floating_point:
_value = settings.value(name(), 0.0f);
break;;
case RuleSet::Feature::Type::string:
_value = settings.value(name(), QString());
break;;
default:
break;
}
settings.endGroup();
}
......
......@@ -17,12 +17,15 @@
using namespace airmap;
//-----------------------------------------------------------------------------
AirMapTelemetry::AirMapTelemetry(AirMapSharedState& shared)
: _shared(shared)
: _shared(shared)
{
}
void AirMapTelemetry::vehicleMavlinkMessageReceived(const mavlink_message_t& message)
//-----------------------------------------------------------------------------
void
AirMapTelemetry::vehicleMessageReceived(const mavlink_message_t& message)
{
switch (message.msgid) {
case MAVLINK_MSG_ID_GLOBAL_POSITION_INT:
......@@ -32,23 +35,24 @@ void AirMapTelemetry::vehicleMavlinkMessageReceived(const mavlink_message_t& mes
_handleGPSRawInt(message);
break;
}
}
bool AirMapTelemetry::isTelemetryStreaming() const
//-----------------------------------------------------------------------------
bool
AirMapTelemetry::isTelemetryStreaming()
{
return _state == State::Streaming;
}
void AirMapTelemetry::_handleGPSRawInt(const mavlink_message_t& message)
//-----------------------------------------------------------------------------
void
AirMapTelemetry::_handleGPSRawInt(const mavlink_message_t& message)
{
if (!isTelemetryStreaming()) {
return;
}
mavlink_gps_raw_int_t gps_raw;
mavlink_msg_gps_raw_int_decode(&message, &gps_raw);
if (gps_raw.eph == UINT16_MAX) {
_lastHdop = 1.f;
} else {
......@@ -56,15 +60,15 @@ void AirMapTelemetry::_handleGPSRawInt(const mavlink_message_t& message)
}
}
void AirMapTelemetry::_handleGlobalPositionInt(const mavlink_message_t& message)
//-----------------------------------------------------------------------------
void
AirMapTelemetry::_handleGlobalPositionInt(const mavlink_message_t& message)
{
if (!isTelemetryStreaming()) {
return;
}
mavlink_global_position_int_t globalPosition;
mavlink_msg_global_position_int_decode(&message, &globalPosition);
Telemetry::Position position{
milliseconds_since_epoch(Clock::universal_time()),
(double) globalPosition.lat / 1e7,
......@@ -84,21 +88,19 @@ void AirMapTelemetry::_handleGlobalPositionInt(const mavlink_message_t& message)
flight.id = _flightID.toStdString();
_shared.client()->telemetry().submit_updates(flight, _key,
{Telemetry::Update{position}, Telemetry::Update{speed}});
}
void AirMapTelemetry::startTelemetryStream(const QString& flightID)
//-----------------------------------------------------------------------------
void
AirMapTelemetry::startTelemetryStream(const QString& flightID)
{
if (_state != State::Idle) {
qCWarning(AirMapManagerLog) << "Not starting telemetry: not in idle state:" << (int)_state;
return;
}
qCInfo(AirMapManagerLog) << "Starting Telemetry stream with flightID" << flightID;
_state = State::StartCommunication;
_flightID = flightID;
_state = State::StartCommunication;
_flightID = flightID;
Flights::StartFlightCommunications::Parameters params;
params.authorization = _shared.loginToken().toStdString();
params.id = _flightID.toStdString();
......@@ -106,7 +108,6 @@ void AirMapTelemetry::startTelemetryStream(const QString& flightID)
_shared.client()->flights().start_flight_communications(params, [this, isAlive](const Flights::StartFlightCommunications::Result& result) {
if (!isAlive.lock()) return;
if (_state != State::StartCommunication) return;
if (result) {
_key = result.value().key;
_state = State::Streaming;
......@@ -119,13 +120,14 @@ void AirMapTelemetry::startTelemetryStream(const QString& flightID)
});
}
void AirMapTelemetry::stopTelemetryStream()
//-----------------------------------------------------------------------------
void
AirMapTelemetry::stopTelemetryStream()
{
if (_state == State::Idle) {
return;
}
qCInfo(AirMapManagerLog) << "Stopping Telemetry stream with flightID" << _flightID;
_state = State::EndCommunication;
Flights::EndFlightCommunications::Parameters params;
params.authorization = _shared.loginToken().toStdString();
......@@ -135,7 +137,6 @@ void AirMapTelemetry::stopTelemetryStream()
Q_UNUSED(result);
if (!isAlive.lock()) return;
if (_state != State::EndCommunication) return;
_key = "";
_state = State::Idle;
});
......
......@@ -16,33 +16,28 @@
#include <QObject>
/// class to send telemetry data to AirMap
/// Class to send telemetry data to AirMap
class AirMapTelemetry : public QObject, public LifetimeChecker
{
Q_OBJECT
public:
AirMapTelemetry(AirMapSharedState& shared);
virtual ~AirMapTelemetry() = default;
AirMapTelemetry (AirMapSharedState& shared);
virtual ~AirMapTelemetry () = default;
/**
* Setup the connection to start sending telemetry
*/
void startTelemetryStream(const QString& flightID);
void stopTelemetryStream();
bool isTelemetryStreaming() const;
void startTelemetryStream (const QString& flightID);
void stopTelemetryStream ();
bool isTelemetryStreaming ();
signals:
void error(const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
public slots:
void vehicleMavlinkMessageReceived(const mavlink_message_t& message);
void vehicleMessageReceived (const mavlink_message_t& message);
private:
void _handleGlobalPositionInt(const mavlink_message_t& message);
void _handleGPSRawInt(const mavlink_message_t& message);
void _handleGlobalPositionInt (const mavlink_message_t& message);
void _handleGPSRawInt (const mavlink_message_t& message);
enum class State {
Idle,
......@@ -52,11 +47,9 @@ private:
};
State _state = State::Idle;
AirMapSharedState& _shared;
std::string _key; ///< key for AES encryption (16 bytes)
std::string _key; ///< key for AES encryption (16 bytes)
QString _flightID;
float _lastHdop = 1.f;
};
......@@ -12,11 +12,19 @@
using namespace airmap;
//-----------------------------------------------------------------------------
AirMapTrafficMonitor::AirMapTrafficMonitor(AirMapSharedState& shared)
: _shared(shared)
{
}
//-----------------------------------------------------------------------------
AirMapTrafficMonitor::~AirMapTrafficMonitor()
{
stop();
}
//-----------------------------------------------------------------------------
void
AirMapTrafficMonitor::startConnection(const QString& flightID)
{
......@@ -39,6 +47,7 @@ AirMapTrafficMonitor::startConnection(const QString& flightID)
_shared.client()->traffic().monitor(params, handler);
}
//-----------------------------------------------------------------------------
void
AirMapTrafficMonitor::_update(Traffic::Update::Type type, const std::vector<Traffic::Update>& update)
{
......@@ -53,6 +62,7 @@ AirMapTrafficMonitor::_update(Traffic::Update::Type type, const std::vector<Traf
}
}
//-----------------------------------------------------------------------------
void
AirMapTrafficMonitor::stop()
{
......
......@@ -28,22 +28,19 @@ class AirMapTrafficMonitor : public QObject, public LifetimeChecker
{
Q_OBJECT
public:
AirMapTrafficMonitor(AirMapSharedState& shared)
: _shared(shared)
{
}
virtual ~AirMapTrafficMonitor();
AirMapTrafficMonitor (AirMapSharedState& shared);
virtual ~AirMapTrafficMonitor ();
void startConnection(const QString& flightID);
void startConnection (const QString& flightID);
void stop();
signals:
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
void trafficUpdate (bool alert, QString traffic_id, QString vehicle_id, QGeoCoordinate location, float heading);
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
void trafficUpdate (bool alert, QString traffic_id, QString vehicle_id, QGeoCoordinate location, float heading);
private:
void _update (airmap::Traffic::Update::Type type, const std::vector<airmap::Traffic::Update>& update);
void _update (airmap::Traffic::Update::Type type, const std::vector<airmap::Traffic::Update>& update);
private:
QString _flightID;
......
......@@ -12,81 +12,58 @@
#include "Vehicle.h"
AirMapVehicleManager::AirMapVehicleManager(AirMapSharedState& shared, const Vehicle& vehicle, QGCToolbox& toolbox)
//-----------------------------------------------------------------------------
AirMapVehicleManager::AirMapVehicleManager(AirMapSharedState& shared, const Vehicle& vehicle)
: AirspaceVehicleManager(vehicle)
, _shared(shared)
, _flightManager(shared)
, _telemetry(shared)
, _trafficMonitor(shared)
, _toolbox(toolbox)
{
connect(&_flightManager, &AirMapFlightManager::flightPermitStatusChanged, this, &AirMapVehicleManager::flightPermitStatusChanged);
connect(&_flightManager, &AirMapFlightManager::flightPermitStatusChanged, this, &AirMapVehicleManager::_flightPermitStatusChanged);
connect(&_flightManager, &AirMapFlightManager::error, this, &AirMapVehicleManager::error);
connect(&_telemetry, &AirMapTelemetry::error, this, &AirMapVehicleManager::error);
connect(&_trafficMonitor, &AirMapTrafficMonitor::error, this, &AirMapVehicleManager::error);
connect(&_trafficMonitor, &AirMapTrafficMonitor::trafficUpdate, this, &AirspaceVehicleManager::trafficUpdate);
}
void
AirMapVehicleManager::createFlight(const QList<MissionItem*>& missionItems)
{
if (!_shared.client()) {
qCDebug(AirMapManagerLog) << "No AirMap client instance. Will not create a flight";
return;
}
//_flightManager.createFlight(missionItems);
}
AirspaceFlightPlanProvider::PermitStatus
AirMapVehicleManager::flightPermitStatus() const
{
return _flightManager.flightPermitStatus();
}
//-----------------------------------------------------------------------------
void
AirMapVehicleManager::startTelemetryStream()
{
if (_flightManager.flightID() != "") {
if (!_flightManager.flightID().isEmpty()) {
_telemetry.startTelemetryStream(_flightManager.flightID());
}
}
//-----------------------------------------------------------------------------
void
AirMapVehicleManager::stopTelemetryStream()
{
_telemetry.stopTelemetryStream();
}
//-----------------------------------------------------------------------------
bool
AirMapVehicleManager::isTelemetryStreaming() const
AirMapVehicleManager::isTelemetryStreaming()
{
return _telemetry.isTelemetryStreaming();
}
//-----------------------------------------------------------------------------
void
AirMapVehicleManager::endFlight()
{
_flightManager.endFlight();
if (!_flightManager.flightID().isEmpty()) {
_flightManager.endFlight(_flightManager.flightID());
}
_trafficMonitor.stop();
}
//-----------------------------------------------------------------------------
void
AirMapVehicleManager::vehicleMavlinkMessageReceived(const mavlink_message_t& message)
{
if (isTelemetryStreaming()) {
_telemetry.vehicleMavlinkMessageReceived(message);
_telemetry.vehicleMessageReceived(message);
}
}
void
AirMapVehicleManager::_flightPermitStatusChanged()
{
// activate traffic alerts
if (_flightManager.flightPermitStatus() == AirspaceFlightPlanProvider::PermitAccepted) {
qCDebug(AirMapManagerLog) << "Subscribing to Traffic Alerts";
// since we already created the flight, we know that we have a valid login token
_trafficMonitor.startConnection(_flightManager.flightID());
}
}
......@@ -16,24 +16,18 @@
#include "AirMapTelemetry.h"
#include "AirMapTrafficMonitor.h"
#include "QGCToolbox.h"
/// AirMap per vehicle management class.
class AirMapVehicleManager : public AirspaceVehicleManager
{
Q_OBJECT
public:
AirMapVehicleManager (AirMapSharedState& shared, const Vehicle& vehicle, QGCToolbox& toolbox);
AirMapVehicleManager (AirMapSharedState& shared, const Vehicle& vehicle);
~AirMapVehicleManager () = default;
void createFlight (const QList<MissionItem*>& missionItems) override;
void startTelemetryStream () override;
void stopTelemetryStream () override;
bool isTelemetryStreaming () const override;
AirspaceFlightPlanProvider::PermitStatus flightPermitStatus() const override;
bool isTelemetryStreaming () override;
signals:
void error (const QString& what, const QString& airmapdMessage, const QString& airmapdDetails);
......@@ -44,13 +38,9 @@ public slots:
protected slots:
virtual void vehicleMavlinkMessageReceived(const mavlink_message_t& message) override;
private slots:
void _flightPermitStatusChanged();
private:
AirMapSharedState& _shared;
AirMapFlightManager _flightManager;
AirMapTelemetry _telemetry;
AirMapTrafficMonitor _trafficMonitor;
QGCToolbox& _toolbox;
};
......@@ -65,7 +65,8 @@ AirMapWeatherInfoManager::_requestWeatherUpdate(const QGeoCoordinate& coordinate
qCDebug(AirMapManagerLog) << "Weather Info: " << _valid << "Icon:" << QString::fromStdString(_weather.icon) << "Condition:" << QString::fromStdString(_weather.condition) << "Temp:" << _weather.temperature;
} else {
_valid = false;
qCDebug(AirMapManagerLog) << "Request Weather Failed";
QString description = QString::fromStdString(result.error().description() ? result.error().description().get() : "");
qCDebug(AirMapManagerLog) << "Request Weather Failed" << QString::fromStdString(result.error().message()) << description;
}
emit weatherChanged();
});
......
......@@ -331,7 +331,7 @@ Item {
}
Flickable {
clip: true
height: ScreenTools.defaultFontPixelHeight * 6
height: ScreenTools.defaultFontPixelHeight * 8
contentHeight: advisoryCol.height
flickableDirection: Flickable.VerticalFlick
anchors.left: parent.left
......@@ -366,6 +366,7 @@ Item {
heightFactor: 0.3333
showBorder: true
width: ScreenTools.defaultFontPixelWidth * 16
visible: _flightPermit !== AirspaceFlightPlanProvider.PermitNone
anchors.horizontalCenter: parent.horizontalCenter
onClicked: {
rootLoader.sourceComponent = planView ? flightDetails : flightBrief
......
......@@ -62,24 +62,27 @@ Item {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
QGCLabel {
text: qsTr("Federal Aviation Administration")
text: qsTr("No Authorization Required")
visible: _flightPermit !== AirspaceFlightPlanProvider.PermitNone
anchors.horizontalCenter: parent.horizontalCenter
}
/*
QGCLabel {
text: qsTr("Automatic authorization to fly in controlled airspace")
visible: _flightPermit !== AirspaceFlightPlanProvider.PermitNone
font.pointSize: ScreenTools.smallFontPointSize
}
*/
Rectangle {
anchors.right: parent.right
anchors.left: parent.left
height: label.height + (ScreenTools.defaultFontPixelHeight * 0.5)
color: {
if(_flightPermit == AirspaceFlightPlanProvider.PermitPending)
if(_flightPermit === AirspaceFlightPlanProvider.PermitPending)
return _colorOrange
if(_flightPermit == AirspaceFlightPlanProvider.PermitAccepted)
if(_flightPermit === AirspaceFlightPlanProvider.PermitAccepted)
return _colorGreen
if(_flightPermit == AirspaceFlightPlanProvider.PermitRejected)
if(_flightPermit === AirspaceFlightPlanProvider.PermitRejected)
return _colorRed
return _colorGray
}
......@@ -164,9 +167,7 @@ Item {
visible: planView
width: ScreenTools.defaultFontPixelWidth * 12
onClicked: {
//-- TODO: Update Plan
mainWindow.enableToolbar()
rootLoader.sourceComponent = null
QGroundControl.airspaceManager.flightPlan.updateFlightPlan()
}
}
QGCButton {
......@@ -174,7 +175,7 @@ Item {
backRadius: 4
heightFactor: 0.3333
showBorder: true
enabled: _flightPermit !== AirspaceFlightPlanProvider.PermitNone
enabled: _flightPermit === AirspaceFlightPlanProvider.PermitAccepted
width: ScreenTools.defaultFontPixelWidth * 12
visible: planView
onClicked: {
......
......@@ -55,6 +55,8 @@ public:
Q_PROPERTY(QmlObjectListModel* rulesFollowing READ rulesFollowing NOTIFY rulesChanged)
Q_PROPERTY(QmlObjectListModel* briefFeatures READ briefFeatures NOTIFY rulesChanged)
Q_INVOKABLE virtual void updateFlightPlan () = 0;
virtual PermitStatus flightPermitStatus () const { return PermitNone; }
virtual QDateTime flightStartTime () const = 0;
virtual QDateTime flightEndTime () const = 0;
......@@ -73,6 +75,8 @@ public:
virtual void setFlightStartTime (QDateTime start) = 0;
virtual void setFlightEndTime (QDateTime end) = 0;
virtual void startFlightPlanning (PlanMasterController* planController) = 0;
//-- TODO: This will submit the current flight plan in memory.
virtual void submitFlightPlan () = 0;
signals:
void flightPermitStatusChanged ();
......
......@@ -9,6 +9,7 @@
#include "AirspaceManager.h"
#include "AirspaceVehicleManager.h"
#include "Vehicle.h"
#include "MissionItem.h"
......
......@@ -16,7 +16,6 @@
#include <QList>
#include <QGeoCoordinate>
class MissionItem;
class Vehicle;
//-----------------------------------------------------------------------------
......@@ -31,23 +30,12 @@ public:
AirspaceVehicleManager (const Vehicle& vehicle);
virtual ~AirspaceVehicleManager () = default;
/**
* create/upload a flight from a mission. This should update the flight permit status.
* There can only be one active flight for each vehicle.
*/
virtual void createFlight (const QList<MissionItem*>& missionItems) = 0;
/**
* get the current flight permit status
*/
virtual AirspaceFlightPlanProvider::PermitStatus flightPermitStatus() const = 0;
/**
* Setup the connection and start sending telemetry
*/
virtual void startTelemetryStream () = 0;
virtual void stopTelemetryStream () = 0;
virtual bool isTelemetryStreaming () const = 0;
virtual bool isTelemetryStreaming () = 0;
public slots:
virtual void endFlight () = 0;
......
......@@ -15,6 +15,9 @@
#include "JsonHelper.h"
#include "MissionManager.h"
#include "KML.h"
#if defined(QGC_AIRMAP_ENABLED)
#include "AirspaceFlightPlanProvider.h"
#endif
#include <QDomDocument>
#include <QJsonDocument>
......
......@@ -60,6 +60,18 @@ QGCGeoBoundingCube::polygon2D() const
return coords;
}
//-----------------------------------------------------------------------------
bool
QGCGeoBoundingCube::operator ==(const QList<QGeoCoordinate>& coords) const
{
QList<QGeoCoordinate> c = polygon2D();
if(c.size() != coords.size()) return false;
for(int i = 0; i < c.size(); i++) {
if(c[i] != coords[i]) return false;
}
return true;
}
//-----------------------------------------------------------------------------
double
QGCGeoBoundingCube::width() const
......
......@@ -48,6 +48,8 @@ public:
return pointNW == other.pointNW && pointSE == other.pointSE;
}
bool operator ==(const QList<QGeoCoordinate>& coords) const;
inline bool operator !=(const QGCGeoBoundingCube& other)
{
return !(*this == other);
......
......@@ -38,6 +38,10 @@
#include "QGCCameraManager.h"
#include "VideoReceiver.h"
#include "VideoManager.h"
#if defined(QGC_AIRMAP_ENABLED)
#include "AirspaceVehicleManager.h"
#endif
QGC_LOGGING_CATEGORY(VehicleLog, "VehicleLog")
#define UPDATE_TIMER 50
......
......@@ -20,10 +20,6 @@
#include "MAVLinkProtocol.h"
#include "UASMessageHandler.h"
#include "SettingsFact.h"
#if defined(QGC_AIRMAP_ENABLED)
#include "AirspaceManager.h"
#include "AirspaceVehicleManager.h"
#endif
class UAS;
class UASInterface;
......@@ -39,6 +35,9 @@ class UASMessage;
class SettingsManager;
class ADSBVehicle;
class QGCCameraManager;
#if defined(QGC_AIRMAP_ENABLED)
class AirspaceVehicleManager;
#endif
Q_DECLARE_LOGGING_CATEGORY(VehicleLog)
......@@ -758,10 +757,6 @@ public:
/// Vehicle is about to be deleted
void prepareDelete();
#if defined(QGC_AIRMAP_ENABLED)
AirspaceVehicleManager* airspaceManager() const { return _airspaceVehicleManager; }
#endif
signals:
void allLinksInactive(Vehicle* vehicle);
void coordinateChanged(QGeoCoordinate coordinate);
......
......@@ -134,8 +134,8 @@ MainWindow::MainWindow()
_ui.setupUi(this);
// Make sure tool bar elements all fit before changing minimum width
setMinimumWidth(1008);
setMinimumHeight(520);
setMinimumWidth(1024);
setMinimumHeight(620);
configureWindowName();
// Setup central widget with a layout to hold the views
......
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