Ref T268, elevation handling improvements

* utility functions
* made storeAircraftSituation virtual and return Aviation::CAircraftSituation
* coordinate toQString in deg/rad
This commit is contained in:
Klaus Basan
2018-07-11 02:34:58 +02:00
parent 226abd0d38
commit a5acd0a1ec
13 changed files with 71 additions and 51 deletions

View File

@@ -965,26 +965,29 @@ namespace BlackCore
this->setOtherClient(client); this->setOtherClient(client);
} }
void CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation) CAircraftSituation CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation, bool allowTestOffset)
{ {
const CCallsign callsign(situation.getCallsign()); const CCallsign callsign(situation.getCallsign());
BLACK_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); BLACK_VERIFY_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign");
if (callsign.isEmpty()) { return; } if (callsign.isEmpty()) { return situation; }
CAircraftSituation correctedSituation(this->testAddAltitudeOffsetToSituation(situation)); CAircraftSituation correctedSituation(allowTestOffset ? this->testAddAltitudeOffsetToSituation(situation) : situation);
if (!correctedSituation.hasGroundElevation() && !correctedSituation.canLikelySkipNearGroundInterpolation()) bool haveRequestedElevation = false;
const bool canLikelySkipNearGround = correctedSituation.canLikelySkipNearGroundInterpolation();
if (!correctedSituation.hasGroundElevation() && !canLikelySkipNearGround)
{ {
// fetch from cache or request // fetch from cache or request
const CAircraftSituationList situations = this->remoteAircraftSituations(callsign); const CAircraftSituationList situations = this->remoteAircraftSituations(callsign);
CElevationPlane ep = situations.findCLosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius())); const CAircraftSituation situationWithElv = situations.findCLosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius()));
if (!ep.isNull()) if (!situationWithElv.getGroundElevation().isNull())
{ {
correctedSituation.setGroundElevation(ep, CAircraftSituation::FromOtherSituations); correctedSituation.transferGroundElevation(situationWithElv);
} }
else else
{ {
const CLength distance(correctedSituation.getDistancePerTime250ms(CElevationPlane::singlePointRadius())); // distnacee per ms 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"); Q_ASSERT_X(ep.isNull() || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius");
correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache);
} }
@@ -1032,13 +1035,23 @@ namespace BlackCore
// CG from provider // CG from provider
const CLength cg = this->getCG(callsign); // always x-check against simulator to override guessed values and reflect changed CGs const CLength cg = this->getCG(callsign); // always x-check against simulator to override guessed values and reflect changed CGs
if (!cg.isNull()) if (!cg.isNull()) { correctedSituation.setCG(cg); }
{
correctedSituation.setCG(cg);
}
// store change object // 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) void CAirspaceMonitor::sendInitialAtcQueries(const CCallsign &callsign)

View File

@@ -224,7 +224,7 @@ namespace BlackCore
//! \threadsafe //! \threadsafe
//! \remark sets gnd flag from parts if parts are available //! \remark sets gnd flag from parts if parts are available
//! \remark uses gnd elevation if found //! \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 //! 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); 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);

View File

@@ -45,7 +45,7 @@ namespace BlackCore
return setup; 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(reference);
Q_UNUSED(callsign); Q_UNUSED(callsign);

View File

