This is rather technical, but there are some nice colorful graphs to enjoy for the effort of reading this.
When a Motorola Oncore UT+ or M12+T GPS receiver is used for timing purposes, it is usually configured in "position hold" mode. In this mode, the receiver has a set of sanctioned coordinates for itself, and only solves the N equations for time, rather than for time+place. Obviously, this means 3 less unknowns and therefore gets a much more over-determined solution with better quality PPS output as result.
Normally one establishes the coordinates used for "position hold" mode by letting the receiver perform a "site survey" which simply means that it takes 10000 position fixes, takes the average values found for latitude, longitude and height, and uses that.
10000 seconds is good enough to get a decent fix, and it is certainly workable for most applications. Unfortunately, there are cases where it is not good enough. One of my receivers happend to do a site-survey during one of the solar storms in autumn 2003 and consequently got a fairly bad position fix, and as a result, the PPS output did a little daily dance when compared to my PRS10 rubidium.
In a mission critical application this is not very comforting, but rather than resort to a manually sanctioned set of coordinates I would rather have my software detect and fix this problem, so that deployment could still be a matter of "turn on and forget". But since the receiver is in "postion hold" mode, we get no position fix from it, so we cannot use that to cure the problem.
One proposed and implemented solution is to take the receiver out of position hold every N seconds, grab a few position samples and put it back in position hold. But since the receiver seems to do a warmstart, this costs up to 20 seconds of lost tracking, and doesn't really provide enough position fixes to be of much help anyway.
Fortunately, a solution seems to be possible: One of the bits of data the Oncore timing receivers can return in the serial data stream is the "Time RAIM status message" and it contains a field with the local time as estimated based on each of the tracked satellites. This field is almost entirely undocumented, and quite tricky to filter correctly, but I think I have managed to find out the missing bits of wisdom to do this.
Another bit of useful data is in the "Satellite Visibility message" which gives the elevation and azimuth of the twelve satellites highest on the sky. It is important to understand that these two angles are relative to the GPS antenna, the elevation gives the angle from the horizon to the satellite, the azimuth gives the angle from north in the local horizontal plane.
And the trick is simply to combine these two bits of information. The plot on the right shows a receiver with a set of coordinates which are significantly wrong in latitude. It is readily appearant that all satellites north of us gives time estimates which are 10 nanoseconds or more off in one direction while satellites south of us are 10 nanoseconds or more off in the other direction.
That is really a good question. These are the positions from nine of the M12+T receivers I have sitting on a row 20cm apart on my shed right now.
The plots have units of meter and a randomly chosen coordinate as origo in order to get usable y-axis values. Each line on the plots connect the before and after coordinates for a one day integration period.
It is interesting to see how the latitude starts out making a big correction, but then subsequently creeps back to more or less where it started. Notice also how some of the receivers "trade places" in the sequence.
I do not have surveyed ground truth values to compare this to, only I know that the receivers are spaced a few millimeters less than 20cm apart in this direction.
Here we have a very clear trend and at the same time the receivers converge on a common longitude as they should. Notice the two outlyers.
Up here on 56N, the height estimate of GPS is about an order of magnitude less precise than the two horizontal coordinates, and that clearly shows in this plot. Even though the receivers do show some convergence, they are still spread over an 2.5m interval. They are probably not perfectly horizontal, but they are certainly a lot closer than this. Again if one ignores the outliers, the result is much better.
If you want to see the full goory details, there is a 14MB PDF file here with a plot for each receiver for each sampling period.
I belive my results already show that the concept as well as my algorithm actually works for errors in the meter range.
It does not converge as fast as I want to, this is mainly due to the fact that the three dimensional error term for each satellite gets broken down into three component vectors and averaged. For reasons of geometry, this results in an underestimate of the magnitude of the true error in the correct direction and a smaller but not neglible misestimate of the actual direction.
I also don't know the amount of noise in the final position, it is currently my hope that I can leave these receivers running for long enough for them to converge on their ideal positions, but real life may not grant me that. Also the two outlyers needs to be investigated, the cause may be an insuficcient mask angle in certain directions.
The algorithm requires very little storage while running, and it could therefore be my hope that Motorola one day would incorporate it, or something better, in the receiver firmware.
I will obviously be working more on this algorithm. If you are interested in joining the effort, let me know. Both the algorithm and my source-code is available under the "Beer-ware" license.
The plot shown above reveal more useful information: at the top the tracks are blue at low elevations and red at higher elevation which points at insufficient mask-angle. I have run a couple of off-line experiments, and I belive it is feasible to calculate a mask angle for each angle of azimuth, and implement this by monitoring the elevation reported in the "Satellite visibility message" and selectively blocking out satellites under our "variable mask angle" using the "Satellite ignore list" command. More on this later.