PPK vs RTK: A look at RTKLIB for post-processing solutions

The “RTK” in RTKLIB is an abbreviation for “Real-time Kinematics”, but RTKLIB is probably used at least as often for “PPK” or “Post-Processed Kinematics” as it is for real-time work.  In applications like precision agriculture, where the solution is part of a real-time feedback loop, RTK is obviously a requirement, but in many other applications there is no need for a real-time solution.  For example, drones are often used for collecting photographic or other sensor data but only need precision positions after the fact to process the data.  PPK is simpler than RTK because there is no need for a real-time data link between GPS receivers and so is often preferable if there is a choice.  The downside of course is that if there is something wrong with the collected data, you may not find out until it’s too late.

For the most part, RTKLIB solutions are identical regardless if they are run on real-time data (RTK) or run on previously collected data (PPK).  The most significant exception to this rule is what RTKLIB calls the “Filter Type”.  This is selected in the configuration and can be set to forward, backward, or combined.  Forward is the default and this is the only mode that can be used in real-time solutions.  In forward mode, the observation data is processed through the kalman filter in the forward direction, starting with the beginning of the data and continuing through to the end.  Backward mode is the opposite,  data is run through the filter starting with the end of the data and continuing to the beginning.  In Combined mode, the filter is run both ways and the two results are combined into a single solution.   This mode is set using the “Filter Type” box in the Options menu if using one of the GUI apps, or with the “pos1-solytpe” input parameter in the configuration file if using a CUI app.

There are two advantages to a combined solution over a forward solution.  First of all, it gives two chances to find a fix for each data point.  Let’s say there is an anomaly in the middle of the data set that causes the solution to switch from fix to float and not come back to fix for some period of time.   It may cause both the forward and backward solutions to lose fix but they will lose fix on opposite sides of the anomaly.  By combining the two solutions we are likely to get a fix for everywhere except right at the anomaly.  Another case where it often helps is in recovering the beginning of a data set.  Let’s say the first fix didn’t occur until five minutes into the data set.  With a forward solution, you would need to guarantee that nothing important happened during that five minutes, but with a combined solution, the backward pass will normally provide a fix all the way to the very beginning of the data set so there is no lost data.

The second advantage of the combined solution is that it provides an extra level of validation of the results.  To understand how this happens, it’s important to understand how RTKLIB combines the forward and reverse solutions.  For each solution position point there are three possibilities; both passes are float, one is float and one is fix, or both are fixed.  If both passes generate a float position, then the combined result will be a float with a value equal to the average of the two positions.  If one is float, and the other is fix, the float is thrown away and the fix is used.  In the case where both are fixed, then RTKLIB will attempt to validate the result by comparing the two values.  If they differ by less than four sigma, then the result will be a fix, otherwise it will be downgraded to a float.  Either way, the value will be the average of the two positions.  This degrading the solution type when the answers from opposite directions differ provides an increased confidence in the solution, at least for points for which we got two fixed values.

I will show a couple examples of the differences between forward and combined modes.  The first example is a more typical case and demonstrates how combined mode will normally give you a higher fix percentage while at the same time increasing confidence in the solution.

The plots below were taken from an M8N receiver on a sailboat using a nearby CORS station as base.  With ambiguity resolution mode set to fix-and-hold, I was able to get a solution with nearly 100% fix except for the initial convergence, but I would prefer to use continuous ambiguity resolution because of the higher confidence of the solution.  In the position plots below, the top was run in forward mode, the middle in backwards mode, and the bottom in combined mode, all in continuous ambiguity resolution mode.

combined1

As you can see the forwards and backwards mode solutions are not bad but both have gaps of float in the middle as well as floats during the initial acquisition.  The combined solution though has almost 100% fix rate and in addition includes the additional confidence knowing that every point found the same solution when running the data in opposite directions.

This second example comes from a data set posted on the Emlid Reach forum with a question on why the combined solution was worse than the forward solution.  In the plots below, the top solution is forward, the middle is backward, and the bottom is combined.

combined2

This data was GPS and SBAS only, so had a fairly low number of satellites, also included a mix of poor observations and the solution was run with full tracking gain (i.e fix-and-hold with the default gain).  Both forward and backward runs found fixed (green) solutions and tracked them all the way through the data set.  However, at least one of them was most likely a false fix, causing the fix to be downgraded to float (yellow) for most of the combined solution as can be seen be seen in the bottom plot.

To confirm this, the plot below shows the difference between the forward and backward solutions.  As you can see, the two differ by a fairly substantial amount and it is not possible from this data to know which one is correct.

combined3

In this case, turning off fix-and-hold and running ambiguity resolution in continuous mode sheds some light on what may be going on.  The plots below are again forward, backward, and combined.  This time the forward solution loses fix early on and never recovers it, whereas the backwards solution maintains a fix through the whole data set and is probably correct since without fix-and-hold enabled, it is very unlikely to stay locked that long to an incorrect solution.  The backward solution is also consistent with the beginning of the forward solution, since the combined solution remains fixed in the early part of the data set where both forward and backward solutions are fixed.

combined4

