Ref T275, interpolator improvements

* flags for same parts/situation status
* transfer elevation (Ref T273) from previous situation
* preset elevation based on network situations if possible
* set elevation info
* function CInterpolator::initInterpolatedSituation
This commit is contained in:
Klaus Basan
2018-06-03 23:44:33 +02:00
parent 6c0c925fa2
commit fe396e19aa
3 changed files with 135 additions and 59 deletions

View File

@@ -43,7 +43,7 @@ namespace BlackMisc
qint64 m_interpolatedTime = -1; //!< "Real time "of interpolated situation qint64 m_interpolatedTime = -1; //!< "Real time "of interpolated situation
int m_situationsAvailable = 0; //!< used situations int m_situationsAvailable = 0; //!< used situations
CInterpolatorPbh m_pbh; //!< the used PBH interpolator CInterpolatorPbh m_pbh; //!< the used PBH interpolator
}; };
} // namespace } // namespace
} // namespace } // namespace

View File

@@ -76,16 +76,16 @@ namespace BlackMisc
{ {
const bool vtol = setup.isForcingVtolInterpolation() || m_model.isVtol(); const bool vtol = setup.isForcingVtolInterpolation() || m_model.isVtol();
CAircraftSituationList validSituations = this->remoteAircraftSituations(m_callsign); CAircraftSituationList validSituations = this->remoteAircraftSituations(m_callsign);
m_currentSituationChange = CAircraftSituationChange(validSituations, m_model.getCG(), vtol, true, true); m_situationsChange = CAircraftSituationChange(validSituations, m_model.getCG(), vtol, true, true);
if (setup.isFixingSceneryOffset() && m_currentSituationChange.hasSceneryDeviation() && m_model.hasCG()) if (setup.isFixingSceneryOffset() && m_situationsChange.hasSceneryDeviation() && m_model.hasCG())
{ {
const CLength os = m_currentSituationChange.getGuessedSceneryDeviationCG(); const CLength os = m_situationsChange.getGuessedSceneryDeviationCG();
m_currentSceneryOffset = os; m_currentSceneryOffset = os;
if (!os.isNull()) if (!os.isNull())
{ {
const CLength addValue = os * -1.0; // positive values means too high, negative values too low const CLength addValue = os * -1.0; // positive values means too high, negative values too low
int changed = validSituations.addAltitudeOffset(addValue); int changed = validSituations.addAltitudeOffset(addValue);
m_currentSituationChange = CAircraftSituationChange(validSituations, m_model.getCG(), vtol, true, true); // recalculate m_situationsChange = CAircraftSituationChange(validSituations, m_model.getCG(), vtol, true, true); // recalculate
Q_UNUSED(changed); Q_UNUSED(changed);
} }
} }
@@ -173,40 +173,16 @@ namespace BlackMisc
return CAircraftSituation::null(); return CAircraftSituation::null();
} }
const CAircraftSituation latest = m_currentSituations.front(); // interpolant as function of derived class
CAircraftSituation currentSituation = m_lastSituation.isNull() ? latest : m_lastSituation;
if (currentSituation.getCallsign() != m_callsign)
{
BLACK_VERIFY_X(false, Q_FUNC_INFO, "Wrong callsign");
currentSituation.setCallsign(m_callsign);
}
// set elevation if available
if (!currentSituation.hasGroundElevation())
{
const CElevationPlane currentGroundElevation = this->findClosestElevationWithinRange(currentSituation, currentSituation.getDistancePerTime(1000));
currentSituation.setGroundElevationChecked(currentGroundElevation); // set as default
}
// fetch CG once
const CLength cg(this->getModelCG());
currentSituation.setCG(cg);
// interpolant function from derived class
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant // CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
SituationLog log; SituationLog log;
const auto interpolant = derived()->getInterpolant(log); const auto interpolant = derived()->getInterpolant(log);
// succeeded so far?
if (!m_currentInterpolationStatus.isInterpolated())
{
m_currentInterpolationStatus.checkIfValidSituation(currentSituation);
return currentSituation;
}
// Pitch bank heading
// first, so follow up steps could use those values
const CInterpolatorPbh pbh = interpolant.pbh(); const CInterpolatorPbh pbh = interpolant.pbh();
// init interpolated situation
CAircraftSituation currentSituation = this->initInterpolatedSituation(pbh.getOldSituation(), pbh.getNewSituation());
// Pitch bank heading first, so follow up steps could use those values
currentSituation.setHeading(pbh.getHeading()); currentSituation.setHeading(pbh.getHeading());
currentSituation.setPitch(pbh.getPitch()); currentSituation.setPitch(pbh.getPitch());
currentSituation.setBank(pbh.getBank()); currentSituation.setBank(pbh.getBank());
@@ -217,12 +193,23 @@ namespace BlackMisc
currentSituation = interpolant.interpolatePositionAndAltitude(currentSituation, interpolateGndFlag); currentSituation = interpolant.interpolatePositionAndAltitude(currentSituation, interpolateGndFlag);
if (!interpolateGndFlag) { currentSituation.guessOnGround(CAircraftSituationChange::null(), m_model); } if (!interpolateGndFlag) { currentSituation.guessOnGround(CAircraftSituationChange::null(), m_model); }
// correct itself // if we do not have a ground elevation from preset, then we try to transfer here
if (!currentSituation.hasGroundElevation())
{
const CLength radius = currentSituation.getDistancePerTime(250);
if (!m_lastSituation.transferGroundElevation(currentSituation, radius))
{
const CElevationPlane groundElevation = this->findClosestElevationWithinRange(currentSituation, radius);
m_lastSituation.setGroundElevationChecked(groundElevation, CAircraftSituation::FromCache);
}
}
// correct altitude itself
CAircraftSituation::AltitudeCorrection altCorrection = CAircraftSituation::NoCorrection; CAircraftSituation::AltitudeCorrection altCorrection = CAircraftSituation::NoCorrection;
if (!interpolateGndFlag && currentSituation.getOnGroundDetails() != CAircraftSituation::OnGroundByGuessing) if (!interpolateGndFlag && currentSituation.getOnGroundDetails() != CAircraftSituation::OnGroundByGuessing)
{ {
// just in case // just in case
altCorrection = currentSituation.correctAltitude(cg, true); altCorrection = currentSituation.correctAltitude(true); // we have CG set
} }
// status // status
@@ -238,10 +225,10 @@ namespace BlackMisc
log.groundFactor = currentSituation.getOnGroundFactor(); log.groundFactor = currentSituation.getOnGroundFactor();
log.altCorrection = CAircraftSituation::altitudeCorrectionToString(altCorrection); log.altCorrection = CAircraftSituation::altitudeCorrectionToString(altCorrection);
log.situationCurrent = currentSituation; log.situationCurrent = currentSituation;
log.change = m_currentSituationChange; log.change = m_situationsChange;
log.usedSetup = m_currentSetup; log.usedSetup = m_currentSetup;
log.elevationInfo = elv.arg(elvStats.first).arg(elvStats.second); log.elevationInfo = elv.arg(elvStats.first).arg(elvStats.second);
log.cgAboveGround = cg; log.cgAboveGround = currentSituation.getCG();
log.sceneryOffset = m_currentSceneryOffset; log.sceneryOffset = m_currentSceneryOffset;
m_logger->logInterpolation(log); m_logger->logInterpolation(log);
} }
@@ -309,7 +296,7 @@ namespace BlackMisc
if (!m_currentPartsStatus.isSupportingParts()) if (!m_currentPartsStatus.isSupportingParts())
{ {
// check if model has been thru model matching // check if model has been thru model matching
parts.guessParts(m_lastSituation, m_currentSituationChange, m_model); parts.guessParts(m_lastSituation, m_situationsChange, m_model);
this->logParts(parts, 0, false); this->logParts(parts, 0, false);
} }
@@ -362,7 +349,7 @@ namespace BlackMisc
this->resetLastInterpolation(); this->resetLastInterpolation();
m_model = CAircraftModel(); m_model = CAircraftModel();
m_currentSceneryOffset = CLength::null(); m_currentSceneryOffset = CLength::null();
m_currentSituationChange = CAircraftSituationChange::null(); m_situationsChange = CAircraftSituationChange::null();
m_currentSituations.clear(); m_currentSituations.clear();
m_currentTimeMsSinceEpoch = -1; m_currentTimeMsSinceEpoch = -1;
m_situationsLastModified = -1; m_situationsLastModified = -1;
@@ -405,9 +392,9 @@ namespace BlackMisc
{ {
const bool inRange = this->isAircraftInRange(m_callsign); const bool inRange = this->isAircraftInRange(m_callsign);
m_lastSituation = CAircraftSituation::null(); // no interpolation possible for that step m_lastSituation = CAircraftSituation::null(); // no interpolation possible for that step
m_currentInterpolationStatus.setExtraInfo(inRange ? static const QString extraNoSituations("No situations, but remote aircraft '%1'");
QString("No situations, but remote aircraft '%1'").arg(m_callsign.asString()) : static const QString extraNoRemoteAircraft("Unknown remote aircraft: '%1'");
QString("Unknown remote aircraft: '%1'").arg(m_callsign.asString())); m_currentInterpolationStatus.setExtraInfo((inRange ? extraNoSituations : extraNoRemoteAircraft).arg(m_callsign.asString()));
} }
else else
{ {
@@ -426,6 +413,68 @@ namespace BlackMisc
return success; return success;
} }
template<typename Derived>
CAircraftSituation CInterpolator<Derived>::initInterpolatedSituation(const CAircraftSituation &oldSituation, const CAircraftSituation &newSituation) const
{
if (m_currentSituations.isEmpty()) { return CAircraftSituation::null(); }
CAircraftSituation currentSituation = m_lastSituation.isNull() ? m_currentSituations.front() : m_lastSituation;
if (currentSituation.getCallsign() != m_callsign)
{
BLACK_VERIFY_X(false, Q_FUNC_INFO, "Wrong callsign");
currentSituation.setCallsign(m_callsign);
}
// do not set elevation here, as we do not know where the situation will be
// after the interpolation step!
this->presetGroundElevation(currentSituation, oldSituation, newSituation);
// fetch CG once
const CLength cg(this->getModelCG());
currentSituation.setCG(cg);
return currentSituation;
}
template<typename Derived>
bool CInterpolator<Derived>::presetGroundElevation(CAircraftSituation &situation, const CAircraftSituation &oldSituation, const CAircraftSituation &newSituation) const
{
// IMPORTANT: we do not know what the situation will be interpolated to, so we cannot transfer
situation.resetGroundElevation();
do
{
if (oldSituation.equalNormalVectorDouble(newSituation))
{
if (oldSituation.hasGroundElevation())
{
// same positions, we can use existing elevation
situation.setGroundElevation(oldSituation.getGroundElevationPlane(), CAircraftSituation::TransferredElevation);
break;
}
}
const CLength distance = newSituation.calculateGreatCircleDistance(oldSituation);
if (distance < newSituation.getDistancePerTime(250))
{
if (oldSituation.hasGroundElevation())
{
// almost same positions, we can use existing elevation
situation.setGroundElevation(oldSituation.getGroundElevationPlane(), CAircraftSituation::TransferredElevation);
break;
}
}
static const CLength allowedStdDev(3, CLengthUnit::ft());
QPair<CAltitude, CAltitude> elvDevMean = m_situationsChange.getElevationStdDevAndMean();
if (!elvDevMean.first.isNull() && elvDevMean.first < allowedStdDev)
{
// not much change in known elevations
situation.setGroundElevation(elvDevMean.second, CAircraftSituation::SituationChange);
break;
}
}
while (false);
return situation.hasGroundElevation();
}
template<typename Derived> template<typename Derived>
void CInterpolator<Derived>::initCorrespondingModel(const CAircraftModel &model) void CInterpolator<Derived>::initCorrespondingModel(const CAircraftModel &model)
{ {
@@ -495,6 +544,7 @@ namespace BlackMisc
m_extraInfo.clear(); m_extraInfo.clear();
m_isValidSituation = false; m_isValidSituation = false;
m_isInterpolated = false; m_isInterpolated = false;
m_isSameSituation = false;
m_situations = -1; m_situations = -1;
} }
@@ -503,20 +553,24 @@ namespace BlackMisc
return QStringLiteral("Interpolated: ") % boolToYesNo(m_isInterpolated) % return QStringLiteral("Interpolated: ") % boolToYesNo(m_isInterpolated) %
QStringLiteral(" | situations: ") % QString::number(m_situations) % QStringLiteral(" | situations: ") % QString::number(m_situations) %
QStringLiteral(" | situation valid: ") % boolToYesNo(m_isValidSituation) % QStringLiteral(" | situation valid: ") % boolToYesNo(m_isValidSituation) %
QStringLiteral(" | same: ") % boolToYesNo(m_isSameSituation) %
( (
m_extraInfo.isEmpty() ? QStringLiteral("") : QStringLiteral(" info: ") % m_extraInfo m_extraInfo.isEmpty() ? QStringLiteral("") : QStringLiteral(" info: ") % m_extraInfo
); );
} }
bool CPartsStatus::allTrue() const
{
return m_supportsParts;
}
void CPartsStatus::reset() void CPartsStatus::reset()
{ {
m_supportsParts = false; m_supportsParts = false;
m_resusedParts = false; m_resusedParts = false;
m_isSameParts = false;
}
QString CPartsStatus::toQString() const
{
return QStringLiteral("Supported parts: ") % boolToYesNo(m_supportsParts) %
QStringLiteral(" | reused: ") % boolToYesNo(m_resusedParts) %
QStringLiteral(" | same: ") % boolToYesNo(m_isSameParts);
} }
// see here for the reason of thess forward instantiations // see here for the reason of thess forward instantiations

