Kalman Filter Adjustments in RTKLIB (the Options-Statistics tab)

In this post, I am going to describe how the Kalman filter in RTKLIB is configured and how it can be adjusted. In most cases, the default values work fine and there is no need to adjust these parameters, but in some cases it can be useful. Also, understanding these parameters can provide useful insight into how RTKLIB generates its solutions.

If you are interested primarily in how to set these values and not in what they do, then you may want to jump down to the end of the post where I discuss a few examples of where I have found adjusting these values to be helpful.

Parameters to enable and disable various filter states are sprinkled over the different tabs in the options menus of RTKPOST and RTKNAVI but the parameters that determine the inner details of the Kalman filter calculations are all listed on the Statistics tab as shown below.

Statistics tab in RTKPOST

Note that the parameters are divided into two sections, measurement errors and process noises. In a Kalman filter, each measurement will have a measurement error estimate associated with it, and each filter state will have a process noise estimate associated with it, both defined in terms of standard deviations (or sigmas). The Kalman treats all of the measurement errors as normally distributed with zero mean. In general, increasing the error estimates of the measurements relative to the process noises will cause the filter to rely more on the model, and reducing the error estimates of the measurements will cause the filter to rely less on the model and more directly on the measurements.

The description below will apply specifically to differential solutions (RTK/PPK) but the PPP solutions use a similar method.

MEASUREMENT ERRORS:
The primary measurement inputs to the Kalman filter are code and phase observations. The amount of error in each observation will be determined by many factors which we cannot determine directly, but in general, both satellite elevation and signal strength will correlate with measurement error. Since the receiver reports a signal strength (C/N0) for each measurement and we can determine the satellite elevation from the ephemeris messages, we can use either or both of these to generate an estimate of the error. For differential solutions (RTK/PPK), errors will also increase as the baseline between rover and base increases. Another option that is sometimes available is to use an error estimate provided directly by the receiver.

The original (2.4.3) version of RTKLIB uses the sum of four squared terms to determine the error estimate as a variance for each phase observation. The first term is a constant, the second term is a constant divided by the sine of the satellite elevation, the third term is a constant multiplied by the distance between base and rover, and the fourth term is a constant multiplied by the time since the last observation. The default values for the first two constants are three mm, and the third is zero. The last term is included to account for satellite clock stability and defaults to 5e-12 sec/sec. These are listed in the options tab as “Carrier-Phase: a+b/sinEl”, “Carrier-Phase: Baseline”, and “Satellite Clock Stability”.

The demo5 version of RTKLIB defaults to the same algorithm and values as the 2.4.3 code but has three additional terms which all default to zero. The first two terms allow the error estimate to be adjusted by the signal strengths of the base and rover observations using the formula a*10^(.1*MAX(snr_max – snr), 0). The two additional terms are a and snr_max in the above equation and correspond to Carrier-Phase: SNR / SNR maxDb” in the options tab. This squared result is added to the previous terms. Using the convention of RTKLIB, snr and snr_max are actually C/N0 values as reported by the receiver.

The last term in the demo5 code is used to include the reported error estimate from the receiver and is only available when the observation files were generated from u-blox binary files with the “-RCVSTDS” receiver option enabled. This option causes RTKCONV or CONVBIN to add the receiver error estimates to unused fields in the RINEX observation files. The receiver error estimates from the RINEX files are multiplied by this last term, squared, and added to the previous terms. This term is labelled “Carrier-Phase: Rcv Errs” in the options tab.

Thus, for the demo5 code, by setting the appropriate terms to zero and non-zero values, the phase observation error estimates can be derived from either the elevation, the signal quality, the receiver error estimates, or any combination of the three.

Finally, for both the 2.4.3 and the demo5 code, the error estimate is adjusted based on which constellation the observation is from. These adjustments are defined in the rtklib.h source file and can not be modified with the config file. GLONASS and IRNSS adjustments are set to 1.5, SBAS is 3.0, and the other constellations are set to 1.0.

Everything so far describes how the error estimates are derived for the phase observations. To determine the error estimates for the code observations, the phase error estimates are simply multiplied by a constant determined by which frequency band the observation is from. These are the “Code / Carrier-Phase Error Ratio L1/L2/L5” parameters in the options tab above. These ratios all default to 100 in the 2.4.3 code which is probably a more appropriate value for higher-end receivers, and 300 in the demo5 code which seems to work better for low-cost receivers.

There is also a parameter for setting the measurement noise for the doppler measurements but these are used only very peripherally in the solution, so adjusting this parameter will have little to no effect on your results.

PROCESS NOISES:
The primary states in the Kalman filter are the single-difference phase biases and the positions. There are nine position states if the “Rec Dynamics” option is enabled (x,y,z for position, velocity, and acceleration) or just three if it’s not enabled (x,y,z for position). For long baseline solutions, additional states can be enabled for tropospheric and ionospheric delays.

Each of these states has a process noise associated with it. The process noises are estimates of the amount of unmodeled error in the state, expressed as a standard deviation. In the case of the position states, the model does not account for any external accelerations of the receiver. Therefore we need to specify non-zero process noises for the acceleration states, assuming the receiver is not static. The position and velocity changes that result from these unmodeled accelerations are accounted for by the model, and hence the position and velocity process noises are set to zero. The process noises for the acceleration states are set with the “Receiver Accel Horiz/Vertical” parameters in the options tab and have units of m/sec^2 The smaller these parameters are set, the less the position solution can jump around from noise, since the filter will constrain the motion to smaller accelerations, but the more lag will be introduced in the filter response if there are real accelerations larger than the specified process noise. If the dynamics option is not enabled, meaning there are no velocity or acceleration states, then there will be unmodeled errors in the position states. In this case, the code does not use the acceleration state process noise values , but sets the process noises for the position states to a large but unconfigurable value.

The phase bias states also have process noises assigned to them and these are set with the “Carrier-Phase Bias” parameter in the options tab. They are set in units of carrier phase cycles but in this case they don’t translate as well into unmodeled physical errors as the acceleration errors do. By definition, these states are modeling values that can only be integers (or half-integers in the case of a phase lock loop that is not fully locked) and don’t change unless there is a cycle slip. The variance of the state is reset if a cycle slip is detected or reported, so the only unmodeled errors should be undetected cycle slips. These are large, discrete, and very infrequent, about as un-gaussian as you can get, yet we are forced by the math behind the Kalman filter to treat them as normally distributed. The default value is 0.0001 cycles which is probably based more on what gives the best results rather than anything physical. Increasing this value will cause the filter to weight recent measurements more heavily relative to earlier measurements.

There are also process noise values for the tropospheric and ionospheric delay states if these states are enabled for long baseline solutions.

Choosing Config Parameter Values:
As I mentioned before, most of the time I just use the defaults for these parameters and don’t try to tune them. There are a few exceptions however, so I will describe them here.

First, I have found that setting the code/carrier-phase error ratio to lower values for more expensive receivers (~100) and to higher values for low-cost receivers (~300) tends to give better results. Lower values increase the weight of the pseudorange measurements relative to the carrier phase measurements. I suspect that the more expensive receivers are able to improve the quality of the pseudorange measurements more than they are able to improve the quality of the carrier-phase measurements relative to the low-cost receivers but that is only conjecture.

Sometimes, I find that forward-only solutions give higher fix percentages than combined (forward+backward) solutions. The reason for this is that RTKLIB validates every fixed point in the combined solution and if the forward solution differs from the backward solution point by more than four standard deviations, then the point is downgraded to float. The purpose of this step is to identify and remove false fixes, but if the observation measurement error estimates are too small, then even quite small differences between the forward and backward solutions that were not caused by false fixes can be downgraded. In this case increasing the constant and elevation weighting terms of the phase observation error estimates from 0.003,0.003 to 0.005,0.005 or 0.006,0.006 usually eliminates some of the unnecessary downgrades and improves the fix rate.

For cell phone solution I increase these values by even more to account for the very poor signal quality.

In a more challenging receiver environment with many obstructions and reflections, observation quality may correlate less strongly to elevation and more strongly to signal quality than in more typical situations, especially for short baselines where atmospheric errors are less significant. Especially with cell phones, several researchers have reported better results when weighting observations by signal quality rather than elevation.

I also suspect that incorporating the receiver quality metrics in addition to the other factors should be helpful but have not proven this in practice, despite some attempt to do this.

I have also noticed that as the interval between base observations increases, the effect of the satellite clock stability term becomes more and more dominant on the observation measurement errors to the point where all of the other terms have almost no effect. I suspect that this is not realistic or desirable but I have not investigated it closely.

If you have found other examples where adjusting these values improved your results, and are willing to share your experience, please leave a comment below.


9 thoughts on “Kalman Filter Adjustments in RTKLIB (the Options-Statistics tab)”

  1. Hi, with cheap receivers (like the M8N from before the firmware upgrade), it takes a long time before a FIX is obtained (up to several hours). Would it be possible to somehow improve this time, by feeding the Kalman filter the initial position of the rover as well? In my situation, I typically put the rover in a holder, and let it acquire a fix (using the static-start positioning mode). Only once this fix is obtained, I will start moving the rover. As the rover will always start in the same position, this should allow a faster time to fix.
    Any guidance how I could enable this (either with the existing options, or by changing the code).
    thanks,
    Marc

    Like

  2. Hello, thanks for the post!

    My students and I have been trying to use a dual frequency Huawei P30 PRO smartphone for precise positioning. We could only get reasonable L1-only PPK results (i.e., at dm and cm level) using the following weighting scheme:

    Code/Carrier-Phase Error Ratio L1/L2/L5: 10.0, 10.0, 10.0
    Carrier-Phase Error: a + b/sinEl: 0.30, 0.30

    Regarding dual frequency (L1 and L5) PPK results, we have not got any goods results so far.

    Any additional tips are welcome!

    Regards, Luiz

    Like

      1. Thank you for the feedback! We have been using a chokering antenna underneath the smartphone to try mitigating multipath in a static positioning. We will look into your posts.

        Like

  3. Hi, I am a PhD student using RTKLIB PPP in my project
    I know RTKLIB is using WGS84 but what realization
    In order to convert RTKLIB WGS84 coordinates to ERTS89, IGS2020 …

    Liked by 1 person

    1. I don’t work with ERTS89 and am not familiar with a tool to convert to or from it. For NAD83 (the North American equivalent to ERTS89), the HTDP tool will do this. WGS84 and IGS2020 are virtually identical so there is usually no need to transform between them, but the HTDP tool will do this too.

      Like

      1. Thank you for your quick reply and interest.
        WGS84 has six different realizations.
        Which version of WGS84 RTKLIB are you using?

        Like

Leave a comment

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