Ref T778, improved "canLikelySkipNearGround" in airspace monitor

* use CAircraftIcaoCode::guessModelParameters as this gives us an impression of speed
* use "breakable" do/while block / fewer nested "if" levels
This commit is contained in:
Klaus Basan
2020-03-27 22:56:59 +01:00
committed by Mat Sutcliffe
parent 5bc09ed2c8
commit e6a12d45c4
2 changed files with 123 additions and 97 deletions

View File

@@ -1370,112 +1370,128 @@ namespace BlackCore
if (callsign.isEmpty()) { return situation; } if (callsign.isEmpty()) { return situation; }
CAircraftSituation correctedSituation(allowTestOffset ? this->addTestAltitudeOffsetToSituation(situation) : situation); CAircraftSituation correctedSituation(allowTestOffset ? this->addTestAltitudeOffsetToSituation(situation) : situation);
bool canLikelySkipNearGround = correctedSituation.canLikelySkipNearGroundInterpolation();
bool needToRequestElevation = false; bool needToRequestElevation = false;
bool canLikelySkipNearGround = correctedSituation.canLikelySkipNearGroundInterpolation();
if (!correctedSituation.hasGroundElevation()) do
{ {
if (canLikelySkipNearGround || correctedSituation.hasGroundElevation()) { break; }
// set a defined state // set a defined state
correctedSituation.resetGroundElevation(); correctedSituation.resetGroundElevation();
if (!canLikelySkipNearGround) // Check if we can bail out and ignore all elevation handling
{ //
// fetch from cache or request // rational:
const CAircraftSituationChange changesBeforeStoring = this->remoteAircraftSituationChanges(callsign).frontOrDefault(); // a) elevation handling is expensive, and might even requests elevation from sim.
// b) elevations not needed pollute the cache with "useless" values
//
if (canLikelySkipNearGround) { break; }
// Check if we can bail out and ignore all elevation handling // Guessing gives better values, also for smaller planes
// // and avoids unnecessary elevation fetching for low flying smaller GA aircraft
// rational: const CAircraftIcaoCode icao = this->getAircraftInRangeModelForCallsign(callsign).getAircraftIcaoCode();
// a) elevation handling is expensive, and might even requests elevation from sim. if (!icao.hasDesignator()) { break; } // what is that?
// b) elevations not needed pollute the cache with "useless" values if (!icao.isVtol())
// {
if (!changesBeforeStoring.isNull()) // Not for VTOLs
CLength cg(nullptr);
CSpeed rotateSpeed(nullptr);
icao.guessModelParameters(cg, rotateSpeed);
if (!rotateSpeed.isNull())
{ {
canLikelySkipNearGround = changesBeforeStoring.isConstAscending(); rotateSpeed *= 1.2; // some margin
if (situation.getGroundSpeed() > rotateSpeed) { break; }
}
}
// fetch from cache or request
const CAircraftSituationChange changesBeforeStoring = this->remoteAircraftSituationChanges(callsign).frontOrDefault();
if (!changesBeforeStoring.isNull())
{
canLikelySkipNearGround = changesBeforeStoring.isConstAscending();
if (canLikelySkipNearGround) { break; }
}
// we NEED elevation
const CLength dpt = correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius());
const CAircraftSituationList situationsBeforeStoring = this->remoteAircraftSituations(callsign);
const CAircraftSituation situationWithElvBeforeStoring = situationsBeforeStoring.findClosestElevationWithinRange(correctedSituation, dpt);
if (situationWithElvBeforeStoring.transferGroundElevationFromMe(correctedSituation, dpt))
{
// from nearby situations of own aircraft, data was transferred above
// we use transfer first as it is slightly faster as cache
}
else
{
// 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");
// also can handle NULL elevations
correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache);
}
// 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, 3);
fromNonMoving = true;
} }
if (!canLikelySkipNearGround) // do we have an elevation yet?
if (!averagePlane.isNull())
{ {
const CLength dpt = correctedSituation.getDistancePerTime(100, CElevationPlane::singlePointRadius()); correctedSituation.setGroundElevation(averagePlane, CAircraftSituation::Average);
const CAircraftSituationList situationsBeforeStoring = this->remoteAircraftSituations(callsign); if (fromNonMoving) { m_foundInNonMovingAircraft++; }
const CAircraftSituation situationWithElvBeforeStoring = situationsBeforeStoring.findClosestElevationWithinRange(correctedSituation, dpt); else { m_foundInElevationsOnGnd++; }
if (situationWithElvBeforeStoring.transferGroundElevationFromMe(correctedSituation, dpt)) }
else
{
// values before updating (i.e. "storing") so the new situation is not yet considered
if (situationsBeforeStoring.size() > 1)
{ {
// from nearby situations of own aircraft, data was transferred above const bool extrapolated = correctedSituation.extrapolateElevation(situationsBeforeStoring[0], situationsBeforeStoring[1], changesBeforeStoring);
// we use transfer first as it is slightly faster as cache triedExtrapolation = true;
couldNotExtrapolate = !extrapolated;
} }
else }
{
// 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");
// also can handle NULL elevations // still no elevation
correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); 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
// we have a new situation, so we try to get the elevation Q_UNUSED(triedExtrapolation)
// so far we have requested it, but we set it upfront either by Q_UNUSED(couldNotExtrapolate)
// }
// a) average value from other planes in the vicinity (cache, not moving) or } // gnd. elevation
// b) by extrapolating }
// while (false); // do we need elevation, find on
// 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, 3);
fromNonMoving = true;
}
// do we have an elevation yet?
if (!averagePlane.isNull())
{
correctedSituation.setGroundElevation(averagePlane, CAircraftSituation::Average);
if (fromNonMoving) { m_foundInNonMovingAircraft++; }
else { m_foundInElevationsOnGnd++; }
}
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?
// do we already have ground details? // do we already have ground details?
if (situation.getOnGroundDetails() == CAircraftSituation::NotSetGroundDetails) if (situation.getOnGroundDetails() == CAircraftSituation::NotSetGroundDetails)

