diff --git a/src/Airmap/AirMapFlightPlanManager.cc b/src/Airmap/AirMapFlightPlanManager.cc index 4a304c70ae004d5d773e9327f96784db695cb8ee..175d3454523bfc7d7013a5f7a0fc923ee289923e 100644 --- a/src/Airmap/AirMapFlightPlanManager.cc +++ b/src/Airmap/AirMapFlightPlanManager.cc @@ -254,7 +254,7 @@ AirMapFlightPlanManager::updateFlightPlan() } _flightPermitStatus = AirspaceFlightPlanProvider::PermitPending; emit flightPermitStatusChanged(); - _updateFlightPlan(); + _updateFlightPlan(true); } //----------------------------------------------------------------------------- @@ -373,9 +373,6 @@ AirMapFlightPlanManager::_createFlightPlan() qCDebug(AirMapManagerLog) << "Flight Start:" << flightStartTime().toString(); qCDebug(AirMapManagerLog) << "Flight End: " << flightEndTime().toString(); - //-- Not Yet - //return; - if (_pilotID == "") { //-- Need to get the pilot id before uploading the flight plan qCDebug(AirMapManagerLog) << "Getting pilot ID"; @@ -413,7 +410,7 @@ AirMapFlightPlanManager::_createFlightPlan() //----------------------------------------------------------------------------- void -AirMapFlightPlanManager::_updateRulesAndFeatures(std::vector& rulesets, std::unordered_map& features) +AirMapFlightPlanManager::_updateRulesAndFeatures(std::vector& rulesets, std::unordered_map& features, bool updateFeatures) { AirMapRulesetsManager* pRulesMgr = dynamic_cast(qgcApp()->toolbox()->airspaceManager()->ruleSets()); if(pRulesMgr) { @@ -422,34 +419,42 @@ AirMapFlightPlanManager::_updateRulesAndFeatures(std::vector& rules //-- If this ruleset is selected if(ruleSet && ruleSet->selected()) { rulesets.push_back(ruleSet->id().toStdString()); - //-- Features within each rule - for(int r = 0; r < ruleSet->rules()->count(); r++) { - AirMapRule* rule = qobject_cast(ruleSet->rules()->get(r)); - if(rule) { - for(int f = 0; f < rule->features()->count(); f++) { - AirMapRuleFeature* feature = qobject_cast(rule->features()->get(f)); - if(feature && feature->value().isValid()) { - switch(feature->type()) { - case AirspaceRuleFeature::Boolean: - //-- Skip not set responses (feature->value is initialized to "2") - if(feature->value().toInt() == 0 || feature->value().toInt() == 1) { - features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toBool()); - } - break; - case AirspaceRuleFeature::Float: - //-- Sanity check for floats - if(std::isfinite(feature->value().toFloat())) { - features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toFloat()); - } - break; - case AirspaceRuleFeature::String: - //-- Skip empty responses - if(!feature->value().toString().isEmpty()) { - features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toString().toStdString()); + //-- Features within each rule (only when updating) + if(updateFeatures) { + for(int r = 0; r < ruleSet->rules()->count(); r++) { + AirMapRule* rule = qobject_cast(ruleSet->rules()->get(r)); + if(rule) { + for(int f = 0; f < rule->features()->count(); f++) { + AirMapRuleFeature* feature = qobject_cast(rule->features()->get(f)); + if(features.find(feature->name().toStdString()) != features.end()) { + qCDebug(AirMapManagerLog) << "Removing duplicate:" << feature->name(); + continue; + } + if(feature && feature->value().isValid()) { + switch(feature->type()) { + case AirspaceRuleFeature::Boolean: + if(feature->value().toInt() == 0 || feature->value().toInt() == 1) { + features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toBool()); + } else { + //-- If not set, default to false + features[feature->name().toStdString()] = RuleSet::Feature::Value(false); + } + break; + case AirspaceRuleFeature::Float: + //-- Sanity check for floats + if(std::isfinite(feature->value().toFloat())) { + features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toFloat()); + } + break; + case AirspaceRuleFeature::String: + //-- Skip empty responses + if(!feature->value().toString().isEmpty()) { + features[feature->name().toStdString()] = RuleSet::Feature::Value(feature->value().toString().toStdString()); + } + break; + default: + qCWarning(AirMapManagerLog) << "Unknown type for feature" << feature->name(); } - break; - default: - qCWarning(AirMapManagerLog) << "Unknown type for feature" << feature->name(); } } } @@ -516,15 +521,19 @@ AirMapFlightPlanManager::_uploadFlightPlan() //----------------------------------------------------------------------------- void -AirMapFlightPlanManager::_updateFlightPlan() +AirMapFlightPlanManager::_updateFlightPlanOnTimer() { - //-- TODO: This is broken as the parameters for updating the plan have - // little to do with those used when creating it. + _updateFlightPlan(false); +} +//----------------------------------------------------------------------------- +void +AirMapFlightPlanManager::_updateFlightPlan(bool interactive) +{ qCDebug(AirMapManagerLog) << "Updating flight plan. State:" << (int)_state; if(_state != State::Idle) { - QTimer::singleShot(100, this, &AirMapFlightPlanManager::_updateFlightPlan); + QTimer::singleShot(100, this, &AirMapFlightPlanManager::_updateFlightPlanOnTimer); return; } //-- Get flight data @@ -546,7 +555,8 @@ AirMapFlightPlanManager::_updateFlightPlan() //-- Rules & Features _flightPlan.rulesets.clear(); _flightPlan.features.clear(); - _updateRulesAndFeatures(_flightPlan.rulesets, _flightPlan.features); + //-- If interactive, we collect features otherwise we don't + _updateRulesAndFeatures(_flightPlan.rulesets, _flightPlan.features, interactive); //-- Geometry: polygon Geometry::Polygon polygon; for (const auto& qcoord : _flight.coords) { @@ -600,6 +610,19 @@ rules_sort(QObject* a, QObject* b) return (int)aa->status() > (int)bb->status(); } +//----------------------------------------------------------------------------- +bool +AirMapFlightPlanManager::_findBriefFeature(const QString& name) +{ + for(int i = 0; i < _briefFeatures.count(); i++ ) { + AirMapRuleFeature* feature = qobject_cast(_briefFeatures.get(i)); + if (feature && feature->name() == name) { + return true; + } + } + return false; +} + //----------------------------------------------------------------------------- void AirMapFlightPlanManager::_pollBriefing() @@ -657,8 +680,12 @@ AirMapFlightPlanManager::_pollBriefing() AirMapRuleFeature* pFeature = new AirMapRuleFeature(feature, this); pRule->_features.append(pFeature); if(rule.status == RuleSet::Rule::Status::missing_info) { - _briefFeatures.append(pFeature); - qCDebug(AirMapManagerLog) << "Adding briefing feature" << pFeature->name() << pFeature->description() << pFeature->type(); + if(!_findBriefFeature(pFeature->name())) { + _briefFeatures.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(); + } } } pRuleSet->_rules.append(pRule); diff --git a/src/Airmap/AirMapFlightPlanManager.h b/src/Airmap/AirMapFlightPlanManager.h index 37a6a669455b215aad653425d94608d474a994dc..589f1060537b6eb8119b6cee828ac484d82fcfb3 100644 --- a/src/Airmap/AirMapFlightPlanManager.h +++ b/src/Airmap/AirMapFlightPlanManager.h @@ -90,6 +90,7 @@ public: AirspaceFlightModel*flightList () override { return &_flightList; } bool loadingFlightList () override { return _loadingFlightList; } QString flightPlanID () {return QString::fromStdString(_flightPlan.id); } + QString flightID () {return _flightId; } void updateFlightPlan () override; void submitFlightPlan () override; @@ -107,13 +108,15 @@ private slots: void _missionChanged (); void _endFlight (); void _uploadFlightPlan (); - void _updateFlightPlan (); + void _updateFlightPlanOnTimer (); void _loadFlightList (); private: void _createFlightPlan (); bool _collectFlightDtata (); - void _updateRulesAndFeatures (std::vector& rulesets, std::unordered_map& features); + void _updateFlightPlan (bool interactive = false); + bool _findBriefFeature (const QString& name); + void _updateRulesAndFeatures (std::vector& rulesets, std::unordered_map& features, bool updateFeatures = false); private: enum class State { diff --git a/src/Airmap/AirMapManager.cc b/src/Airmap/AirMapManager.cc index dd1beb75a131589496deade9e8ee07ba0c990df8..9d5868ed6a82e100099e4e64f88cd14a36e3cf2d 100644 --- a/src/Airmap/AirMapManager.cc +++ b/src/Airmap/AirMapManager.cc @@ -42,8 +42,8 @@ AirMapManager::AirMapManager(QGCApplication* app, QGCToolbox* toolbox) { _logger = std::make_shared(); qt::register_types(); // TODO: still needed? - _logger->logging_category().setEnabled(QtDebugMsg, true); - _logger->logging_category().setEnabled(QtInfoMsg, true); + _logger->logging_category().setEnabled(QtDebugMsg, false); + _logger->logging_category().setEnabled(QtInfoMsg, false); _logger->logging_category().setEnabled(QtWarningMsg, false); _dispatchingLogger = std::make_shared(_logger); connect(&_shared, &AirMapSharedState::error, this, &AirMapManager::_error); diff --git a/src/Airmap/AirMapRulesetsManager.cc b/src/Airmap/AirMapRulesetsManager.cc index f0f04e5617377379121eb95f8578c899298ccfc3..52c9fa9b82fe6aaf6ba7cee44ae669339ee5eb97 100644 --- a/src/Airmap/AirMapRulesetsManager.cc +++ b/src/Airmap/AirMapRulesetsManager.cc @@ -31,6 +31,7 @@ AirMapRuleFeature::AirMapRuleFeature(airmap::RuleSet::Feature feature, QObject* settings.beginGroup(kAirMapFeatureGroup); switch(_feature.type) { case RuleSet::Feature::Type::boolean: + //-- For boolean, we have 3 states: 0 - false, 1 - true and 2 - not set _value = settings.value(name(), 2); break;; case RuleSet::Feature::Type::floating_point: @@ -45,6 +46,14 @@ AirMapRuleFeature::AirMapRuleFeature(airmap::RuleSet::Feature feature, QObject* settings.endGroup(); } +//----------------------------------------------------------------------------- +QVariant +AirMapRuleFeature::value() +{ + //qCDebug(AirMapManagerLog) << "Value of" << name() << "==>" << _value << type(); + return _value; +} + //----------------------------------------------------------------------------- AirspaceRuleFeature::Type AirMapRuleFeature::type() @@ -100,6 +109,25 @@ AirMapRuleFeature::measurement() void AirMapRuleFeature::setValue(const QVariant val) { + switch(_feature.type) { + case RuleSet::Feature::Type::boolean: + if(val.toInt() != 0 && val.toInt() != 1) { + return; + } + break; + case RuleSet::Feature::Type::floating_point: + if(!std::isfinite(val.toDouble())) { + return; + } + break;; + case RuleSet::Feature::Type::string: + if(val.toString().isEmpty()) { + return; + } + break;; + default: + return; + } _value = val; //-- Make value persistent QSettings settings; diff --git a/src/Airmap/AirMapRulesetsManager.h b/src/Airmap/AirMapRulesetsManager.h index 4d5ec47996ef6806d97e7a3c4e3da0b89c396d3b..a0ded075bb396b059fe9b4fb179d22b10302fd5f 100644 --- a/src/Airmap/AirMapRulesetsManager.h +++ b/src/Airmap/AirMapRulesetsManager.h @@ -39,7 +39,7 @@ public: Measurement measurement () override; QString name () override { return QString::fromStdString(_feature.name); } QString description () override { return QString::fromStdString(_feature.description); } - QVariant value () override { return _value; } + QVariant value () override; void setValue (const QVariant val) override; private: airmap::RuleSet::Feature _feature; diff --git a/src/Airmap/AirMapTelemetry.cc b/src/Airmap/AirMapTelemetry.cc index a43a7d3af3e52095fd6e79de3d88434ba23d3518..8550d323b61f9e7e78592453e8030bd54ca189b6 100644 --- a/src/Airmap/AirMapTelemetry.cc +++ b/src/Airmap/AirMapTelemetry.cc @@ -84,6 +84,7 @@ AirMapTelemetry::_handleGlobalPositionInt(const mavlink_message_t& message) globalPosition.vz / 100.f }; + //qCDebug(AirMapManagerLog) << "Telemetry:" << globalPosition.lat / 1e7 << globalPosition.lon / 1e7; Flight flight; flight.id = _flightID.toStdString(); _shared.client()->telemetry().submit_updates(flight, _key, diff --git a/src/Airmap/AirMapVehicleManager.cc b/src/Airmap/AirMapVehicleManager.cc index 4fa62af14f6b133166fcca7721161c04ba7831be..feb4a59ff832e15554b1fc4ccdc3d04b3704f1db 100644 --- a/src/Airmap/AirMapVehicleManager.cc +++ b/src/Airmap/AirMapVehicleManager.cc @@ -7,9 +7,12 @@ * ****************************************************************************/ +#include "AirspaceFlightPlanProvider.h" +#include "AirMapFlightPlanManager.h" #include "AirMapVehicleManager.h" #include "AirMapManager.h" +#include "QGCApplication.h" #include "Vehicle.h" //----------------------------------------------------------------------------- @@ -30,9 +33,13 @@ AirMapVehicleManager::AirMapVehicleManager(AirMapSharedState& shared, const Vehi void AirMapVehicleManager::startTelemetryStream() { - if (!_flightManager.flightID().isEmpty()) { - //-- TODO: This will start telemetry using the current flight ID in memory - _telemetry.startTelemetryStream(_flightManager.flightID()); + AirMapFlightPlanManager* planMgr = (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()); + } else { + qCDebug(AirMapManagerLog) << "AirMap telemetry stream not possible (No Flight ID)"; } } @@ -54,8 +61,9 @@ AirMapVehicleManager::isTelemetryStreaming() void AirMapVehicleManager::endFlight() { - if (!_flightManager.flightID().isEmpty()) { - _flightManager.endFlight(_flightManager.flightID()); + AirMapFlightPlanManager* planMgr = (AirMapFlightPlanManager*)qgcApp()->toolbox()->airspaceManager()->flightPlan(); + if (!planMgr->flightID().isEmpty()) { + _flightManager.endFlight(planMgr->flightID()); } _trafficMonitor.stop(); } diff --git a/src/Airmap/AirmapSettings.qml b/src/Airmap/AirmapSettings.qml index 7efe9a4268f457b142b865e453774b670f958f60..0a9e5df5660b5c0b5fd330b968a110cfb7938e90 100644 --- a/src/Airmap/AirmapSettings.qml +++ b/src/Airmap/AirmapSettings.qml @@ -312,11 +312,11 @@ QGCView { anchors.fill: parent TableView { id: tableView - anchors.top: parent.top - anchors.bottom: parent.bottom model: _flightList selectionMode: SelectionMode.SingleSelection + Layout.alignment: Qt.AlignVCenter Layout.fillWidth: true + Layout.fillHeight: true onCurrentRowChanged: { var o = _flightList.get(tableView.currentRow) if(o) { diff --git a/src/Airmap/FlightFeature.qml b/src/Airmap/FlightFeature.qml index 054b783c289508cabaa461de346976ea86d6c135..59efe91525dbb3f0a44db356c49f0b7bde772dbc 100644 --- a/src/Airmap/FlightFeature.qml +++ b/src/Airmap/FlightFeature.qml @@ -56,10 +56,12 @@ Rectangle { QGCCheckBox { id: checkBox text: "" - checked: feature.value && feature.value < 2 ? feature.value : false onClicked: feature.value = checked anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter + Component.onCompleted: { + checked = feature.value && feature.value < 2 ? feature.value : false + } } QGCLabel { id: label diff --git a/src/AirspaceManagement/AirspaceVehicleManager.cc b/src/AirspaceManagement/AirspaceVehicleManager.cc index 2e92c7cf830d91ef23888ece1b735f4f38b192bf..38c5723108cc1918e02b12d06fbff9f042ddf209 100644 --- a/src/AirspaceManagement/AirspaceVehicleManager.cc +++ b/src/AirspaceManagement/AirspaceVehicleManager.cc @@ -16,6 +16,7 @@ AirspaceVehicleManager::AirspaceVehicleManager(const Vehicle& vehicle) : _vehicle(vehicle) { + qCDebug(AirspaceManagementLog) << "Instatiating AirspaceVehicleManager"; connect(&_vehicle, &Vehicle::armedChanged, this, &AirspaceVehicleManager::_vehicleArmedChanged); connect(&_vehicle, &Vehicle::mavlinkMessageReceived, this, &AirspaceVehicleManager::vehicleMavlinkMessageReceived); } @@ -23,9 +24,11 @@ AirspaceVehicleManager::AirspaceVehicleManager(const Vehicle& vehicle) void AirspaceVehicleManager::_vehicleArmedChanged(bool armed) { if (armed) { + qCDebug(AirspaceManagementLog) << "Starting telemetry"; startTelemetryStream(); _vehicleWasInMissionMode = _vehicle.flightMode() == _vehicle.missionFlightMode(); } else { + qCDebug(AirspaceManagementLog) << "Stopping telemetry"; stopTelemetryStream(); // end the flight if we were in mission mode during arming or disarming // TODO: needs to be improved. for instance if we do RTL and then want to continue the mission...