@@ -148,13 +148,11 @@ namespace BlackMisc
static const QString interpolated("interpolated"); static const QString interpolated("interpolated");
static const QString extrapolated("extrapolated"); static const QString extrapolated("extrapolated");
static const QString avg("average"); static const QString avg("average");
static const QString otherSituations("other situations");
switch (details) switch (details)
{ {
case NoElevationInfo: return noDetails; case NoElevationInfo: return noDetails;
case FromProvider: return provider; case FromProvider: return provider;
case FromOtherSituations: return otherSituations;
case SituationChange: return change; case SituationChange: return change;
case FromCache: return cache; case FromCache: return cache;
case Test: return test; case Test: return test;
@@ -394,13 +392,16 @@ namespace BlackMisc
return this->isPositionNull(); 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; } if (info == NoElevationInfo || info == Test) { return false; }
const int i = static_cast<int>(info); const int i = static_cast<int>(info);
if (i > m_onGroundDetails) { return true; } if (i > m_elvInfo) { return true; }
if (i == m_onGroundDetails) { return !transferred; } // transferred elevations are not better if (i == m_elvInfo)
{
if (m_isElvInfoTransferred == transferred) { return false; } // not better (equal)
return !transferred; // if not transferred it is better
}
return false; return false;
} }
@@ -678,7 +679,7 @@ namespace BlackMisc
QString CAircraftSituation::getGroundElevationInfoAsString() const QString CAircraftSituation::getGroundElevationInfoAsString() const
{ {
return m_isElvInfoTransferred ? return m_isElvInfoTransferred ?
gndElevationInfoToString(this->getGroundElevationInfo()) % QStringLiteral(" - tx") : QStringLiteral("tx: ") % gndElevationInfoToString(this->getGroundElevationInfo()) :
gndElevationInfoToString(this->getGroundElevationInfo()); gndElevationInfoToString(this->getGroundElevationInfo());
} }
@@ -810,7 +811,7 @@ namespace BlackMisc
if (elevationPlane.isNull()) { return false; } if (elevationPlane.isNull()) { return false; }
const CLength distance = this->calculateGreatCircleDistance(elevationPlane); const CLength distance = this->calculateGreatCircleDistance(elevationPlane);
if (distance > elevationPlane.getRadiusOrMinimumRadius()) { return false; } if (distance > elevationPlane.getRadiusOrMinimumRadius()) { return false; }
if (m_groundElevationPlane.isNull() || this->isBetterInfo(info, transferred)) if (m_groundElevationPlane.isNull() || this->isThisElevationInfoBetter(info, transferred))
{ {
// better values // better values
this->setGroundElevation(elevationPlane, info, transferred); this->setGroundElevation(elevationPlane, info, transferred);

View File

@@ -120,7 +120,6 @@ namespace BlackMisc
Test, //!< unit test Test, //!< unit test
SituationChange, //!< from BlackMisc::Aviation::CAircraftSituationChange SituationChange, //!< from BlackMisc::Aviation::CAircraftSituationChange
Extrapolated, //!< extrapolated ("guessing") Extrapolated, //!< extrapolated ("guessing")
FromOtherSituations, //!< transferred from other situations ("sibling situations" same callsign)
Average, //!< average value of "nearby" situation CAircraftSituationList::averageElevationOfNonMovingAircraft Average, //!< average value of "nearby" situation CAircraftSituationList::averageElevationOfNonMovingAircraft
Interpolated, //!< interpolated between 2 elevations Interpolated, //!< interpolated between 2 elevations
FromCache, //!< from cache FromCache, //!< from cache
@@ -174,8 +173,8 @@ namespace BlackMisc
//! Null situation //! Null situation
virtual bool isNull() const override; virtual bool isNull() const override;
//! Is better info (more accurate)? //! Is given info better (more accurate)?
bool isBetterInfo(GndElevationInfo info, bool transferred) const; bool isThisElevationInfoBetter(GndElevationInfo info, bool transferred) const;
//! Equal pitch, bank heading //! Equal pitch, bank heading
//! \sa Geo::ICoordinateGeodetic::equalNormalVectorDouble //! \sa Geo::ICoordinateGeodetic::equalNormalVectorDouble

View File

@@ -347,10 +347,10 @@ namespace BlackMisc
return found; 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; CLength r = range.isNull() || range < CElevationPlane::singlePointRadius() ? CElevationPlane::singlePointRadius() : range;
CElevationPlane ep = CElevationPlane::null(); CAircraftSituation situationWithElevation = CAircraftSituation::null();
CLength bestDistance = CLength::null(); CLength bestDistance = CLength::null();
for (const CAircraftSituation &s : *this) for (const CAircraftSituation &s : *this)
@@ -360,11 +360,11 @@ namespace BlackMisc
if (distance > r) { continue; } if (distance > r) { continue; }
if (bestDistance.isNull() || bestDistance > distance) if (bestDistance.isNull() || bestDistance > distance)
{ {
ep = s.getGroundElevationPlane(); situationWithElevation = s;
bestDistance = distance; bestDistance = distance;
} }
} }
return ep; return situationWithElevation;
} }
int CAircraftSituationList::setOnGround(CAircraftSituation::IsOnGround og) int CAircraftSituationList::setOnGround(CAircraftSituation::IsOnGround og)

View File

@@ -136,7 +136,7 @@ namespace BlackMisc
CAircraftSituationList findOnGroundWithElevation(CAircraftSituation::IsOnGround og) const; CAircraftSituationList findOnGroundWithElevation(CAircraftSituation::IsOnGround og) const;
//! CLosest elevation within given range //! 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 //! Set on ground
int setOnGround(CAircraftSituation::IsOnGround og); int setOnGround(CAircraftSituation::IsOnGround og);

View File

