mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 14:55:36 +08:00
Ref T261, further unify interpolator handling
* return interpolation results parts/situation in one step * base class init for each interpolation step, less redundant code * removed old interpolation/parts function * adjusted unit tests and simulator objects (such as SimObject)
This commit is contained in:
committed by
Roland Winklmeier
parent
bac3d14d50
commit
0808cdb223
@@ -336,7 +336,9 @@ namespace BlackCore
|
||||
//! \param ownAircraftProvider in memory access to own aircraft data
|
||||
//! \param remoteAircraftProvider in memory access to rendered aircraft data such as situation history and aircraft itself
|
||||
//! \param weatherGridProvider in memory access to weather grid data
|
||||
//! \param clientProvider in memory access to client data
|
||||
//! \return driver instance
|
||||
//!
|
||||
virtual ISimulator *create(
|
||||
const BlackMisc::Simulation::CSimulatorPluginInfo &info,
|
||||
BlackMisc::Simulation::IOwnAircraftProvider *ownAircraftProvider,
|
||||
|
||||
@@ -37,16 +37,16 @@ namespace BlackMisc
|
||||
template <typename Derived>
|
||||
CInterpolator<Derived>::CInterpolator(const CCallsign &callsign,
|
||||
ISimulationEnvironmentProvider *simEnvProvider, IInterpolationSetupProvider *setupProvider,
|
||||
IRemoteAircraftProvider *remoteAircraftProvider,
|
||||
IRemoteAircraftProvider *remoteProvider,
|
||||
CInterpolationLogger *logger) : m_callsign(callsign)
|
||||
{
|
||||
// normally when created m_cg is still null since there is no CG in the provider yet
|
||||
|
||||
if (simEnvProvider) { this->setSimulationEnvironmentProvider(simEnvProvider); }
|
||||
if (setupProvider) { this->setInterpolationSetupProvider(setupProvider); }
|
||||
if (remoteAircraftProvider)
|
||||
if (remoteProvider)
|
||||
{
|
||||
this->setRemoteAircraftProvider(remoteAircraftProvider);
|
||||
this->setRemoteAircraftProvider(remoteProvider);
|
||||
QObject::connect(&m_initTimer, &QTimer::timeout, [ = ] { this->deferredInit(); });
|
||||
m_initTimer.setSingleShot(true);
|
||||
m_initTimer.start(2500);
|
||||
@@ -75,13 +75,13 @@ namespace BlackMisc
|
||||
CAircraftSituationList CInterpolator<Derived>::remoteAircraftSituationsAndChange(bool useSceneryOffset)
|
||||
{
|
||||
CAircraftSituationList validSituations = this->remoteAircraftSituations(m_callsign);
|
||||
m_situationChange = CAircraftSituationChange(validSituations, true, true);
|
||||
if (useSceneryOffset && m_situationChange.hasSceneryDeviation() && m_model.hasCG())
|
||||
m_currentSituationChange = CAircraftSituationChange(validSituations, true, true);
|
||||
if (useSceneryOffset && m_currentSituationChange.hasSceneryDeviation() && m_model.hasCG())
|
||||
{
|
||||
const CLength os = m_situationChange.getGuessedSceneryDeviation(m_model.getCG());
|
||||
const CLength os = m_currentSituationChange.getGuessedSceneryDeviation(m_model.getCG());
|
||||
validSituations.addAltitudeOffset(os);
|
||||
m_situationChange = CAircraftSituationChange(validSituations, true, true); // recalculate
|
||||
m_lastSceneryOffset = os;
|
||||
m_currentSituationChange = CAircraftSituationChange(validSituations, true, true); // recalculate
|
||||
m_currentSceneryOffset = os;
|
||||
}
|
||||
return validSituations;
|
||||
}
|
||||
@@ -131,33 +131,36 @@ namespace BlackMisc
|
||||
return cats;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
CAircraftSituation CInterpolator<Derived>::getInterpolatedSituation(
|
||||
qint64 currentTimeMsSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status)
|
||||
template<typename Derived>
|
||||
CInterpolationResult CInterpolator<Derived>::getInterpolation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup)
|
||||
{
|
||||
Q_ASSERT_X(!m_callsign.isEmpty(), Q_FUNC_INFO, "Missing callsign");
|
||||
|
||||
// this code is used by linear and spline interpolator
|
||||
m_interpolatedSituationsCounter++;
|
||||
status.reset();
|
||||
SituationLog log;
|
||||
const bool doLogging = this->hasAttachedLogger() && setup.logInterpolation();
|
||||
|
||||
// any data at all?
|
||||
const CAircraftSituationList situations = this->remoteAircraftSituations(m_callsign);
|
||||
const int situationsCount = situations.size();
|
||||
status.setSituationsCount(situationsCount);
|
||||
if (situations.isEmpty())
|
||||
CInterpolationResult result;
|
||||
do
|
||||
{
|
||||
status.setExtraInfo(this->isAircraftInRange(m_callsign) ?
|
||||
QString("No situations, but remote aircraft '%1'").arg(m_callsign.asString()) :
|
||||
QString("Unknown remote aircraft: '%1'").arg(m_callsign.asString()));
|
||||
return CAircraftSituation(m_callsign);
|
||||
if (!this->initIniterpolationStepData(currentTimeSinceEpoc, setup)) { break; }
|
||||
|
||||
// make sure we can also interpolate parts only (needed in unit tests for instance)
|
||||
const CAircraftSituation interpolatedSituation = this->getInterpolatedSituation();
|
||||
const CAircraftParts interpolatedParts = this->getInterpolatedOrGuessedParts();
|
||||
|
||||
result.setValues(interpolatedSituation, interpolatedParts);
|
||||
}
|
||||
while (false);
|
||||
|
||||
result.setStatus(m_currentInterpolationStatus, m_currentPartsStatus);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
CAircraftSituation CInterpolator<Derived>::getInterpolatedSituation()
|
||||
{
|
||||
if (m_currentSituations.isEmpty())
|
||||
{
|
||||
m_lastInterpolation = CAircraftSituation::null();
|
||||
return CAircraftSituation::null();
|
||||
}
|
||||
|
||||
const CAircraftSituation latest = situations.front();
|
||||
const CAircraftSituation latest = m_currentSituations.front();
|
||||
CAircraftSituation currentSituation = m_lastInterpolation.isNull() ? latest : m_lastInterpolation;
|
||||
if (currentSituation.getCallsign() != m_callsign)
|
||||
{
|
||||
@@ -173,20 +176,18 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
// fetch CG once
|
||||
const CLength cg = latest.hasCG() ? latest.getCG() : this->getAndFetchModelCG();
|
||||
const CLength cg(this->getModelCG());
|
||||
currentSituation.setCG(cg);
|
||||
|
||||
// data, split situations by time
|
||||
if (currentTimeMsSinceEpoc < 0) { currentTimeMsSinceEpoc = QDateTime::currentMSecsSinceEpoch(); }
|
||||
|
||||
// interpolant function from derived class
|
||||
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
|
||||
const auto interpolant = derived()->getInterpolant(currentTimeMsSinceEpoc, setup, status, log);
|
||||
SituationLog log;
|
||||
const auto interpolant = derived()->getInterpolant(log);
|
||||
|
||||
// succeeded so far?
|
||||
if (!status.isInterpolated())
|
||||
if (!m_currentInterpolationStatus.isInterpolated())
|
||||
{
|
||||
status.checkIfValidSituation(currentSituation);
|
||||
m_currentInterpolationStatus.checkIfValidSituation(currentSituation);
|
||||
return currentSituation;
|
||||
}
|
||||
|
||||
@@ -212,20 +213,20 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
// status
|
||||
status.setInterpolatedAndCheckSituation(true, currentSituation);
|
||||
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(true, currentSituation);
|
||||
|
||||
// logging
|
||||
if (doLogging)
|
||||
if (this->doLogging())
|
||||
{
|
||||
static const QString elv("found %1 missed %2");
|
||||
const QPair<int, int> elvStats = this->getElevationsFoundMissed();
|
||||
log.tsCurrent = currentTimeMsSinceEpoc;
|
||||
log.tsCurrent = m_currentTimeMsSinceEpoch;
|
||||
log.callsign = m_callsign;
|
||||
log.groundFactor = currentSituation.getOnGroundFactor();
|
||||
log.altCorrection = CAircraftSituation::altitudeCorrectionToString(altCorrection);
|
||||
log.situationCurrent = currentSituation;
|
||||
log.change = m_situationChange;
|
||||
log.usedSetup = setup;
|
||||
log.change = m_currentSituationChange;
|
||||
log.usedSetup = m_currentSetup;
|
||||
log.elevationInfo = elv.arg(elvStats.first).arg(elvStats.second);
|
||||
log.cgAboveGround = cg;
|
||||
log.sceneryOffset = m_currentSceneryOffset;
|
||||
@@ -238,14 +239,9 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
CAircraftParts CInterpolator<Derived>::getInterpolatedParts(
|
||||
qint64 currentTimeMsSinceEpoch,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup, CPartsStatus &partsStatus, bool log) const
|
||||
CAircraftParts CInterpolator<Derived>::getInterpolatedParts()
|
||||
{
|
||||
// (!) this code is used by linear and spline interpolator
|
||||
Q_UNUSED(setup);
|
||||
partsStatus.reset();
|
||||
if (currentTimeMsSinceEpoch < 0) { currentTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); }
|
||||
|
||||
// Parts are supposed to be in correct order, latest first
|
||||
const CAircraftPartsList validParts = this->remoteAircraftParts(m_callsign);
|
||||
@@ -254,16 +250,16 @@ namespace BlackMisc
|
||||
if (validParts.isEmpty())
|
||||
{
|
||||
static const CAircraftParts emptyParts;
|
||||
this->logParts(currentTimeMsSinceEpoch, emptyParts, validParts.size(), true, log);
|
||||
this->logParts(emptyParts, validParts.size(), true);
|
||||
return emptyParts;
|
||||
}
|
||||
|
||||
partsStatus.setSupportsParts(true);
|
||||
m_currentPartsStatus.setSupportsParts(true);
|
||||
CAircraftParts currentParts;
|
||||
do
|
||||
{
|
||||
// find the first parts earlier than the current time
|
||||
const auto pivot = std::partition_point(validParts.begin(), validParts.end(), [ = ](auto &&p) { return p.getAdjustedMSecsSinceEpoch() > currentTimeMsSinceEpoch; });
|
||||
const auto pivot = std::partition_point(validParts.begin(), validParts.end(), [ = ](auto &&p) { return p.getAdjustedMSecsSinceEpoch() > m_currentTimeMsSinceEpoch; });
|
||||
const auto partsNewer = makeRange(validParts.begin(), pivot).reverse();
|
||||
const auto partsOlder = makeRange(pivot, validParts.end());
|
||||
|
||||
@@ -273,32 +269,38 @@ namespace BlackMisc
|
||||
}
|
||||
while (false);
|
||||
|
||||
this->logParts(currentTimeMsSinceEpoch, currentParts, validParts.size(), false, log);
|
||||
this->logParts(currentParts, validParts.size(), false);
|
||||
return currentParts;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
CAircraftParts CInterpolator<Derived>::getInterpolatedOrGuessedParts(qint64 currentTimeMsSinceEpoch, const CInterpolationAndRenderingSetupPerCallsign &setup, CPartsStatus &partsStatus, bool log) const
|
||||
CAircraftParts CInterpolator<Derived>::getInterpolatedOrGuessedParts()
|
||||
{
|
||||
CAircraftParts parts;
|
||||
if (setup.isAircraftPartsEnabled()) { parts = this->getInterpolatedParts(currentTimeMsSinceEpoch, setup, partsStatus, log); }
|
||||
if (!partsStatus.isSupportingParts())
|
||||
if (m_currentSetup.isAircraftPartsEnabled()) { parts = this->getInterpolatedParts(); }
|
||||
if (!m_currentPartsStatus.isSupportingParts())
|
||||
{
|
||||
// check if model has been thru model matching
|
||||
parts.guessParts(this->getLastInterpolatedSituation(), m_situationChange, m_model);
|
||||
parts.guessParts(m_lastInterpolation, m_currentSituationChange, m_model);
|
||||
}
|
||||
this->logParts(currentTimeMsSinceEpoch, parts, 0, false, log);
|
||||
this->logParts(parts, 0, false);
|
||||
return parts;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
void CInterpolator<Derived>::logParts(qint64 timestamp, const CAircraftParts &parts, int partsNo, bool empty, bool log) const
|
||||
bool CInterpolator<Derived>::doLogging() const
|
||||
{
|
||||
if (!log || !m_logger) { return; }
|
||||
return this->hasAttachedLogger() && m_currentSetup.logInterpolation();
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
void CInterpolator<Derived>::logParts(const CAircraftParts &parts, int partsNo, bool empty) const
|
||||
{
|
||||
if (!this->doLogging()) { return; }
|
||||
PartsLog logInfo;
|
||||
logInfo.callsign = m_callsign;
|
||||
logInfo.noNetworkParts = partsNo;
|
||||
logInfo.tsCurrent = timestamp;
|
||||
logInfo.tsCurrent = m_currentTimeMsSinceEpoch;
|
||||
logInfo.parts = parts;
|
||||
logInfo.empty = empty;
|
||||
m_logger->logParts(logInfo);
|
||||
@@ -328,6 +330,57 @@ namespace BlackMisc
|
||||
{
|
||||
this->resetLastInterpolation();
|
||||
m_model = CAircraftModel();
|
||||
m_currentSceneryOffset = CLength::null();
|
||||
m_currentSituationChange = CAircraftSituationChange::null();
|
||||
m_currentSituations.clear();
|
||||
m_currentTimeMsSinceEpoch = -1;
|
||||
m_situationsLastModified = -1;
|
||||
m_situationsLastModifiedUsed = -1;
|
||||
m_currentInterpolationStatus.reset();
|
||||
m_currentPartsStatus.reset();
|
||||
m_interpolatedSituationsCounter = 0;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
bool CInterpolator<Derived>::initIniterpolationStepData(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup)
|
||||
{
|
||||
Q_ASSERT_X(!m_callsign.isEmpty(), Q_FUNC_INFO, "Missing callsign");
|
||||
|
||||
const bool slowUpdates = ((m_interpolatedSituationsCounter % 25) == 0);
|
||||
m_currentTimeMsSinceEpoch = currentTimeSinceEpoc;
|
||||
m_situationsLastModified = this->situationsLastModified(m_callsign);
|
||||
m_currentSetup = setup;
|
||||
m_currentSituations = this->remoteAircraftSituationsAndChange(true);
|
||||
m_currentInterpolationStatus.reset();
|
||||
m_currentPartsStatus.reset();
|
||||
|
||||
if (!m_model.hasCG() || slowUpdates)
|
||||
{
|
||||
this->getAndFetchModelCG(); // update CG
|
||||
}
|
||||
|
||||
m_currentInterpolationStatus.setSituationsCount(m_currentSituations.size());
|
||||
if (m_currentSituations.isEmpty())
|
||||
{
|
||||
m_lastInterpolation = CAircraftSituation::null(); // no interpolation possible for that step
|
||||
m_currentInterpolationStatus.setExtraInfo(this->isAircraftInRange(m_callsign) ?
|
||||
QString("No situations, but remote aircraft '%1'").arg(m_callsign.asString()) :
|
||||
QString("Unknown remote aircraft: '%1'").arg(m_callsign.asString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_interpolatedSituationsCounter++;
|
||||
|
||||
// with the latest updates of T243 the order and the offsets are supposed to be correct
|
||||
// so even mixing fast/slow updates shall work
|
||||
if (!CBuildConfig::isReleaseBuild())
|
||||
{
|
||||
Q_ASSERT_X(m_currentSituations.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "Wrong sort order");
|
||||
Q_ASSERT_X(m_currentSituations.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
@@ -345,12 +398,32 @@ namespace BlackMisc
|
||||
m_model = model;
|
||||
}
|
||||
}
|
||||
if (m_model.getCG().isNull())
|
||||
{
|
||||
const CLength cg(this->getCG(m_callsign));
|
||||
if (!cg.isNull()) { m_model.setCG(cg); }
|
||||
}
|
||||
m_model.setCallsign(m_callsign);
|
||||
this->getAndFetchModelCG();
|
||||
}
|
||||
|
||||
CInterpolationResult::CInterpolationResult()
|
||||
{
|
||||
this->reset();
|
||||
}
|
||||
|
||||
void CInterpolationResult::setValues(const CAircraftSituation &situation, const CAircraftParts &parts)
|
||||
{
|
||||
m_interpolatedSituation = situation;
|
||||
m_interpolatedParts = parts;
|
||||
}
|
||||
|
||||
void CInterpolationResult::setStatus(const CInterpolationStatus &interpolation, const CPartsStatus &parts)
|
||||
{
|
||||
m_interpolationStatus = interpolation;
|
||||
m_partsStatus = parts;
|
||||
}
|
||||
|
||||
void CInterpolationResult::reset()
|
||||
{
|
||||
m_interpolatedSituation = CAircraftSituation::null();
|
||||
m_interpolatedParts = CAircraftParts::null();
|
||||
m_interpolationStatus.reset();
|
||||
m_partsStatus.reset();
|
||||
}
|
||||
|
||||
void CInterpolationStatus::setExtraInfo(const QString &info)
|
||||
|
||||
@@ -35,108 +35,6 @@ namespace BlackMisc
|
||||
class CInterpolationLogger;
|
||||
class CInterpolatorLinear;
|
||||
class CInterpolatorSpline;
|
||||
struct CInterpolationStatus;
|
||||
struct CPartsStatus;
|
||||
|
||||
//! Interpolator, calculation inbetween positions
|
||||
template <typename Derived>
|
||||
class CInterpolator :
|
||||
protected CSimulationEnvironmentAware,
|
||||
protected CInterpolationSetupAware,
|
||||
protected CRemoteAircraftAware
|
||||
{
|
||||
public:
|
||||
//! Log categories
|
||||
const CLogCategoryList &getLogCategories();
|
||||
|
||||
//! Current interpolated situation
|
||||
Aviation::CAircraftSituation getInterpolatedSituation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup, CInterpolationStatus &status);
|
||||
|
||||
//! Parts before given offset time
|
||||
Aviation::CAircraftParts getInterpolatedParts(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup, CPartsStatus &partsStatus, bool log = false) const;
|
||||
|
||||
//! Interpolated parts, if not available guessed parts
|
||||
Aviation::CAircraftParts getInterpolatedOrGuessedParts(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup, CPartsStatus &partsStatus, bool log = false) const;
|
||||
|
||||
//! Latest interpolation result
|
||||
const Aviation::CAircraftSituation &getLastInterpolatedSituation() const { return m_lastInterpolation; }
|
||||
|
||||
//! Takes input between 0 and 1 and returns output between 0 and 1 smoothed with an S-shaped curve.
|
||||
//!
|
||||
//! Useful for making interpolation seem smoother, efficiently as it just uses simple arithmetic.
|
||||
//! \see https://en.wikipedia.org/wiki/Smoothstep
|
||||
//! \see http://sol.gfxile.net/interpolation/
|
||||
static double smootherStep(double x)
|
||||
{
|
||||
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
//! Attach an observer to read the interpolator's state for debugging
|
||||
//! \remark parts logging has a \c bool \c log flag
|
||||
void attachLogger(CInterpolationLogger *logger) { m_logger = logger; }
|
||||
|
||||
//! Is logger attached?
|
||||
bool hasAttachedLogger() const { return m_logger; }
|
||||
|
||||
//! Get an interpolator info string (for debug info)
|
||||
QString getInterpolatorInfo() const;
|
||||
|
||||
//! Reset last interpolation to null
|
||||
//! \remark mainly needed in UNIT tests
|
||||
void resetLastInterpolation();
|
||||
|
||||
//! Clear all data
|
||||
//! \remark mainly needed in UNIT tests
|
||||
void clear();
|
||||
|
||||
//! Init, or re-init the corressponding model
|
||||
//! \remark either by passing a model or using the provider
|
||||
void initCorrespondingModel(const CAircraftModel &model = {});
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
CInterpolator(const Aviation::CCallsign &callsign,
|
||||
ISimulationEnvironmentProvider *simEnvProvider, IInterpolationSetupProvider *setupProvider, IRemoteAircraftProvider *p3,
|
||||
CInterpolationLogger *logger);
|
||||
|
||||
//! Center of gravity
|
||||
const PhysicalQuantities::CLength &getModelCG() const { return m_model.getCG(); }
|
||||
|
||||
//! Center of gravity, fetched from provider in case needed
|
||||
PhysicalQuantities::CLength getAndFetchModelCG();
|
||||
|
||||
//! Decides threshold when situation is considered on ground
|
||||
//! \sa BlackMisc::Aviation::CAircraftSituation::setOnGroundFromGroundFactorFromInterpolation
|
||||
static double groundInterpolationFactor();
|
||||
|
||||
CAircraftModel m_model; //!< corresponding model
|
||||
const Aviation::CCallsign m_callsign; //!< corresponding callsign
|
||||
Aviation::CAircraftSituation m_lastInterpolation { Aviation::CAircraftSituation::null() }; //!< latest interpolation
|
||||
Aviation::CAircraftSituationChange m_situationChange; //!< situations change
|
||||
PhysicalQuantities::CLength m_lastSceneryOffset = PhysicalQuantities::CLength::null();
|
||||
qint64 m_situationsLastModifiedUsed { -1 }; //!< based on situations last updated
|
||||
int m_interpolatedSituationsCounter = 0; //!< counter for each interpolated situations: statistics, every n-th interpolation ....
|
||||
|
||||
//! Get situations and calculate change, also correct altitudes if applicable
|
||||
Aviation::CAircraftSituationList remoteAircraftSituationsAndChange(bool useSceneryOffset);
|
||||
|
||||
//! Verify gnd flag, times, ... true means "OK"
|
||||
bool verifyInterpolationSituations(const Aviation::CAircraftSituation &oldest, const Aviation::CAircraftSituation &newer, const Aviation::CAircraftSituation &latest,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup = CInterpolationAndRenderingSetupPerCallsign::null());
|
||||
|
||||
private:
|
||||
CInterpolationLogger *m_logger = nullptr; //!< optional interpolation logger
|
||||
QTimer m_initTimer; //!< timer to init model, will be deleted when interpolator is deleted and cancel the call
|
||||
|
||||
//! Log parts
|
||||
void logParts(qint64 timestamp, const Aviation::CAircraftParts &parts, int partsNo, bool empty, bool log) const;
|
||||
|
||||
//! Deferred init
|
||||
void deferredInit();
|
||||
|
||||
Derived *derived() { return static_cast<Derived *>(this); }
|
||||
const Derived *derived() const { return static_cast<const Derived *>(this); }
|
||||
};
|
||||
|
||||
//! Status of interpolation
|
||||
struct BLACKMISC_EXPORT CInterpolationStatus
|
||||
@@ -183,6 +81,12 @@ namespace BlackMisc
|
||||
struct BLACKMISC_EXPORT CPartsStatus
|
||||
{
|
||||
public:
|
||||
//! Ctor
|
||||
CPartsStatus() {}
|
||||
|
||||
//! Ctor
|
||||
CPartsStatus(bool supportsParts) : m_supportsParts(supportsParts) {}
|
||||
|
||||
//! all OK
|
||||
bool allTrue() const;
|
||||
|
||||
@@ -195,16 +99,182 @@ namespace BlackMisc
|
||||
//! Reset to default values
|
||||
void reset();
|
||||
|
||||
//! Ctor
|
||||
CPartsStatus() {}
|
||||
|
||||
//! Ctor
|
||||
CPartsStatus(bool supportsParts) : m_supportsParts(supportsParts) {}
|
||||
|
||||
private:
|
||||
bool m_supportsParts = false; //!< supports parts for given callsign
|
||||
};
|
||||
|
||||
//! Combined results
|
||||
class BLACKMISC_EXPORT CInterpolationResult
|
||||
{
|
||||
public:
|
||||
//! Ctor
|
||||
CInterpolationResult();
|
||||
|
||||
//! Get situation
|
||||
const Aviation::CAircraftSituation &getInterpolatedSituation() const { return m_interpolatedSituation; }
|
||||
|
||||
//! Get parts (interpolated or guessed)
|
||||
const Aviation::CAircraftParts &getInterpolatedParts() const { return m_interpolatedParts; }
|
||||
|
||||
//! Get status
|
||||
const CInterpolationStatus &getInterpolationStatus() const { return m_interpolationStatus; }
|
||||
|
||||
//! Get status
|
||||
const CPartsStatus &getPartsStatus() const { return m_partsStatus; }
|
||||
|
||||
//! Set situation
|
||||
void setInterpolatedSituation(const Aviation::CAircraftSituation &situation) { m_interpolatedSituation = situation; }
|
||||
|
||||
//! Set parts (interpolated or guessed)
|
||||
void setInterpolatedParts(const Aviation::CAircraftParts &parts) { m_interpolatedParts = parts; }
|
||||
|
||||
//! Set values
|
||||
void setValues(const Aviation::CAircraftSituation &situation, const Aviation::CAircraftParts &parts);
|
||||
|
||||
//! Set status
|
||||
void setInterpolationStatus(const CInterpolationStatus &status) { m_interpolationStatus = status; }
|
||||
|
||||
//! Set status
|
||||
void setPartsStatus(const CPartsStatus &status) { m_partsStatus = status; }
|
||||
|
||||
//! Set status values
|
||||
void setStatus(const CInterpolationStatus &interpolation, const CPartsStatus &parts);
|
||||
|
||||
//! Reset values
|
||||
void reset();
|
||||
|
||||
//! Implicit conversion @{
|
||||
operator const Aviation::CAircraftSituation &() const { return m_interpolatedSituation; }
|
||||
operator const Aviation::CAircraftParts &() const { return m_interpolatedParts; }
|
||||
//! @}
|
||||
|
||||
private:
|
||||
Aviation::CAircraftSituation m_interpolatedSituation; //!< interpolated situation
|
||||
Aviation::CAircraftParts m_interpolatedParts; //!< guessed or interpolated parts
|
||||
CInterpolationStatus m_interpolationStatus; //!< interpolation status
|
||||
CPartsStatus m_partsStatus; //!< parts status
|
||||
};
|
||||
|
||||
//! Interpolator, calculation inbetween positions
|
||||
template <typename Derived>
|
||||
class CInterpolator :
|
||||
protected CSimulationEnvironmentAware,
|
||||
protected CInterpolationSetupAware,
|
||||
protected CRemoteAircraftAware
|
||||
{
|
||||
public:
|
||||
//! Log categories
|
||||
static const CLogCategoryList &getLogCategories();
|
||||
|
||||
//! Latest interpolation result
|
||||
const Aviation::CAircraftSituation &getLastInterpolatedSituation() const { return m_lastInterpolation; }
|
||||
|
||||
//! Parts and situation interpolated
|
||||
CInterpolationResult getInterpolation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup);
|
||||
|
||||
//! Takes input between 0 and 1 and returns output between 0 and 1 smoothed with an S-shaped curve.
|
||||
//!
|
||||
//! Useful for making interpolation seem smoother, efficiently as it just uses simple arithmetic.
|
||||
//! \see https://en.wikipedia.org/wiki/Smoothstep
|
||||
//! \see http://sol.gfxile.net/interpolation/
|
||||
static double smootherStep(double x)
|
||||
{
|
||||
return x * x * x * (x * (x * 6.0 - 15.0) + 10.0);
|
||||
}
|
||||
|
||||
//! Attach an observer to read the interpolator's state for debugging
|
||||
//! \remark parts logging has a \c bool \c log flag
|
||||
void attachLogger(CInterpolationLogger *logger) { m_logger = logger; }
|
||||
|
||||
//! Is logger attached?
|
||||
bool hasAttachedLogger() const { return m_logger; }
|
||||
|
||||
//! Get an interpolator info string (for debug info)
|
||||
QString getInterpolatorInfo() const;
|
||||
|
||||
//! Reset last interpolation to null
|
||||
//! \remark mainly needed in UNIT tests
|
||||
void resetLastInterpolation();
|
||||
|
||||
//! Clear all data
|
||||
//! \remark mainly needed in UNIT tests
|
||||
void clear();
|
||||
|
||||
//! Init, or re-init the corressponding model
|
||||
//! \remark either by passing a model or using the provider
|
||||
void initCorrespondingModel(const CAircraftModel &model = {});
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
CInterpolator(const Aviation::CCallsign &callsign,
|
||||
ISimulationEnvironmentProvider *simEnvProvider, IInterpolationSetupProvider *setupProvider, IRemoteAircraftProvider *remoteProvider,
|
||||
CInterpolationLogger *logger);
|
||||
|
||||
//! Inits all data for this current interpolation step
|
||||
bool initIniterpolationStepData(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup);
|
||||
|
||||
//! Current interpolated situation
|
||||
Aviation::CAircraftSituation getInterpolatedSituation();
|
||||
|
||||
//! Parts before given offset time
|
||||
Aviation::CAircraftParts getInterpolatedParts();
|
||||
|
||||
//! Interpolated parts, if not available guessed parts
|
||||
Aviation::CAircraftParts getInterpolatedOrGuessedParts();
|
||||
|
||||
//! Center of gravity
|
||||
const PhysicalQuantities::CLength &getModelCG() const { return m_model.getCG(); }
|
||||
|
||||
//! Do logging
|
||||
bool doLogging() const;
|
||||
|
||||
//! Decides threshold when situation is considered on ground
|
||||
//! \sa BlackMisc::Aviation::CAircraftSituation::setOnGroundFromGroundFactorFromInterpolation
|
||||
static double groundInterpolationFactor();
|
||||
|
||||
const Aviation::CCallsign m_callsign; //!< corresponding callsign
|
||||
CAircraftModel m_model; //!< corresponding model
|
||||
|
||||
// values for current interpolation step
|
||||
qint64 m_currentTimeMsSinceEpoch = -1; //!< current time
|
||||
Aviation::CAircraftSituationList m_currentSituations; //!< current situations
|
||||
Aviation::CAircraftSituationChange m_currentSituationChange; //!< situations change
|
||||
PhysicalQuantities::CLength m_currentSceneryOffset = PhysicalQuantities::CLength::null(); //!< calculated scenery offset if any
|
||||
CInterpolationAndRenderingSetupPerCallsign m_currentSetup; //!< used setup
|
||||
CInterpolationStatus m_currentInterpolationStatus; //!< this step's status
|
||||
CPartsStatus m_currentPartsStatus; //!< this step's status
|
||||
Aviation::CAircraftSituation m_lastInterpolation { Aviation::CAircraftSituation::null() }; //!< latest interpolation
|
||||
|
||||
qint64 m_situationsLastModified { -1 }; //!< whehn situations were last modified
|
||||
qint64 m_situationsLastModifiedUsed { -1 }; //!< interpolant based on situations last updated
|
||||
int m_interpolatedSituationsCounter { 0 }; //!< counter for each interpolated situations: statistics, every n-th interpolation ....
|
||||
|
||||
|
||||
//! Verify gnd flag, times, ... true means "OK"
|
||||
bool verifyInterpolationSituations(const Aviation::CAircraftSituation &oldest, const Aviation::CAircraftSituation &newer, const Aviation::CAircraftSituation &latest,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup = CInterpolationAndRenderingSetupPerCallsign::null());
|
||||
|
||||
private:
|
||||
CInterpolationLogger *m_logger = nullptr; //!< optional interpolation logger
|
||||
QTimer m_initTimer; //!< timer to init model, will be deleted when interpolator is deleted and cancel the call
|
||||
|
||||
//! Log parts
|
||||
void logParts(const Aviation::CAircraftParts &parts, int partsNo, bool empty) const;
|
||||
|
||||
//! Get situations and calculate change, also correct altitudes if applicable
|
||||
//! \remark calculates offset (scenery) and situations change
|
||||
Aviation::CAircraftSituationList remoteAircraftSituationsAndChange(bool useSceneryOffset);
|
||||
|
||||
//! Center of gravity, fetched from provider in case needed
|
||||
PhysicalQuantities::CLength getAndFetchModelCG();
|
||||
|
||||
//! Deferred init
|
||||
void deferredInit();
|
||||
|
||||
Derived *derived() { return static_cast<Derived *>(this); }
|
||||
const Derived *derived() const { return static_cast<const Derived *>(this); }
|
||||
};
|
||||
|
||||
//! \cond PRIVATE
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE CInterpolator<CInterpolatorLinear>;
|
||||
extern template class BLACKMISC_EXPORT_DECLARE_TEMPLATE CInterpolator<CInterpolatorSpline>;
|
||||
|
||||
@@ -97,37 +97,20 @@ namespace BlackMisc
|
||||
return newSituation;
|
||||
}
|
||||
|
||||
CInterpolatorLinear::CInterpolant CInterpolatorLinear::getInterpolant(
|
||||
qint64 currentTimeMsSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status, SituationLog &log)
|
||||
CInterpolatorLinear::CInterpolant CInterpolatorLinear::getInterpolant(SituationLog &log)
|
||||
{
|
||||
Q_UNUSED(setup);
|
||||
status.reset();
|
||||
|
||||
const qint64 tsLastModified = this->situationsLastModified(m_callsign);
|
||||
|
||||
// set default situations
|
||||
CAircraftSituation oldSituation = m_interpolant.getOldSituation();
|
||||
CAircraftSituation newSituation = m_interpolant.getNewSituation();
|
||||
|
||||
if (m_situationsLastModifiedUsed < tsLastModified || m_situationChange.isNull())
|
||||
if (m_situationsLastModifiedUsed < m_situationsLastModified)
|
||||
{
|
||||
m_situationsLastModifiedUsed = tsLastModified;
|
||||
|
||||
// with the latest updates of T243 the order and the offsets are supposed to be correct
|
||||
// so even mixing fast/slow updates shall work
|
||||
const CAircraftSituationList validSituations = this->remoteAircraftSituationsAndChange(true);
|
||||
if (!CBuildConfig::isReleaseBuild())
|
||||
{
|
||||
BLACK_VERIFY_X(validSituations.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "Wrong sort order");
|
||||
Q_ASSERT_X(validSituations.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size");
|
||||
}
|
||||
m_situationsLastModifiedUsed = m_situationsLastModified;
|
||||
|
||||
// find the first situation earlier than the current time
|
||||
const auto pivot = std::partition_point(validSituations.begin(), validSituations.end(), [ = ](auto &&s) { return s.getAdjustedMSecsSinceEpoch() > currentTimeMsSinceEpoc; });
|
||||
const auto situationsNewer = makeRange(validSituations.begin(), pivot);
|
||||
const auto situationsOlder = makeRange(pivot, validSituations.end());
|
||||
const auto pivot = std::partition_point(m_currentSituations.begin(), m_currentSituations.end(), [ = ](auto &&s) { return s.getAdjustedMSecsSinceEpoch() > m_currentTimeMsSinceEpoch; });
|
||||
const auto situationsNewer = makeRange(m_currentSituations.begin(), pivot);
|
||||
const auto situationsOlder = makeRange(pivot, m_currentSituations.end());
|
||||
|
||||
// latest first, now 00:20 split time
|
||||
// time pos
|
||||
@@ -146,7 +129,7 @@ namespace BlackMisc
|
||||
if (situationsOlder.isEmpty())
|
||||
{
|
||||
const CAircraftSituation currentSituation(*(situationsNewer.end() - 1)); // oldest newest
|
||||
status.setInterpolatedAndCheckSituation(false, currentSituation);
|
||||
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(false, currentSituation);
|
||||
m_interpolant = { currentSituation };
|
||||
return m_interpolant;
|
||||
}
|
||||
@@ -155,7 +138,7 @@ namespace BlackMisc
|
||||
if (situationsOlder.size() < 2)
|
||||
{
|
||||
const CAircraftSituation currentSituation(situationsOlder.front()); // latest oldest
|
||||
status.setInterpolatedAndCheckSituation(false, currentSituation);
|
||||
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(false, currentSituation);
|
||||
m_interpolant = { currentSituation };
|
||||
return m_interpolant;
|
||||
}
|
||||
@@ -195,18 +178,18 @@ namespace BlackMisc
|
||||
// < 0 should not happen due to the split, > 1 can happen if new values are delayed beyond split time
|
||||
// 1) values > 1 mean extrapolation
|
||||
// 2) values > 2 mean no new situations coming in
|
||||
const double distanceToSplitTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - currentTimeMsSinceEpoc;
|
||||
const double distanceToSplitTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - m_currentTimeMsSinceEpoch;
|
||||
const double simulationTimeFraction = qMax(1.0 - (distanceToSplitTimeMs / sampleDeltaTimeMs), 0.0);
|
||||
const double deltaTimeFractionMs = sampleDeltaTimeMs * simulationTimeFraction;
|
||||
const qint64 interpolatedTime = oldSituation.getMSecsSinceEpoch() + deltaTimeFractionMs;
|
||||
|
||||
currentSituation.setTimeOffsetMs(oldSituation.getTimeOffsetMs() + (newSituation.getTimeOffsetMs() - oldSituation.getTimeOffsetMs()) * simulationTimeFraction);
|
||||
currentSituation.setMSecsSinceEpoch(interpolatedTime);
|
||||
status.setInterpolatedAndCheckSituation(true, currentSituation);
|
||||
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(true, currentSituation);
|
||||
|
||||
if (this->hasAttachedLogger() && setup.logInterpolation())
|
||||
if (this->doLogging())
|
||||
{
|
||||
log.tsCurrent = currentTimeMsSinceEpoc;
|
||||
log.tsCurrent = m_currentTimeMsSinceEpoch;
|
||||
log.deltaSampleTimesMs = sampleDeltaTimeMs;
|
||||
log.simTimeFraction = simulationTimeFraction;
|
||||
log.deltaSampleTimesMs = sampleDeltaTimeMs;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace BlackMisc
|
||||
};
|
||||
|
||||
//! Get the interpolant for the given time point
|
||||
CInterpolant getInterpolant(qint64 currentTimeMsSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup, CInterpolationStatus &status, SituationLog &log);
|
||||
CInterpolant getInterpolant(SituationLog &log);
|
||||
|
||||
private:
|
||||
CInterpolant m_interpolant; //!< current interpolant
|
||||
|
||||
@@ -22,45 +22,16 @@ namespace BlackMisc
|
||||
m_linear(callsign, p1, p2, p3, logger)
|
||||
{}
|
||||
|
||||
CAircraftSituation CInterpolatorMulti::getInterpolatedSituation(qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status)
|
||||
CInterpolationResult CInterpolatorMulti::getInterpolation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup)
|
||||
{
|
||||
switch (setup.getInterpolatorMode())
|
||||
{
|
||||
case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
|
||||
case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
|
||||
case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolation(currentTimeSinceEpoc, setup);
|
||||
case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolation(currentTimeSinceEpoc, setup);
|
||||
default: break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
CAircraftParts CInterpolatorMulti::getInterpolatedParts(
|
||||
qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const
|
||||
{
|
||||
switch (setup.getInterpolatorMode())
|
||||
{
|
||||
// currently calls the same interpolation for parts
|
||||
case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
default: break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
CAircraftParts CInterpolatorMulti::getInterpolatedOrGuessedParts(
|
||||
qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const
|
||||
{
|
||||
switch (setup.getInterpolatorMode())
|
||||
{
|
||||
// currently calls the same interpolation for parts
|
||||
case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
default: break;
|
||||
}
|
||||
return {};
|
||||
return CInterpolationResult();
|
||||
}
|
||||
|
||||
const CAircraftSituation &CInterpolatorMulti::getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
|
||||
|
||||
@@ -28,20 +28,8 @@ namespace BlackMisc
|
||||
ISimulationEnvironmentProvider *p1, IInterpolationSetupProvider *p2, IRemoteAircraftProvider *p3,
|
||||
CInterpolationLogger *logger = nullptr);
|
||||
|
||||
//! \copydoc CInterpolator::getInterpolatedSituation
|
||||
Aviation::CAircraftSituation getInterpolatedSituation(
|
||||
qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status);
|
||||
|
||||
//! \copydoc CInterpolator::getInterpolatedParts
|
||||
Aviation::CAircraftParts getInterpolatedParts(
|
||||
qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log = false) const;
|
||||
|
||||
//! \copydoc CInterpolator::getInterpolatedOrGuessedParts
|
||||
Aviation::CAircraftParts getInterpolatedOrGuessedParts(
|
||||
qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const;
|
||||
//! \copydoc CInterpolator::getInterpolation
|
||||
CInterpolationResult getInterpolation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup);
|
||||
|
||||
//! \copydoc CInterpolator::getLastInterpolatedSituation
|
||||
const Aviation::CAircraftSituation &getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
|
||||
|
||||
@@ -98,16 +98,16 @@ namespace BlackMisc
|
||||
}
|
||||
}
|
||||
|
||||
bool CInterpolatorSpline::fillSituationsArray(const CAircraftSituationList &validSituations)
|
||||
bool CInterpolatorSpline::fillSituationsArray()
|
||||
{
|
||||
// m_s[0] .. oldest -> m_[2] .. latest
|
||||
// general idea, we interpolate from current situation -> latest situation
|
||||
|
||||
if (m_lastInterpolation.isNull())
|
||||
{
|
||||
if (!validSituations.isEmpty())
|
||||
if (!m_currentSituations.isEmpty())
|
||||
{
|
||||
m_s[0] = m_s[1] = m_s[2] = validSituations.front();
|
||||
m_s[0] = m_s[1] = m_s[2] = m_currentSituations.front();
|
||||
m_s[0].addMsecs(-CFsdSetup::c_positionTimeOffsetMsec * 2);
|
||||
m_s[1].addMsecs(-CFsdSetup::c_positionTimeOffsetMsec);
|
||||
return true;
|
||||
@@ -120,20 +120,17 @@ namespace BlackMisc
|
||||
m_s[0] = m_s[1] = m_s[2] = m_lastInterpolation; // current
|
||||
m_s[0].addMsecs(-CFsdSetup::c_positionTimeOffsetMsec); // oldest
|
||||
m_s[2].addMsecs(CFsdSetup::c_positionTimeOffsetMsec); // latest
|
||||
if (validSituations.isEmpty()) { return true; }
|
||||
if (m_currentSituations.isEmpty()) { return true; }
|
||||
}
|
||||
|
||||
const qint64 currentAdjusted = m_s[1].getAdjustedMSecsSinceEpoch();
|
||||
const CAircraftSituation latest = validSituations.front();
|
||||
const CAircraftSituation latest = m_currentSituations.front();
|
||||
if (latest.isNewerThanAdjusted(m_s[1])) { m_s[2] = latest; }
|
||||
const CAircraftSituation older = validSituations.findObjectBeforeAdjustedOrDefault(currentAdjusted);
|
||||
const CAircraftSituation older = m_currentSituations.findObjectBeforeAdjustedOrDefault(currentAdjusted);
|
||||
if (!older.isNull()) { m_s[0] = older; }
|
||||
|
||||
if (CBuildConfig::isLocalDeveloperDebugBuild())
|
||||
{
|
||||
BLACK_VERIFY_X(validSituations.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "Wrong sort order");
|
||||
BLACK_VERIFY_X(validSituations.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size");
|
||||
|
||||
const bool verified = this->verifyInterpolationSituations(m_s[0], m_s[1], m_s[2]); // oldest -> latest, only verify order
|
||||
if (!verified)
|
||||
{
|
||||
@@ -145,25 +142,16 @@ namespace BlackMisc
|
||||
return true;
|
||||
}
|
||||
|
||||
CInterpolatorSpline::CInterpolant CInterpolatorSpline::getInterpolant(
|
||||
qint64 currentTimeMsSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status,
|
||||
SituationLog &log)
|
||||
CInterpolatorSpline::CInterpolant CInterpolatorSpline::getInterpolant(SituationLog &log)
|
||||
{
|
||||
Q_UNUSED(setup);
|
||||
|
||||
// recalculate derivatives only if they changed
|
||||
const qint64 lastModified = this->situationsLastModified(m_callsign);
|
||||
const bool recalculate = lastModified > m_situationsLastModifiedUsed;
|
||||
int situationsSize = -1;
|
||||
const bool recalculate = m_situationsLastModified > m_situationsLastModifiedUsed;
|
||||
if (recalculate)
|
||||
{
|
||||
// with the latest updates of T243 the order and the offsets are supposed to be correct
|
||||
// so even mixing fast/slow updates shall work
|
||||
m_situationsLastModifiedUsed = lastModified;
|
||||
const CAircraftSituationList validSituations = this->remoteAircraftSituationsAndChange(true);
|
||||
const bool fillStatus = this->fillSituationsArray(validSituations);
|
||||
m_situationsLastModifiedUsed = m_situationsLastModified;
|
||||
const bool fillStatus = this->fillSituationsArray();
|
||||
if (!fillStatus)
|
||||
{
|
||||
return m_interpolant;
|
||||
@@ -186,7 +174,7 @@ namespace BlackMisc
|
||||
// - and the elevation remains (almost) constant for a wider area
|
||||
// - during flying the ground elevation not really matters
|
||||
this->updateElevations();
|
||||
const CLength cg(m_s[2].hasCG() ? m_s[2].getCG() : this->getAndFetchModelCG());
|
||||
const CLength cg(this->getModelCG());
|
||||
const double a0 = m_s[0].getCorrectedAltitude(cg).value(); // oldest
|
||||
const double a1 = m_s[1].getCorrectedAltitude(cg).value();
|
||||
const double a2 = m_s[2].getCorrectedAltitude(cg).value(); // latest
|
||||
@@ -214,7 +202,7 @@ namespace BlackMisc
|
||||
// cur.time 6: dt1=6-5=1, dt2=7-5 => fraction 1/2
|
||||
// cur.time 9: dt1=9-7=2, dt2=10-7=3 => fraction 2/3
|
||||
// we use different offset times for fast pos. updates
|
||||
const double dt1 = static_cast<double>(currentTimeMsSinceEpoc - m_prevSampleAdjustedTime);
|
||||
const double dt1 = static_cast<double>(m_currentTimeMsSinceEpoch - m_prevSampleAdjustedTime);
|
||||
const double dt2 = static_cast<double>(m_nextSampleAdjustedTime - m_prevSampleAdjustedTime);
|
||||
const double timeFraction = dt1 / dt2;
|
||||
|
||||
@@ -224,19 +212,19 @@ namespace BlackMisc
|
||||
const qint64 interpolatedTime = m_prevSampleTime + timeFraction * dt2;
|
||||
|
||||
// time fraction is expected between 0-1
|
||||
status.setInterpolated(true);
|
||||
m_interpolant.setTimes(currentTimeMsSinceEpoc, timeFraction, interpolatedTime);
|
||||
m_currentInterpolationStatus.setInterpolated(true);
|
||||
m_interpolant.setTimes(m_currentTimeMsSinceEpoch, timeFraction, interpolatedTime);
|
||||
|
||||
if (this->hasAttachedLogger() && setup.logInterpolation())
|
||||
if (this->doLogging())
|
||||
{
|
||||
if (situationsSize < 0) { situationsSize = this->remoteAircraftSituationsCount(m_callsign); }
|
||||
log.interpolationSituations.clear();
|
||||
log.interpolationSituations.push_back(m_s[0]);
|
||||
log.interpolationSituations.push_back(m_s[1]);
|
||||
log.interpolationSituations.push_back(m_s[2]); // latest at end
|
||||
log.noNetworkSituations = m_currentSituations.size();
|
||||
log.interpolator = 's';
|
||||
log.deltaSampleTimesMs = dt2;
|
||||
log.simTimeFraction = timeFraction;
|
||||
log.noNetworkSituations = situationsSize;
|
||||
log.tsInterpolated = interpolatedTime; // without offsets
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ namespace BlackMisc
|
||||
public:
|
||||
//! Constructor
|
||||
CInterpolatorSpline(const Aviation::CCallsign &callsign,
|
||||
ISimulationEnvironmentProvider *p1, IInterpolationSetupProvider *p2, IRemoteAircraftProvider *p3,
|
||||
ISimulationEnvironmentProvider *envProvider, IInterpolationSetupProvider *setupProvider, IRemoteAircraftProvider *aircraftProvider,
|
||||
CInterpolationLogger *logger = nullptr) :
|
||||
CInterpolator(callsign, p1, p2, p3, logger) {}
|
||||
CInterpolator(callsign, envProvider, setupProvider, aircraftProvider, logger) {}
|
||||
|
||||
//! Position arrays for interpolation
|
||||
struct BLACKMISC_EXPORT PosArray
|
||||
@@ -80,8 +80,7 @@ namespace BlackMisc
|
||||
};
|
||||
|
||||
//! Strategy used by CInterpolator::getInterpolatedSituation
|
||||
CInterpolant getInterpolant(qint64 currentTimeMsSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup, CInterpolationStatus &status, SituationLog &log);
|
||||
CInterpolant getInterpolant(SituationLog &log);
|
||||
|
||||
private:
|
||||
//! Update the elevations used in CInterpolatorSpline::m_s
|
||||
@@ -97,7 +96,7 @@ namespace BlackMisc
|
||||
bool areAltitudeUnitsSame(const PhysicalQuantities::CLengthUnit &compare = PhysicalQuantities::CLengthUnit::nullUnit()) const;
|
||||
|
||||
//! Fill the situations array
|
||||
bool fillSituationsArray(const BlackMisc::Aviation::CAircraftSituationList &validSituations);
|
||||
bool fillSituationsArray();
|
||||
|
||||
qint64 m_prevSampleAdjustedTime = 0; //!< previous sample time + offset
|
||||
qint64 m_nextSampleAdjustedTime = 0; //!< previous sample time + offset
|
||||
|
||||
@@ -413,13 +413,11 @@ namespace BlackSimPlugin
|
||||
const CCallsign cs = aircraft.getCallsign();
|
||||
if (!m_interpolators.contains(cs)) { continue; }
|
||||
const CInterpolationAndRenderingSetupPerCallsign setup = this->getInterpolationSetupPerCallsignOrDefault(cs); // threadsafe copy
|
||||
const bool log = setup.logInterpolation();
|
||||
CInterpolatorMulti *im = m_interpolators[cs];
|
||||
CInterpolationStatus statusInterpolation;
|
||||
CPartsStatus statusParts;
|
||||
Q_ASSERT_X(im, Q_FUNC_INFO, "interpolator missing");
|
||||
const CAircraftSituation s = im->getInterpolatedSituation(now, setup, statusInterpolation);
|
||||
const CAircraftParts p = im->getInterpolatedOrGuessedParts(now, setup, statusParts, log);
|
||||
CInterpolationResult result = im->getInterpolation(now, setup);
|
||||
const CAircraftSituation s = result;
|
||||
const CAircraftParts p = result;
|
||||
m_countInterpolatedParts++;
|
||||
m_countInterpolatedSituations++;
|
||||
Q_UNUSED(s);
|
||||
|
||||
@@ -172,14 +172,13 @@ namespace BlackSimPlugin
|
||||
Q_UNUSED(event);
|
||||
|
||||
if (m_clientStatus == Disconnected) { return; }
|
||||
CInterpolationStatus status;
|
||||
CInterpolationAndRenderingSetupPerCallsign setup = this->simulator()->getInterpolationSetupPerCallsignOrDefault(m_callsign);
|
||||
const CAircraftSituation situation = m_interpolator.getInterpolatedSituation(-1, setup, status);
|
||||
const CInterpolationAndRenderingSetupPerCallsign setup = this->simulator()->getInterpolationSetupConsolidated(m_callsign);
|
||||
const CInterpolationResult result = m_interpolator.getInterpolation(QDateTime::currentMSecsSinceEpoch(), setup);
|
||||
|
||||
// Test only for successful position. FS9 requires constant positions
|
||||
if (!status.hasValidSituation()) { return; }
|
||||
if (!result.getInterpolationStatus().hasValidSituation()) { return; }
|
||||
|
||||
sendMultiplayerPosition(situation);
|
||||
sendMultiplayerPosition(result);
|
||||
sendMultiplayerParamaters();
|
||||
}
|
||||
|
||||
|
||||
@@ -112,37 +112,16 @@ namespace BlackSimPlugin
|
||||
return m_interpolator->getInterpolatorInfo(mode);
|
||||
}
|
||||
|
||||
void CSimConnectObject::attachInterpolatorLogger(CInterpolationLogger *logger)
|
||||
void CSimConnectObject::attachInterpolatorLogger(CInterpolationLogger *logger) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->attachLogger(logger);
|
||||
}
|
||||
|
||||
CAircraftSituation CSimConnectObject::getInterpolatedSituation(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status) const
|
||||
CInterpolationResult CSimConnectObject::getInterpolation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
|
||||
}
|
||||
|
||||
CAircraftParts CSimConnectObject::getInterpolatedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
}
|
||||
|
||||
CAircraftParts CSimConnectObject::getInterpolatedOrGuessedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
if (!m_interpolator) { CInterpolationResult result; result.reset(); return result; }
|
||||
return m_interpolator->getInterpolation(currentTimeSinceEpoc, setup);
|
||||
}
|
||||
|
||||
const CAircraftSituation &CSimConnectObject::getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
|
||||
|
||||
@@ -160,34 +160,16 @@ namespace BlackSimPlugin
|
||||
//! Was the object really added to simulator
|
||||
bool hasValidRequestAndObjectId() const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolatorMulti::toggleMode
|
||||
void toggleInterpolatorMode();
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatorInfo
|
||||
QString getInterpolatorInfo(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::attachLogger
|
||||
void attachInterpolatorLogger(BlackMisc::Simulation::CInterpolationLogger *logger);
|
||||
void attachInterpolatorLogger(BlackMisc::Simulation::CInterpolationLogger *logger) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatedSituation
|
||||
BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
BlackMisc::Simulation::CInterpolationStatus &status) const;
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolation
|
||||
BlackMisc::Simulation::CInterpolationResult getInterpolation(qint64 currentTimeSinceEpoc, const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatedParts
|
||||
BlackMisc::Aviation::CAircraftParts getInterpolatedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
BlackMisc::Simulation::CPartsStatus &partsStatus, bool log) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatedOrGuessedParts
|
||||
BlackMisc::Aviation::CAircraftParts getInterpolatedOrGuessedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
BlackMisc::Simulation::CPartsStatus &partsStatus, bool log) const;
|
||||
|
||||
//! Last interpolated situation
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getLastInterpolatedSituation
|
||||
const BlackMisc::Aviation::CAircraftSituation &getLastInterpolatedSituation(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
|
||||
|
||||
//! Interpolator
|
||||
|
||||
@@ -1260,17 +1260,14 @@ namespace BlackSimPlugin
|
||||
|
||||
// setup
|
||||
const CInterpolationAndRenderingSetupPerCallsign setup = this->getInterpolationSetupConsolidated(callsign);
|
||||
const bool logInterpolationAndParts = setup.logInterpolation();
|
||||
const bool sendGround = setup.sendGndFlagToSimulator();
|
||||
|
||||
// Interpolated situation
|
||||
CInterpolationStatus interpolatorStatus;
|
||||
const CAircraftSituation interpolatedSituation = simObject.getInterpolatedSituation(currentTimestamp, setup, interpolatorStatus);
|
||||
|
||||
if (interpolatorStatus.hasValidSituation())
|
||||
const CInterpolationResult result = simObject.getInterpolation(currentTimestamp, setup);
|
||||
if (result.getInterpolationStatus().hasValidSituation())
|
||||
{
|
||||
// update situation
|
||||
SIMCONNECT_DATA_INITPOSITION position = this->aircraftSituationToFsxPosition(interpolatedSituation, sendGround);
|
||||
SIMCONNECT_DATA_INITPOSITION position = this->aircraftSituationToFsxPosition(result, sendGround);
|
||||
if (!simObject.isSameAsSent(position))
|
||||
{
|
||||
m_simConnectObjects[simObject.getCallsign()].setPositionAsSent(position);
|
||||
@@ -1290,13 +1287,11 @@ namespace BlackSimPlugin
|
||||
else
|
||||
{
|
||||
static const QString so("SimObject id: %1");
|
||||
CLogMessage(this).warning(this->getInvalidSituationLogMessage(callsign, interpolatorStatus, so.arg(simObject.getObjectId())));
|
||||
CLogMessage(this).warning(this->getInvalidSituationLogMessage(callsign, result.getInterpolationStatus(), so.arg(simObject.getObjectId())));
|
||||
}
|
||||
|
||||
// Interpolated parts
|
||||
CPartsStatus partsStatus;
|
||||
const CAircraftParts parts = simObject.getInterpolatedOrGuessedParts(currentTimestamp, setup, partsStatus, logInterpolationAndParts);
|
||||
this->updateRemoteAircraftParts(simObject, parts, partsStatus);
|
||||
this->updateRemoteAircraftParts(simObject, result);
|
||||
|
||||
} // all callsigns
|
||||
|
||||
@@ -1306,10 +1301,12 @@ namespace BlackSimPlugin
|
||||
m_statsUpdateAircraftTimeAvgMs = m_statsUpdateAircraftTimeTotalMs / m_statsUpdateAircraftCountMs;
|
||||
}
|
||||
|
||||
bool CSimulatorFsxCommon::updateRemoteAircraftParts(const CSimConnectObject &simObject, const CAircraftParts &parts, const CPartsStatus &partsStatus)
|
||||
bool CSimulatorFsxCommon::updateRemoteAircraftParts(const CSimConnectObject &simObject, const CInterpolationResult &result)
|
||||
{
|
||||
if (!simObject.hasValidRequestAndObjectId()) { return false; }
|
||||
if (parts.getPartsDetails() != CAircraftParts::GuessedParts && !partsStatus.isSupportingParts()) { return false; }
|
||||
|
||||
const CAircraftParts parts = result;
|
||||
if (parts.getPartsDetails() != CAircraftParts::GuessedParts && !result.getPartsStatus().isSupportingParts()) { return false; }
|
||||
|
||||
DataDefinitionRemoteAircraftPartsWithoutLights ddRemoteAircraftPartsWithoutLights(parts); // no init, all values will be set
|
||||
return this->sendRemoteAircraftPartsToSimulator(simObject, ddRemoteAircraftPartsWithoutLights, parts.getAdjustedLights());
|
||||
|
||||
@@ -272,8 +272,7 @@ namespace BlackSimPlugin
|
||||
void updateRemoteAircraft();
|
||||
|
||||
//! Update remote aircraft parts (send to FSX)
|
||||
bool updateRemoteAircraftParts(const CSimConnectObject &simObject,
|
||||
const BlackMisc::Aviation::CAircraftParts &parts, const BlackMisc::Simulation::CPartsStatus &partsStatus);
|
||||
bool updateRemoteAircraftParts(const CSimConnectObject &simObject, const BlackMisc::Simulation::CInterpolationResult &result);
|
||||
|
||||
//! Send parts to simulator
|
||||
bool sendRemoteAircraftPartsToSimulator(const CSimConnectObject &simObject, DataDefinitionRemoteAircraftPartsWithoutLights &ddRemoteAircraftParts, const BlackMisc::Aviation::CAircraftLights &lights);
|
||||
|
||||
@@ -678,18 +678,13 @@ namespace BlackSimPlugin
|
||||
|
||||
// setup
|
||||
const CInterpolationAndRenderingSetupPerCallsign setup = this->getInterpolationSetupConsolidated(callsign);
|
||||
const bool logInterpolationAndParts = setup.logInterpolation();
|
||||
|
||||
// interpolated situation
|
||||
CInterpolationStatus interpolatorStatus;
|
||||
const CAircraftSituation interpolatedSituation = xplaneAircraft.getInterpolatedSituation(currentTimestamp, setup, interpolatorStatus);
|
||||
|
||||
// perts
|
||||
CPartsStatus partsStatus;
|
||||
const CAircraftParts parts = xplaneAircraft.getInterpolatedOrGuessedParts(currentTimestamp, setup, partsStatus, logInterpolationAndParts);
|
||||
|
||||
if (interpolatorStatus.hasValidSituation())
|
||||
// interpolated situation/parts
|
||||
const CInterpolationResult result = xplaneAircraft.getInterpolation(currentTimestamp, setup);
|
||||
if (result.getInterpolationStatus().hasValidSituation())
|
||||
{
|
||||
const CAircraftSituation interpolatedSituation(result);
|
||||
|
||||
// update situation
|
||||
if (!xplaneAircraft.isSameAsSent(interpolatedSituation))
|
||||
{
|
||||
@@ -705,10 +700,10 @@ namespace BlackSimPlugin
|
||||
}
|
||||
else
|
||||
{
|
||||
CLogMessage(this).warning(this->getInvalidSituationLogMessage(callsign, interpolatorStatus));
|
||||
CLogMessage(this).warning(this->getInvalidSituationLogMessage(callsign, result.getInterpolationStatus()));
|
||||
}
|
||||
|
||||
this->updateRemoteAircraftParts(xplaneAircraft, parts, partsStatus);
|
||||
this->updateRemoteAircraftParts(xplaneAircraft, result);
|
||||
|
||||
} // all callsigns
|
||||
|
||||
@@ -718,10 +713,10 @@ namespace BlackSimPlugin
|
||||
m_statsUpdateAircraftTimeAvgMs = m_statsUpdateAircraftTimeTotalMs / m_statsUpdateAircraftCountMs;
|
||||
}
|
||||
|
||||
bool CSimulatorXPlane::updateRemoteAircraftParts(const CXPlaneMPAircraft &xplaneAircraft, const CAircraftParts &parts, const CPartsStatus &partsStatus)
|
||||
bool CSimulatorXPlane::updateRemoteAircraftParts(const CXPlaneMPAircraft &xplaneAircraft, const CInterpolationResult &result)
|
||||
{
|
||||
if (!partsStatus.isSupportingParts()) { return false; }
|
||||
return this->sendRemoteAircraftPartsToSimulator(xplaneAircraft, parts);
|
||||
if (!result.getPartsStatus().isSupportingParts()) { return false; }
|
||||
return this->sendRemoteAircraftPartsToSimulator(xplaneAircraft, result);
|
||||
}
|
||||
|
||||
bool CSimulatorXPlane::sendRemoteAircraftPartsToSimulator(const CXPlaneMPAircraft &xplaneAircraft, const CAircraftParts &parts)
|
||||
|
||||
@@ -178,8 +178,7 @@ namespace BlackSimPlugin
|
||||
void updateRemoteAircraft();
|
||||
|
||||
//! Update remote aircraft parts (send to XSwiftBus)
|
||||
bool updateRemoteAircraftParts(const CXPlaneMPAircraft &xplaneAircraft,
|
||||
const BlackMisc::Aviation::CAircraftParts &parts, const BlackMisc::Simulation::CPartsStatus &partsStatus);
|
||||
bool updateRemoteAircraftParts(const CXPlaneMPAircraft &xplaneAircraft, const BlackMisc::Simulation::CInterpolationResult &result);
|
||||
|
||||
//! Send parts to simulator
|
||||
bool sendRemoteAircraftPartsToSimulator(const CXPlaneMPAircraft &xplaneAircraft, const BlackMisc::Aviation::CAircraftParts &parts);
|
||||
|
||||
@@ -42,37 +42,16 @@ namespace BlackSimPlugin
|
||||
return m_interpolator->getInterpolatorInfo(mode);
|
||||
}
|
||||
|
||||
void CXPlaneMPAircraft::attachInterpolatorLogger(CInterpolationLogger *logger)
|
||||
void CXPlaneMPAircraft::attachInterpolatorLogger(CInterpolationLogger *logger) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->attachLogger(logger);
|
||||
}
|
||||
|
||||
CAircraftSituation CXPlaneMPAircraft::getInterpolatedSituation(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CInterpolationStatus &status) const
|
||||
CInterpolationResult CXPlaneMPAircraft::getInterpolation(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->getInterpolatedSituation(currentTimeSinceEpoc, setup, status);
|
||||
}
|
||||
|
||||
CAircraftParts CXPlaneMPAircraft::getInterpolatedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->getInterpolatedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
}
|
||||
|
||||
CAircraftParts CXPlaneMPAircraft::getInterpolatedOrGuessedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
CPartsStatus &partsStatus, bool log) const
|
||||
{
|
||||
Q_ASSERT(m_interpolator);
|
||||
return m_interpolator->getInterpolatedOrGuessedParts(currentTimeSinceEpoc, setup, partsStatus, log);
|
||||
return m_interpolator->getInterpolation(currentTimeSinceEpoc, setup);
|
||||
}
|
||||
|
||||
CCallsignSet CXPlaneMPAircraftObjects::getAllCallsigns() const
|
||||
|
||||
@@ -74,25 +74,10 @@ namespace BlackSimPlugin
|
||||
QString getInterpolatorInfo(BlackMisc::Simulation::CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::attachLogger
|
||||
void attachInterpolatorLogger(BlackMisc::Simulation::CInterpolationLogger *logger);
|
||||
void attachInterpolatorLogger(BlackMisc::Simulation::CInterpolationLogger *logger) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatedSituation
|
||||
BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
BlackMisc::Simulation::CInterpolationStatus &status) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatedParts
|
||||
BlackMisc::Aviation::CAircraftParts getInterpolatedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
BlackMisc::Simulation::CPartsStatus &partsStatus, bool log) const;
|
||||
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolatedOrGuessedParts
|
||||
BlackMisc::Aviation::CAircraftParts getInterpolatedOrGuessedParts(
|
||||
qint64 currentTimeSinceEpoc,
|
||||
const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup,
|
||||
BlackMisc::Simulation::CPartsStatus &partsStatus, bool log) const;
|
||||
//! \copydoc BlackMisc::Simulation::CInterpolator::getInterpolation
|
||||
BlackMisc::Simulation::CInterpolationResult getInterpolation(qint64 currentTimeSinceEpoc, const BlackMisc::Simulation::CInterpolationAndRenderingSetupPerCallsign &setup) const;
|
||||
|
||||
//! Interpolator
|
||||
BlackMisc::Simulation::CInterpolatorMulti *getInterpolator() const { return m_interpolator.data(); }
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace BlackMiscTest
|
||||
const qint64 offset = 5000;
|
||||
for (int i = IRemoteAircraftProvider::MaxSituationsPerCallsign - 1; i >= 0; i--)
|
||||
{
|
||||
CAircraftSituation s(getTestSituation(cs, i, ts, deltaT, offset));
|
||||
const CAircraftSituation s(getTestSituation(cs, i, ts, deltaT, offset));
|
||||
|
||||
// check height above ground
|
||||
CLength hag = (s.getAltitude() - s.getGroundElevation());
|
||||
@@ -75,7 +75,7 @@ namespace BlackMiscTest
|
||||
constexpr int partsCount = 10;
|
||||
for (int i = partsCount - 1; i >= 0; i--)
|
||||
{
|
||||
CAircraftParts p(getTestParts(i, ts, deltaT));
|
||||
const CAircraftParts p(getTestParts(i, ts, deltaT));
|
||||
provider.insertNewAircraftParts(cs, p, false);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ namespace BlackMiscTest
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
|
||||
|
||||
// interpolation functional check
|
||||
CInterpolationStatus status;
|
||||
const CInterpolationAndRenderingSetupPerCallsign setup;
|
||||
double latOld = 360.0;
|
||||
double lngOld = 360.0;
|
||||
@@ -92,10 +91,10 @@ namespace BlackMiscTest
|
||||
// This will use time range
|
||||
// from: ts - 2 * deltaT + offset
|
||||
// to: ts + offset
|
||||
CAircraftSituation currentSituation(
|
||||
interpolator.getInterpolatedSituation(currentTime, setup, status)
|
||||
);
|
||||
QVERIFY2(status.isInterpolated(), "Value was not interpolated");
|
||||
|
||||
const CInterpolationResult result = interpolator.getInterpolation(currentTime, setup);
|
||||
const CAircraftSituation currentSituation(result);
|
||||
QVERIFY2(result.getInterpolationStatus().isInterpolated(), "Value was not interpolated");
|
||||
const double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
|
||||
const double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5);
|
||||
QVERIFY2(latDeg < latOld && lngDeg < lngOld, QString("Values shall decrease: %1/%2 %3/%4").arg(latDeg).arg(latOld).arg(lngDeg).arg(lngOld).toLatin1());
|
||||
@@ -122,10 +121,9 @@ namespace BlackMiscTest
|
||||
// This will use range
|
||||
// from: ts - 2* deltaT + offset
|
||||
// to: ts + offset
|
||||
CAircraftSituation currentSituation(
|
||||
interpolator.getInterpolatedSituation(currentTime, setup, status)
|
||||
);
|
||||
QVERIFY2(status.isInterpolated(), "Not interpolated");
|
||||
const CInterpolationResult result = interpolator.getInterpolation(currentTime, setup);
|
||||
const CAircraftSituation currentSituation(result);
|
||||
QVERIFY2(result.getInterpolationStatus().isInterpolated(), "Not interpolated");
|
||||
QVERIFY2(!currentSituation.getCallsign().isEmpty(), "Empty callsign");
|
||||
QVERIFY2(currentSituation.getCallsign() == cs, "Wrong callsign");
|
||||
const double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
|
||||
@@ -143,11 +141,9 @@ namespace BlackMiscTest
|
||||
timer.start();
|
||||
for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250)
|
||||
{
|
||||
CPartsStatus partsStatus;
|
||||
const CAircraftParts pl(interpolator.getInterpolatedParts(ts, setup, partsStatus));
|
||||
Q_UNUSED(pl);
|
||||
const CInterpolationResult result = interpolator.getInterpolation(currentTime, setup);
|
||||
fetchedParts++;
|
||||
QVERIFY2(partsStatus.isSupportingParts(), "Parts not supported");
|
||||
QVERIFY2(result.getPartsStatus().isSupportingParts(), "Parts not supported");
|
||||
}
|
||||
timeMs = timer.elapsed();
|
||||
qDebug() << timeMs << "ms" << "for" << fetchedParts << "fetched parts";
|
||||
|
||||
@@ -51,7 +51,6 @@ namespace BlackMiscTest
|
||||
QVERIFY2(parts.size() == number, "Wrong parts size of list");
|
||||
|
||||
// interpolation functional check
|
||||
CPartsStatus status;
|
||||
const CInterpolationAndRenderingSetupPerCallsign setup;
|
||||
const qint64 oldestTs = parts.oldestTimestampMsecsSinceEpoch();
|
||||
|
||||
@@ -59,13 +58,15 @@ namespace BlackMiscTest
|
||||
// all on ground flags true
|
||||
provider.insertNewAircraftParts(cs, parts, false); // we work with 0 offsets here
|
||||
QVERIFY2(provider.remoteAircraftPartsCount(cs) == parts.size(), "Wrong parts size");
|
||||
CAircraftParts p = interpolator.getInterpolatedParts(farFuture, setup, status);
|
||||
CInterpolationResult result = interpolator.getInterpolation(farFuture, setup);
|
||||
CAircraftParts p = result;
|
||||
qint64 pTs = p.getAdjustedMSecsSinceEpoch();
|
||||
QVERIFY2(status.isSupportingParts(), "Should support parts");
|
||||
QVERIFY2(result.getPartsStatus().isSupportingParts(), "Should support parts");
|
||||
QVERIFY2(pTs == ts, "Expect latest ts");
|
||||
p = interpolator.getInterpolatedParts(farPast, setup, status);
|
||||
result = interpolator.getInterpolation(farPast, setup);
|
||||
p = result;
|
||||
pTs = p.getAdjustedMSecsSinceEpoch();
|
||||
QVERIFY2(status.isSupportingParts(), "Should support parts");
|
||||
QVERIFY2(result.getPartsStatus().isSupportingParts(), "Should support parts");
|
||||
QVERIFY2(pTs == oldestTs, "Expect oldest ts");
|
||||
|
||||
// Testing for a time >> last time
|
||||
@@ -75,9 +76,10 @@ namespace BlackMiscTest
|
||||
|
||||
parts.setOnGround(false);
|
||||
provider.insertNewAircraftParts(cs, parts, false); // we work with 0 offsets here
|
||||
p = interpolator.getInterpolatedParts(farFuture, setup, status);
|
||||
result = interpolator.getInterpolation(farFuture, setup);
|
||||
p = result;
|
||||
pTs = p.getAdjustedMSecsSinceEpoch();
|
||||
QVERIFY2(status.isSupportingParts(), "Should support parts");
|
||||
QVERIFY2(result.getPartsStatus().isSupportingParts(), "Should support parts");
|
||||
QVERIFY2(p.getAdjustedMSecsSinceEpoch() == pTs, "Expect latest ts");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user