Using RTKLIB to process ComNav receiver data

Previously I collected some data with a pair of ComNav K708 receivers and compared the internal real-time ComNav position solution with a real-time RTKLIB solution from a pair of u-blox M8T receivers.  The results showed, at least for the moving rover case, that the two were quite similar.  In this post I will post-process the ComNav raw data with RTKLIB and compare the results both to the internal ComNav solution and the M8T post-processed RTKLIB solution .  The ComNav receiver configured to sell for sub-$1000 is setup to receive only GPS and GLONASS L1 and L2 frequencies so this is how I ran this test.  The M8T will also receive Galileo and SBAS satellites so I included these in the M8T solutions.

RTKLIB is not able to directly process raw binary ComNav data, but I had configured the receivers to output the raw data in RTCM3, then converted this to Rinex using RTKCONV, so this was not a problem.

Before we can get a solution however, we need to deal with the issue that the ComNav GPS L2 observations are a mix of L2 and L2C as seen in the RINEX observation data below.

comnav4

RTKLIB handles multiple code types for the same frequency like this by choosing the code with higher priority as set in the code priority table in rtkcmn.c.  Unfortunately this choice is made for the full data set, not each individual observation, so the lower priority observations are thrown out even for epochs when the higher priority code observations are not present.  There is an option in the ComNav configuration to force all observations to L2 and this would have been one solution to the problem.  However, in theory, the L2C code should be more robust than the L2 code, so using L2C when we have the option as the ComNav default setup does is probably the right choice.

I was not able to find any simple fix for the RTKLIB code or configuration that would allow it to process both observation types so I simply edited the list of observation types in the RINEX file headers and changed “C2X L2X S2X” in the list to “C2W L2W S2W”.  With this change, all the observations are now described as L2 and none will be thrown out.  It would be a problem if we were mixing L2 observations from the rover with L2C observations from the base, but since both will be consistently L2 or L2C, the differences should cancel, and this should not cause any significant errors in the solution.

I looked at three data sets, all from a moving rover with a local base station.  The first data set is configured as described in my earlier post, with both the M8T and the ComNav rover receivers sharing the same antenna.  In the second two data sets, the rovers are connected to separate antennas. I ran with continuous ambiguity resolution set and GLONASS ambiguity resolution enabled for all solutions.  The only change I made from the default ComNav config settings was to change the “rtkquality” setting from “quick” to “normal” since I had trouble with false fixes when it was set to”quick”.

First of all, let’s compare the ComNav internal solution to the ComNav RTKLIB solution.  Here’s the internal solution on the left, and the RTKLIB solution on the right.  In this case RTKLIB had a little higher fix rate at 76.8% vs the internal solution at 68.8%.

comnav8

What I found more surprising was that the internal solution did not stay fixed for the circles I drove in the parking lot from  23:37 to  23:40.  Normally I rarely have trouble maintaining 100% fix for this part of the route since there are very few trees here and the sky views are almost 100%.

Here’s a comparison of the difference between the two solutions.

comnav9

I expect the difference to be near zero for all fixed sections and for the most part this is true.  There is an exception though between  23:32 and 23:33.   I don’t have an absolute reference to compare to so I can’t be absolutely certain which is correct and which is in error.  However I can compare to the M8T solution and in this case the ComNav RTKLIB solution nearly exactly matches the M8T solution so I am fairly certain that it is the internal ComNav solution that is wrong.  This error is fairly large and is most likely caused by a false fix.  Also, in general, the error in the U-D axis is fairly large in both cases relative to what I am used to, but is worse in the COMNAV internal solution.  Below is the difference between the RTKLIB u-blox and RTKLIB ComNav solutions on the left, and the difference between the RTKLIB u-blox and internal ComNav solutions on the right, both for the U-D axis only.

comnav10

Here is the M8T RTKLIB solution for comparison.  Fix rate was 81.8%, just slightly higher than the ComNav RTKLIB solution.

comnav12

One advantage of post-processing the data over a real-time solution is that solutions can be run in combined mode where the result is a combination of running the solution through the kalman filter forwards and backwards.  Here’s the combined mode results, ComNav on the left, and M8T on the right.

comnav11

In this case both solutions were near 100% fix.  ComNav does sell post-processing software that would probably also let you do the same thing but I do not have a copy of it and don’t know how much it cost.

The results for the second two data sets with separate antennas showed similar differences to this one so I’ll include the plots here but won’t go into any detailed analysis.  In both sets of plots, the left is the ComNav internal solution, the middle is the ComNav RTKLIB solution, and the right is the M8T RTKLIB solution.

comnav13

comnav14

The biggest difference in these two data sets is that the M8T results were slightly worse relative to the ComNav results than in the above example but this is most likely because the antennas were separate and I used a low-cost single feed L1 antenna instead of the higher performance dual feed L1 antenna I prefer to use in these comparisons.  There is a good description here of why the dual-feed antenna should give better results.

It is always dangerous to conclude too much from a single experiment but this data does support what I have found in my other single frequency to dual frequency comparisons.  For short baselines with a pair of matched receivers and moving rovers, an L1+L2 GPS/GLONASS solution tends to be similar in performance to a L1-only GPS/GLONASS/SBAS/Galileo solution.   I expect this would be less true for longer baselines and stationary receivers.

Advertisements

Using SBAS satellites with RTKLIB

I’ve had a few SBAS related questions and issues crop up recently so I thought it would make a good topic for a post.  There are a few tips and tricks to using the SBAS satellites in RTKLIB solutions.   I will try to cover the ones I know about here.

SBAS is short for “Satellite Based Augmentation Systems”.  For anyone not familiar with the details, there is a good description of them at Navipedia.  Different parts of the world use different SBAS systems.  In this post I will focus on the WAAS system over North America and the EGNOS system over Europe but the basic ideas should apply to any SBAS system.

First of all, it’s important to understand that the SBAS satellites can be used by RTKLIB in two fundamentally different ways.  One is to use the correction information transmitted by the SBAS satellites to reduce ephemeris, clock, and atmospheric errors.   The other is to use the pseudorange and carrier phase observations from the SBAS satellites as additional measurements.

The correction information is contained in encoded messages from the SBAS satellites.  These messages can be translated from the raw receiver binary file into an *.sbs file using RTKCONV or CONVBIN if working with post-processed solutions or they are available in the raw binary receiver output if working with real-time solutions.  The pseudorange and carrier phase observations are generated for the SBAS satellites from the raw signals just as they are for the other satellites.

