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 }