Mercurial > hg > beaglert
comparison core/VirtualClock.cpp @ 149:134bff10e561 ClockSync
Added simple one-variable one-measurement Kalman filter, Pid controller(which output is not used). Virtual clock is now much more precise and reactive for period. Still it is lagging behind a bit on the overall offset.
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 21 Sep 2015 03:12:21 +0100 |
parents | 44d07fa9bd03 |
children | ebbfb154351a |
comparison
equal
deleted
inserted
replaced
148:6cd38e261027 | 149:134bff10e561 |
---|---|
1 #include "VirtualClock.h" | 1 #include "VirtualClock.h" |
2 void VirtualClock::init(){ | 2 void VirtualClock::init(float initialValueUs){ |
3 firstRun=true; | 3 firstRun=true; |
4 movingAverage.setLength(101); //TODO: a better filtering algorithm ( Did you say Kalman?) | 4 movingAverage.setLength(101); //TODO: a better filtering algorithm ( Did you say Kalman?) |
5 period=-1; | 5 blockPeriod=-1; |
6 elapsedPeriods=0; | 6 elapsedPeriods=0; |
7 startTime=0; | 7 startTime=0; |
8 startTimeOffset=0; | 8 elapsedPeriodsOffset = 0; |
9 elapsedPeriodsOffset=0; | 9 lastSyncEstimatedTime = 0; |
10 double coefficients[IIR_FILTER_STAGE_COEFFICIENTS] = { | |
11 0.000241359049041961, 0.000482718098083923, 0.000241359049041961, -1.95557824031504, 0.956543676511203 | |
12 }; | |
13 iir.setNumberOfStages(4); | |
14 iir.setCoefficients(coefficients); | |
15 printf("kalmanInit=%f\n",initialValueUs); | |
16 kalman.init(0.01, 158575.715009816 /*measured var() */, | |
17 initialValueUs | |
18 //#ifdef USE_JUCE | |
19 // 5804.98866213152 /*blockSize/Fs*1e6*/ | |
20 //#else | |
21 // 5804.98866213152 /*blockSize/Fs*1e6*/ | |
22 //#endif | |
23 ); | |
10 } | 24 } |
11 | 25 |
12 VirtualClock::VirtualClock(){ | 26 VirtualClock::VirtualClock(){} |
13 init(); | |
14 } | |
15 void VirtualClock::sync(){ | 27 void VirtualClock::sync(){ |
16 sync(1); | 28 sync(1); |
17 } | 29 } |
18 void VirtualClock::sync(double numPeriods){ | 30 void VirtualClock::sync(double numPeriods){ |
19 myClock_t currentTime=Clock::getTimeUs(); | 31 myClock_t currentTime = Clock::getTimeUs(); |
20 static int calls=0; | 32 elapsedPeriods += numPeriods; |
21 elapsedPeriods+=numPeriods; | 33 static int calls = 0; |
22 if(calls==50){ //TODO: this is dangerous as the clock might jump suddenly if currentTime is not precise | 34 if(calls == 0){ |
23 calls=0; | 35 startTime = currentTime; |
24 startTimeOffset=startTime; | 36 //AA lastSyncEstimatedTime = startTime; |
25 startTime=currentTime; | 37 lastSyncEstimatedTime = 0; |
26 elapsedPeriodsOffset=elapsedPeriods; | 38 } else { |
39 double newBlockPeriod = (currentTime - lastSyncTime); | |
40 // period = iir.process(movingAverage.add(newPeriod)); //TODO: replace with Kalman filter | |
41 blockPeriod = iir.process(kalman.process(newBlockPeriod)); | |
42 // period = 22.6760958210091; | |
43 period = blockPeriod / numPeriods; | |
44 lastSyncEstimatedTime += (period * numPeriods); | |
45 // if(calls == 800) | |
46 // lastSyncEstimatedTime = lastSyncTime; | |
47 // printf("%lld, %lld\n", lastSyncTime, lastSyncEstimatedTime); | |
27 } | 48 } |
49 lastSyncTime = currentTime; | |
50 // printf("%lld\n", lastSyncTime); | |
28 calls++; | 51 calls++; |
29 if(firstRun==true){ | |
30 firstRun=false; | |
31 startTime=currentTime; | |
32 } else { | |
33 double newPeriod=(currentTime-lastSync)/numPeriods; | |
34 double expectedPeriod=22.67; | |
35 double maxPeriodDeviation=10; | |
36 if(fabs(newPeriod-expectedPeriod)<maxPeriodDeviation){ // filtering outliers | |
37 period=movingAverage.add(newPeriod); //TODO: replace with Kalman filter | |
38 } else { | |
39 printf("period out of range: %f\n", newPeriod); | |
40 } | |
41 } | |
42 lastSync=currentTime; | |
43 // printf("lastSync: %lld\n",lastSync-startTime); | |
44 } | 52 } |
45 | 53 |
46 double VirtualClock::getNow(){ | 54 double VirtualClock::getNow(){ |
47 myClock_t currentSystemTime=Clock::getTimeUs(); | 55 myClock_t currentSystemTime=Clock::getTimeUs(); |
48 if(period<=0){ | 56 if(blockPeriod<=0){ |
49 return currentSystemTime; // TODO: this is not very meaningful. | 57 return currentSystemTime; // TODO: this is not very meaningful. |
50 } | 58 } |
51 // double beginningOfPeriod=lastSync; // TODO: if sync() does not get called every time (but e.g. only every so often), | 59 double elapsed = (currentSystemTime - startTime) - lastSyncEstimatedTime; |
52 // then this line (and the class) needs editing | 60 double now = elapsedPeriods + elapsed / (double)period; |
53 myClock_t elapsed=(currentSystemTime-startTime); | 61 // if(now>currentSystemTime+10*1e6) |
54 double now=elapsedPeriodsOffset + elapsed/(double)period; | 62 // now=0; |
55 // printf("elapsed=%lld; sincelastSync=%lld; period=%f; now=%f\n", elapsed, currentSystemTime-lastSync, period, now); | 63 // static long long int pastSy=0; |
64 // printf("%lld\n", currentSystemTime-pastSy); | |
65 // pastSy=currentSystemTime; | |
66 static int count=0; | |
67 count++; | |
68 // if(count&1) | |
69 #ifdef USE_JUCE | |
70 #else | |
71 // printf("%f %f %f\n", (currentSystemTime - startTime)/1e6*44100.0, blockPeriod, now); | |
72 #endif | |
56 return now; | 73 return now; |
57 } | 74 } |
58 | 75 |
59 void VirtualClock::addOffset(double periodOffset){ | 76 void VirtualClock::addOffset(double periodOffset){ |
60 elapsedPeriods-=periodOffset; | 77 elapsedPeriods-=periodOffset; |
61 if(elapsedPeriods<0){ | 78 if(elapsedPeriods<0){ |
62 printf("ERROR: periodOffset adjustment of %f resulted in elapsedPeriods=%f\n", periodOffset, elapsedPeriods); | 79 printf("ERROR: periodOffset adjustment of %f resulted in elapsedPeriods=%f\n", periodOffset, elapsedPeriods); |
63 exit(1); | 80 exit(1); |
64 } | 81 } |
82 printf("this is not called\n"); | |
65 movingAverage.reset(); | 83 movingAverage.reset(); |
66 } | 84 } |
67 double VirtualClock::getPeriod(){ | 85 double VirtualClock::getPeriod(){ |
68 return period; | 86 return blockPeriod; |
69 } | 87 } |