Usually in RTKLIB, at least for short baseline RTK solutions, the ephemeris, clock, and atmospheric data come from the broadcast messages provided by the non-SBAS satellites.  The solution sources for this information is selected in RTKLIB with the “pos1-sateph”,  “pos1-ionoopt” and “pos1-tropopt” input parameters.  If “sbas” is chosen for any of these options, then RTKLIB must have access to the SBAS messages.  For post-processing this means that the *.sbs file must be specified in the command line or configuration settings, for real-time solutions it should be available if the receiver is locked to the SBAS satellites and outputting the SBAS messages.

For short baselines, differencing will eliminate most of the errors and there will be little or no advantage to including the SBAS corrections to the broadcast data.  For longer baselines, error cancellation will not be as complete, and there will be an advantage in using the SBAS corrections to directly remove the errors.  However, for the most part, SBAS provides corrections for the GPS satellites only, not for any of the other constellations.  In addition, RTKLIB will not allow use of a mix of corrected and uncorrected observations.  This means that enabling SBAS ephemeris corrections will cause the solution to ignore all non-GPS satellites, usually resulting in a poorer solution, not a better one.

As a general practice, it is always a good idea to look at the measurement residuals with RTKPLOT to quickly verify which satellites were used in a solution and more important, which were not.  The residuals information is in the “out.pos.stat” file.  If you don’t see the “Residuals” option in RTKPLOT or don’t have this file in your output directory then that most likely means that you did not have residuals enabled in your output options.  In this case, another way to verify you did not lose any satellites is to compare RTKPLOT plots of the “number of valid satellites” before and after enabling one of the SBAS options.  By the way, this problem also occurs when using precise ephemeris data downloaded from IGS or other online sources if it does not include data for all of the constellations used in the solution.

I don’t know exactly why RTKLIB doesn’t allow a mix of corrected and uncorrected observations but I suspect that biases between the corrected and uncorrected observations may degrade the solution.

Since I always include all available constellations in my solutions and tend to work with short baselines I have generally not found the SBAS corrections to be particularly useful.  The one exception is for RTKLIB PPP solutions where precise data is very important and SBAS is an easy way to get relatively precise information, especially if internet access is not available (Thanks to JB for pointing this out in a comment to one of my recent posts).

The other way to use the SBAS satellites in RTKLIB solutions is to include their pseudorange and carrier phase measurements in the solution in the same way they are used for the non-SBAS satellites.  The SBAS observations may not be quite as accurate as the other satellites but this is taken into account by the weighting factors RTKLIB uses for measurements from different constellations.  The extra measurements will increase the robustness of the solution, particularly in the case of a moving rover where many satellites may be unusable due to cycle slips.  To enable the SBAS observations to be included in the solution, check the SBAS box in RTKPOST or set bit1 in the “pos1=navsys” input parameter.  I almost always enable this option in my solutions and would recommend others do the same if possible.

This works for the SBAS satellites over North America (WAAS) but unfortunately does not work for the SBAS satellites over Europe (EGNOS).  The EGNOS satellites are marked as unhealthy in their ephemeris data and so RTKLIB ignores them.  In theory, a solution containing EGNOS observations should be identical with SBAS satellites enabled or disabled since RTKLIB is supposed to ignore the unhealthy satellites.  Unfortunately this is not quite true, and RTKLIB does not entirely ignore them.  I think this is a bug rather than a feature but have not looked into the details.  Specifically though, I see that the unhealthy satellites affect the initial phase bias estimates of all the other satellites.  Whenever I find bugs like this, I am always concerned that they are something I have introduced into the demo5 code with my changes, so I always rerun the solution with the 2.4.3 release code.  In this case, I see the same bug (but worse) in the release code.  Here is a comparison of the difference between two solutions for a data set that includes EGNOS observations, one with SBAS enabled, and one with it disabled.   The left plot is for the 2.4.3 release code and the right plot is the demo5 code.  Only GPS satellites are enabled and ambiguity resolution is disabled in both cases to simplify the comparison.

egnosErr

In both cases, enabling the EGNOS satellites caused a transient at 13:06 but as you can see the transient is much larger in the release code.  Both are undesirable though and it is important to turn off SBAS observations in the solution if your receivers are tracking EGNOS satellites no matter which code you are using.  In this particular example, even with the smaller transients in the demo5 code, they were large enough to cause a false fix when ambiguity resolution was enabled.

Since I am located in the U.S. I don’t work much with EGNOS observations but I was curious to understand why they are not usable.  Doing a little research online, I found multiple references to using ranging observations from EGNOS satellites.  Some said it was not possible to use them and others said that if you ignore the unhealthy flag they will work fine.

It turns out that RTKLIB has an option to force unhealthy satellites to be used in the solution.  It is not exactly intuitive, as you force a satellite to be included by putting it in the list of excluded satellites with a”+” in front of the satellite number, but this is documented in the user manual.

The data set above had observations from only one EGNOS satellite but the SBAS satellites are differenced with the GPS satellites so this shouldn’t be an issue.  I went ahead and forced this satellite to be included and re-ran the solution.  Here is the result.  This time I plotted both solutions on top of each other, one in which SBAS observations are disabled (yellow), and one in which they are enabled and forced to be used (green).egnosErr2

Clearly in this case, forcing use of the EGNOS observations made things significantly worse.  Apparently using them requires a little more than just ignoring the unhealthy flag but I don’t know any more than this.  If anyone has successfully included the EGNOS observations in their solutions, I would be curious to know more about how you did it.

That’s about it for tips and tricks I can think of related to SBAS.  If anyone has other tips, or can answer any of my unanswered questions above, or can provide information on some of the SBAS systems I didn’t mention, please leave a comment.

 

 

 

 

 

Initial look at the ComNav K708 receiver

ComNav was kind enough to recently lend me two of their K708 receivers for evaluation.   I also have a Tersus BX306 receiver that was given to me earlier by Tersus for evaluation.  Both of these are relatively low-cost dual frequency receivers that offer full GPS L2 support., unlike the SwiftNav receiver I evaluated in my previous posts which is GPS L2C only.  I have described the Tersus BX306 before in a previous post but last time I was not able to evaluate it with a local base since I did not have a second dual frequency receiver that supported L2.  Tersus has also just recently released their new V1_19 firmware so I included that in this evaluation.   As usual I’ve also included  a pair of u-blox M8T receivers to use as a baseline.

