Post-processing ComNav receiver data with RTKLIB – a more in-depth look

In a couple of my recent posts,  I showed that with the latest firmware from ComNav, the internal RTK solution was very good even for a quite challenging moving rover test, significantly better than a post-processed solution using RTKLIB.   To recap, here are the results side by side, ComNav internal RTK solution on the left, demo5 RTKLIB post-processed solution on the right.  The internal ComNav solution had a 96% fix rate while the RTKLIB solution had only a 68% fix rate.  In the plots below of a drive around the residential streets near my house, green represents a fixed solution and yellow is a float solution.


The RTKLIB solution shown is a forward solution to make it a more direct comparison to the internal solution.  Re-running it as a combined solution helps a little, but still only increased the fix rate to 71%.  Fix rates are only meaningful if the number of false fixes is small, but as I showed previously, the two solutions match quite closely where both are fixed.

Not only is the ComNav RTKLIB solution inferior to the internal ComNav solution, it is also inferior to an RTKLIB solution from a pair of much lower cost single frequency u-blox M8T receivers fed with the same antenna signals as the ComNav receivers.  As I showed in my last post, the RTKLIB M8T solution had an 88% fix rate and again matched the ComNav internal solution very closely when both were fixed.

So why does RTKLIB struggle so much with the ComNav data?  My suspicion is that there is nothing inherently lower quality about the data, it’s just that it’s flaws are different from the flaws of the u-blox data and that RTKLIB, particularly the demo5 version, has evolved to handle the flaws of the u-blox data better than it has for the ComNav data.  Specifically, what I see, is that the u-blox receiver is much better at flagging lower quality observations than ComNav (or other receivers) are.  This puts the burden on the solution code to appropriately handle the lower quality observations, something RTKLIB is not particularly good at.

To test this theory, I ran an experiment with a modified version of RTKLIB.  Usually I like to use the demo5 code for my experiments since it’s available to everyone, but for this exercise I used some experimental code I have been working on for a while now that helps RTKLIB to handle a wider range of measurement quality.  This code doesn’t do anything fundamentally different from the current demo5 version of RTKLIB.  No wide-lane or ionospheric-free linear combinations or any other tricks that are only available with dual frequency measurements.  All it does different is a better job of rejecting or de-weighting lower quality measurements and a more comprehensive search of the integer ambiguity space to find a clean set of ambiguities to use for a fix.

My thinking is that if RTKLIB code with just these changes can match the internal ComNav solution then that would give me confidence that the core mathematical algorithms in RTKLIB are fundamentally sound and capable of handling dual frequency solutions.   If not, then maybe RTKLIB requires some more significant changes to the solution algorithms to take better advantage of the dual frequency measurements.

When I started working with RTKLIB a couple of years ago I found similar performance issues when processing u-blox solutions, and found that relatively minor code changes could made a big difference.  RTKLIB is a fantastic resource but sometimes it is more of an academic toolbox than a true engineering solution.  This is not surprising or unexpected, given that the developers are in fact using it for academic research.

So how did the modified code work?  Here’s a forward solution with the modified RTKLIB code on the left and the difference between this solution and the ComNav internal solution on the right.  The 16.27 meter difference in the vertical axis is due to different handling of the offset between geoid and ellipsoid as I described in my last post.


You can see a big improvement.  The fix rate has increased from 68% to 99% and the vast majority of the differences between the two solutions are still less than 2 cm in the horizontal axes and 4 cm in the vertical axis.  Again, these are combined errors of both solutions, so I consider these numbers quite good.

Of course, the code improvements will affect the M8T single frequency solution too, so I also re-ran that solution to complete the comparison.  And just to make things a little more interesting, I also re-ran the ComNav solution with the modified code using only the L1 observations.  I did this to try and separate how much benefit is coming from the higher cost receiver in general and how much is coming from the L2 measurements specifically.

Here’s the M8T solution on the left with a  94.4% fix rate, and the Comnav L1-only solution on the right with a 98.9% fix rate.  The most challenging measurement environment was in the older neighborhood with larger trees that shows up as the small squares in the far left.  You can see that the ComNav L1 solution is noticeably better than the u-blox M8T solution in this area.


The two receivers did not start collecting data at exactly the same time so I did not include the time to first fix in this comparison.  If I remove that from the ComNav L1/L2 solution above, that increases the fix rate in that solution from 99.0% to 99.1%, slightly better than the 98.9% achieved by the L1 only solution.  The differences in both solutions relative to the internal ComNav solution appeared similar to the errors plotted above for the RTKLIB L1/L2 solution.

So, switching from the u-blox receiver to the ComNav receiver but using only L1 for both solutions improved the fix rate from 94.4% to 98.9% .  Adding L2 to the ComNav solution then increased the fix rate from 98.9% to 99.1%.

This data set is the most challenging I’ve run to date, and so I consider all of these results as quite good.  To provide some level of calibration, here are the observations for the ComNav rover.  You can see there are a significant number of cycle slips and missing data.  There are even more in the M8T observations, but the M8T data does include the Galileo and SBAS satellites as well.


I’ve covered several different results very quickly, so here is a quick summary of all the experiments.

