softwarePLL.cpp
Go to the documentation of this file.
00001 /*
00002 ====================================================================================================
00003 File: softwarePLL.cpp
00004 ====================================================================================================
00005 */
00006 #include "softwarePLL.h"
00007 #include <iostream>
00008 // #include <chrono>
00009 // #include <thread>
00010 #include <math.h>
00011 #include <iterator>
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sstream>
00015 #include <vector>
00016 #include <string>
00017 
00018 
00019 
00020 const double SoftwarePLL::MaxAllowedTimeDeviation = 0.001;
00021 const uint32_t SoftwarePLL::MaxExtrapolationCounter = 5;
00022 
00023 // Helper class for reading csv file with test data
00024 
00025 class CSVRow
00026 {
00027 public:
00028     std::string const& operator[](std::size_t index) const
00029     {
00030         return m_data[index];
00031     }
00032     std::size_t size() const
00033     {
00034         return m_data.size();
00035     }
00036     void readNextRow(std::istream& str)
00037     {
00038         std::string         line;
00039         std::getline(str, line);
00040 
00041         std::stringstream   lineStream(line);
00042         std::string         cell;
00043 
00044         m_data.clear();
00045         while(std::getline(lineStream, cell, ';'))
00046         {
00047             m_data.push_back(cell);
00048         }
00049         // This checks for a trailing comma with no data after it.
00050         if (!lineStream && cell.empty())
00051         {
00052             // If there was a trailing comma then add an empty element.
00053             m_data.push_back("");
00054         }
00055     }
00056 private:
00057     std::vector<std::string>    m_data;
00058 };
00059 
00060 std::istream& operator>>(std::istream& str, CSVRow& data)
00061 {
00062     data.readNextRow(str);
00063     return str;
00064 }
00065 
00066 
00067 
00068 bool SoftwarePLL::pushIntoFifo(double curTimeStamp, uint32_t curtick)
00069 // update tick fifo and update clock (timestamp) fifo
00070 {
00071         for (int i = 0; i < fifoSize - 1; i++)
00072         {
00073                 tickFifo[i] = tickFifo[i + 1];
00074                 clockFifo[i] = clockFifo[i + 1];
00075         }
00076         tickFifo[fifoSize - 1] = curtick; // push most recent tick and timestamp into fifo
00077         clockFifo[fifoSize - 1] = curTimeStamp;
00078 
00079         if (numberValInFifo < fifoSize)
00080         {
00081                 numberValInFifo++; // remember the number of valid number in fifo
00082         }
00083         FirstTick(tickFifo[0]);
00084         FirstTimeStamp(clockFifo[0]);
00085 
00086         return(true);
00087 }
00088 
00089 double SoftwarePLL::extraPolateRelativeTimeStamp(uint32_t tick)
00090 {
00091         uint32_t tempTick = tick;
00092         tempTick -= (uint32_t)(0xFFFFFFFF & FirstTick());
00093         double timeDiff = tempTick * this->InterpolationSlope();
00094         return(timeDiff);
00095 
00096 }
00097 
00098 int SoftwarePLL::findDiffInFifo(double diff, double tol)
00099 {
00100     int numFnd = 0;
00101     double minAllowedDiff = (1.0 - tol) * diff;
00102     double maxAllowedDiff = (1.0 + tol) * diff;
00103 
00104     for (int i = 0; i < numberValInFifo - 1; i++)
00105     {
00106         double diffTime = this->clockFifo[i+1] - clockFifo[i];
00107         if ((diffTime >= minAllowedDiff) && (diffTime <= maxAllowedDiff))
00108         {
00109             numFnd++;
00110         }
00111     }
00112 
00113     return(numFnd);
00114 }
00115 
00124 bool SoftwarePLL::updatePLL(uint32_t sec, uint32_t nanoSec, uint32_t curtick)
00125 {
00126   double start = sec + nanoSec * 1E-9;
00127   bool bRet = true;
00128 
00129   if (false == IsInitialized())
00130   {
00131     pushIntoFifo(start, curtick);
00132     bool bCheck = this->updateInterpolationSlope();
00133     if (bCheck)
00134     {
00135       IsInitialized(true);
00136     }
00137   }
00138 
00139   if (IsInitialized() == false)
00140   {
00141     return(false);
00142   }
00143 
00144   double relTimeStamp = extraPolateRelativeTimeStamp(curtick); // evtl. hier wg. Ueberlauf noch einmal pruefen
00145   double cmpTimeStamp = start - this->FirstTimeStamp();
00146 
00147   bool timeStampVerified = false;
00148   if (nearSameTimeStamp(relTimeStamp, cmpTimeStamp) == true)// if timestamp matches prediction update FIFO
00149   {
00150     timeStampVerified = true;
00151     pushIntoFifo(start, curtick);
00152     updateInterpolationSlope();
00153     ExtrapolationDivergenceCounter(0);
00154   }
00155 
00156   if (timeStampVerified == false)
00157   {
00158     // BEGIN HANDLING Extrapolation divergence
00159     uint32_t tmp = ExtrapolationDivergenceCounter();
00160     tmp++;
00161     ExtrapolationDivergenceCounter(tmp);
00162     if (ExtrapolationDivergenceCounter() >= SoftwarePLL::MaxExtrapolationCounter)
00163     {
00164       IsInitialized(false); // reset FIFO - maybe happened due to abrupt change of time base
00165     }
00166     // END HANDLING Extrapolation divergence
00167   }
00168 
00169   return(true);
00170 }
00171 //TODO Kommentare
00172 bool SoftwarePLL::getCorrectedTimeStamp(uint32_t& sec, uint32_t& nanoSec, uint32_t curtick)
00173 {
00174   if (IsInitialized() == false)
00175   {
00176     return(false);
00177   }
00178 
00179         double relTimeStamp = extraPolateRelativeTimeStamp(curtick); // evtl. hier wg. Ueberlauf noch einmal pruefen
00180         double corrTime = relTimeStamp + this->FirstTimeStamp();
00181         sec = (uint32_t)corrTime;
00182         double frac = corrTime - sec;
00183         nanoSec = (uint32_t)(1E9 * frac);
00184         return(true);
00185 }
00186 
00187 bool SoftwarePLL::nearSameTimeStamp(double relTimeStamp1, double relTimeStamp2)
00188 {
00189         double dTAbs = fabs(relTimeStamp1 - relTimeStamp2);
00190         if (dTAbs < AllowedTimeDeviation())
00191         {
00192                 return(true);
00193         }
00194         else
00195         {
00196                 return(false);
00197         }
00198 }
00199 
00200 bool SoftwarePLL::updateInterpolationSlope() // fifo already updated
00201 {
00202 
00203         if (numberValInFifo < fifoSize)
00204         {
00205                 return(false);
00206         }
00207         std::vector<uint64_t> tickFifoUnwrap;
00208         std::vector<double> clockFifoUnwrap;
00209         clockFifoUnwrap.resize(fifoSize);
00210         tickFifoUnwrap.resize(fifoSize);
00211         uint64_t tickOffset = 0;
00212         clockFifoUnwrap[0] = 0.00;
00213         tickFifoUnwrap[0] = 0;
00214         FirstTimeStamp(this->clockFifo[0]);
00215         FirstTick(this->tickFifo[0]);
00216 
00217         uint64_t tickDivisor = 0x100000000;
00218 
00219 
00220 
00221         for (int i = 1; i < fifoSize; i++)  // typical 643 for 20ms -> round about 32150 --> near to 32768 standard clock in many watches
00222         {
00223                 if (tickFifo[i] < tickFifo[i - 1]) // Overflow
00224                 {
00225                         tickOffset += tickDivisor;
00226                 }
00227                 tickFifoUnwrap[i] = tickOffset + tickFifo[i] - FirstTick();
00228                 clockFifoUnwrap[i] = (this->clockFifo[i] - FirstTimeStamp());
00229         }
00230 
00231         double sum_xy = 0.0;
00232         double  sum_x = 0.0;
00233         double sum_y = 0.0;
00234         double sum_xx = 0.0;
00235         for (int i = 0; i < fifoSize; i++)
00236         {
00237                 sum_xy += tickFifoUnwrap[i] * clockFifoUnwrap[i];
00238                 sum_x += tickFifoUnwrap[i];
00239                 sum_y += clockFifoUnwrap[i];
00240                 sum_xx += tickFifoUnwrap[i] * tickFifoUnwrap[i];
00241         }
00242 
00243         // calculate slope of regression line, interception is 0 by construction
00244         double m = (fifoSize * sum_xy - sum_x * sum_y) / (fifoSize * sum_xx - sum_x*sum_x);
00245 
00246         int matchCnt = 0;
00247         for (int i = 0; i < fifoSize; i++)
00248         {
00249                 double yesti = m * tickFifoUnwrap[i];
00250                 if (this->nearSameTimeStamp(yesti, clockFifoUnwrap[i]))
00251                 {
00252                         matchCnt++;
00253                 }
00254         }
00255 
00256         bool retVal = false;
00257         if (matchCnt == fifoSize)
00258         {
00259                 InterpolationSlope(m);
00260                 retVal = true;
00261         }
00262 
00263         return(retVal);
00264 }
00265 
00266 #if 0
00267 bool SoftwarePLL::getDemoFileData(std::string fileName, std::vector<uint32_t>& tickVec,std::vector<uint32_t>& secVec, std::vector<uint32_t>& nanoSecVec )
00268 {
00269     std::ifstream file(fileName);
00270 
00271     CSVRow row;
00272     tickVec.clear();
00273     secVec.clear();
00274     nanoSecVec.clear();
00275     int lineCnt = 0;
00276     while (file >> row) {
00277         if (lineCnt > 0)
00278                 {
00279                 uint32_t tickVal = (uint32_t)std::stoi(row[0]);
00280                         uint32_t secVal = (uint32_t)std::stoi(row[1]);
00281                         uint32_t nanoSecVal = (uint32_t)std::stoi(row[2]);
00282                         tickVec.push_back(tickVal);
00283                         secVec.push_back(secVal);
00284                         nanoSecVec.push_back(nanoSecVal);
00285                 }
00286         lineCnt++;
00287     }
00288     if (lineCnt <= 1)
00289         return false;
00290     else
00291         return true;
00292 }
00293 #endif
00294 
00295 //TODO update testbed
00296 void SoftwarePLL::testbed()
00297 {
00298     std::cout << "Running testbed for SofwarePLL" << std::endl;
00299     uint32_t curtick = 0;
00300     int cnt = 0;
00301 
00302     SoftwarePLL testPll;
00303     uint32_t sec = 9999;
00304     uint32_t nanoSec = 0;
00305     double tickPerSec = 1E6;
00306     uint32_t tickInc = 1000;
00307     int maxLoop = 20;
00308 
00309         std::vector<uint32_t> tickVec;
00310         std::vector<uint32_t> secVec;
00311         std::vector<uint32_t> nanoSecVec;
00312     bool bRet = false;
00313 
00314     bool testWithDataFile = true;
00315     if (testWithDataFile)
00316         {
00317                 // commented for trusty bRet = testPll.getDemoFileData("/home/rosuser/dumpimu3.csv", tickVec, secVec, nanoSecVec);
00318                 maxLoop = tickVec.size();
00319         }
00320 
00321     for (int i = 0; i < maxLoop; i++)
00322     {
00323         if (testWithDataFile)
00324                 {
00325                 curtick = tickVec[i];
00326                 sec = secVec[i];
00327                 nanoSec = nanoSecVec[i];
00328                 }
00329                 else
00330                 {
00331         cnt++;
00332         curtick += tickInc; // increment tick counter
00333         double deltaT = tickInc / tickPerSec;
00334         nanoSec += (int)(deltaT * 1E9);
00335         if (nanoSec >= 1E9)
00336         {
00337             nanoSec = 0;
00338             sec++;
00339         }
00340         if (cnt >= 8)
00341         {
00342             sec++;
00343         }
00344                 }
00345         printf("Before correction: %3d.%09d\n", sec, nanoSec);
00346                 uint32_t org_sec = sec;
00347                 uint32_t org_nanoSec = nanoSec;
00348 
00349          bool bRet = testPll.getCorrectedTimeStamp(sec, nanoSec, curtick);
00350 
00351         bool corrected = false;
00352         if ((nanoSec != org_nanoSec) || (sec != org_sec))
00353                 {
00354                 corrected =true;
00355                 }
00356         printf("After correction : %3d.%09d %s %s\n", sec, nanoSec, bRet ? "OK     " : "DISMISS", corrected ? "MODI." : "OK   ");
00357     }
00358 
00359     return;
00360 }
00361 
00362 
00363 
00364 #ifdef softwarePLL_MAINTEST
00365 int main(int argc, char **argv)
00366 {
00367         printf("Test for softwarePLL-Class\n");
00368         printf("\n");
00369         SoftwarePLL::testbed();
00370 }
00371 #endif
00372 
00373 
00374 
00375 /* 
00376 Example CMakeLists.txt to generate test-binary-file for testing this class
00377 --- CUT ---
00378 #
00379 #
00380 # softwarePLL
00381 #
00382 #
00383 cmake_minimum_required(VERSION 2.8)
00384 cmake_policy(SET CMP0015 NEW)
00385 project( softwarePLL )
00386 #
00387 #
00388 add_definitions(-D${PROJECT_NAME}_MAINTEST)
00389 
00390 MESSAGE( STATUS "CMKAKE for " ${PROJECT_NAME} )
00391 
00392 include_directories( inc)
00393 file( GLOB LIB_SOURCES src/ *.cpp )
00394 
00395 if(WIN32)
00396 else()
00397 set(CMAKE_CXX_STANDARD 11)
00398 endif()
00399 
00400 add_executable( ${PROJECT_NAME} ${LIB_SOURCES} inc/${PROJECT_NAME}.h)
00401 target_link_libraries( ${PROJECT_NAME})
00402 --- CUT ---
00403 
00404 */


sick_scan
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Tue Jul 9 2019 05:05:35