Here’s a photo that shows the three receivers each with their associated serial port and power cabling.  The u-blox M8T is on the left, Tersus BX306 in the center, and ComNav K708 on the right.  The ComNav receiver is actually only the smaller daughter board in the center of the larger board, everything else is part of the very sturdy but rather clunky dev kit.

rcvrs3

The Tersus BX306 is priced at $1699 but lower priced versions are available. For example, the BX305 supports GPS L1/L2 but Glonass G1 only, and the BX316R is GPS L1/L2 and Glonass G1/G2 but provides only raw observations for post-processing.  Both of these options are priced at $999.

The ComNav K708 is similar to the better known K501G but newer and more capable.  ComNav doesn’t list their prices on their website but they have told me that both the K501G and the K708 configured to be equivalent to the K501G (GPS L1/L2 and GLO G1/G2) are available for less than $1000.

Both the Tersus and the ComNav receivers come with GUI console apps which are good for initially getting familiar with the receivers.  However each had their unique quirks and I found myself fairly quickly abandoning them for the more familiar quirks of the RTKLIB apps.  Managing three simultaneous real-time solutions involving five separate receivers while also logging raw observations for all five was actually quite challenging and I made a couple of unsuccessful runs before I got everything working at the same time.

I found that the key to turning this into a manageable and automated process was replacing each of the different manufacturer’s GUIs with an RTKLIB stream server (STRSVR) and a plotter (RTKPLOT) each with it’s own dedicated .ini file.  Eliminating the GUIs also gave me a better understanding of exactly what the receivers were doing and what the GUIs were doing.

STRSVR provides a standardized, always visible red/yellow/green indicator for each stream along with a continuously updated bps number that indicates not only that the connection is alive, but that data is flowing.  This allowed me to tell at a glance that all streams were flowing and that all the log files were being updated.  Using the “-t” option in the command line to specify a title for each window also helped keep things straight.

Both receivers are configured by sending Novatel-like ASCII commands over the serial port and these can be added to the STRSVR Serial “Cmd” window and saved to a “.cmd” file, similar to configuring the u-blox receiver.  Notice in this example, I also sent a reset to the receiver every three minutes which was a convenient way to automate the testing of acquisition times.

strsvr1

I connected both dual frequency rover receivers to my laptop, using two COM ports for each one and using a USB hub to get enough ports.  I set up both receivers to output NMEA solution messages and raw RTCM observation messages on COM1 at 5 Hz and accept RTCM base station data on COM2.  Both receivers have decent reference manuals to describe their command set but I also found this Hackers Guide to the K501G from Deep South Robotics quite useful for getting started.

For reference, here are the commands I used to configure the Tersus rover:

fix none
unlogall
log com1 gpgga ontime 1 nohold
rtkcommand reset
log com1 gpgga ontime 0.2

log com1 rtcm1004 ontime 0.2
log com1 rtcm1012 ontime 0.2
log com1 rtcm1019 ontime 1
log com1 rtcm1020 ontime 1
interfacemode com2 auto auto on

saveconfig

and here are the commands I used for the ComNav rover:

interfacemode compass compass on
unlogall com1
fix none
refautosetup off
set cpufreq 624
rtkobsmode 0
rtkquality normal
set pvtfreq 5
set rtkfreq 5
log com1 gpgga ontime 0.2 0 nohold
log com1 gprmc ontime 2 0 nohold
log com1 rtcm1005b ontime 10
log com1 rtcm1004b ontime 0.2
log com1 rtcm1012b ontime 0.2
log com1 rtcm1019b ontime 2
log com1 rtcm1020b ontime 2
saveconfig

My intent was to setup the receivers in default RTK mode with a 5 Hz output for NMEA solution messages and RTCM raw observation and navigation messages.  The one exception to default was that I found the “rtkquality” setting on the ComNav receiver defaulted to “quick” which was giving me false fixes, so I changed this to “normal” and that seemed to fix the problem.

By setting things up this way, I only need to click on the correct combination of icons (each tied to it’s own .ini file) from my RTKLIB menu to bring up the correct windows and a few more clicks to start the streams in a simple and repeatable way.

dualFreq3

I’m jumping ahead a little bit, but here is a screen capture of the rover-connected laptop streaming two NTRIP sets of base station data to the rovers while simultaneously logging and plotting the computed solutions for all three rovers along with raw observations for all five receivers,  and also computing an RTK solution for the M8T receivers with RTKNAVI.

Capture3

I should mention that there was one very annoying bug that was introduced to STRSVR in one of the recent RTKLIB releases that gives an error if a data file already exists instead of an overwrite dialog but I did fix this and add it to a new demo5 b29b code release available at the download page on rtkexplorer.com.  The new release also includes a fix for another bug that prevented the “-i” command line option to specify a config file for RTKPLOT from working properly.

I then setup the second ComNav receiver as a base station for both dual frequency rovers and used a single COM port to stream RTCM messages from the receiver to a PC.  I used an STRSVR window on the PC to stream the messages to a NTRIP caster using the free RTK2GO NTRIP caster service as I have previously described.  I used ComNav AT330 antennas for both the base and rovers with the rover antenna shared by all three rover receivers.   I did not have enough connector hardware to share the base antenna so used a separate u-blox antenna for the M8T base receiver.

The next step was to collect some data.  I started with a relatively simple challenge, a static rover with a reasonably open sky view and a short baseline.  The ComNav and Tersus solutions both assume the rover may be moving so I set up the M8T solution as kinematic as well.

Let’s first look first at the ComNav solution compared to the M8T solution.  Both solutions were computed real-time.  RTKPLOT will plot NMEA data but it did not seem to like the mix of NMEA and RTCM data in the same file.  To deal with this, I wrote a simple matlab script to strip the NMEA messages from the log file and put them in a separate file.  Below I have plotted only the Up/Down axis for both receivers just to avoid too much data,  the M8T is on top, and the ComNav below.  Each of the larger breaks in the fix was caused by me disconnecting then reconnecting the antenna to force a re-acquire.

comnav1

