giuliomoro@135
|
1 #include "VirtualClock.h"
|
giuliomoro@135
|
2 void VirtualClock::init(){
|
giuliomoro@135
|
3 firstRun=true;
|
giuliomoro@141
|
4 movingAverage.setLength(101); //TODO: a better filtering algorithm ( Did you say Kalman?)
|
giuliomoro@135
|
5 period=-1;
|
giuliomoro@141
|
6 elapsedPeriods=0;
|
giuliomoro@141
|
7 startTime=0;
|
giuliomoro@141
|
8 startTimeOffset=0;
|
giuliomoro@141
|
9 elapsedPeriodsOffset=0;
|
giuliomoro@135
|
10 }
|
giuliomoro@135
|
11
|
giuliomoro@135
|
12 VirtualClock::VirtualClock(){
|
giuliomoro@135
|
13 init();
|
giuliomoro@135
|
14 }
|
giuliomoro@135
|
15 void VirtualClock::sync(){
|
giuliomoro@135
|
16 sync(1);
|
giuliomoro@135
|
17 }
|
giuliomoro@141
|
18 void VirtualClock::sync(double numPeriods){
|
giuliomoro@135
|
19 myClock_t currentTime=Clock::getTimeUs();
|
giuliomoro@141
|
20 static int calls=0;
|
giuliomoro@141
|
21 elapsedPeriods+=numPeriods;
|
giuliomoro@141
|
22 if(calls==50){ //TODO: this is dangerous as the clock might jump suddenly if currentTime is not precise
|
giuliomoro@141
|
23 calls=0;
|
giuliomoro@141
|
24 startTimeOffset=startTime;
|
giuliomoro@141
|
25 startTime=currentTime;
|
giuliomoro@141
|
26 elapsedPeriodsOffset=elapsedPeriods;
|
giuliomoro@141
|
27 }
|
giuliomoro@141
|
28 calls++;
|
giuliomoro@135
|
29 if(firstRun==true){
|
giuliomoro@135
|
30 firstRun=false;
|
giuliomoro@135
|
31 startTime=currentTime;
|
giuliomoro@135
|
32 } else {
|
giuliomoro@141
|
33 double newPeriod=(currentTime-lastSync)/numPeriods;
|
giuliomoro@141
|
34 double expectedPeriod=22.67;
|
giuliomoro@141
|
35 double maxPeriodDeviation=10;
|
giuliomoro@141
|
36 if(fabs(newPeriod-expectedPeriod)<maxPeriodDeviation){ // filtering outliers
|
giuliomoro@141
|
37 period=movingAverage.add(newPeriod); //TODO: replace with Kalman filter
|
giuliomoro@141
|
38 } else {
|
giuliomoro@141
|
39 printf("period out of range: %f\n", newPeriod);
|
giuliomoro@141
|
40 }
|
giuliomoro@135
|
41 }
|
giuliomoro@135
|
42 lastSync=currentTime;
|
giuliomoro@139
|
43 // printf("lastSync: %lld\n",lastSync-startTime);
|
giuliomoro@135
|
44 }
|
giuliomoro@135
|
45
|
giuliomoro@135
|
46 double VirtualClock::getNow(){
|
giuliomoro@139
|
47 myClock_t currentSystemTime=Clock::getTimeUs();
|
giuliomoro@135
|
48 if(period<=0){
|
giuliomoro@141
|
49 return currentSystemTime; // TODO: this is not very meaningful.
|
giuliomoro@135
|
50 }
|
giuliomoro@135
|
51 // double beginningOfPeriod=lastSync; // TODO: if sync() does not get called every time (but e.g. only every so often),
|
giuliomoro@135
|
52 // then this line (and the class) needs editing
|
giuliomoro@139
|
53 myClock_t elapsed=(currentSystemTime-startTime);
|
giuliomoro@141
|
54 double now=elapsedPeriodsOffset + elapsed/(double)period;
|
giuliomoro@139
|
55 // printf("elapsed=%lld; sincelastSync=%lld; period=%f; now=%f\n", elapsed, currentSystemTime-lastSync, period, now);
|
giuliomoro@139
|
56 return now;
|
giuliomoro@135
|
57 }
|
giuliomoro@135
|
58
|
giuliomoro@141
|
59 void VirtualClock::addOffset(double periodOffset){
|
giuliomoro@141
|
60 elapsedPeriods-=periodOffset;
|
giuliomoro@141
|
61 if(elapsedPeriods<0){
|
giuliomoro@141
|
62 printf("ERROR: periodOffset adjustment of %f resulted in elapsedPeriods=%f\n", periodOffset, elapsedPeriods);
|
giuliomoro@141
|
63 exit(1);
|
giuliomoro@141
|
64 }
|
giuliomoro@141
|
65 movingAverage.reset();
|
giuliomoro@141
|
66 }
|
giuliomoro@135
|
67 double VirtualClock::getPeriod(){
|
giuliomoro@135
|
68 return period;
|
giuliomoro@135
|
69 }
|