diff 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
line wrap: on
line diff
--- a/core/VirtualClock.cpp	Mon Sep 21 03:11:32 2015 +0100
+++ b/core/VirtualClock.cpp	Mon Sep 21 03:12:21 2015 +0100
@@ -1,58 +1,75 @@
 #include "VirtualClock.h"
-void VirtualClock::init(){
+void VirtualClock::init(float initialValueUs){
 	firstRun=true;
 	movingAverage.setLength(101); //TODO: a better filtering algorithm ( Did you say Kalman?)
-	period=-1;
+	blockPeriod=-1;
 	elapsedPeriods=0;
 	startTime=0;
-	startTimeOffset=0;
-	elapsedPeriodsOffset=0;
+	elapsedPeriodsOffset = 0;
+	lastSyncEstimatedTime = 0;
+	double coefficients[IIR_FILTER_STAGE_COEFFICIENTS] = {
+			0.000241359049041961, 0.000482718098083923, 0.000241359049041961, -1.95557824031504, 0.956543676511203
+	};
+	iir.setNumberOfStages(4);
+	iir.setCoefficients(coefficients);
+	printf("kalmanInit=%f\n",initialValueUs);
+	kalman.init(0.01, 158575.715009816 /*measured var() */,
+			initialValueUs
+//#ifdef USE_JUCE
+//			5804.98866213152 /*blockSize/Fs*1e6*/
+//#else
+//			5804.98866213152 /*blockSize/Fs*1e6*/
+//#endif
+			);
 }
 	
-VirtualClock::VirtualClock(){
-	init();
-}
+VirtualClock::VirtualClock(){}
 void VirtualClock::sync(){
 	sync(1);
 }
 void VirtualClock::sync(double numPeriods){
-	myClock_t currentTime=Clock::getTimeUs();
-	static int calls=0;
-	elapsedPeriods+=numPeriods;
-	if(calls==50){ //TODO: this is dangerous as the clock might jump suddenly if currentTime is not precise
-		calls=0;
-		startTimeOffset=startTime;
-		startTime=currentTime;
-		elapsedPeriodsOffset=elapsedPeriods;
+	myClock_t currentTime = Clock::getTimeUs();
+	elapsedPeriods += numPeriods;
+	static int calls = 0;
+	if(calls == 0){
+		startTime = currentTime;
+//AA		lastSyncEstimatedTime = startTime;
+		lastSyncEstimatedTime = 0;
+	} else {
+		double newBlockPeriod = (currentTime - lastSyncTime);
+//		period = iir.process(movingAverage.add(newPeriod)); //TODO: replace with Kalman filter
+		blockPeriod = iir.process(kalman.process(newBlockPeriod));
+//		period = 22.6760958210091;
+		period = blockPeriod / numPeriods;
+		lastSyncEstimatedTime += (period * numPeriods);
+//		if(calls == 800)
+//			lastSyncEstimatedTime = lastSyncTime;
+//		printf("%lld, %lld\n", lastSyncTime, lastSyncEstimatedTime);
 	}
+	lastSyncTime = currentTime;
+//	printf("%lld\n", lastSyncTime);
 	calls++;
-	if(firstRun==true){
-		firstRun=false;
-		startTime=currentTime;
-	} else {
-		double newPeriod=(currentTime-lastSync)/numPeriods;
-		double expectedPeriod=22.67;
-		double maxPeriodDeviation=10;
-		if(fabs(newPeriod-expectedPeriod)<maxPeriodDeviation){ // filtering outliers
-			period=movingAverage.add(newPeriod); //TODO: replace with Kalman filter
-		} else {
-			printf("period out of range: %f\n", newPeriod);
-		}
-	}
-	lastSync=currentTime;
-//	printf("lastSync: %lld\n",lastSync-startTime);
 }
 
 double VirtualClock::getNow(){
 	myClock_t currentSystemTime=Clock::getTimeUs();
-	if(period<=0){
+	if(blockPeriod<=0){
 		return currentSystemTime; // TODO: this is not very meaningful.
 	}
-	//  double beginningOfPeriod=lastSync; // TODO: if sync() does not get called every time (but e.g. only every so often),
-													 // then this line (and the class) needs editing
-	myClock_t elapsed=(currentSystemTime-startTime);
-	double now=elapsedPeriodsOffset + elapsed/(double)period;
-//	printf("elapsed=%lld;  sincelastSync=%lld; period=%f; now=%f\n", elapsed, currentSystemTime-lastSync, period, now);
+	double elapsed = (currentSystemTime - startTime) - lastSyncEstimatedTime;
+	double now = elapsedPeriods + elapsed / (double)period;
+//	if(now>currentSystemTime+10*1e6)
+//		now=0;
+//	static long long int pastSy=0;
+//	printf("%lld\n", currentSystemTime-pastSy);
+//	pastSy=currentSystemTime;
+	static int count=0;
+	count++;
+//	if(count&1)
+#ifdef USE_JUCE
+#else
+//	printf("%f %f %f\n", (currentSystemTime - startTime)/1e6*44100.0, blockPeriod, now);
+#endif
 	return now;
 }
 
@@ -62,8 +79,9 @@
 		printf("ERROR: periodOffset adjustment of %f resulted in elapsedPeriods=%f\n", periodOffset, elapsedPeriods);
 		exit(1);
 	}
+	printf("this is not called\n");
 	movingAverage.reset();
 }
 double VirtualClock::getPeriod(){
-	return period;
+	return blockPeriod;
 }