The M8T configuration was identical in the left and right plots, but the ComNav “rtkquality” parameter was set to “quick” in the left plot, and “normal” in the right plot.  It’s not as obvious here as it is in the other axes but the third ComNav fix in the left plot is a false fix and had over 0.2 meters of error in the N/S axis.  Changing the “rtkquality” parameter to “normal” seemed to help and I did not notice any more false fixes after making that change.

The ComNav receiver typically achieved a fix very quickly regardless of the “rtkquality” setting, usually in less than 30 sec although in one case it took a minute and a half.  This was noticeably faster than the M8T receiver, which took from 1 to 3 minutes each time in this example to achieve a first fix.

The scales are the same in the two sets of plots, so as you can see, the ComNav fixes are a fair bit noisier than the M8T fixes.  I don’t know why this is but it is something that I hope to investigate more.

Unfortunately I got a mix of good and not so good results from the Tersus receiver.   I did not see this behavior in my previous evaluation so I’m fairly certain this is not a problem with the hardware.  I suspect it has something to do either with my setup or with the new firmware.  I am going to hold off on sharing any of the Tersus data until I understand better what is going on.

Next, for a more challenging test, I moved the rover antenna to a spot with fairly poor sky views located between several large trees.  The sky view directly above the antenna was clear but a large percent of the overall view was blocked.   Again, I just plotted the Up/Down axis with the M8T position solution on the top and the ComNav solution on the bottom.

comnav2

I disconnected and reconnected the antenna three times in this experiment.  The M8T did not get a fix in the first try before I gave up after 12 minutes, but it did after 13 and 11 minutes in the second two tries after briefly getting a false fix in the second try.  Definitely marginal conditions for the M8T.  The ComNav receiver did significantly better with two fixes in less than 3 minutes and one in 9 minutes.  The errors were relatively large in the first fix but based on the other two axes it was not a false fix.  You can also see that the ComNav third fix was noticeably noisier than any of the other fixes on either receiver, again for unknown reasons.

For the third part of the experiment I moved the receivers into my car and attached the antenna to the roof and collected data for three spins around the neighborhood.  The results are plotted below.  In each case the M8T real-time solution is on the left, and the ComNav is on the right.  In the data in the first row, I shared a single antenna for all three receivers.  For the data in the second and third row I used separate antennas.  I did not change any of the config settings for any of the receivers between these runs and the above runs except that the rtkquality setting was still set to “quick” for the ComNav receiver for the second and third rows.

 

 

 

comnav5

 

comnav6

comnav7

I have not had a chance to look at this data closely but at first glance, from a fix percentage perspective only, I don’t see significant differences between either of the receivers.  The obvious advantages the ComNav receiver demonstrated in faster fixes in the static tests did not seem to carry over to the moving rover case.  I do plan to look at the raw data more carefully to see if I can understand better why this is.  For whatever reason, the Tersus receiver seemed to perform better with a moving rover than it did with a static rover, and was very similar in fix percentage to the other two receivers in this part of the experiment.

Next I planned to post-process the raw data through RTKLIB to better understand what is going on but as usual, nothing is as simple as you hope for, and I ran into another issue.

Both the Tersus and the ComNav receiver report a mix of 2W and 2X  measurements for the raw GPS L2 measurements.  If the satellite supports the newer L2C code it locks to that and reports a 2X code, if not, it locks to the older L2  and reports a 2W code.   You can see this in this example observation epoch from the Rinex conversion of the ComNav receiver RTCM output.  The left three columns are the L1 measurements, the middle three columns are the L2 (2W) measurements and the right three columns are the L2C (2X) measurements.  You can see that all the GLONASS satellites report L2 measurements only but that the GPS satellites are a mix of L2 and L2C measurements.

comnav4

This is new for the Tersus receiver, it did not do this when I evaluated it with the older firmware.  For the ComNav receiver, this is the default behavior but it is possible to change this through a command to specify L2 only, no L2C.  As far as I can tell, the Tersus only supports the mixed L2/L2C mode.  All the data I collected for this experiment was in the mixed L2/L2C mode.

Unfortunately RTKLIB does not like this format and throws away all of the L2C measurements.  It is possible to fool RTKLIB into using all the measurements by changing the 2X’s in the “Obs Types” list in the file header to 2W’s but I haven’t looked yet at to what extent mixing the code types affects the solution or how to avoid throwing away the L2C data without editing the header.

I will leave a more detailed analysis of the data to a future post.  My initial impression from these results though, is that although there are some obvious advantages with the ComNav receivers, replacing a pair of low cost single frequency receivers with a pair of low cost dual frequency receivers does not magically make the challenges of precision GNSS go away and that it will still require close attention to the details and recognition of their limits to get good results with either set of receivers.

 

 

New Swift firmware with a moving rover

In the last couple of posts I compared the u-blox M8T receiver and the Swift Piksi Multi receiver for a stationary rover and an external base station using the latest 1.2 firmware from Swift.  I did this for both RTK and PPP solutions.  In this post I will look at a moving rover case with a pair of Piksi receivers and a pair of M8T receivers.

The new Swift firmware supports raw observations and float solutions for the GLONASS satellites, but does not yet support ambiguity resolution for GLONASS.  In the previous experiments the lack of GLONASS ambiguity resolution did not affect the comparison since an external (non-matching reciever) base was used. This meant that the RTKLIB solutions were not able to use GLONASS ambiguity resolution either.

In this experiment I did use matching receivers for the base data, so the RTKLIB solutions do include GLONASS ambiguity resolution and so should provide an advantage to the Swift internal solutions.  As I did last time, I will compare the real-time Swift RTK solution with post-processed RTKLIB solutions for the Piksi pair and the M8T pair.  In this case the M8T receivers are from CSG Shop and are running the 3.01 firmware so they include Galileo observations in addition to GPS, GLONASS, and SBAS.

In my previous moving rover experiments I shared a base antenna for the two base receivers but used separate antennas for the two rover receivers.  In this case I decided to also share the rover antenna between the two rover receivers to enable some more direct comparisons.  The base antenna is the same Swift GPS-500 antenna mounted on my roof that I used for the rover in the previous experiment.  The rovers are using a Tallysman TW7872 antenna mounted on top of a car.  In both cases I use a capacitively coupled splitter to isolate the two receivers and allow only one DC supply voltage to reach the antenna.  As usual, the data was collected while driving around my local neighborhood.

