Mercurial > hg > beaglert
comparison core/ClockSync.cpp @ 152:8f98b32d0e23 ClockSync
Last commit on this branch for a while. Overall not very succesful
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 05 Oct 2015 13:06:14 +0100 |
parents | e9c9404e3d1f |
children |
comparison
equal
deleted
inserted
replaced
151:e9c9404e3d1f | 152:8f98b32d0e23 |
---|---|
1 #include "ClockSync.h" | 1 #include "ClockSync.h" |
2 | 2 |
3 void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){ | 3 void ClockSync::setVirtualClock(VirtualClock &aVirtualClock){ |
4 virtualClock=&aVirtualClock; | 4 virtualClock=&aVirtualClock; |
5 } | 5 } |
6 Pid* gClockSyncPid; | |
6 void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){ | 7 void ClockSync::init(bool thisIsSlave, int aPort, VirtualClock &aVirtualClock){ |
7 setVirtualClock(aVirtualClock); | 8 setVirtualClock(aVirtualClock); |
8 slave=thisIsSlave; | 9 slave=thisIsSlave; |
9 setPort(aPort); | 10 setPort(aPort); |
10 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1"); | 11 // isSlave() ? client.setServer("127.0.0.1") : client.setServer("127.0.0.1"); |
13 resetTs(); | 14 resetTs(); |
14 receiveLoopSleepUs=100; | 15 receiveLoopSleepUs=100; |
15 receiveLoopTimeout=1e5; | 16 receiveLoopTimeout=1e5; |
16 movingAverage.setLength(31); | 17 movingAverage.setLength(31); |
17 expectedClockSyncType=isSlave() ? kSync : kNone; | 18 expectedClockSyncType=isSlave() ? kSync : kNone; |
19 gClockSyncPid = &pid; | |
18 } | 20 } |
19 void ClockSync::resetTs(){ | 21 void ClockSync::resetTs(){ |
20 T1=-1; | 22 T1=-1; |
21 T1p=-1; | 23 T1p=-1; |
22 T2=-1; | 24 T2=-1; |
213 expectedClockSyncType=kDelayResp; | 215 expectedClockSyncType=kDelayResp; |
214 break; | 216 break; |
215 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless | 217 case kDelayResp: {//the clockSyncTimestamp is the instant when the master received the kDelayResp clockSync, the localTimestamp is meaningless |
216 T2p=clockSyncTimestamp; | 218 T2p=clockSyncTimestamp; |
217 //TODO: evaluate things | 219 //TODO: evaluate things |
218 double offset=(T1p-T1-T2p+T2)/2.0d; | |
219 if(areTsValid()){ | 220 if(areTsValid()){ |
220 processOffset(offset); | 221 offset = (T1p-T1-T2p+T2)/2.0d; |
221 | 222 processOffset(); |
222 /* | |
223 static int calls=0; | |
224 static double referenceOffset=0; | |
225 | |
226 if(calls<100){ // start by averaging everything | |
227 movingAverage.add(offset); | |
228 } else { //once we get an estimate, start discarding outliers | |
229 float maxOffsetDeviation=20; | |
230 float deviation=fabsf(movingAverage.getAverage()-offset); | |
231 if(deviation<maxOffsetDeviation){ | |
232 movingAverage.add(offset); | |
233 printf("w(end+1)=%4.1f;\n", movingAverage.getAverage()); | |
234 } else { | |
235 // printf("Out of range: %f \n", deviation); | |
236 } | |
237 } | |
238 printf("offset(end+1)=%f;\n", offset); | |
239 if (calls==100){ | |
240 // printf("Update reference\n"); | |
241 referenceOffset=movingAverage.getAverage(); | |
242 } else if (calls==200){ | |
243 calls=99; | |
244 } | |
245 calls++; | |
246 */ | |
247 | |
248 // printf("%lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); | |
249 // if(T2-T1p<0){ | |
250 // printf("Negative: %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); | |
251 // } | |
252 } else { | 223 } else { |
253 printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); | 224 printf("InvalidTs:\n %lld, %lld, %lld, %lld \n", T1, T1p, T2, T2p); |
254 } | 225 } |
255 expectedClockSyncType=kSync; //end of the cycle, wait for next sync. | 226 expectedClockSyncType=kSync; //end of the cycle, wait for next sync. |
256 break; | 227 break; |
259 //printf("Unexpected message type\n"); // we should never get here | 230 //printf("Unexpected message type\n"); // we should never get here |
260 return -1; | 231 return -1; |
261 } | 232 } |
262 return 1; | 233 return 1; |
263 } | 234 } |
264 void ClockSync::processOffset(double offset){ | 235 void ClockSync::processOffset(){ |
265 static int calls=0; | 236 static int calls=0; |
266 // TODO: change the flow control below so that it can happen multiple times | 237 // TODO: change the flow control below so that it can happen multiple times |
267 //(base it upon the length of movingAverage rather than the number of calls) | 238 //(base it upon the length of movingAverage rather than the number of calls) |
268 if(calls<30){ | 239 if(calls<30){ |
269 // wait for the VirtualClock to stabilize and produce meaningful outputs | 240 // wait for the VirtualClock to stabilize and produce meaningful outputs |
278 } else if (calls>50){ //use IIR filter from now on | 249 } else if (calls>50){ //use IIR filter from now on |
279 //filter coefficients obtained from Matlab : [B,A]=butter(2,0.005); | 250 //filter coefficients obtained from Matlab : [B,A]=butter(2,0.005); |
280 static IirFilter iir(1); | 251 static IirFilter iir(1); |
281 static bool init = false; | 252 static bool init = false; |
282 if(init == false){ | 253 if(init == false){ |
254 //cutoff 0.05 | |
283 // double coeffs[5]={0.00554271721028068, 0.0110854344205614, 0.00554271721028068, | 255 // double coeffs[5]={0.00554271721028068, 0.0110854344205614, 0.00554271721028068, |
284 // -1.77863177782459, 0.800802646665708}; | 256 // -1.77863177782459, 0.800802646665708}; |
285 double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113, | 257 //cutoff 0.015 |
286 -1.56101807580072, 0.641351538057563}; | 258 double coeffs[5]={0.000537169774812052, 0.0010743395496241, 0.000537169774812052, |
259 -1.93338022587993, 0.935528904979178}; | |
260 // double coeffs[5]={0.0200833655642113, 0.0401667311284225, 0.0200833655642113, | |
261 // -1.56101807580072, 0.641351538057563}; | |
287 iir.setCoefficients(coeffs); | 262 iir.setCoefficients(coeffs); |
288 init = true; | 263 init = true; |
289 } | 264 } |
290 float expectedOffsetDifferenceMean = 0.2432; | 265 float expectedOffsetDifferenceMean = 0.2432; |
291 float expectedOffsetDifferenceStd = 6.487; | 266 float expectedOffsetDifference = 3.5; |
292 float nlOffset; | 267 static float pastNlOffset = 0; |
293 static float pastOffset = 0; | 268 static float pastIncrement = 0; |
294 float offsetIncrement = offset-pastOffset; | 269 float offsetIncrement = offset-pastNlOffset; |
295 if ( fabsf(offsetIncrement) > 1*expectedOffsetDifferenceStd && calls>51){ | 270 static int filteredOut=0; |
271 if (calls>51 && (fabsf(offsetIncrement) > expectedOffsetDifference && filteredOut < 8)){ | |
296 // non-linear filtering: remove outliers | 272 // non-linear filtering: remove outliers |
297 nlOffset = pastOffset; | 273 nlOffset = pastNlOffset; |
274 // printf("this actually happened\n"); | |
275 //nlOffset=offset; // BYPASS non linear filter | |
298 // printf("%f %f 0,0,0,0,0,0\n", offset,pastOffset); | 276 // printf("%f %f 0,0,0,0,0,0\n", offset,pastOffset); |
277 filteredOut++; | |
299 } else { | 278 } else { |
300 nlOffset=offset; | 279 nlOffset=offset; |
301 } | 280 filteredOut = 0; |
302 pastOffset=nlOffset; | 281 } |
303 float iirOffset = iir.process(nlOffset); | 282 pastIncrement = nlOffset - pastNlOffset; |
283 pastNlOffset = nlOffset; | |
284 iirOffset = iir.process(nlOffset); | |
304 static float maxOffset=0; | 285 static float maxOffset=0; |
305 static float pastIirOffset=0; | 286 static float pastIirOffset=0; |
306 if( calls > 0 ) { | 287 if( calls > 0 ) { |
307 maxOffset=fabsf(iirOffset) > fabsf(maxOffset) ? iirOffset : maxOffset; | 288 maxOffset=fabsf(iirOffset) > fabsf(maxOffset) ? iirOffset : maxOffset; |
308 pid.setError(iirOffset); | 289 pid.setError(iirOffset); |
309 float correction=pid.getOutput()*0.0001; | 290 float correction=pid.getOutput(); |
310 static float oldSamplingRate=44100; | 291 static float oldSamplingRate=44100; |
311 printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n", | 292 if( (calls&0) == 0){ |
312 offset, nlOffset, iirOffset, iirOffset - pastIirOffset, correction, oldSamplingRate); //unfiltered, filtered | 293 printf("%10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f, %10.3f\n", |
294 offset, nlOffset, iirOffset, iirOffset - pastIirOffset, | |
295 pid.getProportionalGain(), pid.getIntegralGain(), pid.getDerivativeGain(), pid.getGlobalGain(), | |
296 correction, pid.getIntegralError(), oldSamplingRate); //unfiltered, filtered | |
297 } | |
313 pastIirOffset = iirOffset; | 298 pastIirOffset = iirOffset; |
314 float targetSamplingRate; | 299 float targetSamplingRate; |
300 // Applit PID | |
301 targetSamplingRate = oldSamplingRate - correction; | |
302 if(targetSamplingRate> 44110) //clip the Pid ! | |
303 targetSamplingRate = 44110; | |
304 if (targetSamplingRate < 44090) | |
305 targetSamplingRate = 44090; | |
306 | |
307 // or use a naive hysteresis comparator | |
315 static int direction=1; | 308 static int direction=1; |
316 float thresholdL = -1; | 309 float thresholdL = -1; |
317 // targetSamplingRate = oldSamplingRate - correction; | |
318 float thresholdH = 3; | 310 float thresholdH = 3; |
319 | |
320 targetSamplingRate = 44100; | 311 targetSamplingRate = 44100; |
321 if( | 312 if( |
322 (iirOffset > thresholdH && direction == 1) || | 313 (iirOffset > thresholdH && direction == 1) || |
323 (iirOffset > thresholdL && direction == -1) | 314 (iirOffset > thresholdL && direction == -1) |
324 ){ | 315 ){ |
328 else if ( | 319 else if ( |
329 (iirOffset < -thresholdH && direction == -1) || | 320 (iirOffset < -thresholdH && direction == -1) || |
330 (iirOffset < -thresholdL && direction == 1) | 321 (iirOffset < -thresholdL && direction == 1) |
331 ) | 322 ) |
332 { | 323 { |
333 iirOffset = 44102; | 324 iirOffset = 44103; |
334 direction = 1; | 325 direction = 1; |
335 } | 326 } |
336 #ifndef USE_JUCE | 327 #ifndef USE_JUCE |
337 if(oldSamplingRate != targetSamplingRate){ | 328 if(oldSamplingRate != targetSamplingRate){ |
338 gAudioCodec->setAudioSamplingRate(targetSamplingRate); | 329 gAudioCodec->setAudioSamplingRate(targetSamplingRate); |
360 | 351 |
361 int ClockSync::sendReceiveLoop(){ | 352 int ClockSync::sendReceiveLoop(){ |
362 if(isSlave()==true){ | 353 if(isSlave()==true){ |
363 //printf("Waiting for a sync clockSync\n"); | 354 //printf("Waiting for a sync clockSync\n"); |
364 } else { //if this is master | 355 } else { //if this is master |
365 usleep(30000); //this times (roughly) how often sync clockSyncs are being sent. | 356 usleep(10000); //this times (roughly) how often sync clockSyncs are being sent. |
366 int ret=masterSendSync(); | 357 int ret=masterSendSync(); |
367 if(ret<=0) | 358 if(ret<=0) |
368 return -1; | 359 return -1; |
369 } | 360 } |
370 int ret=receiveLoop(); | 361 int ret=receiveLoop(); |
371 if(ret<=0) | 362 if(ret<=0) |
372 return -2; | 363 return -2; |
373 return 1; | 364 return 1; |
374 } | 365 } |
375 | 366 |
376 | 367 float ClockSync::getOffset(){ |
368 return offset; | |
369 } | |
370 float ClockSync::getIirOffset(){ | |
371 return iirOffset; | |
372 } |