From a5acd0a1ec57d44539b6aea25e35e845dbb1ffa5 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Wed, 11 Jul 2018 02:34:58 +0200 Subject: [PATCH] Ref T268, elevation handling improvements * utility functions * made storeAircraftSituation virtual and return Aviation::CAircraftSituation * coordinate toQString in deg/rad --- src/blackcore/airspacemonitor.cpp | 39 ++++++++++++------- src/blackcore/airspacemonitor.h | 2 +- src/blackcore/simulator.cpp | 2 +- src/blackmisc/aviation/aircraftsituation.cpp | 17 ++++---- src/blackmisc/aviation/aircraftsituation.h | 5 +-- .../aviation/aircraftsituationlist.cpp | 8 ++-- .../aviation/aircraftsituationlist.h | 2 +- src/blackmisc/geo/coordinategeodetic.cpp | 15 ++++--- src/blackmisc/geo/elevationplane.cpp | 12 ++---- .../simulation/remoteaircraftprovider.cpp | 10 +++-- .../simulation/remoteaircraftprovider.h | 2 +- .../simulationenvironmentprovider.cpp | 5 +++ .../simulationenvironmentprovider.h | 3 ++ 13 files changed, 71 insertions(+), 51 deletions(-) diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 033dac88f..f41413127 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -965,26 +965,29 @@ namespace BlackCore this->setOtherClient(client); } - void CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation) + CAircraftSituation CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation, bool allowTestOffset) { const CCallsign callsign(situation.getCallsign()); BLACK_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); - if (callsign.isEmpty()) { return; } + if (callsign.isEmpty()) { return situation; } - CAircraftSituation correctedSituation(this->testAddAltitudeOffsetToSituation(situation)); - if (!correctedSituation.hasGroundElevation() && !correctedSituation.canLikelySkipNearGroundInterpolation()) + CAircraftSituation correctedSituation(allowTestOffset ? this->testAddAltitudeOffsetToSituation(situation) : situation); + bool haveRequestedElevation = false; + const bool canLikelySkipNearGround = correctedSituation.canLikelySkipNearGroundInterpolation(); + if (!correctedSituation.hasGroundElevation() && !canLikelySkipNearGround) { // fetch from cache or request const CAircraftSituationList situations = this->remoteAircraftSituations(callsign); - CElevationPlane ep = situations.findCLosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius())); - if (!ep.isNull()) + const CAircraftSituation situationWithElv = situations.findCLosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius())); + if (!situationWithElv.getGroundElevation().isNull()) { - correctedSituation.setGroundElevation(ep, CAircraftSituation::FromOtherSituations); + correctedSituation.transferGroundElevation(situationWithElv); } else { const CLength distance(correctedSituation.getDistancePerTime250ms(CElevationPlane::singlePointRadius())); // distnacee per ms - ep = this->findClosestElevationWithinRangeOrRequest(correctedSituation, distance, callsign); + const CElevationPlane ep = this->findClosestElevationWithinRangeOrRequest(correctedSituation, distance, callsign); + haveRequestedElevation = ep.isNull(); // NULL means we requested Q_ASSERT_X(ep.isNull() || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius"); correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); } @@ -1032,13 +1035,23 @@ namespace BlackCore // CG from provider const CLength cg = this->getCG(callsign); // always x-check against simulator to override guessed values and reflect changed CGs - if (!cg.isNull()) - { - correctedSituation.setCG(cg); - } + if (!cg.isNull()) { correctedSituation.setCG(cg); } // store change object - CRemoteAircraftProvider::storeAircraftSituation(correctedSituation, false); // we already added offset if any + correctedSituation = CRemoteAircraftProvider::storeAircraftSituation(correctedSituation, false); // we already added offset if any + + // check if we STILL want to request + if (!haveRequestedElevation && !canLikelySkipNearGround) + { + // we have not requested so far, but we are NEAR ground + // we expect at least not transferred cache or we are moving and have no provider elevation yet + if (correctedSituation.isThisElevationInfoBetter(CAircraftSituation::FromCache, false) || (correctedSituation.isMoving() && correctedSituation.isThisElevationInfoBetter(CAircraftSituation::FromProvider, false))) + { + haveRequestedElevation = this->requestElevation(correctedSituation); + } + } + + return correctedSituation; } void CAirspaceMonitor::sendInitialAtcQueries(const CCallsign &callsign) diff --git a/src/blackcore/airspacemonitor.h b/src/blackcore/airspacemonitor.h index 556ec431e..c6dc62c84 100644 --- a/src/blackcore/airspacemonitor.h +++ b/src/blackcore/airspacemonitor.h @@ -224,7 +224,7 @@ namespace BlackCore //! \threadsafe //! \remark sets gnd flag from parts if parts are available //! \remark uses gnd elevation if found - void storeAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + virtual BlackMisc::Aviation::CAircraftSituation storeAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation, bool allowTestOffset = true) override; //! Add or update aircraft BlackMisc::Simulation::CSimulatedAircraft addOrUpdateAircraftInRange(const BlackMisc::Aviation::CCallsign &callsign, const QString &aircraftIcao, const QString &airlineIcao, const QString &livery, const QString &modelString, BlackMisc::Simulation::CAircraftModel::ModelType modelType, BlackMisc::CStatusMessageList *log); diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index 0f3394888..88dc42196 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -45,7 +45,7 @@ namespace BlackCore return setup; } - bool ISimulator::requestElevation(const Geo::ICoordinateGeodetic &reference, const CCallsign &callsign) + bool ISimulator::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign) { Q_UNUSED(reference); Q_UNUSED(callsign); diff --git a/src/blackmisc/aviation/aircraftsituation.cpp b/src/blackmisc/aviation/aircraftsituation.cpp index 01b1affe6..881e31372 100644 --- a/src/blackmisc/aviation/aircraftsituation.cpp +++ b/src/blackmisc/aviation/aircraftsituation.cpp @@ -148,13 +148,11 @@ namespace BlackMisc static const QString interpolated("interpolated"); static const QString extrapolated("extrapolated"); static const QString avg("average"); - static const QString otherSituations("other situations"); switch (details) { case NoElevationInfo: return noDetails; case FromProvider: return provider; - case FromOtherSituations: return otherSituations; case SituationChange: return change; case FromCache: return cache; case Test: return test; @@ -394,13 +392,16 @@ namespace BlackMisc return this->isPositionNull(); } - bool CAircraftSituation::isBetterInfo(CAircraftSituation::GndElevationInfo info, bool transferred) const + bool CAircraftSituation::isThisElevationInfoBetter(CAircraftSituation::GndElevationInfo info, bool transferred) const { - if (!transferred && info == FromProvider) { return true; } // always override with latest value from provider if (info == NoElevationInfo || info == Test) { return false; } const int i = static_cast(info); - if (i > m_onGroundDetails) { return true; } - if (i == m_onGroundDetails) { return !transferred; } // transferred elevations are not better + if (i > m_elvInfo) { return true; } + if (i == m_elvInfo) + { + if (m_isElvInfoTransferred == transferred) { return false; } // not better (equal) + return !transferred; // if not transferred it is better + } return false; } @@ -678,7 +679,7 @@ namespace BlackMisc QString CAircraftSituation::getGroundElevationInfoAsString() const { return m_isElvInfoTransferred ? - gndElevationInfoToString(this->getGroundElevationInfo()) % QStringLiteral(" - tx") : + QStringLiteral("tx: ") % gndElevationInfoToString(this->getGroundElevationInfo()) : gndElevationInfoToString(this->getGroundElevationInfo()); } @@ -810,7 +811,7 @@ namespace BlackMisc if (elevationPlane.isNull()) { return false; } const CLength distance = this->calculateGreatCircleDistance(elevationPlane); if (distance > elevationPlane.getRadiusOrMinimumRadius()) { return false; } - if (m_groundElevationPlane.isNull() || this->isBetterInfo(info, transferred)) + if (m_groundElevationPlane.isNull() || this->isThisElevationInfoBetter(info, transferred)) { // better values this->setGroundElevation(elevationPlane, info, transferred); diff --git a/src/blackmisc/aviation/aircraftsituation.h b/src/blackmisc/aviation/aircraftsituation.h index be9c719fd..82ae206ae 100644 --- a/src/blackmisc/aviation/aircraftsituation.h +++ b/src/blackmisc/aviation/aircraftsituation.h @@ -120,7 +120,6 @@ namespace BlackMisc Test, //!< unit test SituationChange, //!< from BlackMisc::Aviation::CAircraftSituationChange Extrapolated, //!< extrapolated ("guessing") - FromOtherSituations, //!< transferred from other situations ("sibling situations" same callsign) Average, //!< average value of "nearby" situation CAircraftSituationList::averageElevationOfNonMovingAircraft Interpolated, //!< interpolated between 2 elevations FromCache, //!< from cache @@ -174,8 +173,8 @@ namespace BlackMisc //! Null situation virtual bool isNull() const override; - //! Is better info (more accurate)? - bool isBetterInfo(GndElevationInfo info, bool transferred) const; + //! Is given info better (more accurate)? + bool isThisElevationInfoBetter(GndElevationInfo info, bool transferred) const; //! Equal pitch, bank heading //! \sa Geo::ICoordinateGeodetic::equalNormalVectorDouble diff --git a/src/blackmisc/aviation/aircraftsituationlist.cpp b/src/blackmisc/aviation/aircraftsituationlist.cpp index 7c3c01a04..8d0cd26ee 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.cpp +++ b/src/blackmisc/aviation/aircraftsituationlist.cpp @@ -347,10 +347,10 @@ namespace BlackMisc return found; } - CElevationPlane CAircraftSituationList::findCLosestElevationWithinRange(const ICoordinateGeodetic &coordinate, const CLength &range) const + CAircraftSituation CAircraftSituationList::findCLosestElevationWithinRange(const ICoordinateGeodetic &coordinate, const CLength &range) const { CLength r = range.isNull() || range < CElevationPlane::singlePointRadius() ? CElevationPlane::singlePointRadius() : range; - CElevationPlane ep = CElevationPlane::null(); + CAircraftSituation situationWithElevation = CAircraftSituation::null(); CLength bestDistance = CLength::null(); for (const CAircraftSituation &s : *this) @@ -360,11 +360,11 @@ namespace BlackMisc if (distance > r) { continue; } if (bestDistance.isNull() || bestDistance > distance) { - ep = s.getGroundElevationPlane(); + situationWithElevation = s; bestDistance = distance; } } - return ep; + return situationWithElevation; } int CAircraftSituationList::setOnGround(CAircraftSituation::IsOnGround og) diff --git a/src/blackmisc/aviation/aircraftsituationlist.h b/src/blackmisc/aviation/aircraftsituationlist.h index 55ea88e01..82aef7cdc 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.h +++ b/src/blackmisc/aviation/aircraftsituationlist.h @@ -136,7 +136,7 @@ namespace BlackMisc CAircraftSituationList findOnGroundWithElevation(CAircraftSituation::IsOnGround og) const; //! CLosest elevation within given range - Geo::CElevationPlane findCLosestElevationWithinRange(const Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range = Geo::CElevationPlane::singlePointRadius()) const; + CAircraftSituation findCLosestElevationWithinRange(const Geo::ICoordinateGeodetic &coordinate, const PhysicalQuantities::CLength &range = Geo::CElevationPlane::singlePointRadius()) const; //! Set on ground int setOnGround(CAircraftSituation::IsOnGround og); diff --git a/src/blackmisc/geo/coordinategeodetic.cpp b/src/blackmisc/geo/coordinategeodetic.cpp index d686dd2ec..778745720 100644 --- a/src/blackmisc/geo/coordinategeodetic.cpp +++ b/src/blackmisc/geo/coordinategeodetic.cpp @@ -27,8 +27,7 @@ namespace BlackMisc { QString CCoordinateGeodetic::convertToQString(bool i18n) const { - static const QString s = "Geodetic: {%1, %2, %3}"; - return s.arg(this->latitude().valueRoundedWithUnit(6, i18n), this->longitude().valueRoundedWithUnit(6, i18n), m_geodeticHeight.valueRoundedWithUnit(6, i18n)); + return ICoordinateGeodetic::convertToQString(i18n); } CCoordinateGeodetic CCoordinateGeodetic::fromWgs84(const QString &latitudeWgs84, const QString &longitudeWgs84, const CAltitude &geodeticHeight) @@ -158,10 +157,14 @@ namespace BlackMisc QString ICoordinateGeodetic::convertToQString(bool i18n) const { - Q_UNUSED(i18n); - return this->latitudeAsString() % QLatin1Char(' ') % - QStringLiteral(" | ") % this->longitudeAsString() % QLatin1Char(' ') % - QStringLiteral(" | ") % this->geodeticHeightAsString(); + static const QString s = "Geodetic: {%1/%2, %3/%4, %5}"; + const CLatitude lat = this->latitude(); + const CLongitude lng = this->longitude(); + return s.arg(lat.valueRoundedWithUnit(CAngleUnit::deg(), 6, i18n), + lat.valueRoundedWithUnit(CAngleUnit::rad(), 6, i18n), + lng.valueRoundedWithUnit(CAngleUnit::deg(), 6, i18n), + lng.valueRoundedWithUnit(CAngleUnit::rad(), 6, i18n), + this->geodeticHeight().valueRoundedWithUnit(CLengthUnit::ft(), 2, i18n)); } CVariant CCoordinateGeodetic::propertyByIndex(const BlackMisc::CPropertyIndex &index) const diff --git a/src/blackmisc/geo/elevationplane.cpp b/src/blackmisc/geo/elevationplane.cpp index 2afbe76c8..f0a8d9732 100644 --- a/src/blackmisc/geo/elevationplane.cpp +++ b/src/blackmisc/geo/elevationplane.cpp @@ -21,15 +21,9 @@ namespace BlackMisc { QString CElevationPlane::convertToQString(bool i18n) const { - static const QString s = "Geodetic: {%1/%2, %3/%4, %5} radius: %6"; - const CLatitude lat = this->latitude(); - const CLongitude lng = this->longitude(); - return s.arg(lat.valueRoundedWithUnit(CAngleUnit::deg(), 6, i18n), - lat.valueRoundedWithUnit(CAngleUnit::rad(), 6, i18n), - lng.valueRoundedWithUnit(CAngleUnit::deg(), 6, i18n), - lng.valueRoundedWithUnit(CAngleUnit::rad(), 6, i18n), - this->geodeticHeight().valueRoundedWithUnit(CLengthUnit::ft(), 6, i18n), - m_radius.valueRoundedWithUnit(2, i18n)); + static const QString s = "%1 radius: %2"; + const QString coordinate = CCoordinateGeodetic::toQString(i18n); + return s.arg(coordinate, m_radius.valueRoundedWithUnit(2, i18n)); } CElevationPlane::CElevationPlane(const ICoordinateGeodetic &coordinate, const ICoordinateGeodetic &rangeCoordinate) : diff --git a/src/blackmisc/simulation/remoteaircraftprovider.cpp b/src/blackmisc/simulation/remoteaircraftprovider.cpp index ee8689dc2..14000af59 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.cpp +++ b/src/blackmisc/simulation/remoteaircraftprovider.cpp @@ -222,12 +222,12 @@ namespace BlackMisc return c; } - void CRemoteAircraftProvider::storeAircraftSituation(const CAircraftSituation &situation, bool allowTestOffset) + CAircraftSituation CRemoteAircraftProvider::storeAircraftSituation(const CAircraftSituation &situation, bool allowTestOffset) { const CCallsign cs = situation.getCallsign(); - if (cs.isEmpty()) { return; } + if (cs.isEmpty()) { return situation; } - // verify + // testing if (CBuildConfig::isLocalDeveloperDebugBuild()) { BLACK_VERIFY_X(situation.getTimeOffsetMs() > 0, Q_FUNC_INFO, "Missing offset"); @@ -261,7 +261,7 @@ namespace BlackMisc { newSituationsList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign); newSituationsList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst); - newSituationsList.transferElevationForward(); // transfer elevations + newSituationsList.transferElevationForward(); // transfer elevations, will do nothing if elevations already exist // unify all inbound ground information if (situation.hasInboundGroundDetails()) @@ -296,6 +296,8 @@ namespace BlackMisc this->storeChange(change); emit this->addedAircraftSituation(situationCorrected); + + return situationCorrected; } void CRemoteAircraftProvider::storeAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool removeOutdated) diff --git a/src/blackmisc/simulation/remoteaircraftprovider.h b/src/blackmisc/simulation/remoteaircraftprovider.h index 4479da9e5..9abf6557e 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.h +++ b/src/blackmisc/simulation/remoteaircraftprovider.h @@ -393,7 +393,7 @@ namespace BlackMisc //! Store an aircraft situation //! \remark latest situations are kept first //! \threadsafe - void storeAircraftSituation(const Aviation::CAircraftSituation &situation, bool allowTestOffset = true); + virtual Aviation::CAircraftSituation storeAircraftSituation(const Aviation::CAircraftSituation &situation, bool allowTestOffset = true); //! Store an aircraft part //! \remark latest parts are kept first diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.cpp b/src/blackmisc/simulation/simulationenvironmentprovider.cpp index 28b12aad4..341ce1e18 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.cpp +++ b/src/blackmisc/simulation/simulationenvironmentprovider.cpp @@ -362,6 +362,11 @@ namespace BlackMisc return this->provider()->requestElevation(reference, callsign); } + bool CSimulationEnvironmentAware::requestElevation(const CAircraftSituation &situation) + { + return this->requestElevation(situation, situation.getCallsign()); + } + QPair CSimulationEnvironmentAware::getElevationsFoundMissed() const { if (!this->hasProvider()) { return QPair(0, 0); } diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.h b/src/blackmisc/simulation/simulationenvironmentprovider.h index 3e7200803..0e2f4b676 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.h +++ b/src/blackmisc/simulation/simulationenvironmentprovider.h @@ -229,6 +229,9 @@ namespace BlackMisc //! \copydoc ISimulationEnvironmentProvider::requestElevation bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign); + //! \copydoc ISimulationEnvironmentProvider::requestElevation + bool requestElevation(const Aviation::CAircraftSituation &situation); + //! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissed QPair getElevationsFoundMissed() const;