Whenever connecting two receivers to one antenna, or even locating to antennas close to each other there is always the concern that they may interfere with each other.  So, as a baseline, I first did a run with separate antennas for the rovers.  I used my inexpensive u-blox antenna for the M8T since it has a very long cable allowing me to separate both the receivers and the antennas by over a meter.  Here are the position solutions for the baseline test.  The Swift internal solution is on the left, the RTKLIB post-processed solution in the middle, and the M8T post-processed solution on the right.  As always, green is fixed points and yellow is float.

swift_newfw10

The post-processed solutions were both run forward-only and with continuous ambiguity resolution including GLONASS.  The percent fix for the three solutions were 69% for the Swift internal solution, 33% for the Swift RTKLIB solution, and 75% for the M8T RTKLIB solution.  I will use percent fix as a very coarse measure of goodness for now, later I will look at the solutions in more detail.  In this case I consider the Swift internal solution and the M8T RTKLIB solution roughly equal.  Both achieved 100% fix for a number of circles in a parking lot with open skies (22:30 to 22:35), and both struggled with partial fixes on the rest of the route which had more obstructed sky views driving along residential streets.  The Swift RTKLIB solution was noticeably worse and had 0% fix in the parking lot, and lower percent fix everywhere else.

I then re-ran a similar route a short time later, but this time with the M8T rover sharing the dual frequency antenna with the Swift rover, produced the following results in the same order as above.  The percent fixes were 53% for the Swift internal solution, 79% for the Swift RTKLIB solution, and 62% for the M8T RTKLIB solution.

swift_newfw9

Again I would consider the Swift internal and the M8T RTKLIB solutions roughly equal.  A different parking lot with open skies (1:43 to 1:48), gave no trouble to either solution, but both had only partial fix for the rest of the route.  In this case the Swift RTKLIB solution was noticeably better than the other two solutions which is interesting since last time it was noticeably worse.  This has been my experience in general with the Swift RTKLIB solutions, that they tend to be quite inconsistent.  With the previous firmware I traced some of the reason for this to unreported cycle slips.  I suspect the same is probably going on here but haven’t looked close enough to fully verify that.  As far as any interference occurring between the antennas, if it exists, it is too small to detect with this simple comparison.

Here are the raw observations for the two rovers for the second run, M8T on the left, Swift on the right.  Green lines are dual frequency, yellow are single frequency and red ticks are cycle slips.  There are 19 measurements available for the M8T solution and 22 for the Swift solution.  All are used for ambiguity resolution in the RTKLIB solutions but only the 11 GPS measurements are used for ambiguity resolution in the internal Swift solution.  The relatively cycle-slip-free region from 1:43 to 1:48 is from the parking lot where the sky views are open.

swift_newfw11

Since the exact same signal was fed into both receivers the observations can be compared more directly than in previous experiments.  Here is a zoom into the time in the parking lot and shortly after.   If you look carefully, you will notice that there are definitely more cycle slips reported in the M8T observations than in the Swift data.

swift_newfw7

We can verify if those cycle slips are real or not by plotting the double differences of the bias states from the RTKLIB statistics output file.  I selected two satellites that had more cycle slips in the M8T data, G03 and R04, and plotted their double differences relative to the most cycle-free satellite in their constellation.  In the plots below, the red lines are the double differences from the M8T bias states and the blue lines are the double differences from the Swift bias states.  The red circles are cycle slips reported in the observations and the discrete jumps are actual cycle slips.  The green x’s are half cycle invalid flags and not relevant to this particular example.

swift_newfw8

 

Both plots show good correlation between the reported cycle slips and the true cycle slips as well as confirming that their are more slips in the M8T observations than in the Swift observations.  So, at least in this example, the quality of the Swift observations is noticeably better than the M8T observations, even though both came from the same antenna.  Of course this might be expected since the Swift receiver, although low cost by dual frequency standards,  is still significantly more expensive than the M8T receiver.

The solutions however, don’t reflect this difference in observation quality.  The Swift internal solution appears to be no better, and possibly even a little worse than the RTKLIB M8T solution.  This is probably because the M8T solutions include GLONASS ambiguity resolution and the Swift solutions do not.  Once Swift adds this feature to their firmware I would expect the Swift internal solutions to be better than the M8T solutions.

The variability for the results from the Swift RTKLIB solutions are harder to explain and I don’t have any good answers for this yet.  I still do see cases of unreported cycle slips causing problems even with the new firmware and suspect this is a part of it.  I hope to investigate this further.

Another thing I wanted to look at is how good are the float solutions.  In Swift’s description of the new firmware they state that:

“Swift also suggests that users utilize the estimated accuracy fields
in navigation outputs for an indication of solution quality rather than using the
transition to RTK “fixed” mode as an indicator of solution quality, as the new
and improved float solution performance can often fulfill precision navigation
requirements.”

So, let’s take a look at the float portion of the internal Swift solution.  I loaded the .csv output file from the Swift internal solution into matlab, then plotted histograms for the horizontal and vertical accuracies for the fix and float solution points.  Here’s what it looks like:

swift_newfw_12

Notice that the float accuracies are significantly larger than the fix accuracies but they are probably realistic unlike the RTKLIB float accuracies which I demonstrated to be at least a factor of two overly optimistic in a recent post.

Here is an example of the solution points from the above data set in which the RTKLIB solution re-converges more quickly than the Swift internal solution.  This allows us to evaluate the accuracy of the Swift float values.  The top plot is one component of the horizontal position, and the bottom plot is the vertical position. Yellow is the Swift float solution, Olive green is the RTKLIB float solution and blue is the RTKLIB fix solution.  From the beginning of the data to 22:47:14 both solutions are float.  The RTKLIB solution converges to a fix at 22:47:14 and the Swift internal solution converges to a fix at 22:47:37.  Since both solutions eventually converge to the same value I will assume the RTKLIB fix solution is correct.

swift_newfw_13 The errors in the float solutions appear to be similar between RTKLIB and Swift and consistent with the Swift estimates of accuracy.  So the Swift float solution does not appear to be any more accurate than the RTKLIB float solution but the Swift estimates of the accuracy do seem to be more realistic.  Three quarters of a meter vertical accuracy is better than a single point solution but I suspect it is too large to be useful for many applications.  Still, it is a noticeable improvement from the very noisy float values I saw in the internal Swift solution in my previous comparison.