Again, this can be confirmed by looking at the difference between the forward and backward solutions.  In this case they agree everywhere that both are fixed.

combined5

As this example demonstrates, if post-processing is an option, it often makes sense to run in combined mode with continuous ambiguity resolution instead of forward mode with fix-and-hold enabled.  The additional pass will increase the chances of getting a fixed solution without the risk of locking onto a false fix that fix-and-hold can cause.  Even if you find you can not disable fix-and-hold completely, it may allow you to reduce the tracking gain (pos2-varholdamb)

So one last question is why are there still some float values in the middle of the combined solution? We would expect that since the backwards solution is fixed and the forward solution is float, that the combined solution should just become the backwards solution and all but the very end should be fixed.

The answer to this question turns out to be the way the reverse pass of the kalman filter is initialized.  I have chosen in the demo5 code to not reset the filter between forward and reverse passes if continuous ambiguity resolution is selected.  If fix-and-hold is selected then the demo5 code does re-initialize the kalman filter between passes.  This is different from the release code which always resets the filter between passes.

In this case, the results would have been slightly better if the filter were re-initialized but most of the time I find that allowing the filter to stay converged avoids a large gap in the backwards solution during the active part of the data set where the filter is reconverging. With fix-and-hold enabled I have found the chance of staying locked to an incorrect fix is too high and so it is better to reset the filter.  This is a recent change and hasn’t yet made it into the released version of demo5 but I should get it out soon.  The current version of the demo5 code (b28a) does not reset the filter for either case.

Modifying the if statement in the existing code in postpos.c to match the line below will give you the newest behavior.  Removing the if statement altogether will cause the filter to always be reset and will match the release code.

combined6

The other factor to consider when deciding whether to run the filter type in forward or combined mode is that combined mode will take nearly twice as long to run since it is processing each data point twice.  Most of the time this shouldn’t be an issue since it is not being run in real-time.

So to summarize, my recommendation would be to use combined mode if you do not need a real-time solution as the only real cost is a small amount of additional computation time and it will give you both higher fix percentages and more confidence in those fixes.

Comparison of Swift Piksi Multi to u-blox M8T

 

I recently described an experiment in which I mounted a Tersus BX306 receiver and a u-blox M8T receiver on top of a car and collected simultaneous data while driving around in a parking lot and on residential streets.

In this post I will describe a similar experiment, this time with a Swift Piksi Multi receiver and a u-blox M8T receiver.  In the previous experiment, I had to use a CORS reference station as the base station for the Tersus receiver since I did not have a second full L2 receiver to use as a local base.  I do have two Swift receivers however, so in this experiment I was able to use matched local bases for both rover receivers.  The base receivers were both connected through an antenna splitter to a single dual frequency GPS500 antenna that comes in the Piksi evaluation kit and that was mounted on the roof of my house.

The two rover antennas were both mounted on top of my car.  The Piksi was using a Tallysman 3872 dual frequency antenna and the u-blox M8T was using a Tallysman 1421 antenna, the same antennas I used in the previous Tersus/u-blox experiment.

Here are the raw observations for both rovers, M8T on the left, and Piksi on the right.  Green indicates dual frequency measurements, yellow just a single frequency.  The red ticks indicate cycle slips.  The relatively slip-free region in the middle was collected in the parking lot with very open sky views.  The data before and after this region was collected on the residential streets with more obstructed views and hence more cycle slips.

u-blox M8T                                                                         Swift Piksi

swift_m8t2

As I mentioned before in my earlier description of the Piksi receiver, it uses the new civilian L2C code rather than the standard L2 code for the L2 measurements.  This code is only available on the newer satellites, right now about half of them support it.  Also, the Piksi firmware currently supports only the GPS satellites.  In this particular data set, four of the six GPS satellites were broadcasting L2C codes which meant the Piksi is working with ten measurements from six different satellites.  The M8T, on the other hand, with GPS, GLONASS, SBAS, and Galileo enabled had 19 measurements from 19 different satellites.  In both cases, since they were matched receivers, all measurements were available for ambiguity resolution.

Like the Tersus receiver, the Swift Piksi can only process solutions real-time, it has no capability to post-process data.   I configured the Piksi receiver to save the raw measurements to a USB drive on the receiver and to save the real-time solution in NMEA format to a PC connected to the rover over the serial port.  I set up NTRIP servers for the base stations  and used a hot spot on my cell phone for the real-time data link between receivers as I described in this post.  I then compared the Swift real-time solution to RTKLIB post-processed solutions of the Swift measurements and the u-blox measurements.  I also did run the u-blox solution in real-time and believe it was nearly identical to the post-processed solution I show here but unfortunately I overwrote the solution file with a post-process run so wasn’t able to compare them directly.  I did verify that the real-time u-blox solution had nearly 100% fix before I lost it.  I also tried to re-run a simulated real-time solution with RTKNAVI using the time-tag files but unfortunately it looks like some of the recent changes ported in from the release code have broken this capability.  I need to look into this further but it looks like while attempting to fix some existing incompatibilities in the tag files between the 32 bit and 64 bit versions of RTKLIB, the 32 bit version was broken.  In theory, the real-time solution and the post-processed solutions should be nearly identical, the only difference being the slight delay of the base data over the cell-phone link, so I don’t expect this to have a significant affect on the results.

