Ref T231, Ref T236, Ref T238 improvements of interpolator

* keep last interpolated sitation, removed m_isFirstInterpolation
* allow to obtain the old/new situation
* transfer of elevations to newer situations
This commit is contained in:
Klaus Basan
2018-01-28 05:17:47 +01:00
parent cd5fdfaf14
commit 0a06ad223f
8 changed files with 67 additions and 52 deletions

View File

@@ -57,23 +57,25 @@ namespace BlackMisc
const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints,
CInterpolationStatus &status)
{
// this code is used by linear and spline interpolator
status.reset();
CInterpolationLogger::SituationLog log;
// any data at all?
if (m_aircraftSituations.isEmpty()) { return {}; }
CAircraftSituation currentSituation = m_aircraftSituations.front();
CAircraftSituation currentSituation = m_lastInterpolation.isNull() ? m_aircraftSituations.front() : m_lastInterpolation;
// Update current position by hints' elevation
// * for XP provided by hints.getElevationProvider at current position
// * for FSX/P3D provided as hints.getElevation which is set to current position of remote aircraft in simulator
// * As XP uses lazy init we will call getGroundElevation only when needed
// * default here via getElevationPlane
CAltitude currentGroundElevation(hints.getGroundElevation(currentSituation, false, false));
currentSituation.setGroundElevationChecked(currentGroundElevation); // set as default
CAltitude currentGroundElevation(hints.getGroundElevation(currentSituation, currentSituation.getDistancePerTime(1000), false, false));
currentSituation.setGroundElevation(currentGroundElevation); // set as default
// data, split situations by time
if (currentTimeMsSinceEpoc < 0) { currentTimeMsSinceEpoc = QDateTime::currentMSecsSinceEpoch(); }
currentSituation.setMSecsSinceEpoch(currentTimeMsSinceEpoc);
// interpolant function from derived class
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
@@ -90,7 +92,7 @@ namespace BlackMisc
currentSituation.setPosition(interpolant.interpolatePosition(setup, hints));
currentSituation.setAltitude(interpolant.interpolateAltitude(setup, hints));
// PBH before ground so we can use PBH
// PBH before ground so we can use PBH in guessing ground
if (setup.isForcingFullInterpolation() || hints.isVtolAircraft() || status.isInterpolated())
{
const auto pbh = interpolant.pbh();
@@ -100,16 +102,17 @@ namespace BlackMisc
currentSituation.setGroundSpeed(pbh.getGroundSpeed());
status.setInterpolatedAndCheckSituation(true, currentSituation);
}
m_isFirstInterpolation = false;
// Interpolate between altitude and ground elevation, with proportions weighted according to interpolated onGround flag
constexpr double NoGroundFactor = -1;
double groundFactor = NoGroundFactor;
if (hints.hasAircraftParts())
{
const double groundFactor = hints.getAircraftParts().isOnGroundInterpolated();
log.groundFactor = groundFactor;
groundFactor = hints.getAircraftParts().isOnGroundInterpolated();
if (groundFactor > 0.0)
{
// if not having an ground elevation yet, we fetch from provider
// if not having an ground elevation yet, we fetch from provider (if there is a provider)
if (!currentGroundElevation.isNull())
{
currentGroundElevation = hints.getGroundElevation(currentSituation, true); // "expensive on XPlane" if provider is called
@@ -129,23 +132,10 @@ namespace BlackMisc
}
}
}
else
{
// guess ground flag
constexpr double NoGroundFactor = -1;
CInterpolator::setGroundFlagFromInterpolator(hints, NoGroundFactor, currentSituation);
}
if (m_logger && hints.isLoggingInterpolation())
{
log.timestamp = currentTimeMsSinceEpoc;
log.callsign = m_callsign;
log.groundFactor = groundFactor;
log.situationCurrent = currentSituation;
log.usedHints = hints;
log.usedSetup = setup;
m_logger->logInterpolation(log);
}
// depending on ground factor set ground flag and reliability
// it will use the hints ground flag or elevation/CG or guessing
CInterpolator::setGroundFlagFromInterpolator(hints, groundFactor, currentSituation);
// we transfer ground elevation for future usage
if (currentSituation.hasGroundElevation())
@@ -154,11 +144,23 @@ namespace BlackMisc
ep.setSinglePointRadius();
// transfer to newer situations
const int transfered = m_aircraftSituations.setGroundElevationChecked(ep, currentSituation.getMSecsSinceEpoch());
Q_UNUSED(transfered); // for debugging
log.noTransferredElevations = m_aircraftSituations.setGroundElevationChecked(ep, currentTimeMsSinceEpoc);
}
// logging
if (m_logger && hints.isLoggingInterpolation())
{
log.tsCurrent = currentTimeMsSinceEpoc;
log.callsign = m_callsign;
log.groundFactor = groundFactor;
log.situationCurrent = currentSituation;
log.usedHints = hints;
log.usedSetup = setup;
m_logger->logInterpolation(log);
}
// bye
m_lastInterpolation = currentSituation;
return currentSituation;
}
@@ -214,6 +216,7 @@ namespace BlackMisc
CAircraftParts CInterpolator<Derived>::getInterpolatedParts(qint64 currentTimeMsSinceEpoch,
const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log) const
{
// this code is used by linear and spline interpolator
Q_UNUSED(setup);
partsStatus.reset();
if (currentTimeMsSinceEpoch < 0) { currentTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); }
@@ -284,7 +287,7 @@ namespace BlackMisc
if (!log || !m_logger) { return; }
CInterpolationLogger::PartsLog logInfo;
logInfo.callsign = m_callsign;
logInfo.timestamp = timestamp;
logInfo.tsCurrent = timestamp;
logInfo.parts = parts;
logInfo.empty = empty;
m_logger->logParts(logInfo);
@@ -331,7 +334,7 @@ namespace BlackMisc
QStringLiteral(" parts: ") %
QString::number(m_aircraftParts.size()) %
QStringLiteral(" 1st interpolation: ") %
boolToYesNo(m_isFirstInterpolation);
boolToYesNo(m_lastInterpolation.isNull());
}
template <typename Derived>

