diff --git a/src/blackmisc/simulation/interpolationlogger.cpp b/src/blackmisc/simulation/interpolationlogger.cpp index 66ca6579f..dac8d9b1f 100644 --- a/src/blackmisc/simulation/interpolationlogger.cpp +++ b/src/blackmisc/simulation/interpolationlogger.cpp @@ -281,15 +281,17 @@ namespace BlackMisc static const CLengthUnit ft = CLengthUnit::ft(); const SituationLog firstLog = logs.first(); - qint64 newPosTs = firstLog.situationNew.getMSecsSinceEpoch(); + qint64 newPosTs = firstLog.newestInterpolationSituation().getMSecsSinceEpoch(); CAircraftParts lastParts; // default, so shown if parts are different from default QString tableRows("\n"); for (const SituationLog &log : logs) { - const bool changedNewPosition = newPosTs != log.situationNew.getMSecsSinceEpoch(); + const CAircraftSituation situationOld = log.oldestInterpolationSituation(); + const CAircraftSituation situationNew = log.newestInterpolationSituation(); + const bool changedNewPosition = newPosTs != situationNew.getMSecsSinceEpoch(); const bool changedParts = (lastParts != log.parts); - newPosTs = log.situationNew.getMSecsSinceEpoch(); + newPosTs = situationNew.getMSecsSinceEpoch(); lastParts = log.parts; // concatenating in multiple steps, otherwise C4503 warnings @@ -302,8 +304,8 @@ namespace BlackMisc QStringLiteral("") % msSinceEpochToTime(log.tsCurrent) % QStringLiteral("") % QStringLiteral("") % QString::number(log.tsCurrent - firstLog.tsCurrent) % QStringLiteral("") % - QStringLiteral("") % log.situationOld.getTimestampAndOffset(true) % QStringLiteral("") % - QStringLiteral("") % log.situationNew.getTimestampAndOffset(true) % QStringLiteral("") % + QStringLiteral("") % situationOld.getTimestampAndOffset(true) % QStringLiteral("") % + QStringLiteral("") % situationNew.getTimestampAndOffset(true) % QStringLiteral("") % QStringLiteral("") % log.situationCurrent.getTimestampAndOffset(true) % QStringLiteral("") % QStringLiteral("") % msSinceEpochToTime(log.tsInterpolated) % QStringLiteral("") % @@ -311,26 +313,26 @@ namespace BlackMisc QStringLiteral("") % QString::number(log.simulationTimeFraction) % QStringLiteral(""); tableRows += - QStringLiteral("") % log.situationOld.latitudeAsString() % QStringLiteral("") % - QStringLiteral("") % log.situationNew.latitudeAsString() % QStringLiteral("") % + QStringLiteral("") % situationOld.latitudeAsString() % QStringLiteral("") % + QStringLiteral("") % situationNew.latitudeAsString() % QStringLiteral("") % QStringLiteral("") % log.situationCurrent.latitudeAsString() % QStringLiteral("") % - QStringLiteral("") % log.situationOld.longitudeAsString() % QStringLiteral("") % - QStringLiteral("") % log.situationNew.longitudeAsString() % QStringLiteral("") % + QStringLiteral("") % situationOld.longitudeAsString() % QStringLiteral("") % + QStringLiteral("") % situationNew.longitudeAsString() % QStringLiteral("") % QStringLiteral("") % log.situationCurrent.longitudeAsString() % QStringLiteral(""); tableRows += - QStringLiteral("") % log.situationOld.getAltitude().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % - QStringLiteral("") % log.situationNew.getAltitude().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % + QStringLiteral("") % situationOld.getAltitude().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % + QStringLiteral("") % situationNew.getAltitude().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % QStringLiteral("") % log.situationCurrent.getAltitude().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % - QStringLiteral("") % log.situationOld.getGroundElevation().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % - QStringLiteral("") % log.situationNew.getGroundElevation().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % + QStringLiteral("") % situationOld.getGroundElevation().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % + QStringLiteral("") % situationNew.getGroundElevation().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % QStringLiteral("") % log.situationCurrent.getGroundElevation().valueRoundedWithUnit(ft, 1) % QStringLiteral("") % QStringLiteral("") % QString::number(log.groundFactor) % QStringLiteral("") % - QStringLiteral("") % log.situationOld.getOnGroundInfo() % QStringLiteral("") % - QStringLiteral("") % log.situationNew.getOnGroundInfo() % QStringLiteral("") % + QStringLiteral("") % situationOld.getOnGroundInfo() % QStringLiteral("") % + QStringLiteral("") % situationNew.getOnGroundInfo() % QStringLiteral("") % QStringLiteral("") % log.situationCurrent.getOnGroundInfo() % QStringLiteral(""); tableRows += @@ -408,10 +410,14 @@ namespace BlackMisc bool withCurrentSituation, bool withHints, bool withSetup, bool withElevation, bool withOtherPositions, bool withDeltaTimes, const QString &separator) const { + const CAircraftSituation situationOldInterpolation = this->oldestInterpolationSituation(); + const CAircraftSituation situationNewInterpolation = this->newestInterpolationSituation(); + return QStringLiteral("CS: ") % callsign.asString() % separator % QStringLiteral("ts: ") % CInterpolationLogger::msSinceEpochToTimeAndTimestamp(tsCurrent) % QStringLiteral(" type: ") % this->interpolationType() % QStringLiteral(" gnd.fa.: ") % QString::number(groundFactor) % + QStringLiteral(" #nw.sit.: ") % QString::number(noNetworkSituations) % ( withHints ? separator % QStringLiteral("hints: ") % usedHints.toQString(true) : @@ -431,11 +437,14 @@ namespace BlackMisc ( withDeltaTimes ? separator % - QStringLiteral("int.time: ") % CInterpolationLogger::msSinceEpochToTimeAndTimestamp(tsCurrent) % + QStringLiteral("cur.time: ") % CInterpolationLogger::msSinceEpochToTimeAndTimestamp(tsCurrent) % + QStringLiteral(" int.time: ") % CInterpolationLogger::msSinceEpochToTimeAndTimestamp(tsInterpolated) % + QStringLiteral(" dt.cur.int.: ") % QString::number(deltaCurrentToInterpolatedTime()) % QStringLiteral("ms") % QStringLiteral(" sample dt: ") % QString::number(deltaSampleTimesMs) % QStringLiteral("ms") % QStringLiteral(" fr.[0-1]: ") % QString::number(simulationTimeFraction) % - QStringLiteral(" old pos.: ") % situationOld.getTimestampAndOffset(true) % - QStringLiteral(" new pos.: ") % situationNew.getTimestampAndOffset(true) : + QStringLiteral(" old int.pos.: ") % situationOldInterpolation.getTimestampAndOffset(true) % + QStringLiteral(" new int.pos.: ") % situationNewInterpolation.getTimestampAndOffset(true) % + QStringLiteral(" #int.pos.: ") % QString::number(interpolationSituations.size()) : QStringLiteral("") ) % ( @@ -447,9 +456,9 @@ namespace BlackMisc ( withOtherPositions ? separator % - QStringLiteral("old: ") % situationOld.toQString(true) % + QStringLiteral("old: ") % situationOldInterpolation.toQString(true) % separator % - QStringLiteral("new: ") % situationNew.toQString(true) : + QStringLiteral("new: ") % situationNewInterpolation.toQString(true) : QStringLiteral("") ); } diff --git a/src/blackmisc/simulation/interpolationlogger.h b/src/blackmisc/simulation/interpolationlogger.h index fd8d6c3b1..b3a5b731e 100644 --- a/src/blackmisc/simulation/interpolationlogger.h +++ b/src/blackmisc/simulation/interpolationlogger.h @@ -16,7 +16,7 @@ #include "interpolationhints.h" #include "blackmisc/simulation/remoteaircraftprovider.h" #include "blackmisc/aviation/aircraftpartslist.h" -#include "blackmisc/aviation/aircraftsituation.h" +#include "blackmisc/aviation/aircraftsituationlist.h" #include "blackmisc/aviation/aircraftpartslist.h" #include "blackmisc/logcategorylist.h" #include @@ -52,54 +52,6 @@ namespace BlackMisc //! Get the log directory static QString getLogDirectory(); - //! Log entry for situation interpolation - struct BLACKMISC_EXPORT SituationLog - { - QChar interpolator; //!< what interpolator is used - qint64 tsCurrent = -1; //!< current timestamp - qint64 tsInterpolated = -1; //!< timestamp interpolated - double groundFactor = -1; //!< current ground factor - double vtolAircraft = false; //!< VTOL aircraft - double simulationTimeFraction = -1; //!< time fraction, expected 0..1 - double deltaSampleTimesMs = -1; //!< delta time between samples (i.e. 2 situations) - bool useParts = false; //!< supporting aircraft parts - int noTransferredElevations = 0; //!< transferred elevation to n situations - Aviation::CCallsign callsign; //!< current callsign - Aviation::CAircraftParts parts; //!< corresponding parts used in interpolator - Aviation::CAircraftSituation situationOld; //!< old situation - Aviation::CAircraftSituation situationNew; //!< new situation - Aviation::CAircraftSituation situationCurrent; //!< interpolated situation - PhysicalQuantities::CLength cgAboveGround; //!< center of gravity - CInterpolationAndRenderingSetup usedSetup; //!< used setup - CInterpolationHints usedHints; //!< hints - - //! Delta time between interpolation and current time - double deltaCurrentToInterpolatedTime() const - { - return static_cast(tsCurrent - tsInterpolated); - } - - //! Full name of interpolator - const QString &interpolationType() const; - - //! To string - QString toQString( - bool withCurrentSituation, bool withHints, bool withSetup, bool withElevation, - bool withOtherPositions, bool withDeltaTimes, const QString &separator = {" "}) const; - }; - - //! Log entry for parts interpolation - struct BLACKMISC_EXPORT PartsLog - { - qint64 tsCurrent = -1; //!< current timestamp - bool empty = false; //!< empty parts? - Aviation::CCallsign callsign; //!< current callsign - Aviation::CAircraftParts parts; //!< parts to be logged - - //! To string - QString toQString(const QString &separator = {" "}) const; - }; - //! Log current interpolation cycle, only stores in memory, for performance reasons //! \remark const to allow const interpolator functions //! \threadsafe diff --git a/src/blackmisc/simulation/interpolator.h b/src/blackmisc/simulation/interpolator.h index f38ec2048..3ede1d7d5 100644 --- a/src/blackmisc/simulation/interpolator.h +++ b/src/blackmisc/simulation/interpolator.h @@ -79,6 +79,9 @@ namespace BlackMisc //! \remark parts logging has a \c bool \c log flag void attachLogger(CInterpolationLogger *logger) { m_logger = logger; } + //! Is logger attached + bool hasAttachedLogger() const { return m_logger; } + //! Get an interpolator info string (for debug info) QString getInterpolatorInfo() const; diff --git a/src/blackmisc/simulation/interpolatorlinear.cpp b/src/blackmisc/simulation/interpolatorlinear.cpp index 56673fe04..3e5b92c47 100644 --- a/src/blackmisc/simulation/interpolatorlinear.cpp +++ b/src/blackmisc/simulation/interpolatorlinear.cpp @@ -122,8 +122,6 @@ namespace BlackMisc const double sampleDeltaTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - oldSituation.getAdjustedMSecsSinceEpoch(); Q_ASSERT_X(sampleDeltaTimeMs >= 0, Q_FUNC_INFO, "Negative delta time"); log.interpolator = 'l'; - log.tsCurrent = currentTimeMsSinceEpoc; - log.deltaSampleTimesMs = sampleDeltaTimeMs; // Fraction of the deltaTime, ideally [0.0 - 1.0] // < 0 should not happen due to the split, > 1 can happen if new values are delayed beyond split time @@ -132,16 +130,23 @@ namespace BlackMisc const double distanceToSplitTimeMs = newSituation.getAdjustedMSecsSinceEpoch() - currentTimeMsSinceEpoc; const double simulationTimeFraction = qMax(1.0 - (distanceToSplitTimeMs / sampleDeltaTimeMs), 0.0); const double deltaTimeFractionMs = sampleDeltaTimeMs * simulationTimeFraction; - log.simulationTimeFraction = simulationTimeFraction; - log.deltaSampleTimesMs = sampleDeltaTimeMs; currentSituation.setTimeOffsetMs(oldSituation.getTimeOffsetMs() + (newSituation.getTimeOffsetMs() - oldSituation.getTimeOffsetMs()) * simulationTimeFraction); currentSituation.setMSecsSinceEpoch(oldSituation.getMSecsSinceEpoch() + deltaTimeFractionMs); status.setInterpolatedAndCheckSituation(true, currentSituation); - log.tsInterpolated = currentSituation.getAdjustedMSecsSinceEpoch(); - log.situationOld = oldSituation; - log.situationNew = newSituation; + if (this->hasAttachedLogger()) + { + log.tsCurrent = currentTimeMsSinceEpoc; + log.deltaSampleTimesMs = sampleDeltaTimeMs; + log.simulationTimeFraction = simulationTimeFraction; + log.deltaSampleTimesMs = sampleDeltaTimeMs; + log.tsInterpolated = interpolatedTime; + log.interpolationSituations.clear(); + log.interpolationSituations.push_back(newSituation); // newest at front + log.interpolationSituations.push_back(oldSituation); // oldest at back + } + return { oldSituation, newSituation, simulationTimeFraction }; } diff --git a/src/blackmisc/simulation/interpolatorspline.cpp b/src/blackmisc/simulation/interpolatorspline.cpp index 130de59a8..8f1fd3fd5 100644 --- a/src/blackmisc/simulation/interpolatorspline.cpp +++ b/src/blackmisc/simulation/interpolatorspline.cpp @@ -118,7 +118,7 @@ namespace BlackMisc return m_interpolant; } - std::array s {{ *(situationsOlder.begin() + 1), *situationsOlder.begin(), *(situationsNewer.end() - 1) }}; + m_s = std::array {{ *(situationsOlder.begin() + 1), *situationsOlder.begin(), *(situationsNewer.end() - 1) }}; // - altitude unit must be the same for all three, but the unit itself does not matter // - ground elevantion here normally is not available @@ -130,22 +130,22 @@ namespace BlackMisc if (!hints.getElevationPlane().isNull()) { // do not override existing values - s[0].setGroundElevationChecked(hints.getElevationPlane()); - s[1].setGroundElevationChecked(hints.getElevationPlane()); - s[2].setGroundElevationChecked(hints.getElevationPlane()); + m_s[0].setGroundElevationChecked(hints.getElevationPlane()); + m_s[1].setGroundElevationChecked(hints.getElevationPlane()); + m_s[2].setGroundElevationChecked(hints.getElevationPlane()); } - const double a0 = s[0].getCorrectedAltitude(hints.getCGAboveGround()).value(); - const double a1 = s[1].getCorrectedAltitude(hints.getCGAboveGround()).value(); - const double a2 = s[2].getCorrectedAltitude(hints.getCGAboveGround()).value(); + const double a0 = m_s[0].getCorrectedAltitude(hints.getCGAboveGround()).value(); + const double a1 = m_s[1].getCorrectedAltitude(hints.getCGAboveGround()).value(); + const double a2 = m_s[2].getCorrectedAltitude(hints.getCGAboveGround()).value(); - const std::array, 3> normals {{ s[0].getPosition().normalVectorDouble(), s[1].getPosition().normalVectorDouble(), s[2].getPosition().normalVectorDouble() }}; + const std::array, 3> normals {{ m_s[0].getPosition().normalVectorDouble(), m_s[1].getPosition().normalVectorDouble(), m_s[2].getPosition().normalVectorDouble() }}; PosArray pa; pa.x = {{ normals[0][0], normals[1][0], normals[2][0] }}; pa.y = {{ normals[0][1], normals[1][1], normals[2][1] }}; pa.z = {{ normals[0][2], normals[1][2], normals[2][2] }}; pa.a = {{ a0, a1, a2 }}; - pa.t = {{ static_cast(s[0].getAdjustedMSecsSinceEpoch()), static_cast(s[1].getAdjustedMSecsSinceEpoch()), static_cast(s[2].getAdjustedMSecsSinceEpoch()) }}; + pa.t = {{ static_cast(m_s[0].getAdjustedMSecsSinceEpoch()), static_cast(m_s[1].getAdjustedMSecsSinceEpoch()), static_cast(m_s[2].getAdjustedMSecsSinceEpoch()) }}; pa.dx = getDerivatives(pa.t, pa.x); pa.dy = getDerivatives(pa.t, pa.y); @@ -160,12 +160,17 @@ namespace BlackMisc const double dt1 = static_cast(currentTimeMsSinceEpoc - m_prevSampleTime); const double dt2 = static_cast(m_nextSampleTime - m_prevSampleTime); const double timeFraction = dt1 / dt2; - log.interpolator = 's'; - log.situationOld = m_interpolant.pbh().getOldSituation(); - log.situationNew = m_interpolant.pbh().getNewSituation(); - log.deltaSampleTimesMs = dt2; - log.simulationTimeFraction = timeFraction; - log.tsInterpolated = log.situationNew.getMSecsSinceEpoch(); // without offset + + if (this->hasAttachedLogger()) + { + log.interpolationSituations.push_back(m_s[0]); + log.interpolationSituations.push_back(m_s[1]); + log.interpolationSituations.push_back(m_s[2]); // latest at end + log.interpolator = 's'; + log.deltaSampleTimesMs = dt2; + log.simulationTimeFraction = timeFraction; + log.tsInterpolated = log.newestInterpolationSituation().getMSecsSinceEpoch(); // without offset + } status.setInterpolated(true); m_interpolant.setTimes(currentTimeMsSinceEpoc, timeFraction); diff --git a/src/blackmisc/simulation/interpolatorspline.h b/src/blackmisc/simulation/interpolatorspline.h index c2c545b84..8b2383131 100644 --- a/src/blackmisc/simulation/interpolatorspline.h +++ b/src/blackmisc/simulation/interpolatorspline.h @@ -95,6 +95,7 @@ namespace BlackMisc private: qint64 m_prevSampleTime = 0; qint64 m_nextSampleTime = 0; + std::array m_s; Interpolant m_interpolant; }; } // ns