mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-03 15:45:46 +08:00
Ref T421, interpolation log messages in interpolator(s)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user