Given that the M8T has nearly twice as many measurements to work with as the Piksi, I would expect the M8T results to be better than the Piksi and that indeed is the case.  The Swift internal RTK solution did a good job when the car was in the parking lot with nearly unobstructed views as you seen in the middle plot where the zigzag section is all fixed (green).  On the residential streets, the solution bounces back and forth between fix and float.  It is interesting that when the internal solution reverts to a float solution, it becomes quite noisy relative to the RTKLIB float solution as you can see in the z-axis.  The RTKLIB solution for the Piksi data is not as good as the internal Swift solution.  This may be a combination of an imperfect match of cycle-slip definitions between Swift and RTKLIB and RTKLIB not taking full advantage of the dual-frequency measurements.

swift_m8t3

I don’t think there were any real surprises here.  Until the Piksi receiver adds firmware support for the other satellite constellations and until more GPS satellites support the L2C codes, the Swift receiver is going to have difficulty matching the results of receivers with more measurements.  In the long-term, the L2C code is a good choice, especially for moving rovers because it is a stronger signal and a more robust code than using the encrypted L2 code, but in the short term I’m not sure I would recommend this receiver, at least for this sort of application.  It is still the least expensive dual frequency receiver available as far as I know, so it may still be the right choice for other applications.

Like my previous comparison, this was all based on a single set of data and is not intended to be a comprehensive analysis, more of a first impression.  If anyone disagrees with any of this or can add more details, please respond in the comment section below.

If anybody would like to compare the data themselves, I have uploaded the data and the config files I used to process the data to the “Sample Data Set” section of my website.

New code, new gps data

I’ve just released the b28 version of the demo5 code.  It includes all of the updates in the b28 update of the official RTKLIB 2.4.3 code.  It also now supports both Tersus and Swift low cost dual frequency receivers.  The Tersus updates were part of the official 2.4.3 release although I did make a few changes to fully support the L2 measurements as well as some changes to the makefiles to get all apps to build.  The Swift receiver support is based on code I pulled from the Swift RTKLIB Github page.  I suspect the receiver specific RTKLIB code for both receivers could use some improvements in translating from the raw binary formats to the Rinex/internal observation formats but at least this is a starting point.  The executables are available from the download section at rtkexplorer.com.  The source code is available on my Github page.

I’ve also uploaded some data sets comparing the Swift Piksi Multi and the u-blox M8T as well as between the Tersus BX306 receiver and the u-blox M8T.  This data is also available from the download section at rtkexplorer.com.

 

 

Tersus/M8T moving rover comparison

In my last couple of posts I compared a u-blox M8T single frequency receiver to a Tersus BX306 dual frequency receiver for a static rover using a fairly distant CORS receiver for base data.  Both receivers had over twenty raw phase measurements, but the Tersus receiver had much better overlap with the CORS receiver with twelve measurements available for ambiguity resolution (GPS L1 and L2) while the M8T had only six (GPS L1).  Not surprisingly, the Tersus provided a much better solution than the M8T.  I also compared the RTKLIB solution and the internal Tersus RTK solution and showed that they appeared to be roughly comparable.

In this post, I will add a second M8T receiver and compare a M8T to M8T short baseline solution to the Tersus to CORS longer baseline solution.  While this may not sound like a fair comparison, it could be a reasonable choice given that two M8T receivers are still significantly less expensive than one Tersus receiver.   Also, to make things more interesting,  I will use a moving rover this time rather than a stationary one.

For the experiment, I mounted both receivers in a car, each with it’s own antenna on the roof.  Given that we are making a comparison to a relatively expensive solution I felt it wouldn’t be unreasonable to add $20 to the M8T solution and upgraded its antenna from the standard $20 u-blox antenna I usually use to a Tallysman 1421 antenna available at Digikey for $42.   For the Tersus receiver I used a Tallysman dual frequency 3872 antenna which I believe is roughly a $200 antenna.  For the M8T base station, I used the same antenna on my house roof as in the previous experiment which gave a baseline less than 1 km for most of the M8T pair solution whereas the Tersus/CORS baseline was roughly 16-18 km.  For RTKLIB post-processing, I also ran a solution using base data from the nearest CORS station which gave a baseline of 7-9 km but I couldn’t use this data for the Tersus internal RTK solution because it is not available real-time.   Also, it should be noted that I collected all this data a few weeks ago before Tersus released their most recent firmware so it was all done using their previous version.

I chose a driving route very similar to the one I used for this M8N to M8T comparison in which I drive through a residential neighborhood with a moderate tree canopy.  This time I added a section of the route in a parking lot with no tree obstructions.  The parking lot is intended to be a low-stress environment and the neighborhood streets a moderate-stress environment.  Here’s a Google Earth image of the previous route to give a feel for the terrain.  Unfortunately this map feature no longer works in RTKLIB because Google has discontinued the API to Google Earth.

 

walker1

