mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-02 23:35:40 +08:00
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:
committed by
Mat Sutcliffe
parent
5bc09ed2c8
commit
e6a12d45c4
@@ -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)
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user