mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-30 20:15:35 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user