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;
}