View File

@@ -86,7 +86,7 @@ namespace BlackMisc
Aviation::CAircraftSituationList m_aircraftSituations; //!< recent situations for one aircraft
Aviation::CAircraftPartsList m_aircraftParts; //!< recent parts for one aircraft
Aviation::CCallsign m_callsign; //!< callsign
bool m_isFirstInterpolation = true; //!< set to false after the first successful interpolation
Aviation::CAircraftSituation m_lastInterpolation; //!< last interpolation
//! Constructor
CInterpolator(const QString &objectName, const Aviation::CCallsign &callsign, QObject *parent);
@@ -129,8 +129,8 @@ namespace BlackMisc
PhysicalQuantities::CAngle getPitch() const;
PhysicalQuantities::CAngle getBank() const;
PhysicalQuantities::CSpeed getGroundSpeed() const;
Aviation::CAircraftSituation getOldSituation() const { return m_oldSituation; }
Aviation::CAircraftSituation getNewSituation() const { return m_newSituation; }
const Aviation::CAircraftSituation &getOldSituation() const { return m_oldSituation; }
const Aviation::CAircraftSituation &getNewSituation() const { return m_newSituation; }
//! @}
//! Change time fraction

View File

@@ -119,27 +119,29 @@ namespace BlackMisc
CAircraftSituation currentSituation(oldSituation); // also sets ground elevation if available
// Time between start and end packet
const double deltaTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - oldSituation.getAdjustedMSecsSinceEpoch();
Q_ASSERT_X(deltaTimeMs >= 0, Q_FUNC_INFO, "Negative delta time");
const double sampleDeltaTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - oldSituation.getAdjustedMSecsSinceEpoch();
Q_ASSERT_X(sampleDeltaTimeMs >= 0, Q_FUNC_INFO, "Negative delta time");
log.interpolator = 'l';
log.deltaTimeMs = deltaTimeMs;
log.tsCurrent = currentTimeMsSinceEpoc;
log.deltaSampleTimesMs = sampleDeltaTimeMs;
// Fraction of the deltaTime, ideally [0.0 - 1.0]
// < 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 simulationTimeFraction = 1.0 - (distanceToSplitTimeMs / deltaTimeMs);
const double deltaTimeFractionMs = deltaTimeMs * simulationTimeFraction;
const double simulationTimeFraction = qMax(1.0 - (distanceToSplitTimeMs / sampleDeltaTimeMs), 0.0);
const double deltaTimeFractionMs = sampleDeltaTimeMs * simulationTimeFraction;
log.simulationTimeFraction = simulationTimeFraction;
log.deltaTimeFractionMs = deltaTimeFractionMs;
log.deltaSampleTimesMs = sampleDeltaTimeMs;
currentSituation.setTimeOffsetMs(oldSituation.getTimeOffsetMs() + (newSituation.getTimeOffsetMs() - oldSituation.getTimeOffsetMs()) * simulationTimeFraction);
currentSituation.setMSecsSinceEpoch(oldSituation.getMSecsSinceEpoch() + deltaTimeFractionMs);
status.setInterpolatedAndCheckSituation(true, currentSituation);
log.tsInterpolated = currentSituation.getAdjustedMSecsSinceEpoch();
log.oldSituation = oldSituation;
log.newSituation = newSituation;
log.situationOld = oldSituation;
log.situationNew = newSituation;
return { oldSituation, newSituation, simulationTimeFraction };
}

