More Moving Rover / Fixed Base Data

I decided to try something a little more challenging for the next data set. Here’s a section of a dirt road with many trees on one side of the road and just a few on the other side. It could be representative of a farm field bordered by woods. The trees should cause a fairly large number of cycle slips on some of the satellites and just a few on others. The road is also rough enough to bounce the receiver around a bit. This should add some vertical and lateral accelerations.

road (1024x768)

I used the same two Ublox M8N receivers and antennas as last time, only this time I remembered to bring the pie pan so didn’t have to use the old beer can again for a ground plane. Here’s a photo of the improved base station.

piepan (1024x768)

I again set the receivers up to collect 5 Hz GPS and GLONASS data. Last time this worked with no issue, but this time I saw what other people have reported … I got 5 Hz data but all the GLONASS satellites were missing. After a bit of fiddling with the receiver setup what I found was that I had to first collect a brief bit of data at 1 Hz, then switch the receivers to 5 Hz and everything worked fine. To make this easier, I added an extra line to the beginning of the list of startup commands in STRSVR to set the sample rate.

I now have two startup files, one for 1Hz and the other for 5 Hz.

The 1 Hz startup file now looks like this:

!UBX CFG-RATE 1000 1 1
!UBX CFG-GNSS 0 32 32 1 0 10 32 0 1
!UBX CFG-GNSS 0 32 32 1 6 8 16 0 1
!UBX CFG-MSG 3 15 0 1 0 1 0 0
!UBX CFG-MSG 3 16 0 1 0 1 0 0
!UBX CFG-MSG 1 32 0 1 0 1 0 0

and the 5 Hz startup file looks like this:

!UBX CFG-RATE 200 1 1
!UBX CFG-GNSS 0 32 32 1 0 10 32 0 1
!UBX CFG-GNSS 0 32 32 1 6 8 16 0 1
!UBX CFG-MSG 3 15 0 1 0 1 0 0
!UBX CFG-MSG 3 16 0 1 0 1 0 0
!UBX CFG-MSG 1 32 0 1 0 1 0 0

Once I got past this hurdle, I was able to collect some data. I set up the base station in the middle of the field with unobstructed skies and attached the rover receiver and antenna to the top of the car. For the first fifteen minutes the car was stationary on a part of the road with relatively unobstructed skies, and for the remaining time I drove back and forth along the edge of the trees. Here’s a couple plots of the observation data files, base on the left, and rover on the right. The red ticks indicate cycle slips.


As expected, the base data is free of cycle slips, but the rover starts to see a fairly large number of them as soon as the trees start to obstruct the rover antenna. For comparison, in the previous data set I collected in open skies, the rover data was nearly completely free of cycle slips.

Processing the data with RTKCONV, then running the solution with my demo3 version of RTKLIB, gave the following solution, ground track on the left, and position on the right.


So the results looks very good, 100% fixes after the initial acquire and through all the cycle slips. But how do we know the positions are all correct? In the earlier data sets, I mounted both receivers on a single rover which forced the solution to be a circle of fixed radius. In that case any point that fell off the circle must be an error and was quite easily spotted. In this case, verifying the data is more difficult because we don’t know what the correct solution is. I don’t think there is any one easy answer to this question, but there are some things we can do to gain confidence in the results. If we run the solution with different input configurations and different sets of satellites and get the same answer, that helps. Sometimes errors are more obvious in the vertical component since it tends to be more constrained. For example, if you drive in circles and the starting point varies by 10 cm in the x or y direction that could be normal variation, but if you end up 10 cm deeper every circle something is probably wrong.

The best single test I was able to come up with is to compare two solutions, one with ambiguity resolution mode set to fix-and-hold and the other with it set to continuous. In continuous AR mode, fixes are much more independent of each other since there is no direct input to the kalman filter from the result of the fixes. That is not true of fix-and-hold, which feeds information from the previous fix into the kalman filter to help find subsequent fixes. In general, most problems with erroneous fixes occur when fix-and-hold is enabled. So the goal won’t be to prove the position is correct, only that fixes are validated as reliably with fix-and-hold enabled as they are with continuous AR mode.

RTKPLOT has a nice feature that makes this comparison quite easy. After running both solutions and then opening them as solution 1 and solution 2 in RTKPLOT, you can then plot the difference using the ‘1-2’ button in the top left of the GUI.

For this particular instance, to make the two runs even more independent and to validate my code changes, I ran the continuous AR case using the original RTKLIB code and configuration without any of my modifications (except enabling dynamics), and ran the fix-and-hold case with my demo3 code and configuration file with the extended fix-and-hold enabled for both GPS and GLONASS satellites.

Below on the left is the continuous AR solution. It finds fixes quite easily while the rover is stationary but after the rover starts moving and cycle slips start occurring it has more trouble and gradually drifts off, getting fewer and fewer fixes. The plot on the right below shows the difference between the two solutions. The green indicates where both solutions had fixes, and the yellow where one or both were not fixed.


