From 4120a2c77d78f21fe53ad0266783f8ab597cf9df Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 18 Feb 2020 03:10:31 +0100 Subject: [PATCH] Ref T773, use "on ground" cached elevations for situations in simulator and airspace monitor --- src/blackcore/airspacemonitor.cpp | 130 ++++++++++++++++++++---------- src/blackcore/simulator.cpp | 15 ++-- 2 files changed, 94 insertions(+), 51 deletions(-) diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 8db2821e8..0262123fe 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -1358,8 +1358,9 @@ namespace BlackCore if (callsign.isEmpty()) { return situation; } CAircraftSituation correctedSituation(allowTestOffset ? this->addTestAltitudeOffsetToSituation(situation) : situation); - bool haveRequestedElevation = false; - const bool canLikelySkipNearGround = correctedSituation.canLikelySkipNearGroundInterpolation(); + bool canLikelySkipNearGround = correctedSituation.canLikelySkipNearGroundInterpolation(); + bool needToRequestElevation = false; + if (!correctedSituation.hasGroundElevation()) { // set a defined state @@ -1368,54 +1369,95 @@ namespace BlackCore if (!canLikelySkipNearGround) { // fetch from cache or request - const CAircraftSituationList situations = this->remoteAircraftSituations(callsign); - const CAircraftSituation situationWithElv = situations.findCLosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius())); - if (!situationWithElv.getGroundElevation().isNull()) - { - // from nearby situations of own aircraft - correctedSituation.transferGroundElevation(situationWithElv); - } - else - { - // from cache - const CLength distance(correctedSituation.getDistancePerTime250ms(CElevationPlane::singlePointRadius())); // distance per ms - const CElevationPlane ep = this->findClosestElevationWithinRangeOrRequest(correctedSituation, distance, callsign); - haveRequestedElevation = ep.isNull(); // NULL means we requested - Q_ASSERT_X(haveRequestedElevation || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius"); + const CAircraftSituationChange changesBeforeStoring = this->remoteAircraftSituationChanges(callsign).frontOrDefault(); - // also can handle NULL elevations - correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); + // Check if we can bail out and ignore all elevation handling + // + // rational: + // a) elevation handling is expensive, and might even requests elevation from sim. + // b) elevations not needed pollute the cache with "useless" values + // + if (!changesBeforeStoring.isNull()) + { + canLikelySkipNearGround = changesBeforeStoring.isConstAscending(); } - // we have a new situation, so we try to get the elevation - // so far we have requested it, but we set it upfront either by - // a) average value from other planes in the vicinity or - // b) by extrapolating - // - // if we would NOT preset it, we could end up with oscillation - // - if (!correctedSituation.hasGroundElevation()) + if (!canLikelySkipNearGround) { - const CElevationPlane averagePlane = this->averageElevationOfNonMovingAircraft(situation, CElevationPlane::majorAirportRadius(), 2); - if (!averagePlane.isNull()) + const CAircraftSituationList situationsBeforeStoring = this->remoteAircraftSituations(callsign); + const CAircraftSituation situationWithElvBeforeStoring = situationsBeforeStoring.findClosestElevationWithinRange(correctedSituation, correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius())); + if (!situationWithElvBeforeStoring.getGroundElevation().isNull()) { - correctedSituation.setGroundElevation(averagePlane, CAircraftSituation::Average); + // from nearby situations of own aircraft, data was transferred above + // we use transfer first as it is slightly faster as cache } else { - // values before updating (i.e. "storing") so the new situation is not yet considered - const CAircraftSituationList oldSituations = this->remoteAircraftSituations(callsign); - const CAircraftSituationChangeList oldChanges = this->remoteAircraftSituationChanges(callsign); - if (oldSituations.size() > 1) - { - const bool extrapolated = correctedSituation.extrapolateElevation(oldSituations[0], oldSituations[1], oldChanges.frontOrDefault()); - Q_UNUSED(extrapolated) + // from cache + const CLength distance(correctedSituation.getDistancePerTime250ms(CElevationPlane::singlePointRadius())); // distance per ms + const CElevationPlane ep = this->findClosestElevationWithinRange(correctedSituation, distance); + needToRequestElevation = ep.isNull(); + Q_ASSERT_X(needToRequestElevation || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius"); - // extrapolation only works if there is a provider and already data - // BLACK_AUDIT_X(extrapolated, Q_FUNC_INFO, "Cannot extrapolate"); - } + // also can handle NULL elevations + correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); } - } // gnd. elevation + + // we have a new situation, so we try to get the elevation + // so far we have requested it, but we set it upfront either by + // + // a) average value from other planes in the vicinity (cache, not moving) or + // b) by extrapolating + // + // if we would NOT preset it, we could end up with oscillation + // + if (!correctedSituation.hasGroundElevation()) + { + // average elevation + // 1) from cache + // 2) from planes on ground not moving + bool fromNonMoving = false; + bool triedExtrapolation = false; + bool couldNotExtrapolate = false; + + CElevationPlane averagePlane = this->averageElevationOfOnGroundAircraft(situation, CElevationPlane::majorAirportRadius(), 2, 3); + if (averagePlane.isNull()) + { + averagePlane = this->averageElevationOfNonMovingAircraft(situation, CElevationPlane::majorAirportRadius(), 2); + } + + // do we have a elevation yet? + if (!averagePlane.isNull()) + { + correctedSituation.setGroundElevation(averagePlane, CAircraftSituation::Average); + } + else + { + // values before updating (i.e. "storing") so the new situation is not yet considered + if (situationsBeforeStoring.size() > 1) + { + const bool extrapolated = correctedSituation.extrapolateElevation(situationsBeforeStoring[0], situationsBeforeStoring[1], changesBeforeStoring); + triedExtrapolation = true; + couldNotExtrapolate = !extrapolated; + } + } + + // still no elevation + if (!correctedSituation.hasGroundElevation()) + { + if (CBuildConfig::isLocalDeveloperDebugBuild()) + { + // experimental, could become ASSERT + BLACK_VERIFY_X(needToRequestElevation, Q_FUNC_INFO, "Request should already be set"); + } + needToRequestElevation = true; // should be the true already + + Q_UNUSED(triedExtrapolation) + Q_UNUSED(couldNotExtrapolate) + } + } // gnd. elevation + + } // can skip? } // can skip? } // have already elevation? @@ -1442,18 +1484,18 @@ namespace BlackCore // store corrected situation correctedSituation = CRemoteAircraftProvider::storeAircraftSituation(correctedSituation, false); // we already added offset if any - // check if we STILL want to request - if (!haveRequestedElevation && !canLikelySkipNearGround) + // check if we need want to request + if (needToRequestElevation && !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.isOtherElevationInfoBetter(CAircraftSituation::FromCache, false) || (correctedSituation.isMoving() && correctedSituation.isOtherElevationInfoBetter(CAircraftSituation::FromProvider, false))) { - haveRequestedElevation = this->requestElevation(correctedSituation); + needToRequestElevation = this->requestElevation(correctedSituation); } } - Q_UNUSED(haveRequestedElevation) + Q_UNUSED(needToRequestElevation) return correctedSituation; } diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index 53775b0eb..b900bcc26 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -365,12 +365,13 @@ namespace BlackCore if (this->isShuttingDown()) { return; } if (plane.isNull()) { return; } - // update in simulator - ISimulationEnvironmentProvider::rememberGroundElevation(callsign, plane); // in simulator + // Update in remote aircraft for given callsign + bool updatedForOnGroundPosition = false; + const int updated = CRemoteAircraftAware::updateAircraftGroundElevation(callsign, plane, CAircraftSituation::FromProvider, &updatedForOnGroundPosition); - // and in remote aircraft for given callsign - const int updated = CRemoteAircraftAware::updateAircraftGroundElevation(callsign, plane, CAircraftSituation::FromProvider); - Q_UNUSED(updated) + // update in simulator + const bool likelyOnGroundElevation = updated > 0 && updatedForOnGroundPosition; + ISimulationEnvironmentProvider::rememberGroundElevation(callsign, likelyOnGroundElevation, plane); // in simulator // signal we have received the elevation // used by log display @@ -877,7 +878,7 @@ namespace BlackCore { const int aircraftCount = this->getAircraftInRangeCount(); this->setMaxElevationsRemembered(aircraftCount * 3); // at least 3 elevations per aircraft, even better as not all are requesting elevations - this->rememberGroundElevation(callsign, elevation); + this->rememberGroundElevation(callsign, false, elevation); } const QString modelString = model.getModelString(); @@ -1192,7 +1193,7 @@ namespace BlackCore const CCallsign cs = situation.hasCallsign() ? situation.getCallsign() : ownAircraft.getCallsign(); const CLength radius = settings.getRecordedGndRadius().isNull() ? CElevationPlane::singlePointRadius() : settings.getRecordedGndRadius(); const CElevationPlane ep(situation, radius); - const bool remembered = this->rememberGroundElevation(cs, ep, radius); + const bool remembered = this->rememberGroundElevation(cs, situation.isOnGround(), ep, radius); Q_UNUSED(remembered) // false means it was already in that cache, or something else is wrong } }