View File

@@ -46,6 +46,12 @@ namespace BlackMisc
//! Set succeeded //! Set succeeded
void setInterpolated(bool interpolated) { m_isInterpolated = interpolated; } void setInterpolated(bool interpolated) { m_isInterpolated = interpolated; }
//! Interpolating between 2 same situations?
bool isSameSituation() const { return m_isSameSituation; }
//! Interpolating between 2 same situations?
void setSameSituation(bool same) { m_isSameSituation = same; }
//! Set situations count //! Set situations count
void setSituationsCount(int count) { m_situations = count; } void setSituationsCount(int count) { m_situations = count; }
@@ -73,8 +79,9 @@ namespace BlackMisc
private: private:
bool m_isInterpolated = false; //!< position is interpolated (means enough values, etc.) bool m_isInterpolated = false; //!< position is interpolated (means enough values, etc.)
bool m_isValidSituation = false; //!< is valid situation bool m_isValidSituation = false; //!< is valid situation
bool m_isSameSituation = false; //!< interpolation between 2 same situations
int m_situations = -1; //!< number of situations used for interpolation int m_situations = -1; //!< number of situations used for interpolation
QString m_extraInfo; //!< optional details QString m_extraInfo; //!< optional details
}; };
//! Status regarding parts //! Status regarding parts
@@ -87,27 +94,35 @@ namespace BlackMisc
//! Ctor //! Ctor
CPartsStatus(bool supportsParts) : m_supportsParts(supportsParts) {} CPartsStatus(bool supportsParts) : m_supportsParts(supportsParts) {}
//! all OK
bool allTrue() const;
//! Supporting parts //! Supporting parts
bool isSupportingParts() const { return m_supportsParts; } bool isSupportingParts() const { return m_supportsParts; }
//! Set support flag //! Set support flag
void setSupportsParts(bool supports) { m_supportsParts = supports; } void setSupportsParts(bool supports) { m_supportsParts = supports; }
//! Is a reused parts, means using last value again //! Is a reused parts object?
bool isReusedPArts() const { return m_resusedParts; } //! \remark means using last value again
bool isReusedParts() const { return m_resusedParts; }
//! Mark as reused //! Mark as reused
void setReusedParts(bool reused) { m_resusedParts = reused; } void setReusedParts(bool reused) { m_resusedParts = reused; }
//! Same parts as last parts?
bool isSameParts() const { return m_isSameParts; }
//! Same parts as last parts?
void setSameParts(bool same) { m_isSameParts = same; }
//! Reset to default values //! Reset to default values
void reset(); void reset();
//! Info string
QString toQString() const;
private: private:
bool m_supportsParts = false; //!< supports parts for given callsign bool m_supportsParts = false; //!< supports parts for given callsign
bool m_resusedParts = false; //!< reusing from last step bool m_resusedParts = false; //!< reusing from last step
bool m_isSameParts = false; //!< same as last parts?
}; };
//! Combined results //! Combined results
@@ -226,9 +241,16 @@ namespace BlackMisc
//! \param aircraftNumber passing the aircraft number allows to equally distribute among the steps and not to do it always together for all aircraft //! \param aircraftNumber passing the aircraft number allows to equally distribute among the steps and not to do it always together for all aircraft
bool initIniterpolationStepData(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup, int aircraftNumber); bool initIniterpolationStepData(qint64 currentTimeSinceEpoc, const CInterpolationAndRenderingSetupPerCallsign &setup, int aircraftNumber);
//! Init the interpolated situation
Aviation::CAircraftSituation initInterpolatedSituation(const Aviation::CAircraftSituation &oldSituation, const Aviation::CAircraftSituation &newSituation) const;
//! Current interpolated situation //! Current interpolated situation
Aviation::CAircraftSituation getInterpolatedSituation(); Aviation::CAircraftSituation getInterpolatedSituation();
//! Preset the ground elevation based on info we already have
//! \remark either sets a gnd.elevation or sets it to null
bool presetGroundElevation(Aviation::CAircraftSituation &situation, const Aviation::CAircraftSituation &oldSituation, const Aviation::CAircraftSituation &newSituation) const;
//! Parts before given offset time //! Parts before given offset time
Aviation::CAircraftParts getInterpolatedParts(); Aviation::CAircraftParts getInterpolatedParts();
@@ -251,10 +273,10 @@ namespace BlackMisc
// values for current interpolation step // values for current interpolation step
qint64 m_currentTimeMsSinceEpoch = -1; //!< current time qint64 m_currentTimeMsSinceEpoch = -1; //!< current time
Aviation::CAircraftSituationList m_currentSituations; //!< current situations Aviation::CAircraftSituationList m_currentSituations; //!< current situations
Aviation::CAircraftSituationChange m_currentSituationChange; //!< situations change Aviation::CAircraftSituationChange m_situationsChange; //!< situations change of provider (i.e. network) situations
CInterpolationAndRenderingSetupPerCallsign m_currentSetup; //!< used setup CInterpolationAndRenderingSetupPerCallsign m_currentSetup; //!< used setup
CInterpolationStatus m_currentInterpolationStatus; //!< this step's status CInterpolationStatus m_currentInterpolationStatus; //!< this step's situation status
CPartsStatus m_currentPartsStatus; //!< this step's status CPartsStatus m_currentPartsStatus; //!< this step's parts status
CPartsStatus m_lastPartsStatus; //!< status for last parts, used when last parts are re-used because of m_partsToSituationInterpolationRatio CPartsStatus m_lastPartsStatus; //!< status for last parts, used when last parts are re-used because of m_partsToSituationInterpolationRatio
int m_partsToSituationInterpolationRatio = 2; //!< ratio between parts and situation interpolation, 1..always, 2..every 2nd situation int m_partsToSituationInterpolationRatio = 2; //!< ratio between parts and situation interpolation, 1..always, 2..every 2nd situation
Aviation::CAircraftSituation m_lastSituation { Aviation::CAircraftSituation::null() }; //!< latest interpolation Aviation::CAircraftSituation m_lastSituation { Aviation::CAircraftSituation::null() }; //!< latest interpolation