#pragma once #include "SensorDatumConcept.h" #include #include #include #include "fmt/core.h" #include #include "AftrUtil_numeric.h" namespace Aftr { //These 4 helpers enable us to use either a reference or a pointer in our Template T parameter template T* ptr( T& obj ) { return &obj; } //turn reference into pointer! template T* ptr( T* obj ) { return obj; } //obj is already pointer, return it template T* ptr( std::unique_ptr& obj ) { return obj.get(); } //obj is already pointer, return it template T* ptr( std::shared_ptr& obj ) { return obj.get(); } //obj is already pointer, return it template< SensorDatumConcept T > /* , typename C > could template the clock type as well */ class SensorDatumTraversal { public: using value_type = T; ///static_assert( //(std::is_base_of::value) || /// (std::is_base_of::value), /// "ERROR: T::value_type is not derived from the Aftr::AftrSensorData base class...\n" ); ///typedef typename std::enable_if::value, T>::type base; ///typedef typename std::enable_if::value, T>::type::value_type value_type; SensorDatumTraversal(); SensorDatumTraversal( std::vector&& dat ); SensorDatumTraversal& operator=( SensorDatumTraversal&& toMove ) noexcept; SensorDatumTraversal( const SensorDatumTraversal& toCopy ) = delete; SensorDatumTraversal& operator=( const SensorDatumTraversal& toAssign ) = delete; ~SensorDatumTraversal(); /// Initializes this data set for playback starting at index zero. When execution enters this method, the system clock /// is used to mark the "stopwatch" used to march this data forward. The "stopwatch" progresses using wall time. std::chrono::utc_clock::time_point initPlayback(); /// Initializes this data set for playback starting at index zero. This overloaded method sets the "stopwatch" /// to the in passed point in time. The "stopwatch" progresses using wall time. /// This overload let's one initialize many Data sets with an identically synchronized "stopwatch" so /// all the data is traversed along the same wall time. std::chrono::utc_clock::time_point initPlayback( std::chrono::utc_clock::time_point const& initializationTimePoint ); /// Returns the closest data point to wall time since last call to initPlayback. /// Both getNextDatum and getNextNearestDatum internally mutate a reference to the most recently /// returned datum. Therefore calling one and then the other are not associative. /// Typically, one would call only getNextDatum for an entire run (to replay *every* point) OR /// one would call only getNextNearestDatum for an entire run to replay at wall clock time. const T& getNextNearestDatum( bool interpolate = false ); /// Returns the next adjacent data point immediately next to the last replayed data point. /// This getter lets you replay every single data point and is *not* tied to wall clock time. /// Both getNextDatum and getNextNearestDatum internally mutate a reference to the most recently /// returned datum. Therefore calling one and then the other are not associative. /// Typically, one would call only getNextDatum for an entire run (to replay *every* point) OR /// one would call only getNextNearestDatum for an entire run to replay at wall clock time. const T& getNextDatum() noexcept; void setTimeMultiplier( double multiplier ); double getTimeMultiplier(); const std::vector& getData() { return this->dat; } double getPlaybackLocation() const; size_t getPlaybackLocationIdx() const; void setPlaybackLocation( double parametricProgressThruData, std::chrono::utc_clock::time_point const& timeNow ); void setPlaybackLocationIdx( size_t datumIndex, std::chrono::utc_clock::time_point const& timeNow ); //Finds first time series datum, d, where pred is true. Returns that [d,d+length) as new SensorDatumTraversal. SensorDatumTraversal static trimDataSetTo( std::function pred, int length, SensorDatumTraversal&& dat ); private: std::vector< T > dat; ///< Log Data stored in this instance /// Time point at which initPlayback() is invoked. std::chrono::utc_clock::time_point startTime; /// Timepoint at dat[0]. std::chrono::utc_clock::time_point timeAtFirstDatum; size_t curIdx = 0; ///< Last index retrieved via getDatum /// Determines how much faster or slower than "wall time" this data is traversed (played back). /// A value of 1.0 will play back the data at the same rate as timestamps unfold in the data /// A value of 2.0 will play back the data at twice normal speed /// A value of -1.0 will "rewind" the data at normal speed. double timeMultiplier = 1.0; }; } //namespace Aftr #include "SensorDatumTraversal.cpptemplate.h"