A second raw GPS data set: Fix-and-Hold issues again

In the previous series of posts I focused on a particular data set taken while driving a car around a parking lot with both receivers mounted on top of the car. By analyzing the data and making various changes to the input configuration and to the code I was able to noticeably improve the solution results. Now it’s time to try those changes on another data set to begin to find out how universal those improvements really are. After all, it’s very easy to deceive yourself when using the same data to evaluate a change that you used to develop it in the first place. I expect it will take several iterations of improvements over several data sets before finding something that is consistently reliable.

I have been given a very nice data set for this purpose. It was taken with two Emlid Reach receivers mounted fore and aft on a kayak while paddling around in the ocean. The Reach receivers are a fully integrated RTK solution built around Ublox M8T receivers  and although I have not used them myself, they look to be a good choice for someone who wants to get up to speed with working hardware very quickly. They are a little expensive to meet my goal of “ultra-low cost” but still much lower priced than any traditional alternative. (Related note: Emlid has kindly offered to send me a couple of their receivers to play with and I plan to take them up on their offer at some point here in the fairly near future.)

The data I have is from a small company called Reefmaster that provides software solutions for processing sonar images. (Thanks to Matt for providing me with the data and helping analyze the results.) They have some very cool looking sonar mosaics on their website created by stitching together multiple sonar scans. They hope to use RTKLIB to improve the location tagging of the sonar scans to improve the stitching process. This could be an ideal application for RTKLIB; open sky visibility combined with relatively slow velocities and accelerations from the boat. These sort of well defined, friendly environments are, at least in the short term, where I believe RTKLIB is going to be most successful. Sometimes it seems that people are expecting too much from these low cost receivers, using them in very challenging environments, and then being disappointed when they don’t perform well.

As in the previous data set, both receivers were mounted on the rover so I can evaluate the accuracy of the solution by measuring the deviation from a perfect circle in the difference between the two receivers. In this case I really should use a sphere instead of a circle because, unlike the previous example, there is occasionally a significant elevation variation between the two receivers. Most of this occurs when the kayak is being rolled up and down over an embankment to get it in and out of the water. For now, I’ll just focus on the data taken while on the water and ignore the extra dimension.

Let’s start by running with the final code and configuration we ended up with in the demo1 code which is available in my Github repository (For now I am going to put aside the recent experiments I made with “fix-and-bump” and GLONASS AR). The ground track result is plotted below. This is not a good start! It’s better than the original default configuration, but not by much.


I’m always suspicious of fix-and-hold because of it’s tendency to lock to an incorrect fix so let’s first turn it off and see what happens. In the plot below, the solution was run after “pos2-armode” in the configuration file was changed from “fix-and-hold” to “continuous”.  Again, I am only plotting the time period when the kayak was on the water.



Much better! It looks like fix-and-hold is the culprit. In the demo1 changes, I added a couple of criteria (minfixsats, minholdsats) to try and prevent exactly this kind of issue but clearly my changes were not sufficient.

A quick analysis of the fix-and-hold enabled results shows that the fix criteria was met very early, while there was still large errors in all the kalman states. When fix-and-hold was disabled, these errors were only temporary, but when fix-and-hold was enabled, the states corrupted by the incorrect fix were locked in a short time later when the fix-and-hold criteria were met, and the solution never recovered. Based on the results obtained with fix-and-hold disabled, the rest of the changes in the demo1 code/configuration look like they are working well on this data set.

It really does not make sense to look for a fix while all the states are still converging so it might be reasonable to disable integer ambiguity resolution for some period of time at the beginning of the data until the states have time to converge. In this article, Carcanague lists disabling integer ambiguity resolution for the first three minutes of data as part of his procedure.

Rather than picking an arbitrary time to elapse before enabling AR, I have chosen to wait until the variance in the position solution drops below a threshold. This seems like a little more direct measurement of what we are interested in, and will get re-engaged if we get a severe disturbance and all phase-biases get reset, unlike a pure time-from-start criteria.

Interestingly enough, in the 2.4.3 release of RTKLIB, four new parameters have been added to the config file: pos-arthres1, pos-arthres2, pos-arthres3, and pos-arthres4. Apparently someone else was thinking that integer ambiguity resolution needed some additional constraints. At the moment, though, these new parameters are unused in the code, so we will co-opt pos-arthres1 for our own use.