@@ -27,8 +27,7 @@ namespace BlackMisc
{ {
QString CCoordinateGeodetic::convertToQString(bool i18n) const QString CCoordinateGeodetic::convertToQString(bool i18n) const
{ {
static const QString s = "Geodetic: {%1, %2, %3}"; return ICoordinateGeodetic::convertToQString(i18n);
return s.arg(this->latitude().valueRoundedWithUnit(6, i18n), this->longitude().valueRoundedWithUnit(6, i18n), m_geodeticHeight.valueRoundedWithUnit(6, i18n));
} }
CCoordinateGeodetic CCoordinateGeodetic::fromWgs84(const QString &latitudeWgs84, const QString &longitudeWgs84, const CAltitude &geodeticHeight) CCoordinateGeodetic CCoordinateGeodetic::fromWgs84(const QString &latitudeWgs84, const QString &longitudeWgs84, const CAltitude &geodeticHeight)
@@ -158,10 +157,14 @@ namespace BlackMisc
QString ICoordinateGeodetic::convertToQString(bool i18n) const QString ICoordinateGeodetic::convertToQString(bool i18n) const
{ {
Q_UNUSED(i18n); static const QString s = "Geodetic: {%1/%2, %3/%4, %5}";
return this->latitudeAsString() % QLatin1Char(' ') % const CLatitude lat = this->latitude();
QStringLiteral(" | ") % this->longitudeAsString() % QLatin1Char(' ') % const CLongitude lng = this->longitude();
QStringLiteral(" | ") % this->geodeticHeightAsString(); 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 CVariant CCoordinateGeodetic::propertyByIndex(const BlackMisc::CPropertyIndex &index) const

View File

@@ -21,15 +21,9 @@ namespace BlackMisc
{ {
QString CElevationPlane::convertToQString(bool i18n) const QString CElevationPlane::convertToQString(bool i18n) const
{ {
static const QString s = "Geodetic: {%1/%2, %3/%4, %5} radius: %6"; static const QString s = "%1 radius: %2";
const CLatitude lat = this->latitude(); const QString coordinate = CCoordinateGeodetic::toQString(i18n);
const CLongitude lng = this->longitude(); return s.arg(coordinate, m_radius.valueRoundedWithUnit(2, i18n));
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));
} }
CElevationPlane::CElevationPlane(const ICoordinateGeodetic &coordinate, const ICoordinateGeodetic &rangeCoordinate) : CElevationPlane::CElevationPlane(const ICoordinateGeodetic &coordinate, const ICoordinateGeodetic &rangeCoordinate) :

View File

@@ -222,12 +222,12 @@ namespace BlackMisc
return c; return c;
} }
void CRemoteAircraftProvider::storeAircraftSituation(const CAircraftSituation &situation, bool allowTestOffset) CAircraftSituation CRemoteAircraftProvider::storeAircraftSituation(const CAircraftSituation &situation, bool allowTestOffset)
{ {
const CCallsign cs = situation.getCallsign(); const CCallsign cs = situation.getCallsign();
if (cs.isEmpty()) { return; } if (cs.isEmpty()) { return situation; }
// verify // testing
if (CBuildConfig::isLocalDeveloperDebugBuild()) if (CBuildConfig::isLocalDeveloperDebugBuild())
{ {
BLACK_VERIFY_X(situation.getTimeOffsetMs() > 0, Q_FUNC_INFO, "Missing offset"); 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.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign);
newSituationsList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst); newSituationsList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst);
newSituationsList.transferElevationForward(); // transfer elevations newSituationsList.transferElevationForward(); // transfer elevations, will do nothing if elevations already exist
// unify all inbound ground information // unify all inbound ground information
if (situation.hasInboundGroundDetails()) if (situation.hasInboundGroundDetails())
@@ -296,6 +296,8 @@ namespace BlackMisc
this->storeChange(change); this->storeChange(change);
emit this->addedAircraftSituation(situationCorrected); emit this->addedAircraftSituation(situationCorrected);
return situationCorrected;
} }
void CRemoteAircraftProvider::storeAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool removeOutdated) void CRemoteAircraftProvider::storeAircraftParts(const CCallsign &callsign, const CAircraftParts &parts, bool removeOutdated)

View File

@@ -393,7 +393,7 @@ namespace BlackMisc
//! Store an aircraft situation //! Store an aircraft situation
//! \remark latest situations are kept first //! \remark latest situations are kept first
//! \threadsafe //! \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 //! Store an aircraft part
//! \remark latest parts are kept first //! \remark latest parts are kept first

View File

@@ -362,6 +362,11 @@ namespace BlackMisc
return this->provider()->requestElevation(reference, callsign); return this->provider()->requestElevation(reference, callsign);
} }
bool CSimulationEnvironmentAware::requestElevation(const CAircraftSituation &situation)
{
return this->requestElevation(situation, situation.getCallsign());
}
QPair<int, int> CSimulationEnvironmentAware::getElevationsFoundMissed() const QPair<int, int> CSimulationEnvironmentAware::getElevationsFoundMissed() const
{ {
if (!this->hasProvider()) { return QPair<int, int>(0, 0); } if (!this->hasProvider()) { return QPair<int, int>(0, 0); }

View File

@@ -229,6 +229,9 @@ namespace BlackMisc
//! \copydoc ISimulationEnvironmentProvider::requestElevation //! \copydoc ISimulationEnvironmentProvider::requestElevation
bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign); bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign);
//! \copydoc ISimulationEnvironmentProvider::requestElevation
bool requestElevation(const Aviation::CAircraftSituation &situation);
//! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissed //! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissed
QPair<int, int> getElevationsFoundMissed() const; QPair<int, int> getElevationsFoundMissed() const;