Fix-and-Hold extended to GLONASS and SBAS

I have just added a demo3  branch to my GitHub repository with a couple of new features.  The first is an extension of the fix-and-hold feature to enable ambiguity resolution for the GLONASS and SBAS satellites. This is what I will discuss in this post. I have also added a ambiguity resolution filter to prevent misbehaving satellites from being added to the set of satellites used for AR but I will leave that to a future post.

A couple posts back I discussed double differences of the raw data and the kalman filter phase-bias states, in the context of cycle slips. I will do something similar here but this time focusing on the initial acquire, when the solution first locks on to the correct set of integer ambiguities.

First, let’s go over a little background material.

The kalman filter can have a varying number of states depending on the input configuration settings but the most important states are the position states and the phase-bias states. The position states are estimates of the receiver position. The phase-bias states are estimates of the missing offsets that need to be added to the carrier phase measurements. There is one for each satellite, and they represent single differences between measurements from the two receivers. Subtracting one phase-bias state from another results in a double difference, which is what we looked at in the earlier post. If all error sources are counted for exactly, then the double differences will always be integers for geometric reasons.

At the end of each epoch, after the phase-bias states have been updated, the integer ambiguity resolution algorithm attempts to map the set of double differences float values to a set of integers. If it can do that with enough confidence to meet the ambiguity resolution criteria, then we have a fix and the plot line in RTKLPOT will switch from yellow to green. RTKLIB then uses the phase-bias estimates to update the position states. If we have a successful ambiguity resolution, the position states are updated from a position derived from the set of integers and is referred to as a fixed solution. If the ambiguity resolution was unsuccessful, the position update is derived from the non-integer phase-bias values instead and is referred to as a float solution.

In the example below, from RTKPLOT, the first successful ambiguity resolution occurs between 17:30 and 17:31, at which point you can see the switch from yellow to green, and the sudden jump in position when it is first derived from the integer values instead of the float values.


Unlike the position states, the phase-bias states are always updated from the float values and not the integer values, whether a successful fix occurred or not. Hence there is no corresponding jump in the double difference phase-biases when the first fix occurs. You can see this in the plot of a phase-bias double difference plot below for the same example as above.  There is no jump where the first fix occurred between 17:30 and 17:31 in either plot line. The red line is for a run with continuous ambiguity resolution, the blue line for one with fix-and-hold enabled.

So that’s a quick attempt to describe the ‘fix” in “fix-and-hold” What about the hold?

In the plot above, you can see in the red line for the continuous AR run that there is no discontinuity at all. The phase-bias double difference gradually and continuously approaches the the actual double difference integer of 4. That is what happens when there is no “hold”. When fix and hold is enabled however, and the hold criteria are all met, then an additional update is made to the phase bias states using the set of integer values from the ambiguity resolution. This is a very high gain update and the response in the phase-bias filter states is almost immediate. In the plot above, hold is enabled between 17:31 and 17:32, and you can see the response in the sudden jump in the blue line.

In the plot below, the same phase-bias DD is plotted on the left with fix-and-hold enabled. The lower plot is zoomed into when the hold occurs. You can see the correction is nearly immediate and the result is very close to the actual integer value on the first correction. This is for a GPS satellite. The significant errors for the GPS satellites are all accounted for,at least for short baselines, and so the initial correction can be quite accurate.  The corrections continue every epoch for which the hold criteria are met, and if the remaining error is visible to the kalman filter, the value will continue to converge to the integer value.


Below is the same plot for a GLONASS satellite. In this case, there is a significant unaccounted for error in the double difference, namely the inter-channel bias that we’ve discussed before, and which comes from the fact that the GLONASS system uses multiple frequencies. This error is invisible to the kalman filter and hence the double difference never converges to the actual integer value. You can see below, the jump to near zero from the hold update, but then the line does not converge towards zero after that.