So what does all this mean?  I would summarize by saying that the results for a pair of Swift receivers with the new firmware are noticeably better than the results in my previous comparison and so are definitely a step in the right direction.  At least in my particular example, though, it still only puts them roughly on par with the results from a pair of M8T receivers.  They certainly seem to have the potential to be better than the M8T’s and hopefully with further improvements from Swift and maybe improvements in RTKLIB as well, we will see this soon.

I did not include a single M8T or Swift receiver paired with an external CORS or similar base station example in this moving rover comparison but would expect the Swift receiver to outperform the M8T receiver in that case because  of a better overlap in satellite pairs.  Also keep in mind that the Swift receiver does have some definite advantages in static and long baseline experiments as I showed in my previous two posts, especially the ability to get accurate locations for the base station using PPP solutions.

As always I want to emphasize that these are only one users results in one particular configuration and other users experiences in other environments could be quite different.  I have uploaded the raw data and RTKLIB config files to the sample data section on the rtkexplorer.com website if anybody would like to explore further.

I am just getting my newly borrowed NavCom receivers up and running and have upgraded my Tersus receiver with their new firmware so I hope to have results for these other low-cost dual frequency receivers soon.

 

 

PPP solutions with the Swiftnav Piksi Multi

I have had a couple recent questions about the Swiftnav receiver and PPP solutions so before leaving the stationary rover for a moving rover, I thought I would take a quick look at this subject.

Unlike RTK or PPK which are differential solutions using two receivers, PPP (precise point positioning) is an absolute solution done with just a single receiver.  Since we don’t have the advantage of eliminating the errors through differencing, it is a more challenging problem and is usually (but not always) done with dual frequency receivers for stationary targets.  RTKLIB does support PPP solutions and we will look at them too, but in general I prefer using one of the free online services since it is easier to do this and the answers are more accurate.  PPP solutions require precise clock and ephemeris data which must be downloaded from the internet.  Since you need to be connected to the internet anyways to download these, I see very little advantage to trying to run your own solution with RTKLIB unless you are using it as a learning tool.

There are several different online services available and they all have their own advantages and disadvantages.  I will use the CSRS service, provided by the government of Canada, in this experiment for a few reasons.

First of all, unlike some of the other services, CSRS uses the GLONASS satellites in the PPP solution.  This is particularly relevant for the Swift receiver since it is L2C and only half of the GPS satellites include dual frequency measurements.  In this case, including the GLONASS satellites roughly triples the number of measurements.  CSRS will also process L2C data directly.  Some of the other services won’t work with L2C data unless you modify the header of the observation file.   If you do run into this problem trying to use another service, manually editing the Rinex file header and changing the observation type from C2 to P2 in the file header will usually work.

Another reason for using CSRS for this experiment is that it will solve for single frequency data sets as well as dual frequency.  The single frequency solutions are based on code observations only and significantly less accurate than the dual frequency solutions but they are available.   In this case I will take advantage of this to compare the PPP solution for both single frequency M8T data and dual frequency Swift data.

CSRS also has a very convenient data submission tool that can be downloaded to your computer.  With this tool installed and configured, you simply need to drag any observation file onto the tool icon and it will email you a solution a few minutes later.  It’s hard to get much simpler than that!  You do need to setup an account before accessing the service or downloading the tool but that is a relatively quick and easy process and only has to be done once.

One last feature that CSRS provides that many of the other services don’t is the option to process kinematic data sets as well as static but I have not tried this out yet.

For this experiment, I used eight hours of data collected from the Swiftnav GPS-500 antenna on my roof which was connected to both a Swiftnav receiver and a u-blox M8T receiver through a splitter.  The antenna is mounted on a one meter pole at the bottom edge of a low-angled roof so has a reasonably good, but certainly not ideal, sky view.

The accuracy of the PPP solution will depend on the accuracy of the ephemeris used.  This will vary based on how long it has been since the measurement data was collected.  Here is a list from their website of the three possibilities along with their wait times and accuracies for the CSRS solutions.

  • FINAL (+/- 2 cm): combined weekly and available 13 -15 days after the end of the week
  • RAPID (+/- 5 cm): available the next day
  • ULTRA RAPID (+/- 15 cm): available every 90 minutes

In my case, I had collected this data a few days earlier so CSRS was able to use the rapid precise ephemeris data for the solution.

I converted both raw binary files to Rinex format using the RTKCONV app in RTKLIB.  CSRS only accepts the older 2.11 format so I did need to specify this in the RTKCONV options.  Usually I use the newer 3.03 format since it is easier to read and to parse with Matlab.

Next I dragged the two files onto the CSRS tool icon and a few minutes later both solutions appeared in my email folder.  I had previously configured the tool with a few bits of information including my email address.  The results included a pdf summary file and a csv file with the epoch by epoch convergence of the solution.

Here is the solution from the csv file for the Swift receiver.  The results in the file are in LLH format where latitude and longitude are both in degrees.  I converted both from degrees to meters using the appropriate meters per degree constants for my particular location, then subtracted the final point to generate the plot below.    Note that this is a different coordinate system than I used in the plots in my last post in which I converted the LLH coordinates to earth-centric XYZ coordinates.  In XYZ coordinates, the Z coordinate is only equivalent to height if you made the measurement at the North or South pole.  In this case I have used the angle to meter conversion to preserve the separation between vertical and horizontal components to better show their relative accuracies.

ppp1

In this case the horizontal components converged to something very close to the final answer in about two and a half hours whereas the vertical component doesn’t seem to have fully converged even in eight hours.

The 95% confidence levels for the results reported in the summary file were about one cm for the combined horizontal components and 2.5 cm for the vertical component.  This was consistent with my best guess for the actual errors based on both RTK and PPP measurements made with multiple receivers and online services. I estimate the actual error being about one cm in the combined horizontal components and about 1.5 cm in the vertical component.

I did not include any antenna calibration corrections in my solutions since I am not aware of a calibration file available for the GPS-500 antenna.  This means my solutions will be for the location of the phase center of the antenna, not the geometric center.    In this particular experiment, since I am only using the results to compare with other results from the same antenna, the errors will cancel and can be ignored.   Normally though, this offset will an add additional error to the position measurements.  Ideally for accurate absolute measurements, a calibrated antenna would be used, in which case the calibration file can be specified in the solution and RTKLIB will apply the correction to remove this error.

