Ref T778, special terrain probe value handling for XP

* only request terrain probe up to a max. distance
* detect "isSuspiciousTerrainValue"
* See also https://discordapp.com/channels/539048679160676382/539925070550794240/696786452855390218
This commit is contained in:
Klaus Basan
2020-04-07 21:00:17 +02:00
committed by Mat Sutcliffe
parent cfa96a3aeb
commit 8206fc6bb9
3 changed files with 140 additions and 46 deletions

View File

@@ -35,60 +35,60 @@ namespace BlackMisc
}
const CLength minRange = ISimulationEnvironmentProvider::minRange(epsilon);
const double elvFt = elevationCoordinate.geodeticHeight().value(CLengthUnit::ft());
CCoordinateGeodetic alreadyInRange;
CCoordinateGeodetic alreadyInRangeGnd;
{
QReadLocker l(&m_lockElvCoordinates);
if (!m_enableElevation) { return false; }
// check if we have already an elevation within range
CCoordinateGeodetic alreadyInRange = m_elvCoordinatesGnd.findFirstWithinRangeOrDefault(elevationCoordinate, minRange);
constexpr double maxDistFt = 30.0;
if (!alreadyInRange.isNull())
{
// found
const double distFt = qAbs(alreadyInRange.geodeticHeight().value(CLengthUnit::ft()) - elevationCoordinate.geodeticHeight().value(CLengthUnit::ft()));
if (distFt > maxDistFt)
{
// we such a huge distance to existing value
CLogMessage(this).debug(u"Suspicious gnd. elevation distance '%1': %2ft") << requestedForCallsign.asString() << distFt;
BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Suspicious gnd. elevation distance");
}
return false;
}
alreadyInRange = m_elvCoordinates.findFirstWithinRangeOrDefault(elevationCoordinate, minRange);
if (!alreadyInRange.isNull())
{
// found
const double distFt = qAbs(alreadyInRange.geodeticHeight().value(CLengthUnit::ft()) - elevationCoordinate.geodeticHeight().value(CLengthUnit::ft()));
if (distFt > maxDistFt)
{
// we such a huge distance to existing value
CLogMessage(this).debug(u"Suspicious elevation distance '%1': %2ft") << requestedForCallsign.asString() << distFt;
BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Suspicious elevation distance");
}
return false;
}
alreadyInRangeGnd = m_elvCoordinatesGnd.findFirstWithinRangeOrDefault(elevationCoordinate, minRange);
alreadyInRange = m_elvCoordinates.findFirstWithinRangeOrDefault(elevationCoordinate, minRange);
}
constexpr double maxDistFt = 30.0;
// here we deal with gnd situation and do not expect a lot of variance
if (!alreadyInRangeGnd.isNull())
{
// found
const double distFt = qAbs(alreadyInRangeGnd.geodeticHeight().value(CLengthUnit::ft()) - elvFt);
if (distFt > maxDistFt)
{
// such a huge distance to existing value
CLogMessage(this).debug(u"Suspicious GND elevation distance '%1': %2ft at %3") << requestedForCallsign.asString() << distFt << elevationCoordinate.geodeticHeight().valueRoundedAsString(CLengthUnit::ft(), 1);
BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Suspicious gnd. elevation distance");
}
return false;
}
// here we deal with all kind of values, so it can be that
// values vary in a much larger range
if (!alreadyInRange.isNull())
{
// found
const double distFt = qAbs(alreadyInRange.geodeticHeight().value(CLengthUnit::ft()) - elvFt);
if (distFt > maxDistFt)
{
// such a huge distance to existing value
CLogMessage(this).debug(u"Suspicious NON GND elevation distance for '%1': %2ft at %3") << requestedForCallsign.asString() << distFt << elevationCoordinate.geodeticHeight().valueRoundedAsString(CLengthUnit::ft(), 1);
// BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Suspicious elevation distance");
}
return false;
}
const qint64 now = QDateTime::currentMSecsSinceEpoch();
{
// we keep latest at front
// * we assume we find them faster
// * and need them more frequently (the recent ones)
const qint64 now = QDateTime::currentMSecsSinceEpoch();
QWriteLocker l(&m_lockElvCoordinates);
if (likelyOnGroundElevation)
{
if (m_elvCoordinatesGnd.size() > m_maxElevationsGnd) { m_elvCoordinatesGnd.pop_back(); }
m_elvCoordinatesGnd.push_front(elevationCoordinate);
const bool valid = !elevationCoordinate.geodeticHeight().isNull() && !elevationCoordinate.geodeticHeight().isZeroEpsilonConsidered();
if (!valid)
{
BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Suspicious value");
CLogMessage(this).debug(u"Suspicious gnd.cache value: %1") << elevationCoordinate.convertToQString();
}
}
else
{

View File

@@ -182,10 +182,66 @@ namespace BlackSimPlugin
return u > 0;
}
bool CSimulatorXPlane::handleProbeValue(const CElevationPlane &plane, const CCallsign &callsign, const QString &hint, bool ignoreOutsideRange)
{
// XPlane specific checks for T778
// https://discordapp.com/channels/539048679160676382/577213275184562176/696780159969132626
if (!plane.hasMSLGeodeticHeight()) { return false; }
if (isSuspiciousTerrainValue(plane))
{
// ignore values up to +- 1.0meters, those most likely mean no scenery
const CLength distance = this->getDistanceToOwnAircraft(plane);
if (ignoreOutsideRange && distance > maxTerrainRequestDistance()) { return false; }
static const CLength threshold = maxTerrainRequestDistance() * 0.50;
if (distance > threshold)
{
// we expect scenery to be loaded within threshold range
// outside that range we assue a suspicous value "represents no scenery"
// of course this can be wrong, but in that case we would geth those values
// once we get inside range
this->setMinTerrainProbeDistance(distance);
CLogMessage(this).debug(u"Suspicous XPlane probe [%1] value %2 for '%3' ignored, distance: %4 min.disance: %5")
<< hint
<< plane.getAltitude().valueRoundedAsString(CLengthUnit::m(), 4)
<< callsign.asString()
<< distance.valueRoundedAsString(CLengthUnit::NM(), 2)
<< m_minSuspicousTerrainProbe.valueRoundedAsString(CLengthUnit::NM(), 2);
return false;
}
}
return true;
}
void CSimulatorXPlane::callbackReceivedRequestedElevation(const CElevationPlane &plane, const CCallsign &callsign)
{
static const QString hint("probe callback");
if (!this->handleProbeValue(plane, callsign, hint, false))
{
this->removePendingElevationRequest(callsign);
return;
}
CSimulatorPluginCommon::callbackReceivedRequestedElevation(plane, callsign);
}
bool CSimulatorXPlane::isSuspiciousTerrainValue(const CElevationPlane &elevation)
{
if (!elevation.hasMSLGeodeticHeight()) { return true; }
const double valueFt = qAbs(elevation.getAltitudeValue(CLengthUnit::ft()));
return valueFt < 1.0;
}
const CLength &CSimulatorXPlane::maxTerrainRequestDistance()
{
static const CLength d(70.0, CLengthUnit::NM());
return d;
}
void CSimulatorXPlane::clearAllRemoteAircraftData()
{
m_aircraftAddedFailed.clear();
CSimulatorPluginCommon::clearAllRemoteAircraftData();
m_minSuspicousTerrainProbe.setNull();
}
bool CSimulatorXPlane::requestElevation(const ICoordinateGeodetic &reference, const CCallsign &callsign)
@@ -197,6 +253,13 @@ namespace BlackSimPlugin
if (callsign.isEmpty()) { return false; }
if (!this->isAircraftInRange(callsign)) { return false; }
const CLength d = this->getDistanceToOwnAircraft(reference);
if (!d.isNull() && d > maxTerrainRequestDistance())
{
// no request, too far away
return false;
}
CCoordinateGeodetic pos(reference);
if (!pos.hasMSLGeodeticHeight())
{
@@ -344,7 +407,6 @@ namespace BlackSimPlugin
};
this->updateOwnParts(parts);
this->requestRemoteAircraftDataFromXPlane();
CCallsignSet invalid;
for (CXPlaneMPAircraft &xplaneAircraft : m_xplaneAircraftObjects)
@@ -369,6 +431,14 @@ namespace BlackSimPlugin
this->triggerRemoveAircraft(cs, ++i * 100);
}
// KB: IMHO those data are pretty useless for XPlane
// no need to request them all the times
if ((m_slowTimerCalls % 3u) == 0u)
{
this->requestRemoteAircraftDataFromXPlane();
}
// FPS
if ((m_slowTimerCalls % 5u) == 0u)
{
@@ -494,10 +564,10 @@ namespace BlackSimPlugin
QColor color = "cyan";
/* switch (message.getSeverity())
{
case CStatusMessage::SeverityDebug: color = "teal"; break;
case CStatusMessage::SeverityInfo: color = "cyan"; break;
case CStatusMessage::SeverityDebug: color = "teal"; break;
case CStatusMessage::SeverityInfo: color = "cyan"; break;
case CStatusMessage::SeverityWarning: color = "orange"; break;
case CStatusMessage::SeverityError: color = "red"; break;
case CStatusMessage::SeverityError: color = "red"; break;
} */
m_serviceProxy->addTextMessage("swift: " + message.getMessage(), color.redF(), color.greenF(), color.blueF());
@@ -1052,6 +1122,7 @@ namespace BlackSimPlugin
}
const CCallsignSet logCallsigns = this->getLogCallsigns();
static const QString hint("remote acft.");
for (int i = 0; i < size; i++)
{
const bool emptyCs = callsigns[i].isEmpty();
@@ -1077,7 +1148,10 @@ namespace BlackSimPlugin
CLength(cgValue, CLengthUnit::m(), CLengthUnit::ft());
// if we knew "on ground" here we could set it as parameter of rememberElevationAndSimulatorCG
this->rememberElevationAndSimulatorCG(cs, xpAircraft.getAircraftModel(), false, elevation, cg);
// this->rememberElevationAndSimulatorCG(cs, xpAircraft.getAircraftModel(), false, elevation, cg);
// with T778 we do NOT use this function for elevation here if "isSuspicious"
const bool useElevation = this->handleProbeValue(elevation, cs, hint, true);
this->rememberElevationAndSimulatorCG(cs, xpAircraft.getAircraftModel(), false, useElevation ? elevation : CElevationPlane::null(), cg);
// loopback
if (logCallsigns.contains(cs))
@@ -1140,6 +1214,15 @@ namespace BlackSimPlugin
}
}
void CSimulatorXPlane::setMinTerrainProbeDistance(const CLength &distance)
{
if (distance.isNull()) { return; }
if (m_minSuspicousTerrainProbe.isNull() || distance < m_minSuspicousTerrainProbe)
{
m_minSuspicousTerrainProbe = distance;
}
}
void CSimulatorXPlane::updateAirportsInRange()
{
if (this->isConnected()) { m_serviceProxy->updateAirportsInRange(); }

View File

@@ -144,6 +144,7 @@ namespace BlackSimPlugin
virtual void resetAircraftStatistics() override;
virtual BlackMisc::CStatusMessageList getInterpolationMessages(const BlackMisc::Aviation::CCallsign &callsign) const override;
virtual bool testSendSituationAndParts(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Aviation::CAircraftSituation &situation, const BlackMisc::Aviation::CAircraftParts &parts) override;
virtual void callbackReceivedRequestedElevation(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign) override;
//! @}
//! \copydoc BlackMisc::Simulation::ISimulationEnvironmentProvider::requestElevation
@@ -235,6 +236,15 @@ namespace BlackSimPlugin
//! Settings have changed
void onXSwiftBusSettingsChanged();
//! Min.distance of "failed" (suspicious) terrain probe requests
void setMinTerrainProbeDistance(const BlackMisc::PhysicalQuantities::CLength &distance);
//! Handle a probe value
bool handleProbeValue(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign, const QString &hint, bool ignoreOutsideRange);
static bool isSuspiciousTerrainValue(const BlackMisc::Geo::CElevationPlane &elevation);
static const BlackMisc::PhysicalQuantities::CLength &maxTerrainRequestDistance();
DBusMode m_dbusMode;
BlackMisc::CSetting<BlackMisc::Simulation::Settings::TXSwiftBusSettings> m_xSwiftBusServerSettings { this, &CSimulatorXPlane::onXSwiftBusSettingsChanged };
static constexpr qint64 TimeoutAdding = 10000;
@@ -253,9 +263,10 @@ namespace BlackSimPlugin
BlackMisc::Aviation::CAirportList m_airportsInRange; //!< aiports in range of own aircraft
CXPlaneMPAircraftObjects m_xplaneAircraftObjects; //!< XPlane multiplayer aircraft
BlackMisc::Simulation::CSimulatedAircraftList m_pendingToBeAddedAircraft; //!< aircraft to be added
QHash<BlackMisc::Aviation::CCallsign, qint64> m_addingInProgressAircraft; //!< aircraft just adding
BlackMisc::Simulation::CSimulatedAircraftList m_aircraftAddedFailed; //!< aircraft for which adding failed
BlackMisc::Simulation::CSimulatedAircraftList m_pendingToBeAddedAircraft; //!< aircraft to be added
QHash<BlackMisc::Aviation::CCallsign, qint64> m_addingInProgressAircraft; //!< aircraft just adding
BlackMisc::Simulation::CSimulatedAircraftList m_aircraftAddedFailed; //!< aircraft for which adding failed
BlackMisc::PhysicalQuantities::CLength m_minSuspicousTerrainProbe { nullptr }; //!< min. distance of "failed" (suspicious) terrain probe requests
XPlaneData m_xplaneData; //!< XPlane data
// statistics