From 8206fc6bb92916f8e79a554fb1b7e6b48ff37571 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 7 Apr 2020 21:00:17 +0200 Subject: [PATCH] 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 --- .../simulationenvironmentprovider.cpp | 76 +++++++-------- .../simulator/xplane/simulatorxplane.cpp | 93 ++++++++++++++++++- .../simulator/xplane/simulatorxplane.h | 17 +++- 3 files changed, 140 insertions(+), 46 deletions(-) diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.cpp b/src/blackmisc/simulation/simulationenvironmentprovider.cpp index a45218377..a9f1e1728 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.cpp +++ b/src/blackmisc/simulation/simulationenvironmentprovider.cpp @@ -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 { diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index d714b407c..d8526598f 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -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(); } diff --git a/src/plugins/simulator/xplane/simulatorxplane.h b/src/plugins/simulator/xplane/simulatorxplane.h index ef66800f6..ff653a619 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.h +++ b/src/plugins/simulator/xplane/simulatorxplane.h @@ -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 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 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 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