Unfortunately the CSRS PPP single frequency results for the M8T data were much less accurate with about half a meter of error in the horizontal components and three quarters of a meter error in the vertical axis.

ppp2

I then ran a PPP solution with RTKLIB for both data sets using a configuration similar to what is recommended in this tutorial.   The Swift data produced a result with very similar accuracies to the CSRS result in the horizontal components but nearly five cm of error in the vertical component.  Note that the convergence times are longer in the RTKLIB solution.  It is likely that both solutions would have reduced vertical errors if I had run with a longer data set.  The typical recommendation for PPP solutions is at least two hours of measurement data but longer data sets will generally improve accuracy.  Here is a plot of the RTKLIB PPP solution for the Swift data.

ppp3

In this case I was not able to get an RTKLIB PPP solution for the M8T data because of too large residual errors.  In other cases I have got PPP solutions with single frequency data but the accuracy of the solutions has always been much lower than the dual frequency data.  I do not have a lot of experience with the PPP settings in RTKLIB so it is possible I am not getting the most out of RTKLIB.  I hope to dig into this side of things more in the future.

PPP is great for locating static receivers but if you need to track moving rovers, you will still want to use RTK or PPK solutions for that.  The ability to get accurate locations for your base station using a PPP solution though is a significant advantage of using dual frequency receivers rather than single frequency receivers.  This is particularly true  if your base station is not close enough to a CORS type reference station to get an RTK/PPK solution for your base station location.

There is a significant advantage in having two identical receivers for RTK/PPK solutions since it will give the maximum number of overlapping measurements to difference and will allow ambiguity resolution with the GLONASS satellites.   In this case the simplest configuration would be to use Swift receivers for both base and rover.  A less expensive alternative worth considering would be to connect a Swift receiver and M8T receiver to the base station antenna through a splitter and then use an M8T receiver for the rover.   You could then use the Swift receiver to find your base location and the two M8T receivers to find the rover location relative to the base position.

For me at least, this ability to locate the base with PPP would be the most compelling reason to justify the extra cost of the Swift receivers over the M8T receivers.

Hopefully, this time in my next post, I will actually get to looking at the moving rover case with the Swift receivers.  After that I hope to do a four way comparison between the M8T, and low cost dual frequency receivers from Swift, Tersus, and ComNav.  I met Andy from ComNav at the recent drone expo in Las Vegas and he was kind enough to lend me two of their receivers and antennas for a couple months to use for evaluation.  I also understand that Tersus has recently updated their firmware so I’m quite excited about all the different options becoming available in the low cost dual frequency receiver market.

 

A first look at the new SwiftNav firmware

Swift Navigation just released a major upgrade to the firmware for the Piksi Multi low cost dual frequency receiver.  This should significantly improve performance since it adds support for the GLONASS L1 and L2 satellites.  This is an L1/L2C only receiver so it only supports L2 on about half of the GPS satellites, those recent enough to support the new codes.    On GLONASS however, there is no L2/L2C distinction and the Swift receiver supports the second frequency on all of the GLONASS satellites.  There are fewer GLONASS satellites than GPS satellites but overall this change roughly doubles the measurements available to the solution.  Looking at a recent six hour data set I took, the number of GPS satellites varied from 7 to 9 and the total L1 plus L2 GPS measurements varied from 11 to 14.  During the same time there were only 5 to 7 GLONASS satellites but 10 to 14 total GLONASS measurements including L1 and L2.

Unfortunately, the update does not include ambiguity resolution for the GLONASS satellites within the Swift internal RTK solution.  The raw GLONASS measurements are available though and RTKLIB supports GLONASS ambiguity resolution provided both receivers are identical.  This means you can use GLONASS ambiguity resolution if you have two Swift receivers and are doing post-processing with RTKLIB.

I did a comparison between the Ublox M8T and the Swift Piksi Multi a few months ago and found that with only L1 GPS and partial L2 GPS, the Piksi simply did not provide enough measurements to generate a robust solution.   With the new measurements available, along with other improvements they have added with the new firmware, I thought it was time to give it another test.

As I did previously, I will compare a Swift internal RTK solution to an RTKLIB post-processed PPK solution using the Swift data as well as an RTKLIB post-processed solution from a u-blox M8T L1 receiver.   Swift does not provide any tools for doing post-processed solutions so the Swift internal solution will have to be real-time.

My first test was with a static rover to make evaluation of the results easier.  Even though the rover was stationary, I ran all solutions in kinematic mode to get a better sense for the errors.   For the rover I used a SwiftNav GPS-500 antenna mounted on my roof and connected through a signal splitter to both a Piksi Multi and a u-blox M8T receiver.  For the base I used the P041 CORS/UNAVCO station which is the closest station for which I have real time access to through the UNAVCO network.  It is about 17 kilometers away so a long enough baseline to be fairly challenging.  I did run from early evening to late night so the ionospheric errors were not as large as they would have been at mid-day.  There also happened to be about two inches of snow that fell during the measurement period, possibly affecting the result through snow accumulation on base or rover antennas?  Other than the snow, this is very similar to the test I ran previously comparing  a Tersus dual frequency receiver to an M8T receiver.

Let me start by giving my usual warning that these comparisons are only meant to be a snapshot of one users experience and not a comprehensive evaluation of any sort.  Measurement environments vary tremendously and there is no guarantee that other people’s results will match mine.

I ran the test for approximately eight hours.  Here are the rover observations for both receivers, Swift on the left, and M8T on the right.  Green lines indicate dual frequency measurements and yellow are single frequency.  The Swift receiver has GPS and GLONASS observations, the M8T has GPS, GLONASS, Galileo, and SBAS.  Both receivers averaged roughly 25 measurements with the additional L2 measurements on the Swift roughly balancing the additional satellites on the M8T.

swift_newfw2

To more easily compare the internal Swift solutions to the RTKLIB solutions I wrote a simple matlab script that translates the csv logs written by the Swift receiver to the format of an RTKLIB  .pos file, allowing me to plot both together using RTKPLOT.

When I first plotted the solutions I saw DC offsets between the Swift solution and the RTKLIB solutions.  I had seen this before in my previous test.  Last time I had ignored the offsets assuming they were coming from datum differences but this time wanted to pinpoint exactly where they were coming from.  Usually it is easier to do these comparisons with relative measurements between the two receivers (ENU coordinates) rather than absolute solutions since the absolute solutions often involve translating between different datums.  In this case though , the relative solutions were giving differences in the z axis exceeding 45 meters!  I eventually traced the source of this error to different origins for the ENU coordinates between Swift and RTKLIB.  Swift uses the rover as the origin and RTKLIB uses the base as origin, causing a rotation of the axis of the two ENU coordinate systems.  Combined distance in three dimensions is the same either way but the distribution between axes changes significantly.