View File

@@ -56,11 +56,17 @@ namespace BlackMisc
//! Interpolator for pitch, bank, heading, groundspeed
const CInterpolatorPbh &pbh() const { return m_pbh; }
//! Old situation
const Aviation::CAircraftSituation &getOldSituation() const { return m_oldSituation; }
//! New situation
const Aviation::CAircraftSituation &getNewSituation() const { return m_newSituation; }
private:
int m_situationsAvailable = 0;
Aviation::CAircraftSituation m_oldSituation;
Aviation::CAircraftSituation m_newSituation;
double m_simulationTimeFraction = 0.0;
double m_simulationTimeFraction = 0.0; //!< 0..1
const CInterpolatorPbh m_pbh;
};

View File

@@ -129,12 +129,10 @@ namespace BlackMisc
// - flying the ground elevation not really matters
if (!hints.getElevationPlane().isNull())
{
const CAltitude groundElevation = hints.getElevationPlane().getAltitude();
// do not override existing values
s[0].setGroundElevationChecked(groundElevation);
s[1].setGroundElevationChecked(groundElevation);
s[2].setGroundElevationChecked(groundElevation);
s[0].setGroundElevationChecked(hints.getElevationPlane());
s[1].setGroundElevationChecked(hints.getElevationPlane());
s[2].setGroundElevationChecked(hints.getElevationPlane());
}
const double a0 = s[0].getCorrectedAltitude(hints.getCGAboveGround()).value();
@@ -163,11 +161,11 @@ namespace BlackMisc
const double dt2 = static_cast<double>(m_nextSampleTime - m_prevSampleTime);
const double timeFraction = dt1 / dt2;
log.interpolator = 's';
log.oldSituation = m_interpolant.pbh().getOldSituation();
log.newSituation = m_interpolant.pbh().getNewSituation();
log.deltaTimeMs = dt1;
log.deltaTimeFractionMs = dt2;
log.situationOld = m_interpolant.pbh().getOldSituation();
log.situationNew = m_interpolant.pbh().getNewSituation();
log.deltaSampleTimesMs = dt2;
log.simulationTimeFraction = timeFraction;
log.tsInterpolated = log.situationNew.getMSecsSinceEpoch(); // without offset
status.setInterpolated(true);
m_interpolant.setTimes(currentTimeMsSinceEpoc, timeFraction);

View File

@@ -70,6 +70,12 @@ namespace BlackMisc
//! Interpolator for pitch, bank, heading, groundspeed
const CInterpolatorPbh &pbh() const { return m_pbh; }
//! Old situation
const Aviation::CAircraftSituation &getOldSituation() const { return pbh().getOldSituation(); }
//! New situation
const Aviation::CAircraftSituation &getNewSituation() const { return pbh().getNewSituation(); }
//! Set the time values
void setTimes(qint64 currentTimeMs, double timeFraction);