In this case the M8T  was receiving signals from the GPS, GLONASS, SBAS, and Galileo satellites and started the data set with a total of 21 phase measurements.  All of these can be used for ambiguity resolution since the two receivers are identical hardware.   The Tersus receiver measured only GPS and GLONASS but for all but a couple of satellites got both an L1 and an L2 measurement.  It started the data set with 24 phase measurements of which I would expect that only the 14 GPS phase measurements are available for ambiguity resolution because the receivers are not identical.

The previous time I ran this experiment I was able to get a nearly 100% fix solution from both the M8N and the M8T  receiver pairs but had to use some solution tracking gain (fix-and-hold) to achieve that.

In this case, with the extra Galileo satellites and the more expensive antenna, I was able to get nearly 100% fix using continuous ambiguity resolution instead of fix-and-hold. Continuous AR has the advantage of reducing the chances of locking to a false fix and is normally a preferrable solution if it is achievable.  The only float part of the solution was at the very end of the route where I parked the car underneath a large tree.

Here are three versions of the M8T receiver pair solution all run with continuous ambiguity resolution.  In all the plots, green is a fixed solution and yellow is a float solution.  The top left solution was run with 5 Hz measurements which is what I normally use for moving rovers.  I then realized that the Tersus data was only 1 Hz, so I re-ran the M8T solution after decimating the raw data down to 1 Hz (the latest Tersus firmware supports 5 Hz RTK solution).  The decimation can sometimes cause problems because the cycle slips aren’t always handled properly in the decimated data but in this case it seemed to work fine as can be seen in the plot on the top right.   The only noticeable difference is that the 1 sec data took a little longer to get to first fix.  This is less important in post-processed solutions because the solution can always be run in combined (forward/backward) mode which will usually get a fix for the beginning of the data.  This can be seen here in the bottom left solution which was run in combined mode.

ter_kin1

The zig-zag line from 21:22 to 21:26 is the lower stress circles in the parking lot followed by the moderate stress route through the residential neighborhood.

Next, let’s look at the Tersus solutions.  The internal Tersus RTK solution was run with the Tersus default settings.  The user interface for the Tersus console app is much simpler than RTKLIB so there are many fewer options to play with.  For most users this is probably an advantage because it avoids the rather overwhelming array of options that RTKLIB gives.   The RTKLIB solution was run with continuous ambiguity resolution with settings very similar to the M8T solution, just adjusted for dual frequency.  The internal solution is on the left and the RTKLIB solution on the right.

ter_kin2

The two solutions are fairly similar, both did well in the lower stress parking lot environment but struggled with the moderate stress on the residential streets.  The internal solution did a little better with scattered fixes in the latter part of the data.

Comparing differences between the internal and RTKLIB solutions and between the Tersus and M8T solutions for only the fixed points, it looks like most of the errors between the different solutions when they have a fix are small.  The Tersus/M8T differences are indicated by the distance from the circle as I have described before. I’m not too worried about the DC offsets between them.  It is somewhat tricky to get all the offsets correct and I did not spend a lot of time on that.  It is likely to be a issue with coordinate differences or handling of antenna offsets that explains the DC shifts.

ter_kin4

The above Tersus RTKLIB solutions were run with only GPS ambiguity resolution as I would not expect the GLONASS measurements to be useful for ambiguity resolution because of the inter-channel bias differences between the non-identical receivers.  However I was surprised to find that I did get fixes with the GLONASS ambiguity resolution set to “On” in the RTKLIB configuration file.  The solution was slightly worse than the GPS-only AR but I did verify that the GLONASS satellites were included in the ambiguity resolution.  I’m not quite sure what to make of this observation, whether or not it makes sense to include the GLONASS measurements in the ambiguity resolution, but I suspect it makes sense to leave them out for the reason mentioned above.

ter_kin5

I then ran another RTKLIB post-processed solution using the Tersus and base station data from a closer CORS base station.  This was to see how reducing the baseline affected the answer.  Here’s the result from a base station that is only 7-9 km away.

ter_kin6

Even though we reduced the baseline by a factor of two the solution only got slightly better and time to first fix actually increased.  This suggests that the long baseline may not be the primary reason for the poorer Tersus solution.

My suspicion is that it is a combination of two things,  at least for the RTKLIB solutions.  First of all I believe there is a mismatch between how RTKLIB interprets a cycle slip flag and how the cycle slip flag is defined in the Rinex spec.  The problem is that RTKLIB resets the phase bias estimate in the same epoch as the cycle slip is logged regardless of whether the receiver has had time to relock or not.  This can cause large errors in the bias estimates if the receiver flags a cycle slip before it has recovered from it.  In some of my earlier posts I have described having the same problem with the M8T receiver but in that case I have made some changes in the u-blox specific RTKLIB code to delay the cycle slips until the receiver has re-locked.  Something similar may need to be done for other RTKLIB receiver specific code  including the Tersus or it may be possible to modify the main RTKLIB code to better interpret these cycle slip flags.

