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
int m_situationsAvailable = 0; //!< used situations
CInterpolatorPbh m_pbh; //!< the used PBH interpolator
CInterpolatorPbh m_pbh; //!< the used PBH interpolator
};
} // namespace
} // namespace

View File

@@ -76,16 +76,16 @@ namespace BlackMisc
{
const bool vtol = setup.isForcingVtolInterpolation() || m_model.isVtol();
CAircraftSituationList validSituations = this->remoteAircraftSituations(m_callsign);
m_currentSituationChange = CAircraftSituationChange(validSituations, m_model.getCG(), vtol, true, true);
if (setup.isFixingSceneryOffset() && m_currentSituationChange.hasSceneryDeviation() && m_model.hasCG())
m_situationsChange = CAircraftSituationChange(validSituations, m_model.getCG(), vtol, true, true);
if (setup.isFixingSceneryOffset() && m_situationsChange.hasSceneryDeviation() && m_model.hasCG())
{
const CLength os = m_currentSituationChange.getGuessedSceneryDeviationCG();
const CLength os = m_situationsChange.getGuessedSceneryDeviationCG();
m_currentSceneryOffset = os;
if (!os.isNull())
{
const CLength addValue = os * -1.0; // positive values means too high, negative values too low
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);
}
}
@@ -173,40 +173,16 @@ namespace BlackMisc
return CAircraftSituation::null();
}
const CAircraftSituation latest = m_currentSituations.front();
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
// interpolant as function of derived class
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
SituationLog 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();
// 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.setPitch(pbh.getPitch());
currentSituation.setBank(pbh.getBank());
@@ -217,12 +193,23 @@ namespace BlackMisc
currentSituation = interpolant.interpolatePositionAndAltitude(currentSituation, interpolateGndFlag);
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;
if (!interpolateGndFlag && currentSituation.getOnGroundDetails() != CAircraftSituation::OnGroundByGuessing)
{
// just in case
altCorrection = currentSituation.correctAltitude(cg, true);
altCorrection = currentSituation.correctAltitude(true); // we have CG set
}
// status
@@ -238,10 +225,10 @@ namespace BlackMisc
log.groundFactor = currentSituation.getOnGroundFactor();
log.altCorrection = CAircraftSituation::altitudeCorrectionToString(altCorrection);
log.situationCurrent = currentSituation;
log.change = m_currentSituationChange;
log.change = m_situationsChange;
log.usedSetup = m_currentSetup;
log.elevationInfo = elv.arg(elvStats.first).arg(elvStats.second);
log.cgAboveGround = cg;
log.cgAboveGround = currentSituation.getCG();
log.sceneryOffset = m_currentSceneryOffset;
m_logger->logInterpolation(log);
}
@@ -309,7 +296,7 @@ namespace BlackMisc
if (!m_currentPartsStatus.isSupportingParts())
{
// 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);
}
@@ -362,7 +349,7 @@ namespace BlackMisc
this->resetLastInterpolation();
m_model = CAircraftModel();
m_currentSceneryOffset = CLength::null();
m_currentSituationChange = CAircraftSituationChange::null();
m_situationsChange = CAircraftSituationChange::null();
m_currentSituations.clear();
m_currentTimeMsSinceEpoch = -1;
m_situationsLastModified = -1;
@@ -405,9 +392,9 @@ namespace BlackMisc
{
const bool inRange = this->isAircraftInRange(m_callsign);
m_lastSituation = CAircraftSituation::null(); // no interpolation possible for that step
m_currentInterpolationStatus.setExtraInfo(inRange ?
QString("No situations, but remote aircraft '%1'").arg(m_callsign.asString()) :
QString("Unknown remote aircraft: '%1'").arg(m_callsign.asString()));
static const QString extraNoSituations("No situations, but remote aircraft '%1'");
static const QString extraNoRemoteAircraft("Unknown remote aircraft: '%1'");
m_currentInterpolationStatus.setExtraInfo((inRange ? extraNoSituations : extraNoRemoteAircraft).arg(m_callsign.asString()));
}
else
{
@@ -426,6 +413,68 @@ namespace BlackMisc
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>
void CInterpolator<Derived>::initCorrespondingModel(const CAircraftModel &model)
{
@@ -495,6 +544,7 @@ namespace BlackMisc
m_extraInfo.clear();
m_isValidSituation = false;
m_isInterpolated = false;
m_isSameSituation = false;
m_situations = -1;
}
@@ -503,20 +553,24 @@ namespace BlackMisc
return QStringLiteral("Interpolated: ") % boolToYesNo(m_isInterpolated) %
QStringLiteral(" | situations: ") % QString::number(m_situations) %
QStringLiteral(" | situation valid: ") % boolToYesNo(m_isValidSituation) %
QStringLiteral(" | same: ") % boolToYesNo(m_isSameSituation) %
(
m_extraInfo.isEmpty() ? QStringLiteral("") : QStringLiteral(" info: ") % m_extraInfo
);
}
bool CPartsStatus::allTrue() const
{
return m_supportsParts;
}
void CPartsStatus::reset()
{
m_supportsParts = 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

View File

@@ -46,6 +46,12 @@ namespace BlackMisc
//! Set succeeded
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
void setSituationsCount(int count) { m_situations = count; }
@@ -73,8 +79,9 @@ namespace BlackMisc
private:
bool m_isInterpolated = false; //!< position is interpolated (means enough values, etc.)
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
QString m_extraInfo; //!< optional details
QString m_extraInfo; //!< optional details
};
//! Status regarding parts
@@ -87,27 +94,35 @@ namespace BlackMisc
//! Ctor
CPartsStatus(bool supportsParts) : m_supportsParts(supportsParts) {}
//! all OK
bool allTrue() const;
//! Supporting parts
bool isSupportingParts() const { return m_supportsParts; }
//! Set support flag
void setSupportsParts(bool supports) { m_supportsParts = supports; }
//! Is a reused parts, means using last value again
bool isReusedPArts() const { return m_resusedParts; }
//! Is a reused parts object?
//! \remark means using last value again
bool isReusedParts() const { return m_resusedParts; }
//! Mark as 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
void reset();
//! Info string
QString toQString() const;
private:
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
@@ -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
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
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
Aviation::CAircraftParts getInterpolatedParts();
@@ -251,10 +273,10 @@ namespace BlackMisc
// values for current interpolation step
qint64 m_currentTimeMsSinceEpoch = -1; //!< current time
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
CInterpolationStatus m_currentInterpolationStatus; //!< this step's status
CPartsStatus m_currentPartsStatus; //!< this step's status
CInterpolationStatus m_currentInterpolationStatus; //!< this step's situation 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
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