From 29536dac4d979be1c6d8c4251fb493929beba2aa Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Mon, 9 Jul 2018 22:24:04 +0200 Subject: [PATCH] Ref T268, simulator improvements * use virtual function to emit setup signal * callback public so it can be used from "log display" for testing * sim. environment provider statistics --- src/blackcore/simulator.cpp | 36 +++++----- src/blackcore/simulator.h | 16 ++--- .../simulationenvironmentprovider.cpp | 67 +++++++++++++++++-- .../simulationenvironmentprovider.h | 48 ++++++++++--- 4 files changed, 122 insertions(+), 45 deletions(-) diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index bc539666b..0f3394888 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace BlackConfig; using namespace BlackMisc; @@ -55,9 +56,8 @@ namespace BlackCore { if (this->isShuttingDown()) { return; } - // CLogMessage(this).info("'%1' Received req. elevation") << callsign.asString(); - this->rememberGroundElevation(plane); - const int updated = this->updateAircraftGroundElevation(callsign, plane, CAircraftSituation::FromProvider); + ISimulationEnvironmentProvider::rememberGroundElevation(callsign, plane); // in simulator + const int updated = CRemoteAircraftAware::updateAircraftGroundElevation(callsign, plane, CAircraftSituation::FromProvider); if (updated < 1) { return; } emit this->receivedRequestedElevation(plane, callsign); } @@ -113,8 +113,8 @@ namespace BlackCore if (!elevation.isNull()) { const int aircraftCount = this->getAircraftInRangeCount(); - this->setRememberMaxElevations(aircraftCount * 3); // at least 3 elevations per aircraft, even better as not all are requesting elevations - this->rememberGroundElevation(elevation); + this->setMaxElevationsRemembered(aircraftCount * 3); // at least 3 elevations per aircraft, even better as not all are requesting elevations + this->rememberGroundElevation(callsign, elevation); } if (!cg.isNull() && !this->hasSameCG(cg, callsign)) { this->insertCG(cg, modelString, callsign); } } @@ -135,31 +135,27 @@ namespace BlackCore } } + void ISimulator::emitInterpolationSetupChanged() + { + QPointer myself(this); + QTimer::singleShot(0, this, [ = ] + { + if (!myself) { return; } + emit this->interpolationAndRenderingSetupChanged(); + }); + } + + bool ISimulator::setInterpolationSetupGlobal(const CInterpolationAndRenderingSetupGlobal &setup) { if (!IInterpolationSetupProvider::setInterpolationSetupGlobal(setup)) { return false; } const bool r = setup.isRenderingRestricted(); const bool e = setup.isRenderingEnabled(); - emit this->interpolationAndRenderingSetupChanged(); emit this->renderRestrictionsChanged(r, e, setup.getMaxRenderedAircraft(), setup.getMaxRenderedDistance()); return true; } - bool ISimulator::setInterpolationSetupsPerCallsign(const CInterpolationSetupList &setups, bool ignoreSameAsGlobal) - { - if (!IInterpolationSetupProvider::setInterpolationSetupsPerCallsign(setups, ignoreSameAsGlobal)) { return false; } - emit this->interpolationAndRenderingSetupChanged(); - return true; - } - - bool ISimulator::setInterpolationSetupPerCallsign(const CInterpolationAndRenderingSetupPerCallsign &setup, const CCallsign &callsign, bool removeGlobalSetup) - { - if (!IInterpolationSetupProvider::setInterpolationSetupPerCallsign(setup, callsign, removeGlobalSetup)) { return false; } - emit this->interpolationAndRenderingSetupChanged(); - return true; - } - ISimulatorListener::ISimulatorListener(const CSimulatorPluginInfo &info) : QObject(), m_info(info) { diff --git a/src/blackcore/simulator.h b/src/blackcore/simulator.h index 8158750c3..a11d220a4 100644 --- a/src/blackcore/simulator.h +++ b/src/blackcore/simulator.h @@ -198,6 +198,10 @@ namespace BlackCore //! \sa ISimulator::callbackReceivedRequestedElevation virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override; + //! A requested elevation has been received + //! \remark public for testing purposes + virtual void callbackReceivedRequestedElevation(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign); + //! Allows to print out simulator specific statistics virtual QString getStatisticsSimulatorSpecific() const { return QString(); } @@ -224,9 +228,6 @@ namespace BlackCore //! \copydoc BlackMisc::Simulation::IInterpolationSetupProvider::setInterpolationSetupGlobal virtual bool setInterpolationSetupGlobal(const BlackMisc::Simulation::CInterpolationAndRenderingSetupGlobal &setup) override; - //! \copydoc BlackMisc::Simulation::IInterpolationSetupProvider::setInterpolationSetupsPerCallsign - virtual bool setInterpolationSetupsPerCallsign(const BlackMisc::Simulation::CInterpolationSetupList &setups, bool ignoreSameAsGlobal = true) override; - //! Register help static void registerHelp(); @@ -295,16 +296,13 @@ namespace BlackCore //! Set elevation and CG in the providers void rememberElevationAndCG(const BlackMisc::Aviation::CCallsign &callsign, const QString &modelString, const BlackMisc::Geo::CElevationPlane &elevation, const BlackMisc::PhysicalQuantities::CLength &cg); - //! A requested elevation has been received - virtual void callbackReceivedRequestedElevation(const BlackMisc::Geo::CElevationPlane &plane, const BlackMisc::Aviation::CCallsign &callsign); - - //! \copydoc BlackMisc::Simulation::IInterpolationSetupProvider::setInterpolationSetupPerCallsign - virtual bool setInterpolationSetupPerCallsign(const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup, const BlackMisc::Aviation::CCallsign &callsign, bool removeGlobalSetup) override; - //! Emit the combined status //! \param oldStatus optionally one can capture and provide the old status for comparison. In case of equal status values no signal will be sent //! \sa simulatorStatusChanged; void emitSimulatorCombinedStatus(SimulatorStatus oldStatus = Unspecified); + + //! Emit the signal + virtual void emitInterpolationSetupChanged() override; }; //! Interface to a simulator listener. diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.cpp b/src/blackmisc/simulation/simulationenvironmentprovider.cpp index 33e24f4b8..28b12aad4 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.cpp +++ b/src/blackmisc/simulation/simulationenvironmentprovider.cpp @@ -17,7 +17,7 @@ namespace BlackMisc { namespace Simulation { - bool ISimulationEnvironmentProvider::rememberGroundElevation(const ICoordinateGeodetic &elevationCoordinate, const CLength &epsilon) + bool ISimulationEnvironmentProvider::rememberGroundElevation(const CCallsign &requestedForCallsign, const ICoordinateGeodetic &elevationCoordinate, const CLength &epsilon) { { // no 2nd elevation nearby? @@ -29,17 +29,26 @@ namespace BlackMisc // we keep latest at front // * we assume we find them faster // * and need the more frequently (the recent ones) + const qint64 now = QDateTime::currentMSecsSinceEpoch(); QWriteLocker l(&m_lockElvCoordinates); if (m_elvCoordinates.size() > m_maxElevations) { m_elvCoordinates.pop_back(); } m_elvCoordinates.push_front(elevationCoordinate); + if (m_pendingElevationRequests.contains(requestedForCallsign)) + { + const qint64 startedMs = m_pendingElevationRequests.value(requestedForCallsign); + const qint64 deltaMs = now - startedMs; + m_pendingElevationRequests.remove(requestedForCallsign); + m_statsCurrentElevRequestTimeMs = deltaMs; + if (m_statsMaxElevRequestTimeMs < deltaMs) { m_statsMaxElevRequestTimeMs = deltaMs; } + } } return true; } - bool ISimulationEnvironmentProvider::rememberGroundElevation(const CElevationPlane &elevationPlane) + bool ISimulationEnvironmentProvider::rememberGroundElevation(const CCallsign &requestedForCallsign, const CElevationPlane &elevationPlane) { if (!elevationPlane.hasMSLGeodeticHeight()) { return false; } - return this->rememberGroundElevation(elevationPlane, elevationPlane.getRadius()); + return this->rememberGroundElevation(requestedForCallsign, elevationPlane, elevationPlane.getRadius()); } bool ISimulationEnvironmentProvider::insertCG(const CLength &cg, const CCallsign &cs) @@ -122,7 +131,7 @@ namespace BlackMisc CElevationPlane ISimulationEnvironmentProvider::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const CLength &range) const { // for single point we use a slightly optimized version - const bool singlePoint = (&range == &CElevationPlane::singlePointRadius() || range <= CElevationPlane::singlePointRadius()); + const bool singlePoint = (&range == &CElevationPlane::singlePointRadius() || range.isNull() || range <= CElevationPlane::singlePointRadius()); const CCoordinateGeodetic coordinate = singlePoint ? this->getElevationCoordinates().findFirstWithinRangeOrDefault(reference, CElevationPlane::singlePointRadius()) : this->getElevationCoordinates().findClosestWithinRange(reference, range); @@ -147,11 +156,19 @@ namespace BlackMisc const CElevationPlane ep = ISimulationEnvironmentProvider::findClosestElevationWithinRange(reference, range); if (ep.isNull()) { + const qint64 now = QDateTime::currentMSecsSinceEpoch(); this->requestElevation(reference, callsign); + QWriteLocker l(&m_lockElvCoordinates); + m_pendingElevationRequests[callsign] = now; } return ep; } + bool ISimulationEnvironmentProvider::requestElevationBySituation(const CAircraftSituation &situation) + { + return this->requestElevation(situation, situation.getCallsign()); + } + QPair ISimulationEnvironmentProvider::getElevationsFoundMissed() const { QReadLocker l(&m_lockElvCoordinates); @@ -168,6 +185,20 @@ namespace BlackMisc return info.arg(f).arg(m).arg(QString::number(hitRatioPercent, 'f', 1)); } + QPair ISimulationEnvironmentProvider::getElevationRequestTimes() const + { + QReadLocker l(&m_lockElvCoordinates); + return QPair(m_statsCurrentElevRequestTimeMs, m_statsMaxElevRequestTimeMs); + } + + QString ISimulationEnvironmentProvider::getElevationRequestTimesInfo() const + { + static const QString info("%1ms/%2ms"); + QPair times = this->getElevationRequestTimes(); + if (times.first < 0 || times.second < 0) { return QStringLiteral("no req. times"); } + return info.arg(times.first).arg(times.second); + } + CSimulatorPluginInfo ISimulationEnvironmentProvider::getSimulatorPluginInfo() const { QReadLocker l(&m_lockSimInfo); @@ -217,19 +248,27 @@ namespace BlackMisc return m_cgsPerCallsign[callsign] == cg; } - int ISimulationEnvironmentProvider::setRememberMaxElevations(int max) + int ISimulationEnvironmentProvider::setMaxElevationsRemembered(int max) { QWriteLocker l(&m_lockElvCoordinates); m_maxElevations = qMax(max, 50); return m_maxElevations; } - int ISimulationEnvironmentProvider::getRememberMaxElevations() const + int ISimulationEnvironmentProvider::getMaxElevationsRemembered() const { QReadLocker l(&m_lockElvCoordinates); return m_maxElevations; } + void ISimulationEnvironmentProvider::resetSimulationEnvironmentStatistics() + { + QWriteLocker l(&m_lockElvCoordinates); + m_statsCurrentElevRequestTimeMs = -1; + m_statsMaxElevRequestTimeMs = -1; + m_elvFound = m_elvMissed = 0; + } + ISimulationEnvironmentProvider::ISimulationEnvironmentProvider(const CSimulatorPluginInfo &pluginInfo) : m_simulatorPluginInfo(pluginInfo) { } @@ -284,6 +323,9 @@ namespace BlackMisc { QWriteLocker l(&m_lockElvCoordinates); m_elvCoordinates.clear(); + m_pendingElevationRequests.clear(); + m_statsCurrentElevRequestTimeMs = -1; + m_statsMaxElevRequestTimeMs = -1; m_elvFound = m_elvMissed = 0; } @@ -299,6 +341,7 @@ namespace BlackMisc this->clearDefaultModel(); this->clearElevations(); this->clearCGs(); + this->resetSimulationEnvironmentStatistics(); } CElevationPlane CSimulationEnvironmentAware::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const @@ -331,6 +374,18 @@ namespace BlackMisc return this->provider()->getElevationsFoundMissedInfo(); } + QPair CSimulationEnvironmentAware::getElevationRequestTimes() const + { + if (!this->hasProvider()) { return QPair(-1, -1); } + return this->provider()->getElevationRequestTimes(); + } + + QString CSimulationEnvironmentAware::getElevationRequestTimesInfo() const + { + if (!this->hasProvider()) { return QString(); } + return this->provider()->getElevationRequestTimesInfo(); + } + CSimulatorPluginInfo CSimulationEnvironmentAware::getSimulatorPluginInfo() const { if (!this->hasProvider()) { return CSimulatorPluginInfo(); } diff --git a/src/blackmisc/simulation/simulationenvironmentprovider.h b/src/blackmisc/simulation/simulationenvironmentprovider.h index 84a5ac940..3e7200803 100644 --- a/src/blackmisc/simulation/simulationenvironmentprovider.h +++ b/src/blackmisc/simulation/simulationenvironmentprovider.h @@ -14,10 +14,13 @@ #include "simulatorplugininfo.h" #include "aircraftmodel.h" -#include "blackmisc/provider.h" -#include "blackmisc/pq/length.h" +#include "blackmisc/aviation/aircraftsituation.h" +#include "blackmisc/aviation/percallsign.h" #include "blackmisc/geo/coordinategeodeticlist.h" #include "blackmisc/geo/elevationplane.h" +#include "blackmisc/pq/length.h" +#include "blackmisc/provider.h" + #include #include #include @@ -47,14 +50,26 @@ namespace BlackMisc //! \threadsafe virtual bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign) = 0; + //! Request elevation, there is no guarantee the requested elevation will be available in the provider + //! \threadsafe + bool requestElevationBySituation(const BlackMisc::Aviation::CAircraftSituation &situation); + //! Elevations found/missed statistics //! \threadsafe QPair getElevationsFoundMissed() const; + //! The elevation request times + //! \threadsafe + QPair getElevationRequestTimes() const; + //! Elevations found/missed statistics info as string //! \threadsafe QString getElevationsFoundMissedInfo() const; + //! Elevation request times + //! \threadsafe + QString getElevationRequestTimesInfo() const; + //! Get the represented plugin //! \threadsafe CSimulatorPluginInfo getSimulatorPluginInfo() const; @@ -85,11 +100,15 @@ namespace BlackMisc //! Set number of elevations kept //! \threadsafe - int setRememberMaxElevations(int max); + int setMaxElevationsRemembered(int max); //! Get number of max. number of elevations //! \threadsafe - int getRememberMaxElevations() const; + int getMaxElevationsRemembered() const; + + //! Reset statistics + //! \threadsafe + void resetSimulationEnvironmentStatistics(); protected: //! Ctor @@ -145,11 +164,11 @@ namespace BlackMisc //! Remember a given elevation //! \threadsafe - bool rememberGroundElevation(const Geo::ICoordinateGeodetic &elevationCoordinate, const PhysicalQuantities::CLength &epsilon = Geo::CElevationPlane::singlePointRadius()) ; + bool rememberGroundElevation(const Aviation::CCallsign &requestedForCallsign, const Geo::ICoordinateGeodetic &elevationCoordinate, const PhysicalQuantities::CLength &epsilon = Geo::CElevationPlane::singlePointRadius()); //! Remember a given elevation //! \threadsafe - bool rememberGroundElevation(const Geo::CElevationPlane &elevationPlane) ; + bool rememberGroundElevation(const Aviation::CCallsign &requestedForCallsign, const Geo::CElevationPlane &elevationPlane) ; //! Insert or replace a CG //! \remark passing a NULL value will remove the CG @@ -180,12 +199,15 @@ namespace BlackMisc QString m_simulatorVersion; //!< Simulator version CAircraftModel m_defaultModel; //!< default model int m_maxElevations = 100; //!< How many elevations we keep - Geo::CCoordinateGeodeticList m_elvCoordinates; - QHash m_cgsPerCallsign; //! CGs per callsign - QHash m_cgsPerModel; //!< CGs per model string + Geo::CCoordinateGeodeticList m_elvCoordinates; //!< elevation cache + Aviation::CTimestampPerCallsign m_pendingElevationRequests; //!< pending elevation requests + Aviation::CLengthPerCallsign m_cgsPerCallsign; //!< CGs per callsign + QHash m_cgsPerModel; //!< CGs per model string + qint64 m_statsMaxElevRequestTimeMs = -1; + qint64 m_statsCurrentElevRequestTimeMs = -1; mutable int m_elvFound = 0; //!< statistics only mutable int m_elvMissed = 0; //!< statistics only - mutable QReadWriteLock m_lockElvCoordinates; //!< lock m_coordinates + mutable QReadWriteLock m_lockElvCoordinates; //!< lock m_coordinates, m_pendingElevationRequests mutable QReadWriteLock m_lockCG; //!< lock CGs mutable QReadWriteLock m_lockModel; //!< lock models mutable QReadWriteLock m_lockSimInfo; //!< lock plugin info @@ -213,6 +235,12 @@ namespace BlackMisc //! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissedInfo QString getElevationsFoundMissedInfo() const; + //! \copydoc ISimulationEnvironmentProvider::getElevationRequestTimes + QPair getElevationRequestTimes() const; + + //! \copydoc ISimulationEnvironmentProvider::getElevationRequestTimesInfo + QString getElevationRequestTimesInfo() const; + //! \copydoc ISimulationEnvironmentProvider::getSimulatorPluginInfo CSimulatorPluginInfo getSimulatorPluginInfo() const;