Maybe more important, though, is the difference in the measurements between the two receivers.  As mentioned before, the M8T receiver has 21 phase measurements all of which can be used for ambiguity resolution while the Tersus has 24 of which only 14 can be used for ambiguity resolution assuming we don’ t try and use the GLONASS satellites.  Note, though, that there are only seven different satellite-receiver paths for the Tersus since each satellite is providing two measurements.  This compares to the 21 satellite-receiver paths for the M8T receiver where each satellite only provides a single measurement.  Now imagine that the receivers are under a partial tree canopy and four of the satellites are obstructed for both receivers.   The M8T will lose four measurements and still have 17 to work with but the Tersus receiver will lose 8 measurements and only have six to work with.  This is a significant disadvantage and I suspect can explain a large part of the difference in results.

If I had used a local Tersus base station, then the matched Tersus receiver pair would enable use of the GLONASS satellites for ambiguity resolution.  In the case of four obstructed satellites, the two cases would be much more similar with 17 available measurements for the M8T and 16 for the Tersus.  As more satellites were obstructed the M8T would start to gain a bigger advantage since the Tersus would lose two measurements for each obstructed satellite and the M8T would only lose one.  Of course the M8T would tend to have more obstructed satellites than the Tersus since it has more satellites to start with that can be obstructed.  That would work in favor of the Tersus reciever.  It’s hard to say which would give a better solution but my suspicion would be that if the cycle slip handling issue in RTKLIB was fixed the two solutions would be fairly similar when calculated with RTKLIB.  I don’t know enough about the internal Tersus RTK engine to predict how it would do.  Hopefully I can get my hands on a second full dual frequency receiver and run this experiment soon.

Although I ran this experiment at a random time without looking at the satellite alignment first, it may be that the satellite alignment was such that it accentuated this effect.  Note in the observations (Tersus on the top, M8T on the bottom) that the Galileo (Exx) and SBAS (Ixx) satellites have less cycle slips than any of the other satellites.

ter_kin7

Looking at the skyplot for those observations we see that three of the four Galileo satellites are at very high elevations which will tend to be blocked less from nearby trees. This would have helped the M8T solution since the Tersus receiver did not have access to these high elevation satellites.

ter_kin8

I will try to summarize what I think this data suggests but let me first emphasize that this is by no means intended to be any sort of rigorous analysis.  I don’t have the time, resources or knowledge to do that.  Instead, please take these as no more than the sharing of my thought process as I try to understand some of the differences between single and dual frequency RTK solutions.

Rover to CORS or other traditional dual frequency receiver:  Tersus has a significant advantage over the M8T both because of more matched measurements and opportunities to take advantage of the nature of the dual frequency measurements.  This advantage applies both to the RTKLIB solution and the Tersus solution although I suspect the Tersus solution takes better advantage of the dual-frequency measurements.  The advantage also increases as the baseline increases.

Matched pair of receivers with short baseline:  Good results with the RTKLIB solution will be limited to low stress environments for a pair of Tersus receivers because of limitations in the cycle slip flag handling.   With the M8N and M8T, RTKLIB can also handle moderate stress environments because of receiver specific changes in the RTKLIB cycle slip handling code.   Relative to a Tersus/CORS combination, the M8T matched pair solution will in general be superior for short baselines because of more matched measurements.

Matched pair of receivers with long baseline:  The data in this experiment doesn’t cover this case but as the baseline increases the dual frequency receiver pair should have a greater advantage because of the additional information that can be derived from the dual frequency measurements.

From a cost trade-off perspective, this suggests that the ideal way to combine these receivers might be to build the base with both an M8T single frequency receiver and a Tersus dual frequency receiver, both sharing a single antenna.  The rover would then be a second M8T receiver.  This would give the advantage of the dual frequency receiver for locating the absolute position of the base using long baseline solutions to distant reference stations or even PPP solutions while taking advantage of the matched pair of lower cost receivers for the moving rover piece of the solution.

 

Corrections to last post

Turns out there was a significant error in the experiment I posted yesterday.

For the base station data for the post-processed RTKLIB solution I had downloaded a RINEX file from the CORS website.  This contained only GPS data, and there was no option to request GLONASS measurements, so I had assumed this receiver only supports GPS measurements.  It turns out though, that the real-time stream from the UNAVCO NTRIP server for the same receiver includes GLONASS measurements as well as GPS.

So, when I compared the Tersus real-time solution to the RTKLIB post-processed solution, the Tersus solution included double-differences for the GLONASS satellites while the RTKLIB solution did not.  This caused me to conclude that the Tersus solution algorithm was better than RTKLIB when really it just had more measurements to work with.

The extra GLONASS measurements won’t change the number of measurements used for ambiguity resolution, at least for RTKLIB, since the inter-channel biases prevent the GLONASS measurements being used for ambiguity resolution unless the base and rover receivers are using identical hardware.  They do, however, increase the number of double differences used for the float solution which will help indirectly with ambiguity resolution.

Fortunately I was able to download a RINEX file from the UNAVCO website which included the GLONASS measurements and re-run the RTKLIB solution with that data.  In this case, the two solutions look much more similar.

Here is a comparison of the initial time-to-fix and the following six times-to-fix after the antenna obstructions.  Yellow/green is Tersus, olive/blue is RTKLIB.  The Tersus initial acquire is still noticeably faster than the RTKLIB initial acquire but five of six of the RTKLIB re-acquires are faster than the Tersus re-acquires.  Of course, time-to-fix by itself is not a very good metric because it does not take into account what level of confidence is required by the two solutions before asserting a fix.