I modified the function resamb_LAMBA as shown below to add one more condition that must be met before invoking integer ambiguity resolution. rtk->P[0] is the variance of the x direction of the position state and rtk->opt.thresar[1] is the variable that pos-arthres1 is copied into.


if (rtk->opt.mode<=PMODE_DGPS||rtk->opt.modear==ARMODE_OFF||
     rtk->opt.thresar[0]<1.0) {
     return 0;


if (rtk->opt.mode<=PMODE_DGPS||rtk->opt.modear==ARMODE_OFF||
     rtk->opt.thresar[0]<1.0 || rtk->P[0]>=rtk->opt.thresar[1]) {
     return 0;

I arbitrarily set pos-arthres1 to 0.002 because it was a round number that very roughly corresponded to three minutes into the data set.  The standard deviations of the positions are output to the .pos solution file along with the position values.  We get the variance by squaring the standard deviation.  Here is the variance of x plotted for the first 300 secs of this data set.



Re-running with fix-and-hold enabled and with the new code gave the following result.



Very similar to the previous result, but with a slightly earlier first correct fix because we have removed the very early bad fix.

Overall, quite good. I suspect this is not the last additional constraint we will need to add to fix-and-hold before we are done!


3 thoughts on “A second raw GPS data set: Fix-and-Hold issues again”

  1. Hi rtklibexplorer,
    I made some tests with your latest advices.
    I recompiled rtklib with the bugfix about min-lock-count and I also added the check of X variance before invoking integer ambiguity resolution improvement (I noticed that you have changed the thr value from 0.05 to 0.002).
    I obtained better results but I encountered a big issue related to slip. Often the receiver looses signal from satellites (lost lock) and the ratio falls down to zero and resets the kalman filter. The satellites are then locked again after min-lock-count.
    The signal loss duration is very small (one cycle). Can I do something in order to filter out the small signal loss glitch?
    I also make some thought about the thresholds SNRmask and pos1-elmask. Is there any hysteresis window around these thresholds? Otherwise there are a lot of signal spikes during the threshold crossing.


    1. Hi Generaldin.

      Cycle slips are something that RTKLIB doesn’t handle well and something that is not easy to fix. Once the receiver has lost lock to a satellite, the associated kalman filter state is no longer valid. It must be reset, then re-converged. Even though the slip only lasts one cycle, the re-convergence takes much longer. There are algorithms in the literature that attempt to correct the cycle slip count in a single epoch rather than reconverge the filter but RTKLIB does not have this capability and it’s not clear how reliable they would be, especially with the noisier data that comes from low cost receeivers and antennas. Your best bet is to do everything you can to avoid cycle slips in the first place (clear skies, good ground planes, low velocities and accelerations, vibration isolation, EMI avoidance, etc)

      I don’t believe there is any hysteresis in the SNR/el masks other than every time a satellite drops out, it will not be used for at least arlockcount epochs (assuming you have my bug fix in your code).

      Sorry about the value change. The initial value was wrong … I had mistook the output data in the position file for variance when it was really standard deviation. I was hoping I changed it before anybody noticed, but you were too quick!


      1. thank you for the fast reply.
        Yes I was very fast because I’m involved in a personal project for agricoltural gps guided rover and while for the stuff like electronics, automated controls, etc.. I have no problem, I cannot find any resources to optimize and tune the rtklib.
        I have very good results if you take into account the low cost receiver and antenna but I cannot reach a reliable signal with a reasonable on-time (ex.: 2h).

        Got it about slip. It’s something that we cannot filter out or interpolate through the other data. I’ll try to reduce EMI and put bigger ground plane. Then I’ll let you know.
        Yes, I have implemented the arlockcount bug fix, but when I talked about hysteresis I had in mind to substitute the arlockcount method (or part of it) due to slip issue. I try to explain. If you fix the arlockcount bug and you have a slip event then the re-convergence will apply only after arlockcount epochs. This is a very long time. But if you set arlockcount to zero and implement the hysteresis window to avoid satellites signal ping-pong around the threshold you will have faster re-convergence and good satellite lock


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: