Brief description of class still missing. More...
#include <PPSBuffer.h>
Public Member Functions | |
PPSBuffer (UbxDevice *gpsDevice) | |
~PPSBuffer () | |
Protected Member Functions | |
virtual int | bytesAvailable (char *buffer, int byteCount) |
Brief description of class still missing.
Full description of class still missing
PPSBuffer::PPSBuffer | ( | UbxDevice * | gpsDevice | ) |
Description of constructor still missing
References TRACE.
: DynamicBuffer(0) { TRACE; _gpsDevice=gpsDevice; _lastPPS=0; }
int PPSBuffer::bytesAvailable | ( | char * | buffer, |
int | byteCount | ||
) | [protected, virtual] |
Implements GpCoreTools::DynamicBuffer.
References GpCoreTools::LinearRegression::a(), QGpCoreTools::abs(), GpCoreTools::LinearRegression::add(), GpCoreTools::LinearRegression::at(), GpCoreTools::LinearRegression::b(), GpCoreTools::LinearRegression::badValue(), GpCoreTools::LinearRegression::calculate(), GpCoreTools::LinearRegression::count(), UbxDevice::isResetPpsDrift(), UbxDevice::LostPpsLock, UbxDevice::monitorDriftMode(), UbxDevice::NoLock, UbxDevice::PpsLock, GpCoreTools::LinearRegression::remove(), GpCoreTools::LinearRegression::reset(), UbxDevice::resetGpsDrift(), UbxDevice::setPpsDriftCount(), UbxDevice::setTimeStatus(), GpCoreTools::LinearRegression::stddev(), UbxDevice::timeStatus(), and TRACE.
{ TRACE; if(byteCount!=1) { // Ignore if more than one byte is received Log::write(0, "more than one byte for PPS, fix GPS config\n"); return byteCount; } // Record immediately the current time timeval sysTime, deltaTime; /*timespec clockTime; if(clock_gettime(CLOCK_REALTIME, &clockTime)!=0) { Log::write(0, "cannot get clock\n"); return byteCount; }*/ gettimeofday(&sysTime, 0); if(_gpsDevice->timeStatus()==UbxDevice::NoLock || _gpsDevice->timeStatus()==UbxDevice::LostPpsLock) { return byteCount; // First wait for GPS lock before doing anything else } //Log::write(0, "pps clock %i s; %lf us\n", clockTime.tv_sec, (double)clockTime.tv_nsec*0.001); //Log::write(0, "pps timeofday %i s; %i us\n", sysTime.tv_sec, sysTime.tv_usec); deltaTime.tv_sec=0; // Fix average bias observed versus PPS on RNG: 30 ms of pulse length+transmission delay. //sysTime.tv_usec-=31640; // Fix average bias observed versus PPS on RNG: 180 ms of pulse length+transmission delay. sysTime.tv_usec-=181640; if(sysTime.tv_usec>500000) { deltaTime.tv_usec=1000000-sysTime.tv_usec; sysTime.tv_sec++; } else { deltaTime.tv_usec=-sysTime.tv_usec; } #ifdef MONITOR_DRIFT_MODE if(_gpsDevice->monitorDriftMode()) { Log::write(0, "pps time delay %i %.3f ms\n", time(NULL), deltaTime.tv_usec); return byteCount; } #endif if(_gpsDevice->isResetPpsDrift()) { Log::write(0, "pps drift reset\n"); _drift.reset(); } _drift.add(sysTime.tv_sec, deltaTime.tv_usec); //Log::writeNoStamp(0, "pps_drift %i %lg ms\n", sysTime.tv_sec, deltaTime.tv_usec*1e-3); if(_drift.count()>30) { _drift.calculate(); float stddev=_drift.stddev(); int badValueIndex=_drift.badValue(2.5*stddev); // From experience, if stddev if larger than 5 ms, the estimation of clock drift is not correct, continue stacking if(badValueIndex>=0) { Log::write(5, "pps drift dt(t)= %.20lg *t+ %.20lg bad value %i standard deviation= %f\n", _drift.a(), _drift.b(), badValueIndex, stddev); _drift.remove(badValueIndex); } else if(stddev>5000) { Log::write(5, "pps drift dt(t)= %.20lg *t+ %.20lg standard deviation=%f ms > 5 ms \n", _drift.a(), _drift.b(), stddev*0.001); if(_drift.count()>40) { _drift.reset(); } } else { Log::write(10, "pps drift: dt(t)= %lg *t+ %lg, dt(now)= %lg ms\n", _drift.a(), _drift.b(), _drift.at(sysTime.tv_sec)*0.001); Log::write(5, "pps drift standard deviation= %f us.\n", stddev); deltaTime.tv_usec=_drift.at(sysTime.tv_sec); // System clock considered locked if delta is less than 10 ms int absDeltaUSec=abs(deltaTime.tv_usec); if(absDeltaUSec<10000) { if(adjtime(&deltaTime, 0)!=0) { Log::write(0, "pps adjust time: %s\n", strerror(errno)); } else { if(absDeltaUSec>2000) { Log::write(2, "pps adjust time larger than 2 ms: %.3lf ms\n", deltaTime.tv_usec*0.001); } if(_gpsDevice->timeStatus()!=UbxDevice::PpsLock) { _gpsDevice->setTimeStatus(UbxDevice::PpsLock); if(_gpsDevice->timeStatus()==UbxDevice::PpsLock) { Log::write(0, "time locked to gps and pps\n"); } } } } else { Log::write(0, "system clock and pps differ by %.3f ms: force system time.\n", deltaTime.tv_usec*0.001); //sysTime.tv_usec=31640; sysTime.tv_usec=181640; Log::write(0, "pps set time to %li.%06li\n", sysTime.tv_sec, sysTime.tv_usec); if(settimeofday(&sysTime, 0)!=0) { Log::write(0, "pps set time: %s\n", strerror(errno)); } else { // Repeate time because the time stamping in log file might have a big jump Log::write(0, "pps time set to %li.%06li\n", sysTime.tv_sec, sysTime.tv_usec); } // Strong change in time, so reset Gps drift and status if(_gpsDevice->timeStatus()!=UbxDevice::PpsLock) { _gpsDevice->setTimeStatus(UbxDevice::NoLock); } _gpsDevice->resetGpsDrift(); } _drift.reset(); } } time_t t=sysTime.tv_sec; tm * d=gmtime(&t); if(_gpsDevice->timeStatus()==UbxDevice::PpsLock) { ScreenClient::write(12, 0, "%02i:%02i:%02i", d->tm_hour, d->tm_min, d->tm_sec); // Monitor and log missing PPSs if(_lastPPS!=sysTime.tv_sec-1 && _lastPPS!=0) { Log::write(0, "missing %i ppses\n", sysTime.tv_sec-_lastPPS-1); if(_lastPPS<sysTime.tv_sec-61) { // More than a minute without PPS _gpsDevice->setTimeStatus(UbxDevice::LostPpsLock); _lastPPS=0; } else { _lastPPS=sysTime.tv_sec; } } else { _lastPPS=sysTime.tv_sec; } } else { ScreenClient::write(12, 0, "PPS %3i ", _drift.count()); _gpsDevice->setPpsDriftCount(_drift.count()); } return byteCount; }