But we know the double difference really is an integer, and at this point we should have accounted for all the other significant errors, so it might not be entirely unreasonable to assume this remaining difference is caused by the inter-channel bias and remove it, especially if we remove it slowly enough that the removal does not interact with any other feedback path.  We need to be careful how we handle it though. It won’t work to try and simply push the bias-estimate to the nearest integer. If we did that, the feedback loop would see the error and push it back. Instead we create a new array of variables to hold the inter-channel biases and move the error for each GLONASS satellite into this array. We can then adjust the double differences by these error values before feeding them into the kalman filter. To see exactly how this is done, you can look at the changes in holdamb() where the biases are adjusted and ddres() where the IC biases are removed from the kalman filter errors. To avoid upsetting anything else in the loop, I chose to be quite conservative about how quickly the adjustment occurs. It does not need to be done quickly. The plots below shows the error removed from the phase-bias state at a 0.5% per epoch rate (red) and a 1% (yellow) rate.  Again, the lower plot is zoomed in to after the hold.



This is fast enough to remove enough error to resolve the GLONASS ambiguities in 1 to 2 minutes after the GPS ambiguities have been resolved.  If necessary it could probably be done much more quickly.   Note that we do need to wait until the GPS ambiguities are resolved before beginning this process because before that point we have not yet accurately determined the other error terms.

Here’s an example ambiguity resolution output from the trace file for a run with this feature enabled.


Each double difference is made up of a reference satellite and a fix satellite. They are listed in the first two lines. “N(0)” is the float solution for the double differences. “N(1)” is the set of integers with lowest residuals, and “N(2)” is the set of integers with the second lowest residuals. “Ratio” is the ratio of the residuals between the best two sets. In general, the larger this number, the more confidence we have in the solution. Satellite numbers less than or equal to 32 are GPS, 33 to 59 are GLONASS. In this example there are seven GPS satellite pairs, and four GLONASS pairs. The other three pairs are SBAS satellites paired with a GPS satellite. I’m not sure why SBAS satellites are not usable without this feature since they use the same single frequency as the GPS satellites, but at least with the NEO-M8N, I have found that until I added this feature, I had to disable them. Unfortunately, unlike the GLONASS satellites, RTKLIB does not have a mechanism to allow SBAS satellites to be used for positioning without ambiguity resolution so they have to be removed completely.

In this example, after adding the SBAS satellites, enabling this feature has doubled the number of satellite pairs used for ambiguity resolution, and increased the number used for positioning by almost 25%.

So far, I’ve tried this on several data sets and have consistently resolved the ambiguities on the GLONASS and SBAS satellites, but I would say it is still fairly experimental at this point. If you’d like to try it on your data, you can download the code from the demo3 branch. To enable the feature for the GLONASS satellites, set “pos2-gloarmode” in the config file to “fix-and-hold”. If you want to enable the SBAS satellites as well, set bit1 in “pos1-navsys” .

If you do try it, let me know how it goes. I’d be happy to help if you have any difficulties with it. You can always contact me at

For those of you that read my previous post on GLONASS integer ambiguity resolution, this method is related to that one, but I think this should do a better job of driving the IC bias errors to zero because of the more continuous, lower gain nature of the updates to the IC biases.

2 thoughts on “Fix-and-Hold extended to GLONASS and SBAS”

  1. I also tried adding SBAS to AR, but at least for me, most SBAS satellites are unhealthy and are discarded right away. See for example row 2, col 4 of S20 in the rinex navigation of your dataset:

    S20 2016 5 24 8 25 36 .000000000000E+00 .000000000000E+00 .203224000000E+06
    .406367200000E+05 .000000000000E+00 .000000000000E+00 .100000000000E+01
    -.112459160000E+05 .000000000000E+00 .000000000000E+00 .327670000000E+05
    .000000000000E+00 .000000000000E+00 .000000000000E+00 .000000000000E+00

    When forcing them healthy the single solution fails as the residuals exceed by a large amount the threshold.
    From your results I assume you worked around this issue?


    P.S.: Thanks for the enlightening post


    1. Hi Michele. Glad you enjoyed the post. The example in my post was from data taken in the U.S. and the SBAS satellites were from the WAAS system. The data set you are looking at was taken in France and the SBAS satellites are from the EGNOS system. Apparently the EGNOS satellites do not provide ranging information. This is something I just learned yesterday.


Leave a Reply

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

You are commenting using your 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 )

Google+ photo

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

Connecting to %s