ter_static8

Here is a zoom-in of the higher frequency, smaller amplitude differences.  Again, the two solutions look much more similar than they previously did.  As I mentioned before, I believe the DC offsets are probably caused by me not paying close attention to the various offsets in the setup.  The variation in the z-axis is larger than I am used to seeing and presumably comes from the long baseline.

ter_static6

At this point, the two solutions look similar enough that with this limited amount of data, it is difficult to say one is better than the other.   That doesn’t mean they are equal, just that I don’t believe this particular experiment can differentiate between them with any confidence.

Part of the original experiment was to compare the Tersus data to the M8T data.  Adding the extra GLONASS base measurements did not appreciably change the M8T solution so the conclusions from that part of the experiment don’t change.  The Tersus data with 12 satellite pairs available for ambiguity resolution was still significantly better than the M8T data with only six satellite pairs.

So, maybe I was a little hard on RTKLIB a couple of posts ago when I first looked at it’s dual frequency capabilities.  Intuitively it still feels to me that there should be some advantage in explicitly using knowledge of the physical relationship between the dual frequency measurements in the ambiguity resolution but the data supports the commentors who argued otherwise.

 

RTKLIB with a Tersus BX306 dual frequency receiver

[Update 6/27/17:  There is a significant error in the data in this post.  I used the RINEX files from the CORS website for the base station data for the post-processing solutions described below. These contain only GPS data.  However, the real-time stream I used from UNAVCO for the same receiver contains GLONASS observations as well.  I did not realize this when I compared the Tersus real-time solution to the RTKLIB post-processed solution and concluded that the Tersus solution was better than the RTKLIB solution.  Once I re-processed the RTKLIB solution with the GLONASS measurements, the two solutions were much more similar.  See the following post for more details]

Last post I finished up by comparing some raw observation data collected from a moving rover with both Tersus and Swift receivers.  Before analyzing that data I will start with some static data collected simultaneously with the Tersus receiver and a u-blox M8T, both connected to a dual frequency antenna through a signal splitter.

I’d like to compare the RTKLIB solution for the Tersus data with the solution from the internal Tersus RTK engine as well as compare solutions for the Tersus data to solutions with the u-blox M8T data.  Since Tersus does not provide any post-processing tools I needed to run the experiment in real-time.  For the base data I used the closest available CORS station with real-time data access.  This was a GPS only station located 17 km from my home.  This makes it a fairly challenging exercise both because of the long distance between receivers and the small number of base station measurements.

The Tersus receiver does not offer a configuration setting for static or kinematic mode, it always assumes the receiver may be moving.  To put both receivers on equal footing, I also set up RTKLIB for a kinematic solution with continuous ambiguity resolution .  Therefore, although the rover was not actually moving, neither the internal Tersus RTK engine or RTKLIB knew this, and both treated it as if it were a moving rover.  To make the experiment more interesting, I intentionally obstructed the antenna view fairly severely every few minutes to simulate a rover passing under a heavy tree canopy or other obstruction.   I did this because I wanted to compare how well the RTKLIB and internal solutions recovered from losing a fix.

In addition, the location of the “rover” antenna was not ideal.  It was located on one edge of a low angle sloping roof.  This meant partial blockage from the roof as well as a few nearby trees and probable multipath from a few metal vents on the roof.  As always, I choose non-ideal conditions to add stress to the solution and make it more representative of real-world conditions.

Here are the raw observations, M8T above and Tersus below (yellow are single freq measurements, green are dual freq)

ter_static1

I show only the GPS observations since they are the only ones with matching observations in the base station data and hence the only ones that double differences can be calculated for.  At the beginning of the data set, the M8T has six GPS observations (all L1) and the Tersus has twelve (L1+L2).  The points where I obstructed the antenna are obvious in both data sets from the cycle slips.  The additional cycle slips seen in the Tersus data occur on the L2 observations for the most part.

First let’s look at the M8T RTKLIB solution.  With only six double difference observations and a 17 km baseline, the opportunity to resolve the ambiguities is just too limited and nearly the entire solution is float rather than fix.  In some similar data sets the solution may be better than this, but in general I find when using only the L1 GPS satellites there is very little margin and the results can vary tremendously from run to run.

ter_static4

 

Here are the solutions for the Tersus receiver.  Yellow/Green is the internal solution and Olive/Blue is the RTKLIB solution.  They are both significantly better than the M8T solution with fixes acquired reasonably quickly then broken by the antenna obstructions, followed by a re-acquire.

ter_static3

 

In this case having 12 double-differenceable observations to work with instead of 6 makes a huge difference, and for this particular comparison, there doesn’t seem any point in spending more time examining the M8T solution.

What is more interesting is the differences between the internal solution and the RTKLIB solution.   The Tersus advertises a 60 second time to first fix and most of the time, it achieved that easily even with the long baseline, significantly outperforming the RTKLIB solution which often took two minutes or more to recover. In the worst case however, (around 1:00 in the above plot), RTKLIB did significantly better than the internal solution acquiring a fix in just over two minutes while the internal solution required over eight.  I think this must be a glitch in the Tersus firmware.  For this excercise I used the new firmware just released last week but it does not appear to be perfect yet.  They acknowledge that they are still maturing the firmware and it should improve with time.  I don’t know what they are doing differently in their internal solution from the RTKLIB solution that gives them significantly faster re-acquire times, but if I had to guess, I would suspect that they are taking better advantage of the dual frequency measurements as I discussed in my previous post.

Here is a zoom in of the previous plot showing some of the higher frequency smaller amplitude differences.  I don’t believe the small DC offsets are significant, they most likely come from me not paying close attention to the various offsets in the setup.  Notice that the Tersus solution often loses fix momentarily where the RTKLIB solution stays fixed.  This may just be a more conservative approach in the Tersus solution to declaring a fix.  The momentary float values do not appear to add much error to the solution.

ter_static2

The above example was done with a fairly distant reference station to meet our requirement for real-time base station data. What if we don’t need real-time?  There are many more CORS stations available for post-processing than real-time so that often means being able to use a closer base station, maybe one that is more likely to have GLONASS satellites as well.  In my case, the closest CORS station is only 7 km away and does have GLONASS measurements as well as GPS.  The receivers are not identical so the GLONASS measurements can only be used for the float solution, not for ambiguity resolution, but they should still help some.  Here are the results using that base station.  Yellow/Green is the Tersus RTKLIB solution and Olive/Blue is the M8T RTKLIB solution.

ter_static5

Clearly more satellites and shorter baselines helps.  At this point the Tersus solution is still better than the M8T solution but the difference is not as dramatic.

So to summarize, this one example suggests that given the case of a single local receiver working with a distant reference station, there could be a significant advantage in using a Tersus dual-frequency receiver over a u-blox M8T single frequency receiver and that there is also an advantage in using the internal real-time RTK solution over the RTKLIB solution.  Part of this advantage is simply because the satellite set that the dual frequency receiver uses (L1+L2) better matches what is available from the reference stations and allows for more double difference pairs.

It would be unwise to conclude too much from this one example but hopefully it at least provides a little insight in how the two receivers and the two RTK engines differ.

So this example was a comparison between one dual frequency receiver and one single frequency receiver, both paired with a fairly distant base station.  In the next post I will compare a pair of matched local single frequency receivers to the same dual frequency receiver again paired with a fairly distant base.

A first look at RTKLIB with dual frequency receivers

As I mentioned in my last couple of posts, I have recently been exploring the use of RTKLIB with a couple of different low-cost dual frequency receivers.  Low-cost is a relative term here.  At $600 to $1700 for the receivers, plus the cost of the antenna, these configurations are significantly more expensive than the u-blox based single frequency versions I usually work with.  Still, they are quite a bit less expensive than models from the more traditional manufacturers.

The first receiver I have is a Piksi Multi from Swift Navigation.

piksi-multi-032817

It is available from their website for $595 for the receiver board, or $1995 for a complete evaluation kit including two receivers, antennas, and radios.  This receiver relies on the new L2C codes for the second (L2) frequency and so does not support the traditional P2 codes.  L2C is an unencrypted code that is only available on the newer GPS satellites.  Roughly half the GPS satellites are currently broadcasting these codes but this number will increase as newer satellites are launched.  This does mean that the Multi can only make dual frequency measurements on the satellites that have L2C capability.  Also, although the receiver hardware is capable of supporting GLONASS G1/G2, BeiDou B1/B2, Galileo E1/E5b, QZSS L1/L2 and SBAS signals, these constellations are not supported in the current firmware.  This means that the current capability of this receiver is somewhat limited, but it should improve as they release new firmware and more satellites are launched.

The second receiver I have been evaluating is a more expensive option, the Precis-BX306 from Tersus which is available from their website for $1699.

BX306 (2)

 

This receiver does support the P2 codes on the L2 frequency and therefore is able to receive dual frequency signals from all the GPS satellites.  It also supports Glonass G1/G2 and Beidou B1/B2 in the current hardware and firmware.  Tersus also has similar receivers that are less expensive but also less capable than this one.  The Precis-BX305 fully supports GPS L1/L2 but only has support for GLONASS G1 and Beidou B1/B3.  The Precis-BX316R supports all the same constellations as the BX306 but only provides raw measurements, it has no internal RTK engine.  Both of these models sell for $999.

In the spirit of full disclosure, I should mention that Tersus gave me the BX306 receiver to evaluate and one of my consulting clients gave me permission to use their Piksi Multi receiver for this evaluation.  I appreciate both of them for their generosity.

Before digging into the details of the receivers, it’s worth first discussing what the advantages of a dual frequency receiver are over a single frequency receiver and also to what extent RTKLIB is capable of exploiting these advantages.  All of this is fairly new to me so the following analysis is based on my somewhat limited understanding.  If I get anything wrong, I am hoping one of my more experienced readers will jump in and correct me.

The most obvious advantage of the dual frequency receiver is that it provides more measurements than the single frequency receiver for the same satellite constellation.  However, if this were the only advantage, then the Piksi Multi, with GPS support only, would still be less capable than the u-blox M8T when the additional GLONASS, SBAS, and Galileo measurements are all taken into account.  Dual frequency receivers do also tend to have more high-end circuitry and tend to be paired with more expensive antennas.

The biggest advantage, though, comes from having multiple measurement of the same path through the atmosphere made with different frequencies.  Using linear combinations of these pairs of measurements in different ways we can glean information that is just not available with the single frequency measurements.  Two linear combinations that are particularly useful are the ionosphere-free combination and the wide lane combination.

The ionosphere-free combination takes advantage of the fact that the ionospheric delay is inversely proportional to the square of the frequency.  By taking the difference of the squares of the two phase measurements,  more than 99% of the ionospheric delay error can be eliminated.  The ionosphere-free combination provides the ability to deal with much longer baselines between the two receivers and also makes possible accurate PPP measurements.

The wide lane combination is simply the difference of the phase measurements made at the two frequencies and the advantage of this combination is that the effective wavelength of this measurement is a function of the difference in frequencies between the two measurements.  In the L1/L2 case, the difference in frequencies is 348 Mhz and the wavelength is 86 cms.  Resolving integer cycle ambiguities over an 86 cm cycle is significantly easier than resolving them over the much shorter L1 wavelength of 19 cm, the only option available with the single frequency receivers.  Once the wide lane ambiguities have been resolved, they can be used to assist in resolving the shorter cycle L1 and L2 ambiguities.  This can lead to much faster times to first fix with the dual frequency receivers.

Of course, these additional opportunities are only valuable if the solution algorithm takes advantage of them.  Unfortunately RTKLIB appears to be quite disappointing in this regard.  For the most part, the default configuration of RTKLIB for RTK handles the two frequency measurements independently and takes very little advantage of the linear combinations.  This makes them no more valuable than if they were two measurements from different satellites.  There is an option to enable ionosphere free combinations (pos1-ionoopt =dual-freq) in the config file which uses the ionosphere-free combinations to estimate the phase biases instead of the individual measurements.  The user manual indicates, though, that the ionosphere-free model is not applied for the RTK solution modes and I have found that setting this option when running an RTK solution breaks the ambiguity resolution.  There is also an option in the code for a wide lane ambiguity resolution but this option is not mentioned in the user manual and if set it attempts to call an external function that is not included with the RTKLIB source code.  There may be a little more support for dual frequency in the PPP solution modes.  However, the current RTKLIB version does not make any attempt at ambiguity resolution in the PPP modes.  The 2.4.2 release of RTKLIB does include what the manual describes as a beta version of ambiguity resolution but that has been removed in the 2.4.3 release.  Without ambiguity resolution, my experience with PPP solutions has been that I can get much better solutions using some of the free online PPP services that do use ambiguity resolution than I can get with RTKLIB.  I am hoping someone can prove me wrong and provide a config file that generates an RTK or PPP solution with RTKLIB that takes full advantage of the linear combinations of the dual frequency measurements but from everything I can see, there is not much code to support this capability.

Fortunately, both receivers do include the capability to calculate their own RTK solutions without RTKLIB.    So the goal in the following experiments will be to both compare the two receivers against an M8T single frequency receiver and also to compare their internal solutions to the RTKLIB solutions.  Unfortunately, neither receiver is set up to handle the post-processing of previously collected measurements and so all of the internal RTK solutions need to be done in real-time.  In my last post I described how I configured the receivers to receive real-time base station data over a cell phone link.

So, let’s start by taking a look at some actual measurement data.

Here is a set of measurement observations collected simultaneously from two receivers on a moving car.  The observations on the left are from a u-blox M8T receiver and on the right are from the Tersus receiver.  Satellites with lock to L1 only are indicated in yellow, those locked to L1 and L2 are in green.

tersus_obs

At the start of the data set, the M8T is locked to 8 GPS, 7 Glonass, 4 Galileo satellites, and 3 SBAS, for a total of 21 measurements.  The Tersus receiver is locked to 8 GPS L1, 7 GPS L2, 6 Glonass L1 and 5 Glonass L2 for a total of 26 measurements.  The greater number of satellites should give the Tersus an advantage over the M8T even before considering the extra advantages of the L1/L2 combinations or the more expensive electronics and antenna.

Here is a similar set of data.  The M8T receiver is on the left again, this time the Swift is on the right.  Again yellow is a single frequency measurement, green is for measurements at two frequencies.

 

swift_obs This time there were a few less satellites in the sky.  At the start of the data set the M8T is locked to 7 GPS, 7 Glonass, 2 Galileo, and 3 SBAS for a total of 19 measurements.  The Swift receiver has 6 GPS L1, and 4 GPS L2 for a total of only 10 measurements.  Particularly for RTKLIB which does not take advantage of the extra information in the L1/L2 combinations, it will be difficult to make up for the small number of measurements.

As mentioned before, this should improve as Swift releases firmware to support GLONASS, BeiDou, Galileo, QZSS, and SBAS, and as more GPS satellites are launched with L2C capability.

In my next post I will compare solutions generated with these different measurements, both from RTKLIB and from the internal RTK engines.