00001
00002 #include <iostream>
00003 #include <iomanip>
00004
00005 #define AVGSIZE 3
00006
00007 #define PHI 1.618033989 // golden ratio
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 class TimestampSensor
00019 {
00020 private:
00021 double clockScale;
00022 double clockShiftS;
00023 double clockShiftH;
00024 double latency;
00025 double averagingLength;
00026
00027 bool first;
00028 unsigned sector;
00029 double next_sector_date;
00030 double delay_min;
00031 double currentAvgLength;
00032 unsigned nAvgLength;
00033
00034 double sectorBestS[AVGSIZE];
00035 double sectorBestH[AVGSIZE];
00036
00037 public:
00047 TimestampSensor(double clockScale, double latency, double averagingLength = 30):
00048 clockScale(clockScale), latency(latency), averagingLength(averagingLength), first(true), sector(0), currentAvgLength(0.1), nAvgLength(0)
00049 {}
00050
00058 double filter(double sensorDate, double hostDate)
00059 {
00060
00061 if (first)
00062 {
00063 clockShiftS = sensorDate;
00064 clockShiftH = hostDate - latency;
00065 delay_min = 1e9;
00066 first = false;
00067 next_sector_date = hostDate + currentAvgLength;
00068 return hostDate;
00069 }
00070
00071
00072 if (hostDate > next_sector_date)
00073 {
00074 if (sector >= AVGSIZE-1)
00075 {
00076 unsigned best1, best2;
00077 double max_scale = 0.;
00078 for(int i = 0; i < AVGSIZE-1; ++i)
00079 for(int j = i+1; j < AVGSIZE; ++j)
00080 {
00081
00082 unsigned s1 = (sector+1+i) % AVGSIZE;
00083 unsigned s2 = (sector+1+j) % AVGSIZE;
00084 double scale = (sectorBestH[s2]-sectorBestH[s1])/(sectorBestS[s2]-sectorBestS[s1]);
00085
00086
00087 bool compatible = true;
00088 for(int k = 0; k < AVGSIZE; ++k) if (k != s1 && k != s2)
00089 if (sectorBestH[k] - (sectorBestH[s2] + (sectorBestS[k]-sectorBestS[s2])*scale) < 0)
00090 { compatible = false; break; }
00091
00092
00093 if (compatible && scale > max_scale) { max_scale = scale; best1 = s1; best2 = s2; }
00094 }
00095
00096
00097 clockScale = (sectorBestH[best2]-sectorBestH[best1])/(sectorBestS[best2]-sectorBestS[best1]);
00098 clockShiftS = sectorBestS[best2];
00099 clockShiftH = sectorBestH[best2]-latency;
00100 }
00101
00102 if (nAvgLength == 0)
00103 {
00104 currentAvgLength *= PHI;
00105 if (currentAvgLength > averagingLength) { currentAvgLength = averagingLength; nAvgLength++; }
00106 } else
00107 if (nAvgLength <= AVGSIZE) nAvgLength++;
00108
00109
00110 if (nAvgLength <= AVGSIZE)
00111 {
00112 unsigned s1 = (sector+1) % AVGSIZE;
00113 unsigned s2 = (sector+2) % AVGSIZE;
00114
00115 if ((sectorBestH[s1] - (clockShiftH + (sectorBestS[s1]-clockShiftS)*clockScale + latency))
00116 < (sectorBestH[s2] - (clockShiftH + (sectorBestS[s2]-clockShiftS)*clockScale + latency)))
00117 {
00118 sectorBestS[s2] = sectorBestS[s1];
00119 sectorBestH[s2] = sectorBestH[s1];
00120 }
00121 }
00122
00123 ++sector;
00124 next_sector_date += currentAvgLength;
00125 delay_min = 1e9;
00126 }
00127
00128
00129 double fixedDate = clockShiftH + (sensorDate-clockShiftS)*clockScale;
00130 double delay = hostDate - (fixedDate + latency);
00131
00132
00133 if (delay < 0)
00134 {
00135 clockShiftH += delay;
00136 fixedDate += delay;
00137 sectorBestS[sector % AVGSIZE] = sensorDate;
00138 sectorBestH[sector % AVGSIZE] = hostDate;
00139 delay_min = 0;
00140 }
00141
00142 if (delay < delay_min)
00143 {
00144 sectorBestS[sector % AVGSIZE] = sensorDate;
00145 sectorBestH[sector % AVGSIZE] = hostDate;
00146 delay_min = delay;
00147 }
00148
00149 return fixedDate;
00150 }
00151
00152
00157
00158
00159 #if 0 // SYNC
00160 private:
00161 TimestampSensor *syncSensor;
00162 double syncShift;
00163
00164 public:
00165 void syncTo(TimestampSensor *sensor, double shift);
00166 #endif
00167 };
00168
00169
00170
00171 class TimestampManager
00172 {
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 };