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
This commit is contained in:
Klaus Basan
2018-07-09 22:24:04 +02:00
parent 6e880b950c
commit 29536dac4d
4 changed files with 122 additions and 45 deletions

View File

@@ -14,6 +14,7 @@
#include <QFlag> #include <QFlag>
#include <Qt> #include <Qt>
#include <QtGlobal> #include <QtGlobal>
#include <QPointer>
using namespace BlackConfig; using namespace BlackConfig;
using namespace BlackMisc; using namespace BlackMisc;
@@ -55,9 +56,8 @@ namespace BlackCore
{ {
if (this->isShuttingDown()) { return; } if (this->isShuttingDown()) { return; }
// CLogMessage(this).info("'%1' Received req. elevation") << callsign.asString(); ISimulationEnvironmentProvider::rememberGroundElevation(callsign, plane); // in simulator
this->rememberGroundElevation(plane); const int updated = CRemoteAircraftAware::updateAircraftGroundElevation(callsign, plane, CAircraftSituation::FromProvider);
const int updated = this->updateAircraftGroundElevation(callsign, plane, CAircraftSituation::FromProvider);
if (updated < 1) { return; } if (updated < 1) { return; }
emit this->receivedRequestedElevation(plane, callsign); emit this->receivedRequestedElevation(plane, callsign);
} }
@@ -113,8 +113,8 @@ namespace BlackCore
if (!elevation.isNull()) if (!elevation.isNull())
{ {
const int aircraftCount = this->getAircraftInRangeCount(); const int aircraftCount = this->getAircraftInRangeCount();
this->setRememberMaxElevations(aircraftCount * 3); // at least 3 elevations per aircraft, even better as not all are requesting elevations this->setMaxElevationsRemembered(aircraftCount * 3); // at least 3 elevations per aircraft, even better as not all are requesting elevations
this->rememberGroundElevation(elevation); this->rememberGroundElevation(callsign, elevation);
} }
if (!cg.isNull() && !this->hasSameCG(cg, callsign)) { this->insertCG(cg, modelString, callsign); } if (!cg.isNull() && !this->hasSameCG(cg, callsign)) { this->insertCG(cg, modelString, callsign); }
} }
@@ -135,31 +135,27 @@ namespace BlackCore
} }
} }
void ISimulator::emitInterpolationSetupChanged()
{
QPointer<ISimulator> myself(this);
QTimer::singleShot(0, this, [ = ]
{
if (!myself) { return; }
emit this->interpolationAndRenderingSetupChanged();
});
}
bool ISimulator::setInterpolationSetupGlobal(const CInterpolationAndRenderingSetupGlobal &setup) bool ISimulator::setInterpolationSetupGlobal(const CInterpolationAndRenderingSetupGlobal &setup)
{ {
if (!IInterpolationSetupProvider::setInterpolationSetupGlobal(setup)) { return false; } if (!IInterpolationSetupProvider::setInterpolationSetupGlobal(setup)) { return false; }
const bool r = setup.isRenderingRestricted(); const bool r = setup.isRenderingRestricted();
const bool e = setup.isRenderingEnabled(); const bool e = setup.isRenderingEnabled();
emit this->interpolationAndRenderingSetupChanged();
emit this->renderRestrictionsChanged(r, e, setup.getMaxRenderedAircraft(), setup.getMaxRenderedDistance()); emit this->renderRestrictionsChanged(r, e, setup.getMaxRenderedAircraft(), setup.getMaxRenderedDistance());
return true; 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) : ISimulatorListener::ISimulatorListener(const CSimulatorPluginInfo &info) :
QObject(), m_info(info) QObject(), m_info(info)
{ {

View File

@@ -198,6 +198,10 @@ namespace BlackCore
//! \sa ISimulator::callbackReceivedRequestedElevation //! \sa ISimulator::callbackReceivedRequestedElevation
virtual bool requestElevation(const BlackMisc::Geo::ICoordinateGeodetic &reference, const BlackMisc::Aviation::CCallsign &callsign) override; 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 //! Allows to print out simulator specific statistics
virtual QString getStatisticsSimulatorSpecific() const { return QString(); } virtual QString getStatisticsSimulatorSpecific() const { return QString(); }
@@ -224,9 +228,6 @@ namespace BlackCore
//! \copydoc BlackMisc::Simulation::IInterpolationSetupProvider::setInterpolationSetupGlobal //! \copydoc BlackMisc::Simulation::IInterpolationSetupProvider::setInterpolationSetupGlobal
virtual bool setInterpolationSetupGlobal(const BlackMisc::Simulation::CInterpolationAndRenderingSetupGlobal &setup) override; 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 //! Register help
static void registerHelp(); static void registerHelp();
@@ -295,16 +296,13 @@ namespace BlackCore
//! Set elevation and CG in the providers //! 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); 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 //! 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 //! \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; //! \sa simulatorStatusChanged;
void emitSimulatorCombinedStatus(SimulatorStatus oldStatus = Unspecified); void emitSimulatorCombinedStatus(SimulatorStatus oldStatus = Unspecified);
//! Emit the signal
virtual void emitInterpolationSetupChanged() override;
}; };
//! Interface to a simulator listener. //! Interface to a simulator listener.

View File

@@ -17,7 +17,7 @@ namespace BlackMisc
{ {
namespace Simulation 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? // no 2nd elevation nearby?
@@ -29,17 +29,26 @@ namespace BlackMisc
// we keep latest at front // we keep latest at front
// * we assume we find them faster // * we assume we find them faster
// * and need the more frequently (the recent ones) // * and need the more frequently (the recent ones)
const qint64 now = QDateTime::currentMSecsSinceEpoch();
QWriteLocker l(&m_lockElvCoordinates); QWriteLocker l(&m_lockElvCoordinates);
if (m_elvCoordinates.size() > m_maxElevations) { m_elvCoordinates.pop_back(); } if (m_elvCoordinates.size() > m_maxElevations) { m_elvCoordinates.pop_back(); }
m_elvCoordinates.push_front(elevationCoordinate); 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; return true;
} }
bool ISimulationEnvironmentProvider::rememberGroundElevation(const CElevationPlane &elevationPlane) bool ISimulationEnvironmentProvider::rememberGroundElevation(const CCallsign &requestedForCallsign, const CElevationPlane &elevationPlane)
{ {
if (!elevationPlane.hasMSLGeodeticHeight()) { return false; } 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) 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 CElevationPlane ISimulationEnvironmentProvider::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const CLength &range) const
{ {
// for single point we use a slightly optimized version // 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 ? const CCoordinateGeodetic coordinate = singlePoint ?
this->getElevationCoordinates().findFirstWithinRangeOrDefault(reference, CElevationPlane::singlePointRadius()) : this->getElevationCoordinates().findFirstWithinRangeOrDefault(reference, CElevationPlane::singlePointRadius()) :
this->getElevationCoordinates().findClosestWithinRange(reference, range); this->getElevationCoordinates().findClosestWithinRange(reference, range);
@@ -147,11 +156,19 @@ namespace BlackMisc
const CElevationPlane ep = ISimulationEnvironmentProvider::findClosestElevationWithinRange(reference, range); const CElevationPlane ep = ISimulationEnvironmentProvider::findClosestElevationWithinRange(reference, range);
if (ep.isNull()) if (ep.isNull())
{ {
const qint64 now = QDateTime::currentMSecsSinceEpoch();
this->requestElevation(reference, callsign); this->requestElevation(reference, callsign);
QWriteLocker l(&m_lockElvCoordinates);
m_pendingElevationRequests[callsign] = now;
} }
return ep; return ep;
} }
bool ISimulationEnvironmentProvider::requestElevationBySituation(const CAircraftSituation &situation)
{
return this->requestElevation(situation, situation.getCallsign());
}
QPair<int, int> ISimulationEnvironmentProvider::getElevationsFoundMissed() const QPair<int, int> ISimulationEnvironmentProvider::getElevationsFoundMissed() const
{ {
QReadLocker l(&m_lockElvCoordinates); QReadLocker l(&m_lockElvCoordinates);
@@ -168,6 +185,20 @@ namespace BlackMisc
return info.arg(f).arg(m).arg(QString::number(hitRatioPercent, 'f', 1)); return info.arg(f).arg(m).arg(QString::number(hitRatioPercent, 'f', 1));
} }
QPair<qint64, qint64> ISimulationEnvironmentProvider::getElevationRequestTimes() const
{
QReadLocker l(&m_lockElvCoordinates);
return QPair<qint64, qint64>(m_statsCurrentElevRequestTimeMs, m_statsMaxElevRequestTimeMs);
}
QString ISimulationEnvironmentProvider::getElevationRequestTimesInfo() const
{
static const QString info("%1ms/%2ms");
QPair<qint64, qint64> 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 CSimulatorPluginInfo ISimulationEnvironmentProvider::getSimulatorPluginInfo() const
{ {
QReadLocker l(&m_lockSimInfo); QReadLocker l(&m_lockSimInfo);
@@ -217,19 +248,27 @@ namespace BlackMisc
return m_cgsPerCallsign[callsign] == cg; return m_cgsPerCallsign[callsign] == cg;
} }
int ISimulationEnvironmentProvider::setRememberMaxElevations(int max) int ISimulationEnvironmentProvider::setMaxElevationsRemembered(int max)
{ {
QWriteLocker l(&m_lockElvCoordinates); QWriteLocker l(&m_lockElvCoordinates);
m_maxElevations = qMax(max, 50); m_maxElevations = qMax(max, 50);
return m_maxElevations; return m_maxElevations;
} }
int ISimulationEnvironmentProvider::getRememberMaxElevations() const int ISimulationEnvironmentProvider::getMaxElevationsRemembered() const
{ {
QReadLocker l(&m_lockElvCoordinates); QReadLocker l(&m_lockElvCoordinates);
return m_maxElevations; 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) ISimulationEnvironmentProvider::ISimulationEnvironmentProvider(const CSimulatorPluginInfo &pluginInfo) : m_simulatorPluginInfo(pluginInfo)
{ } { }
@@ -284,6 +323,9 @@ namespace BlackMisc
{ {
QWriteLocker l(&m_lockElvCoordinates); QWriteLocker l(&m_lockElvCoordinates);
m_elvCoordinates.clear(); m_elvCoordinates.clear();
m_pendingElevationRequests.clear();
m_statsCurrentElevRequestTimeMs = -1;
m_statsMaxElevRequestTimeMs = -1;
m_elvFound = m_elvMissed = 0; m_elvFound = m_elvMissed = 0;
} }
@@ -299,6 +341,7 @@ namespace BlackMisc
this->clearDefaultModel(); this->clearDefaultModel();
this->clearElevations(); this->clearElevations();
this->clearCGs(); this->clearCGs();
this->resetSimulationEnvironmentStatistics();
} }
CElevationPlane CSimulationEnvironmentAware::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const CElevationPlane CSimulationEnvironmentAware::findClosestElevationWithinRange(const ICoordinateGeodetic &reference, const PhysicalQuantities::CLength &range) const
@@ -331,6 +374,18 @@ namespace BlackMisc
return this->provider()->getElevationsFoundMissedInfo(); return this->provider()->getElevationsFoundMissedInfo();
} }
QPair<qint64, qint64> CSimulationEnvironmentAware::getElevationRequestTimes() const
{
if (!this->hasProvider()) { return QPair<qint64, qint64>(-1, -1); }
return this->provider()->getElevationRequestTimes();
}
QString CSimulationEnvironmentAware::getElevationRequestTimesInfo() const
{
if (!this->hasProvider()) { return QString(); }
return this->provider()->getElevationRequestTimesInfo();
}
CSimulatorPluginInfo CSimulationEnvironmentAware::getSimulatorPluginInfo() const CSimulatorPluginInfo CSimulationEnvironmentAware::getSimulatorPluginInfo() const
{ {
if (!this->hasProvider()) { return CSimulatorPluginInfo(); } if (!this->hasProvider()) { return CSimulatorPluginInfo(); }

View File

@@ -14,10 +14,13 @@
#include "simulatorplugininfo.h" #include "simulatorplugininfo.h"
#include "aircraftmodel.h" #include "aircraftmodel.h"
#include "blackmisc/provider.h" #include "blackmisc/aviation/aircraftsituation.h"
#include "blackmisc/pq/length.h" #include "blackmisc/aviation/percallsign.h"
#include "blackmisc/geo/coordinategeodeticlist.h" #include "blackmisc/geo/coordinategeodeticlist.h"
#include "blackmisc/geo/elevationplane.h" #include "blackmisc/geo/elevationplane.h"
#include "blackmisc/pq/length.h"
#include "blackmisc/provider.h"
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include <QPair> #include <QPair>
@@ -47,14 +50,26 @@ namespace BlackMisc
//! \threadsafe //! \threadsafe
virtual bool requestElevation(const Geo::ICoordinateGeodetic &reference, const Aviation::CCallsign &callsign) = 0; 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 //! Elevations found/missed statistics
//! \threadsafe //! \threadsafe
QPair<int, int> getElevationsFoundMissed() const; QPair<int, int> getElevationsFoundMissed() const;
//! The elevation request times
//! \threadsafe
QPair<qint64, qint64> getElevationRequestTimes() const;
//! Elevations found/missed statistics info as string //! Elevations found/missed statistics info as string
//! \threadsafe //! \threadsafe
QString getElevationsFoundMissedInfo() const; QString getElevationsFoundMissedInfo() const;
//! Elevation request times
//! \threadsafe
QString getElevationRequestTimesInfo() const;
//! Get the represented plugin //! Get the represented plugin
//! \threadsafe //! \threadsafe
CSimulatorPluginInfo getSimulatorPluginInfo() const; CSimulatorPluginInfo getSimulatorPluginInfo() const;
@@ -85,11 +100,15 @@ namespace BlackMisc
//! Set number of elevations kept //! Set number of elevations kept
//! \threadsafe //! \threadsafe
int setRememberMaxElevations(int max); int setMaxElevationsRemembered(int max);
//! Get number of max. number of elevations //! Get number of max. number of elevations
//! \threadsafe //! \threadsafe
int getRememberMaxElevations() const; int getMaxElevationsRemembered() const;
//! Reset statistics
//! \threadsafe
void resetSimulationEnvironmentStatistics();
protected: protected:
//! Ctor //! Ctor
@@ -145,11 +164,11 @@ namespace BlackMisc
//! Remember a given elevation //! Remember a given elevation
//! \threadsafe //! \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 //! Remember a given elevation
//! \threadsafe //! \threadsafe
bool rememberGroundElevation(const Geo::CElevationPlane &elevationPlane) ; bool rememberGroundElevation(const Aviation::CCallsign &requestedForCallsign, const Geo::CElevationPlane &elevationPlane) ;
//! Insert or replace a CG //! Insert or replace a CG
//! \remark passing a NULL value will remove the CG //! \remark passing a NULL value will remove the CG
@@ -180,12 +199,15 @@ namespace BlackMisc
QString m_simulatorVersion; //!< Simulator version QString m_simulatorVersion; //!< Simulator version
CAircraftModel m_defaultModel; //!< default model CAircraftModel m_defaultModel; //!< default model
int m_maxElevations = 100; //!< How many elevations we keep int m_maxElevations = 100; //!< How many elevations we keep
Geo::CCoordinateGeodeticList m_elvCoordinates; Geo::CCoordinateGeodeticList m_elvCoordinates; //!< elevation cache
QHash<Aviation::CCallsign, PhysicalQuantities::CLength> m_cgsPerCallsign; //! CGs per callsign Aviation::CTimestampPerCallsign m_pendingElevationRequests; //!< pending elevation requests
QHash<QString, PhysicalQuantities::CLength> m_cgsPerModel; //!< CGs per model string Aviation::CLengthPerCallsign m_cgsPerCallsign; //!< CGs per callsign
QHash<QString, PhysicalQuantities::CLength> m_cgsPerModel; //!< CGs per model string
qint64 m_statsMaxElevRequestTimeMs = -1;
qint64 m_statsCurrentElevRequestTimeMs = -1;
mutable int m_elvFound = 0; //!< statistics only mutable int m_elvFound = 0; //!< statistics only
mutable int m_elvMissed = 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_lockCG; //!< lock CGs
mutable QReadWriteLock m_lockModel; //!< lock models mutable QReadWriteLock m_lockModel; //!< lock models
mutable QReadWriteLock m_lockSimInfo; //!< lock plugin info mutable QReadWriteLock m_lockSimInfo; //!< lock plugin info
@@ -213,6 +235,12 @@ namespace BlackMisc
//! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissedInfo //! \copydoc ISimulationEnvironmentProvider::getElevationsFoundMissedInfo
QString getElevationsFoundMissedInfo() const; QString getElevationsFoundMissedInfo() const;
//! \copydoc ISimulationEnvironmentProvider::getElevationRequestTimes
QPair<qint64, qint64> getElevationRequestTimes() const;
//! \copydoc ISimulationEnvironmentProvider::getElevationRequestTimesInfo
QString getElevationRequestTimesInfo() const;
//! \copydoc ISimulationEnvironmentProvider::getSimulatorPluginInfo //! \copydoc ISimulationEnvironmentProvider::getSimulatorPluginInfo
CSimulatorPluginInfo getSimulatorPluginInfo() const; CSimulatorPluginInfo getSimulatorPluginInfo() const;