I then switched to comparing absolute solutions using LLH coordinates.  I specified the same base location to both solutions using the numbers I got from the base station location file.  The offsets were still there but smaller now, just a few centimeters.  Eventually I realized that Swift was not using the base location I specified on the settings page but was substituting a slightly different base location generated from location messages in the incoming base RTCM stream, presumably from a different datum.  I switched the RTKLIB solutions to use this base location and this eliminated the DC offsets.  RTKCONV places the base location provided in the RTCM stream into the “APPROX POSITION XYZ” field in the Rinex file header, so selecting “rinexhead” option for the base station location in the config file accomplishes this.

Here are the position solutions for the first hour of the test after sorting out the offsets.  On the left is a comparison of the internal Swift solution to the RTKLIB Swift solution.  The yellow/green line is the internal Swift solution and the olive/blue line is the RTKLIB Swift solution.  On the right is the RTKLIB M8T solution (yellow/green) and the RTKLIB Swift solution (olive/blue).  The large errors are caused by the initial acquires of the RTKLIB solution (the Swift solution had already acquired when I started the data collection) and from me disconnecting the antenna twice to force a re-acquire of all solutions.

swift_newfw1

The Swift solution is re-acquiring after losing fix much more quickly than the RTKLIB solutions.  In these two examples, the Swift solution re-acquired in less than one minute while the RTKLIB solutions required 5 to 10 minutes.  Interestingly, the RTKLIB re-acquire times were roughly the same for the M8T or the Swift data.  Presumably the Swift solution is taking advantage of linear combinations of the L1 and L2 measurements in ways that RTKLIB is not.  Previously I was seeing the Swift solution sometimes take very long to re-acquire (well over ten minutes).  This issue seems to be fixed and the Swift solution now seems to re-acquire quickly and reliably.  So, by this metric, the Swift receiver is a clear winner, provided you are using the internal solution.  For the RTKLIB solutions, the two receivers are very similar.  This might be expected since they are both working with roughly the same number of raw measurements.  I should mention that GLONASS ambiguity resolution was disabled in the RTKLIB solutions since the base and rover were not using identical hardware.

Next let’s compare the relative accuracy of the three solutions.  I will ignore any errors that are common to all three solutions and focus on differences between the three.  To do this I will use the mean of all three solutions in each axis as the “correct rover location”.  I will also only use the fixed points for now, and ignore the float.  First let me show the rest of the eight hours of data in which I did not disconnect the antenna at all.   Again the Swift internal (green/yellow) vs Swift RTKLIB (olive/blue) solutions on the left, and M8T RTKLIB (green/yellow) vs Swift RTKLIB (olive/blue) solutions on the right.

swift_newfw3

Clearly several disruptions are common to all three solutions.  Again, the Swift solution re-converges much more quickly than the RTKLIB solutions.  Given that the disruptions are common to both M8T and Swift receivers, the most likely suspect is the base station.  Sure enough, the base observations show simultaneous cycle slips on multiple satellites at most of the disruption points.  I’m not sure what caused these anomalies but am more interested in the solution responses to them than their actual cause, as they are common to all solutions.

swift_newfw4

The mean rover position was very close for all three solutions, as were the standard deviations for each axis. It is difficult for me to interpret errors measured in degrees of latitude or longitude so I converted the LLH positions to ECEF for comparison.  Here are the results, all in meters.  The maximum deviation from the combined mean was 7 mm and the largest standard deviation was 1.5 cm.  These errors are all small enough and similar enough that I would say the differences between them are probably not very meaningful.

Swift internal: dx=0.003  dy=0.007  dz=0.003
Swift RTKLIB:  dx=-0.002 dy=-0.003 dz=-0.001
M8T RTKLIB:   dx=-0.001 dy=-0.004 dz=-0.002

Swift Internal: stdx=0.006 stdy=0.013 stdz=0.010
Swift RTKLIB:  stdx=0.006 stdy=0.012 stdz=0.014
M8T RTKLIB:   stdx=0.005 stdy=0.012 stdz=0.015

Here are the plots of the three solutions all laid on top of each other, all relative to the combined means.  All three are fairly well correlated, but in particular I find it surprising how correlated the Swift RTKLIB solution is to the M8T RTKLIB solution.  They overlay on top of each other so well that it is difficult to even see the Swift solution but that is only because the M8T is on top, both had roughly the same percent of fixed points.

swift_newfw5

So in terms of accuracy, there is very little difference in any of the three solutions.  However, it is clear from these plots that in relatively long baseline situations like this, the Swift internal solution will fix and re-acquire more quickly and hence would take less time to make a measurement.   This difference would be smaller for shorter baselines where all solutions would fix fairly quickly and be nearly 100% fixed.

RTKLIB does have some additional flexibility over the Swift internal solution, especially in a post-processing situation which could be used to improve the RTKLIB solution, including static vs kinematic, continuous AR vs kinematic AR, and combined (forward/backward) mode instead of just forward.  In this case, probably combined mode would be the most effective choice since it causes the solution to approach the anomalies in the raw data from both directions and minimize their disruption.  Here is the same solution as above for the M8T RTKLIB solution (green/yellow) and the Swift RTKLIB solution (olive/blue) , but processed in combined mode.  It improves both solutions significantly and brings the Swift solution to nearly 100% fix.

swift_newfw6

Overall, the new Swift firmware looks like a significant improvement over the previous version, particularly for real-time applications where time to first fix is most important and post-processing options are not available.

In my next post, I will extend the comparison to a moving rover case.

 

 

 

 

 

 

 

 

 

 

 

 

 

UAV Expo in Las Vegas next week

I’ll be visiting the UAV Expo in Las Vegas on Oct 25-26 to find out more about what’s going on in the world of commercial drones and how they are incorporating precision GNSS into their systems.

If anyone else is planning to be there and would like to meet, send me an email at rtklibexplorer@gmail.com.  I always enjoy finding out more about what people are doing with RTKLIB and low cost precision GNSS.