View File

@@ -247,8 +247,8 @@ namespace BlackMisc
if (!guessedCGOut.isNull() && !guessedVRotateOut.isNull()) { return; } if (!guessedCGOut.isNull() && !guessedVRotateOut.isNull()) { return; }
// init to defaults // init to defaults
CLength guessedCG = CLength(1.5, CLengthUnit::m()); CLength guessedCG = CLength(1.5, CLengthUnit::m());
CSpeed guessedVRotate = this->isVtol() ? CSpeed::null() : CSpeed(70, CSpeedUnit::km_h()); CSpeed guessedVRotate = CSpeed(70, CSpeedUnit::km_h());
const int engines = this->getEnginesCount(); const int engines = this->getEnginesCount();
const QChar engineType = this->getEngineTypeChar().toUpper(); const QChar engineType = this->getEngineTypeChar().toUpper();
@@ -267,26 +267,36 @@ namespace BlackMisc
{ {
// a B737 has VR 105-160kts // a B737 has VR 105-160kts
guessedVRotate = CSpeed(120, CSpeedUnit::kts()); guessedVRotate = CSpeed(120, CSpeedUnit::kts());
guessedCG = CLength(2.5, CLengthUnit::m()); guessedCG = CLength(2.5, CLengthUnit::m());
break; break;
} }
} }
else if (engines > 2) else if (engines > 2)
{ {
guessedCG = CLength(4.0, CLengthUnit::m()); guessedCG = CLength(4.0, CLengthUnit::m());
guessedVRotate = CSpeed(70, CSpeedUnit::kts()); guessedVRotate = CSpeed(70, CSpeedUnit::kts());
if (engineType == 'J') if (engineType == 'J')
{ {
// A typical B747 has VR around 160kts // A typical B747 has VR around 160kts
guessedCG = CLength(6.0, CLengthUnit::m()); guessedCG = CLength(6.0, CLengthUnit::m());
guessedVRotate = CSpeed(140, CSpeedUnit::kts()); guessedVRotate = CSpeed(140, CSpeedUnit::kts());
break; break;
} }
} }
if (engineType == 'J')
{
// MIL Jets a bit faster
if (this->isMilitary()) { guessedVRotate *= 1.20; }
else if (this->matchesDesignator("CONC")) { guessedVRotate = CSpeed(199, CSpeedUnit::kts()); }
}
// VTOL
if (this->isVtol()) { guessedVRotate = CSpeed(0, CSpeedUnit::kts()); }
} }
while (false); while (false);
if (guessedCGOut.isNull()) { guessedCGOut = guessedCG; } if (guessedCGOut.isNull()) { guessedCGOut = guessedCG; }
if (guessedVRotateOut.isNull()) { guessedVRotateOut = guessedVRotate; } if (guessedVRotateOut.isNull()) { guessedVRotateOut = guessedVRotate; }
} }