mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-04 08:36:52 +08:00
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:
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 };
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user