As you can see, every time both solutions get a fix, they differ by less than a couple centimeters in the x and y directions and a little more in the z direction. These are usually quite acceptable and too small to be caused by invalid fixes since one cycle is about 20 cm. We can not directly confirm the positions for which the continuous AR mode did not get fixes but based on the continuity of the points in between they are most likely correct as well.  So, at least for this data set I believe the fix-and-hold has reliably given us the correct position.

What happens with this test if there are erroneous positions in the fix-and-hold data? On the left below is an example of another fix-and-hold solution of the same data set. Although this one also has 100% fix after the initial acquire, it is definitely incorrect. You can see after six passes on the road, the car is now half a meter higher than it started! Comparing it with the same continuous AR case as above gives the plot on the left, where it is even more obvious that it is not correct since the green dots are all significantly distant from zero.


I was able to create the incorrect solution above simply by delaying the starting point of the solution from the beginning of the data where the car was stationary and there were no cycle slips, to a point later in time where the car was moving and there were numerous cycle slips. You can see in the above plots that the solution starts at 7:16, where previously it started at 7:00. There is nothing magic about 7:16, I just moved the starting point around until I found a point where it broke the solution.

This brings up a very important point. Fix-and-hold is always going to be most vulnerable to error before it has acquired its first fix. There are things we can do to reduce this vulnerability but that will always be its weakest point. For that reason, I believe it is essential when using fix-and-hold, at least in it’s current state, to start it only on clean data where the rover is stationary and the skies are unobstructed. This would normally be done by turning the receivers on and leaving them in a fixed, open-sky position for some amount of time before letting the rover move. How long this is will depend on the quality of the antennas, whether GLONASS satellites are enabled, etc. If the data was being processed real-time, it would be easy to use an LED to indicate when fix-and-hold has locked to the data. I imagine some people are already doing this.

I’ve added this data and the configuration file I used with it to my library of data sets available here in the argeles_car folder in case anyone else wants to experiment with it.

6 thoughts on “More Moving Rover / Fixed Base Data”

  1. Hi,

    Thanks for sharing this information.
    I notice that in your command line, you have turned on USB and UART (e.g., !UBX CFG-MSG 3 15 0 1 0 1 0 0)
    I am wondering why you would use USB and UART at the same time when collecting the data.

    Also, I’m testing STRSVR with NEO-M8T and wondering if I need to also turn on both (e.g., !UBX CFG-MSG 2 21 0 1 0 1 0 0).


  2. Hi Tim,

    First, please let me congratulate on your exciting blog.

    May I kindly ask you to express your opinion on the following subjects:
    1. The effect of SNR-masking to the overall positioning (i.e. AR) reliability
    2. I am aware that you are using U-blox M8N receivers, but the slightly more pricey M8T receivers with the latest firmware can give you true GLONASS pseudoranges (as you have noticed) and also raw Galileo data (the current constellation affords two satellites to be used for most of the time). Do you think it is hard to implement a mixed GPS-Galileo AR?
    3. For post-processing, do you think the current RTKLIB algorithm squeezes all the information available (for me it seems it is just the the same realtime KF running back and forth), though double differencing may utilize data from very different epochs.

    Thank you for kind answers and please keep up the good work!



    1. Hi Marton. Good questions. I can make a few comments:

      1. I’ve played with SNR masking a little bit and found that setting the thresholds a little below the average SNRs can be effective at screening out cycle slips since the cycle slips tend to correlate with drops in the signal strength. It seems to me in its current form, though, it would need to be tuned separately for every receiver/antenna combination since SNRs will differ between them and even then I’m not sure how well it would handle normal variation between data sets. I suspect a screen based on deviation from a moving average rather than absolute thresholds might work better, but that is just speculation. Carcanague, in his thesis, did find it could be quite effective when tuned properly.

      2. I believe based on a recent comment by Tomaji on the FOSS_GPS forum that Galileo AR is already implemented in RTKLIB. It will only difference GPS satellites with other GPS satellites and Galileo satellites with other Galileo satellites however. By mixed GPS-Galileo AR, I’m not sure if you mean that or if you mean differencing GPS satellites with Galileo satellites. If you mean the latter, it might be possible using a similar technique I used for the GLONASS and SBAS satellites in my last post.

      3. RTKLIB appears to be primarily intended for real time analysis given that the only feature that takes advantage of future data is the “combined solution” method that you refer to in your question. I suspect you are right that other ways could be found to incorporate all this additional information, but haven’t looked into it at all. Even though all my examples have all been done with post-processing, that is for convenience only, I have avoided adding anything that could not be used in real time.


  3. Hi,
    Can you use Google earth check the FIX results? If you drive on the road which has 3 or 4 lanes you changes lanes during drive then map result into Google Earth. That should verify the result. Am I right?



    1. Hi Dan. I don’t know what the accuracy of the GPS positions on Google map photos are but I strongly suspect it is too coarse to resolve errors of small fractions of a meter as we are talking about here. Likewise, a lane change is large relative to a single cycle fix error for which the combined x, y, and z components could be as small as 20 cm. The lane change will only see errors in one of the three axes so the part of the fix error visible in the lane change could be even smaller than 20 cm.


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 )

Google photo

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