ComNav internal solution:                              Fix rate = 96%
ComNav demo5 RTKLIB L1/L2 solution:      Fix rate = 68%
M8T demo5 RTKLIB L1 solution:                   Fix rate = 88%

ComNav modified RTKLIB L1/L2 solution:  Fix rate=99.1%
ComNav modified RTKLIB L1 solution:        Fix rate=98.9%
M8T modified RTKLIB L1 solution:               Fix rate=94.4%

So what can you conclude from this experiment?  This is what I get from it:

1) The existing core RTKLIB  algorithms are capable of high quality dual frequency solutions if the flaws in the observations are properly handled.

2) The current demo5 RTKLIB code is better matched to the M8T observations, so the opportunity for improvement is smaller than it is for the ComNav observations but there is still some opportunity even with the M8T.

3) A significant fraction of the improvement in the ability to maintain a fix on a moving rover between M8T and ComNav is likely not because of the additional L2 measurements, but simply because the overall quality of the more expensive receiver is higher.  The dual frequency measurements likely have a more significant advantage when it comes to faster first fixes and longer baselines.

The code is experimental only at this point and needs more work before it is ready for release but I do hope to make some form of it available eventually.


17 thoughts on “Post-processing ComNav receiver data with RTKLIB – a more in-depth look”

  1. What is the icon on the RTKPLOT Ground Track screen that is located at the extreme lower right edge? It looks to toggle the cursor information but this feature is not mentioned anywhere in the documentation. I’m particularly interested when it is toggled to read R:0.0000 m D:(degree heading?) what the “R” and “D” values are telling me.


    1. Hi Chris. Very interesting! I must have used RTKPLOT a thousand times and never noticed that icon. As you suggested, it toggles the units of the cursor location. It has three settings: 0=latitude and longitude, 1=E/W and N/S distance from base, and 2=horizontal distance from base and heading.


  2. Great post! Can you go into any more detail about metrics you used to flag lower quality data from the Comnav receiver? Is this something that is specific to Comnav or could apply to other receivers as well?


    1. Hi Tom. Probably the two most significant enhancements to the standard RTKLIB code were using separate thresholds for phase and pseudorange outliers and then modifying the response to the outliers so as not to confuse the kalman filter. I have found that most receivers are not as good at flagging bad samples as u-blox is so these changes should help with many of these receivers. These changes are included in a “premium” version of RTKLIB that I have been working on for the past year or so and which includes some more significant features beyond what I have added to the demo5 code. I hope to be making this available in the near future.


  3. Hello Tim, Thanks a lot for your great blog (I read it from the beginning).
    Is your experimental code available somewhere to run it on some m8t dataset ?


    1. Hi Tophe. The experimental code is still a work in progress. Most likely, I’ll eventually incorporate some of the features into the demo5 code but other changes are not universal enough. They either don’t work well with all receivers in all environments or they cause legacy issues with the existing code, or the computational requirements might be too great for a small CPU running real-time. In general I try to use the demo5 code for all my experiments so that they can be duplicated by others but in this particular case the limitations of the released code were getting in the way of the point I was trying to demonstrate. The experimental versions of code (and my matlab/python scripts) tend to be rather hacked and not really suitable for general use so I prefer not to share them since they tend to generate more requests for support than I can handle with my limited bandwidth.


  4. Dear Tim, I have one more idea on a test for robustness. It would be very interesting to see how the age of rtk corrections influences the horizontal and vertical accuracy of the solution on various receivers. I read that correctoin loss for few seconds or even a minute may still be acceptable for some applications. I ask this because I live in Europe where we have a nice dense CORS network equivalent but most countries charge a fee for its usage based on time (units are seconds mostly). So one could save lots of money by asking for corrections less frequently (maybe every 10 seconds).


    1. Hi Kozuch. Lots of good suggestions! I will add them to my list of things to explore. I’m definitely interested in working with the u-blox L1/L2/L5 units, I’m just not sure how long it will be till they are available.


      1. Is anyone know any low cost GPS L2C or/and L5 receiver? If not, is there any IF data file contains L2C or L5 signal available to download. I can use rtl-sdr to record some data, but the sample frequency is only 2.048Mhz not good enough (maybe OK for L2C)


  5. Hi Tim I appreciate your post. I am very interested in getting the most of low-cost receivers in an urban-canyon scenario like for instance autonomous vehicles encounter. I think this area has a lot of potential especially with the newly annonced L1/L2/L5 hardware. It would be nice to see your further tests go in this direction – i think you just reached almost 100% fix in your scenario so it is really time to move to more challenging environments so that the receivers can really show the differences between them. I think solution robustness is very important and I think it can at least partly be tested with artificial obstacles (partly or completely hiding the antenna with metal shield etc.). I am also very interested in fix re-acqusition times which are part of the robustness tests.

    This guy did artificial sky blocking:


  6. halo,
    Thank you for your very clear explanation.
    I am very new in RTKLIB
    and i just compile RTKlib QT in Ubuntu 16.04
    It is running but the menu bar (file,open,etc) dont appear. Do you know what is goes wrong ?
    Thank you


  7. Good Job, I am also working on the coarse measurement rejection in rtklib. Seems better, but not as good as you did. 🙂


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 )

Connecting to %s

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

%d bloggers like this: