Ref T421, interpolation log messages in interpolator(s)

This commit is contained in:
Klaus Basan
2018-10-31 15:27:02 +01:00
parent 2581ec5582
commit 41685df4ee
6 changed files with 141 additions and 37 deletions

View File

@@ -179,13 +179,15 @@ namespace BlackMisc
// CInterpolatorLinear::Interpolant or CInterpolatorSpline::Interpolant
SituationLog log;
const auto interpolant = derived()->getInterpolant(log);
const bool isValid = interpolant.isValid();
const bool isValidInterpolant = interpolant.isValid();
CAircraftSituation currentSituation = m_lastSituation;
CAircraftSituation::AltitudeCorrection altCorrection = CAircraftSituation::NoCorrection;
if (isValid)
bool isValidInterpolation = false;
do
{
if (!isValidInterpolant) { break; }
const CInterpolatorPbh pbh = interpolant.pbh();
// init interpolated situation
@@ -200,6 +202,8 @@ namespace BlackMisc
// use derived interpolant function
const bool interpolateGndFlag = pbh.getNewSituation().hasGroundDetailsForGndInterpolation() && pbh.getOldSituation().hasGroundDetailsForGndInterpolation();
currentSituation = interpolant.interpolatePositionAndAltitude(currentSituation, interpolateGndFlag);
if (currentSituation.isNull()) { break; }
if (CBuildConfig::isLocalDeveloperDebugBuild())
{
Q_ASSERT_X(currentSituation.isValidVectorRange(), Q_FUNC_INFO, "Invalid interpolation situation");
@@ -235,35 +239,62 @@ namespace BlackMisc
currentSituation.setPitch(correctedPitchOnGround);
}
}
isValidInterpolation = true;
}
else
while (false);
const bool valid = isValidInterpolant && isValidInterpolation;
if (!valid)
{
// further handling could go here, mainly we continue with last situation
m_invalidSituations++;
// further handling could go here, mainly we continue with last situation
const bool noSituation = currentSituation.isNull();
const qint64 diff = noSituation ? -1 : m_currentTimeMsSinceEpoch - currentSituation.getAdjustedMSecsSinceEpoch();
const qint64 thresholdMs = noSituation ? qRound(CFsdSetup::c_interimPositionTimeOffsetMsec * 0.5) : qRound(currentSituation.getTimeOffsetMs() * 0.5);
const bool threshold = diff > thresholdMs;
if (noSituation || threshold)
// avoid flooding of log.
if (m_currentTimeMsSinceEpoch - m_lastInvalidLogTs > m_lastSituation.getTimeOffsetMs())
{
m_lastInvalidLogTs = m_currentTimeMsSinceEpoch;
const bool noSituation = m_lastSituation.isNull();
// Problem 1, we have no "last situation"
// Problem 2, "it takes too long to recover"
CStatusMessage m;
if (noSituation)
{
CLogMessage(this).warning("No situation no %1 for interpolation reported for '%2'") << m_invalidSituations << m_callsign.asString();
m = CStatusMessage(this).warning("No situation #%1 for interpolation reported for '%2' (Interpolant: %3 interpolation: %4)") <<
m_invalidSituations << m_callsign.asString() << boolToTrueFalse(isValidInterpolant) << boolToTrueFalse(isValidInterpolation);
}
else
{
CLogMessage(this).warning("Invalid situation, diff %1ms no %2 for interpolation reported for '%3'") << diff << m_invalidSituations << m_callsign.asString();
const qint64 diff = noSituation ? -1 : m_currentTimeMsSinceEpoch - currentSituation.getAdjustedMSecsSinceEpoch();
m = CStatusMessage(this).warning("Invalid situation, diff. %1ms #%2 for interpolation reported for '%3' (Interpolant: %4 interpolation: %5)") <<
diff << m_invalidSituations << m_callsign.asString() << boolToTrueFalse(isValidInterpolant) << boolToTrueFalse(isValidInterpolation);
}
if (!m.isEmpty())
{
if (m_interpolationMessages.isEmpty())
{
// display first message as a hint in the general log
CLogMessage::preformatted(m);
}
m_interpolationMessages.push_back(m);
}
}
}// valid?
// status
Q_ASSERT_X(currentSituation.hasMSLGeodeticHeight(), Q_FUNC_INFO, "No MSL altitude");
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(isValid, currentSituation);
m_lastSituation = currentSituation;
// situation and status
if (valid)
{
Q_ASSERT_X(currentSituation.hasMSLGeodeticHeight(), Q_FUNC_INFO, "No MSL altitude");
m_lastSituation = currentSituation;
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(valid, currentSituation);
}
else
{
currentSituation = m_lastSituation;
m_currentInterpolationStatus.setSameSituation(true);
m_currentInterpolationStatus.setInterpolatedAndCheckSituation(valid, currentSituation);
}
// logging
if (this->doLogging())
@@ -332,33 +363,36 @@ namespace BlackMisc
if (!doGuess && !doInterpolation)
{
m_currentPartsStatus = m_lastPartsStatus;
m_currentPartsStatus.setReusedParts(true);
return m_lastParts;
// reuse
return this->logAndReturnNullParts("neither guess nor interpolation", true);
}
CAircraftParts parts;
CAircraftParts parts = CAircraftParts::null();
if (m_currentSetup.isAircraftPartsEnabled())
{
// this already logs
// this already logs and sets status
parts = this->getInterpolatedParts();
}
// if we have supported parts, we skip this step, but it can happen
// the parts are still empty
// if we have supported parts, we skip this step, but it can happen the parts are still empty
if (!m_currentPartsStatus.isSupportingParts())
{
if (!doGuess)
{
m_currentPartsStatus = m_lastPartsStatus;
m_currentPartsStatus.setReusedParts(true);
return m_lastParts;
return this->logAndReturnNullParts("not supporting parts, and marked for guessing", true);
}
// check if model has been thru model matching
Q_ASSERT_X(!m_lastSituation.isNull(), Q_FUNC_INFO, "null situations");
parts.guessParts(m_lastSituation, m_pastSituationsChange, m_model);
this->logParts(parts, 0, false);
if (!m_lastSituation.isNull())
{
parts.guessParts(m_lastSituation, m_pastSituationsChange, m_model);
this->logParts(parts, 0, false);
}
else
{
// quite normal initial situation, just return NULL
return this->logAndReturnNullParts("guessing, but no situation yet", false);
}
}
m_lastParts = parts;
@@ -366,6 +400,27 @@ namespace BlackMisc
return parts;
}
template<typename Derived>
const CAircraftParts &CInterpolator<Derived>::logAndReturnNullParts(const QString &info, bool log)
{
if (!m_lastParts.isNull())
{
m_currentPartsStatus = m_lastPartsStatus;
m_currentPartsStatus.setReusedParts(true);
return m_lastParts;
}
if (log)
{
const CStatusMessage m = CStatusMessage(this).warning("NULL parts reported for '%1', '%2')") << m_callsign.asString() << info;
if (m_interpolationMessages.isEmpty()) { CLogMessage::preformatted(m); }
m_interpolationMessages.push_back(m);
}
m_currentPartsStatus.reset();
return CAircraftParts::null();
}
template<typename Derived>
bool CInterpolator<Derived>::doLogging() const
{
@@ -418,6 +473,9 @@ namespace BlackMisc
m_currentInterpolationStatus.reset();
m_currentPartsStatus.reset();
m_interpolatedSituationsCounter = 0;
m_invalidSituations = 0;
m_lastInvalidLogTs = -1;
m_interpolationMessages.clear();
}
template<typename Derived>
@@ -564,6 +622,7 @@ namespace BlackMisc
void CInterpolationStatus::checkIfValidSituation(const CAircraftSituation &situation)
{
m_isValidSituation = !situation.isPositionOrAltitudeNull();
if (!m_isValidSituation) { m_isValidSituation = false; }
}
bool CInterpolationStatus::hasValidInterpolatedSituation() const

View File

@@ -22,6 +22,7 @@
#include "blackmisc/aviation/aircraftpartslist.h"
#include "blackmisc/aviation/callsign.h"
#include "blackmisc/logcategorylist.h"
#include "blackmisc/statusmessagelist.h"
#include <QObject>
#include <QString>
@@ -233,6 +234,12 @@ namespace BlackMisc
//! Get count of invalid situations
int getInvalidSituationsCount() const { return m_invalidSituations; }
//! Interpolation messages
const CStatusMessageList &getInterpolationMessages() const { return m_interpolationMessages; }
//! Do we have interpolation messages
bool hasInterpolationMessages() const { return !m_interpolationMessages.isEmpty(); }
protected:
//! Constructor
CInterpolator(const Aviation::CCallsign &callsign,
@@ -281,6 +288,9 @@ namespace BlackMisc
int m_partsToSituationInterpolationRatio = 2; //!< ratio between parts and situation interpolation, 1..always, 2..every 2nd situation
int m_partsToSituationGuessingRatio = 5; //!< ratio between parts guessing and situation interpolation
int m_invalidSituations = 0; //!< mainly when there are no new situations
qint64 m_lastInvalidLogTs = -1; //!< last invalid situation timestamp
CStatusMessageList m_interpolationMessages; //!< interpolation messages
Aviation::CAircraftSituation m_lastSituation { Aviation::CAircraftSituation::null() }; //!< latest interpolation
Aviation::CAircraftParts m_lastParts { Aviation::CAircraftParts::null() }; //!< latest parts
PhysicalQuantities::CLength m_currentSceneryOffset { PhysicalQuantities::CLength::null() }; //!< calculated scenery offset if any
@@ -312,8 +322,13 @@ namespace BlackMisc
//! Deferred init
void deferredInit();
//! Return NULL parts and log
const BlackMisc::Aviation::CAircraftParts &logAndReturnNullParts(const QString &info, bool log);
//! Derived class @{
Derived *derived() { return static_cast<Derived *>(this); }
const Derived *derived() const { return static_cast<const Derived *>(this); }
//! @}
};
//! \cond PRIVATE

View File

