mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-21 04:45:31 +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:
@@ -43,13 +43,13 @@ namespace BlackMisc
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CAircraftSituationList::setGroundElevationChecked(const CElevationPlane &elevationPlane, qint64 newerThan, bool ignoreNullValues, bool overrideExisting)
|
int CAircraftSituationList::setGroundElevationChecked(const CElevationPlane &elevationPlane, qint64 newerThanAdjustedMs, bool ignoreNullValues, bool overrideExisting)
|
||||||
{
|
{
|
||||||
if (ignoreNullValues && elevationPlane.isNull()) { return 0; }
|
if (ignoreNullValues && elevationPlane.isNull()) { return 0; }
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (CAircraftSituation &s : *this)
|
for (CAircraftSituation &s : *this)
|
||||||
{
|
{
|
||||||
if (s.getMSecsSinceEpoch() <= newerThan) { continue; }
|
if (s.getAdjustedMSecsSinceEpoch() <= newerThanAdjustedMs) { continue; }
|
||||||
const bool set = s.setGroundElevationChecked(elevationPlane, ignoreNullValues, overrideExisting);
|
const bool set = s.setGroundElevationChecked(elevationPlane, ignoreNullValues, overrideExisting);
|
||||||
if (set) { c++; }
|
if (set) { c++; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace BlackMisc
|
|||||||
int setGroundElevationChecked(const Geo::CElevationPlane &elevationPlane, bool ignoreNullValues = true, bool overrideExisting = true);
|
int setGroundElevationChecked(const Geo::CElevationPlane &elevationPlane, bool ignoreNullValues = true, bool overrideExisting = true);
|
||||||
|
|
||||||
//! Set ground elevation from elevation plane
|
//! Set ground elevation from elevation plane
|
||||||
int setGroundElevationChecked(const Geo::CElevationPlane &elevationPlane, qint64 newerThan, bool ignoreNullValues = true, bool overrideExisting = true);
|
int setGroundElevationChecked(const Geo::CElevationPlane &elevationPlane, qint64 newerThanAdjustedMs, bool ignoreNullValues = true, bool overrideExisting = true);
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -57,23 +57,25 @@ namespace BlackMisc
|
|||||||
const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints,
|
const CInterpolationAndRenderingSetup &setup, const CInterpolationHints &hints,
|
||||||
CInterpolationStatus &status)
|
CInterpolationStatus &status)
|
||||||
{
|
{
|
||||||
|
// this code is used by linear and spline interpolator
|
||||||
status.reset();
|
status.reset();
|
||||||
CInterpolationLogger::SituationLog log;
|
CInterpolationLogger::SituationLog log;
|
||||||
|
|
||||||
// any data at all?
|
// any data at all?
|
||||||
if (m_aircraftSituations.isEmpty()) { return {}; }
|
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
|
// Update current position by hints' elevation
|
||||||
// * for XP provided by hints.getElevationProvider at current position
|
// * 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
|
// * 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
|
// * As XP uses lazy init we will call getGroundElevation only when needed
|
||||||
// * default here via getElevationPlane
|
// * default here via getElevationPlane
|
||||||
CAltitude currentGroundElevation(hints.getGroundElevation(currentSituation, false, false));
|
CAltitude currentGroundElevation(hints.getGroundElevation(currentSituation, currentSituation.getDistancePerTime(1000), false, false));
|
||||||
currentSituation.setGroundElevationChecked(currentGroundElevation); // set as default
|
currentSituation.setGroundElevation(currentGroundElevation); // set as default
|
||||||
|
|
||||||
// data, split situations by time
|
// data, split situations by time
|
||||||
if (currentTimeMsSinceEpoc < 0) { currentTimeMsSinceEpoc = QDateTime::currentMSecsSinceEpoch(); }
|
if (currentTimeMsSinceEpoc < 0) { currentTimeMsSinceEpoc = QDateTime::currentMSecsSinceEpoch(); }
|
||||||
|
currentSituation.setMSecsSinceEpoch(currentTimeMsSinceEpoc);
|
||||||
|
|
||||||
// interpolant function from derived class
|
// interpolant function from derived class
|
||||||
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
|
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
|
||||||
@@ -90,7 +92,7 @@ namespace BlackMisc
|
|||||||
currentSituation.setPosition(interpolant.interpolatePosition(setup, hints));
|
currentSituation.setPosition(interpolant.interpolatePosition(setup, hints));
|
||||||
currentSituation.setAltitude(interpolant.interpolateAltitude(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())
|
if (setup.isForcingFullInterpolation() || hints.isVtolAircraft() || status.isInterpolated())
|
||||||
{
|
{
|
||||||
const auto pbh = interpolant.pbh();
|
const auto pbh = interpolant.pbh();
|
||||||
@@ -100,16 +102,17 @@ namespace BlackMisc
|
|||||||
currentSituation.setGroundSpeed(pbh.getGroundSpeed());
|
currentSituation.setGroundSpeed(pbh.getGroundSpeed());
|
||||||
status.setInterpolatedAndCheckSituation(true, currentSituation);
|
status.setInterpolatedAndCheckSituation(true, currentSituation);
|
||||||
}
|
}
|
||||||
m_isFirstInterpolation = false;
|
|
||||||
|
|
||||||
// Interpolate between altitude and ground elevation, with proportions weighted according to interpolated onGround flag
|
// Interpolate between altitude and ground elevation, with proportions weighted according to interpolated onGround flag
|
||||||
|
constexpr double NoGroundFactor = -1;
|
||||||
|
double groundFactor = NoGroundFactor;
|
||||||
|
|
||||||
if (hints.hasAircraftParts())
|
if (hints.hasAircraftParts())
|
||||||
{
|
{
|
||||||
const double groundFactor = hints.getAircraftParts().isOnGroundInterpolated();
|
groundFactor = hints.getAircraftParts().isOnGroundInterpolated();
|
||||||
log.groundFactor = groundFactor;
|
|
||||||
if (groundFactor > 0.0)
|
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())
|
if (!currentGroundElevation.isNull())
|
||||||
{
|
{
|
||||||
currentGroundElevation = hints.getGroundElevation(currentSituation, true); // "expensive on XPlane" if provider is called
|
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())
|
// depending on ground factor set ground flag and reliability
|
||||||
{
|
// it will use the hints ground flag or elevation/CG or guessing
|
||||||
log.timestamp = currentTimeMsSinceEpoc;
|
CInterpolator::setGroundFlagFromInterpolator(hints, groundFactor, currentSituation);
|
||||||
log.callsign = m_callsign;
|
|
||||||
log.groundFactor = groundFactor;
|
|
||||||
log.situationCurrent = currentSituation;
|
|
||||||
log.usedHints = hints;
|
|
||||||
log.usedSetup = setup;
|
|
||||||
m_logger->logInterpolation(log);
|
|
||||||
}
|
|
||||||
|
|
||||||
// we transfer ground elevation for future usage
|
// we transfer ground elevation for future usage
|
||||||
if (currentSituation.hasGroundElevation())
|
if (currentSituation.hasGroundElevation())
|
||||||
@@ -154,11 +144,23 @@ namespace BlackMisc
|
|||||||
ep.setSinglePointRadius();
|
ep.setSinglePointRadius();
|
||||||
|
|
||||||
// transfer to newer situations
|
// transfer to newer situations
|
||||||
const int transfered = m_aircraftSituations.setGroundElevationChecked(ep, currentSituation.getMSecsSinceEpoch());
|
log.noTransferredElevations = m_aircraftSituations.setGroundElevationChecked(ep, currentTimeMsSinceEpoc);
|
||||||
Q_UNUSED(transfered); // for debugging
|
}
|
||||||
|
|
||||||
|
// 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
|
// bye
|
||||||
|
m_lastInterpolation = currentSituation;
|
||||||
return currentSituation;
|
return currentSituation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +216,7 @@ namespace BlackMisc
|
|||||||
CAircraftParts CInterpolator<Derived>::getInterpolatedParts(qint64 currentTimeMsSinceEpoch,
|
CAircraftParts CInterpolator<Derived>::getInterpolatedParts(qint64 currentTimeMsSinceEpoch,
|
||||||
const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log) const
|
const CInterpolationAndRenderingSetup &setup, CPartsStatus &partsStatus, bool log) const
|
||||||
{
|
{
|
||||||
|
// this code is used by linear and spline interpolator
|
||||||
Q_UNUSED(setup);
|
Q_UNUSED(setup);
|
||||||
partsStatus.reset();
|
partsStatus.reset();
|
||||||
if (currentTimeMsSinceEpoch < 0) { currentTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); }
|
if (currentTimeMsSinceEpoch < 0) { currentTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); }
|
||||||
@@ -284,7 +287,7 @@ namespace BlackMisc
|
|||||||
if (!log || !m_logger) { return; }
|
if (!log || !m_logger) { return; }
|
||||||
CInterpolationLogger::PartsLog logInfo;
|
CInterpolationLogger::PartsLog logInfo;
|
||||||
logInfo.callsign = m_callsign;
|
logInfo.callsign = m_callsign;
|
||||||
logInfo.timestamp = timestamp;
|
logInfo.tsCurrent = timestamp;
|
||||||
logInfo.parts = parts;
|
logInfo.parts = parts;
|
||||||
logInfo.empty = empty;
|
logInfo.empty = empty;
|
||||||
m_logger->logParts(logInfo);
|
m_logger->logParts(logInfo);
|
||||||
@@ -331,7 +334,7 @@ namespace BlackMisc
|
|||||||
QStringLiteral(" parts: ") %
|
QStringLiteral(" parts: ") %
|
||||||
QString::number(m_aircraftParts.size()) %
|
QString::number(m_aircraftParts.size()) %
|
||||||
QStringLiteral(" 1st interpolation: ") %
|
QStringLiteral(" 1st interpolation: ") %
|
||||||
boolToYesNo(m_isFirstInterpolation);
|
boolToYesNo(m_lastInterpolation.isNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace BlackMisc
|
|||||||
Aviation::CAircraftSituationList m_aircraftSituations; //!< recent situations for one aircraft
|
Aviation::CAircraftSituationList m_aircraftSituations; //!< recent situations for one aircraft
|
||||||
Aviation::CAircraftPartsList m_aircraftParts; //!< recent parts for one aircraft
|
Aviation::CAircraftPartsList m_aircraftParts; //!< recent parts for one aircraft
|
||||||
Aviation::CCallsign m_callsign; //!< callsign
|
Aviation::CCallsign m_callsign; //!< callsign
|
||||||
bool m_isFirstInterpolation = true; //!< set to false after the first successful interpolation
|
Aviation::CAircraftSituation m_lastInterpolation; //!< last interpolation
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
CInterpolator(const QString &objectName, const Aviation::CCallsign &callsign, QObject *parent);
|
CInterpolator(const QString &objectName, const Aviation::CCallsign &callsign, QObject *parent);
|
||||||
@@ -129,8 +129,8 @@ namespace BlackMisc
|
|||||||
PhysicalQuantities::CAngle getPitch() const;
|
PhysicalQuantities::CAngle getPitch() const;
|
||||||
PhysicalQuantities::CAngle getBank() const;
|
PhysicalQuantities::CAngle getBank() const;
|
||||||
PhysicalQuantities::CSpeed getGroundSpeed() const;
|
PhysicalQuantities::CSpeed getGroundSpeed() const;
|
||||||
Aviation::CAircraftSituation getOldSituation() const { return m_oldSituation; }
|
const Aviation::CAircraftSituation &getOldSituation() const { return m_oldSituation; }
|
||||||
Aviation::CAircraftSituation getNewSituation() const { return m_newSituation; }
|
const Aviation::CAircraftSituation &getNewSituation() const { return m_newSituation; }
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
//! Change time fraction
|
//! Change time fraction
|
||||||
|
|||||||
@@ -119,27 +119,29 @@ namespace BlackMisc
|
|||||||
CAircraftSituation currentSituation(oldSituation); // also sets ground elevation if available
|
CAircraftSituation currentSituation(oldSituation); // also sets ground elevation if available
|
||||||
|
|
||||||
// Time between start and end packet
|
// Time between start and end packet
|
||||||
const double deltaTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - oldSituation.getAdjustedMSecsSinceEpoch();
|
const double sampleDeltaTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - oldSituation.getAdjustedMSecsSinceEpoch();
|
||||||
Q_ASSERT_X(deltaTimeMs >= 0, Q_FUNC_INFO, "Negative delta time");
|
Q_ASSERT_X(sampleDeltaTimeMs >= 0, Q_FUNC_INFO, "Negative delta time");
|
||||||
log.interpolator = 'l';
|
log.interpolator = 'l';
|
||||||
log.deltaTimeMs = deltaTimeMs;
|
log.tsCurrent = currentTimeMsSinceEpoc;
|
||||||
|
log.deltaSampleTimesMs = sampleDeltaTimeMs;
|
||||||
|
|
||||||
// Fraction of the deltaTime, ideally [0.0 - 1.0]
|
// 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
|
// < 0 should not happen due to the split, > 1 can happen if new values are delayed beyond split time
|
||||||
// 1) values > 1 mean extrapolation
|
// 1) values > 1 mean extrapolation
|
||||||
// 2) values > 2 mean no new situations coming in
|
// 2) values > 2 mean no new situations coming in
|
||||||
const double distanceToSplitTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - currentTimeMsSinceEpoc;
|
const double distanceToSplitTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - currentTimeMsSinceEpoc;
|
||||||
const double simulationTimeFraction = 1.0 - (distanceToSplitTimeMs / deltaTimeMs);
|
const double simulationTimeFraction = qMax(1.0 - (distanceToSplitTimeMs / sampleDeltaTimeMs), 0.0);
|
||||||
const double deltaTimeFractionMs = deltaTimeMs * simulationTimeFraction;
|
const double deltaTimeFractionMs = sampleDeltaTimeMs * simulationTimeFraction;
|
||||||
log.simulationTimeFraction = simulationTimeFraction;
|
log.simulationTimeFraction = simulationTimeFraction;
|
||||||
log.deltaTimeFractionMs = deltaTimeFractionMs;
|
log.deltaSampleTimesMs = sampleDeltaTimeMs;
|
||||||
|
|
||||||
currentSituation.setTimeOffsetMs(oldSituation.getTimeOffsetMs() + (newSituation.getTimeOffsetMs() - oldSituation.getTimeOffsetMs()) * simulationTimeFraction);
|
currentSituation.setTimeOffsetMs(oldSituation.getTimeOffsetMs() + (newSituation.getTimeOffsetMs() - oldSituation.getTimeOffsetMs()) * simulationTimeFraction);
|
||||||
currentSituation.setMSecsSinceEpoch(oldSituation.getMSecsSinceEpoch() + deltaTimeFractionMs);
|
currentSituation.setMSecsSinceEpoch(oldSituation.getMSecsSinceEpoch() + deltaTimeFractionMs);
|
||||||
status.setInterpolatedAndCheckSituation(true, currentSituation);
|
status.setInterpolatedAndCheckSituation(true, currentSituation);
|
||||||
|
log.tsInterpolated = currentSituation.getAdjustedMSecsSinceEpoch();
|
||||||
|
|
||||||
log.oldSituation = oldSituation;
|
log.situationOld = oldSituation;
|
||||||
log.newSituation = newSituation;
|
log.situationNew = newSituation;
|
||||||
return { oldSituation, newSituation, simulationTimeFraction };
|
return { oldSituation, newSituation, simulationTimeFraction };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,11 +56,17 @@ namespace BlackMisc
|
|||||||
//! Interpolator for pitch, bank, heading, groundspeed
|
//! Interpolator for pitch, bank, heading, groundspeed
|
||||||
const CInterpolatorPbh &pbh() const { return m_pbh; }
|
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:
|
private:
|
||||||
int m_situationsAvailable = 0;
|
int m_situationsAvailable = 0;
|
||||||
Aviation::CAircraftSituation m_oldSituation;
|
Aviation::CAircraftSituation m_oldSituation;
|
||||||
Aviation::CAircraftSituation m_newSituation;
|
Aviation::CAircraftSituation m_newSituation;
|
||||||
double m_simulationTimeFraction = 0.0;
|
double m_simulationTimeFraction = 0.0; //!< 0..1
|
||||||
const CInterpolatorPbh m_pbh;
|
const CInterpolatorPbh m_pbh;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -129,12 +129,10 @@ namespace BlackMisc
|
|||||||
// - flying the ground elevation not really matters
|
// - flying the ground elevation not really matters
|
||||||
if (!hints.getElevationPlane().isNull())
|
if (!hints.getElevationPlane().isNull())
|
||||||
{
|
{
|
||||||
const CAltitude groundElevation = hints.getElevationPlane().getAltitude();
|
|
||||||
|
|
||||||
// do not override existing values
|
// do not override existing values
|
||||||
s[0].setGroundElevationChecked(groundElevation);
|
s[0].setGroundElevationChecked(hints.getElevationPlane());
|
||||||
s[1].setGroundElevationChecked(groundElevation);
|
s[1].setGroundElevationChecked(hints.getElevationPlane());
|
||||||
s[2].setGroundElevationChecked(groundElevation);
|
s[2].setGroundElevationChecked(hints.getElevationPlane());
|
||||||
}
|
}
|
||||||
|
|
||||||
const double a0 = s[0].getCorrectedAltitude(hints.getCGAboveGround()).value();
|
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 dt2 = static_cast<double>(m_nextSampleTime - m_prevSampleTime);
|
||||||
const double timeFraction = dt1 / dt2;
|
const double timeFraction = dt1 / dt2;
|
||||||
log.interpolator = 's';
|
log.interpolator = 's';
|
||||||
log.oldSituation = m_interpolant.pbh().getOldSituation();
|
log.situationOld = m_interpolant.pbh().getOldSituation();
|
||||||
log.newSituation = m_interpolant.pbh().getNewSituation();
|
log.situationNew = m_interpolant.pbh().getNewSituation();
|
||||||
log.deltaTimeMs = dt1;
|
log.deltaSampleTimesMs = dt2;
|
||||||
log.deltaTimeFractionMs = dt2;
|
|
||||||
log.simulationTimeFraction = timeFraction;
|
log.simulationTimeFraction = timeFraction;
|
||||||
|
log.tsInterpolated = log.situationNew.getMSecsSinceEpoch(); // without offset
|
||||||
|
|
||||||
status.setInterpolated(true);
|
status.setInterpolated(true);
|
||||||
m_interpolant.setTimes(currentTimeMsSinceEpoc, timeFraction);
|
m_interpolant.setTimes(currentTimeMsSinceEpoc, timeFraction);
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ namespace BlackMisc
|
|||||||
//! Interpolator for pitch, bank, heading, groundspeed
|
//! Interpolator for pitch, bank, heading, groundspeed
|
||||||
const CInterpolatorPbh &pbh() const { return m_pbh; }
|
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
|
//! Set the time values
|
||||||
void setTimes(qint64 currentTimeMs, double timeFraction);
|
void setTimes(qint64 currentTimeMs, double timeFraction);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user