@@ -57,6 +57,18 @@ namespace BlackMisc
m_spline.initCorrespondingModel(model);
}
const CStatusMessageList &CInterpolatorMulti::getInterpolationMessages(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
{
switch (mode)
{
case CInterpolationAndRenderingSetupBase::Spline: return m_spline.getInterpolationMessages();
case CInterpolationAndRenderingSetupBase::Linear: return m_linear.getInterpolationMessages();
default: break;
}
static const CStatusMessageList empty;
return empty;
}
QString CInterpolatorMulti::getInterpolatorInfo(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const
{
switch (mode)

View File

@@ -14,6 +14,7 @@
#include "blackmisc/simulation/interpolatorlinear.h"
#include "blackmisc/simulation/interpolatorspline.h"
#include "blackmisc/statusmessagelist.h"
namespace BlackMisc
{
@@ -34,6 +35,9 @@ namespace BlackMisc
//! \copydoc CInterpolator::getLastInterpolatedSituation
const Aviation::CAircraftSituation &getLastInterpolatedSituation(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
//! \copydoc CInterpolator::getInterpolationMessages
const CStatusMessageList &getInterpolationMessages(CInterpolationAndRenderingSetupBase::InterpolatorMode mode) const;
//! \copydoc CInterpolator::attachLogger
void attachLogger(CInterpolationLogger *logger);

View File

@@ -312,31 +312,38 @@ namespace BlackMisc
const double t1 = m_pa.t[1];
const double t2 = m_pa.t[2]; // latest (adjusted)
if (CBuildConfig::isLocalDeveloperDebugBuild())
bool valid = (t1 < t2) && (m_currentTimeMsSinceEpoc >= t1) && (m_currentTimeMsSinceEpoc < t2);
if (!valid && CBuildConfig::isLocalDeveloperDebugBuild())
{
Q_ASSERT_X(t1 < t2, Q_FUNC_INFO, "Expect sorted times, latest first");
Q_ASSERT_X(m_currentTimeMsSinceEpoc >= t1, Q_FUNC_INFO, "invalid timestamp t1");
Q_ASSERT_X(m_currentTimeMsSinceEpoc < t2, Q_FUNC_INFO, "invalid timestamp t2"); // t1==t2 results in div/0
Q_ASSERT_X(t1 < t2, Q_FUNC_INFO, "Expect sorted times, latest first"); // that means a bug in our code init the values
BLACK_VERIFY_X(m_currentTimeMsSinceEpoc >= t1, Q_FUNC_INFO, "invalid timestamp t1");
BLACK_VERIFY_X(m_currentTimeMsSinceEpoc < t2, Q_FUNC_INFO, "invalid timestamp t2"); // t1==t2 results in div/0
}
if (!valid) { return CAircraftSituation::null(); }
const double newX = evalSplineInterval(m_currentTimeMsSinceEpoc, t1, t2, m_pa.x[1], m_pa.x[2], m_pa.dx[1], m_pa.dx[2]);
const double newY = evalSplineInterval(m_currentTimeMsSinceEpoc, t1, t2, m_pa.y[1], m_pa.y[2], m_pa.dy[1], m_pa.dy[2]);
const double newZ = evalSplineInterval(m_currentTimeMsSinceEpoc, t1, t2, m_pa.z[1], m_pa.z[2], m_pa.dz[1], m_pa.dz[2]);
if (CBuildConfig::isLocalDeveloperDebugBuild())
valid = CAircraftSituation::isValidVector(m_pa.x) && CAircraftSituation::isValidVector(m_pa.y) && CAircraftSituation::isValidVector(m_pa.z);
if (!valid && CBuildConfig::isLocalDeveloperDebugBuild())
{
BLACK_VERIFY_X(CAircraftSituation::isValidVector(m_pa.x), Q_FUNC_INFO, "invalid X"); // all x values
BLACK_VERIFY_X(CAircraftSituation::isValidVector(m_pa.y), Q_FUNC_INFO, "invalid Y"); // all y values
BLACK_VERIFY_X(CAircraftSituation::isValidVector(m_pa.z), Q_FUNC_INFO, "invalid Z"); // all z values
}
if (!valid) { return CAircraftSituation::null(); }
CAircraftSituation newSituation(currentSituation);
const std::array<double, 3> normalVector = {{ newX, newY, newZ }};
const CCoordinateGeodetic currentPosition(normalVector);
if (CBuildConfig::isLocalDeveloperDebugBuild())
valid = CAircraftSituation::isValidVector(normalVector);
if (!valid && CBuildConfig::isLocalDeveloperDebugBuild())
{
BLACK_VERIFY_X(CAircraftSituation::isValidVector(normalVector), Q_FUNC_INFO, "invalid vector");
BLACK_VERIFY_X(valid, Q_FUNC_INFO, "invalid vector");
}
if (!valid) { return CAircraftSituation::null(); }
const double newA = evalSplineInterval(m_currentTimeMsSinceEpoc, t1, t2, m_pa.a[1], m_pa.a[2], m_pa.da[1], m_pa.da[2]);
const CAltitude alt(newA, m_altitudeUnit);