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.

 

 

Advertisements

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.

 

 

 

 

 

 

 

 

 

 

 

 

 

RTKLIB solution accuracy

OK, so let’s say you’ve just gone out and collected some decent raw measurement data, everything looks like it is working properly and you get a nice-looking solution from RTKLIB, maybe something like this.

stdev1

The next thing you might want to know is how accurate is that solution?  Fortunately, RTKLIB does include accuracy estimates in the solution file.  These are expressed as standard deviations, one for each axis.  Here’s an example for a solution calculated in ENU (east/north/up) coordinates.  The sde, sdn, and sdu columns are the standard deviation estimates for each solution point and are given in meters.  If the solution were calculated in XYZ coordinates, the columns would be labelled sdx, sdy, and sdz.

stdev5

You can display these on the solution plot with RTKPLOT by setting “Error Bar/Circle” in the options menu to “Dots” or “Bar/Circle”.  You can see the gray lines in the plot below that represent the solution value plus and minus one standard deviation.

stdev2

Visually, I prefer to see three standard deviations plotted, rather than just one.  Three standard deviations represents 99.7% of the distribution, so the correct value should nearly always appear between the two gray lines.  One standard deviation, on the other hand,  represents only 68% of the distribution which is hard for me to attach any physical meaning to.  This can be easily changed in RTKLPLOT by replacing SQRT(s[j]) with 3*SQRT(s[j]) all three places it appears in the plotdraw.cpp file and recompiling RTKPLOT which gives this:

stdev3

Of course these are just estimates of the solution uncertainty made by the kalman filter in RTKLIB and we can not assume they are accurate without some analysis.  They are a function of the input parameters that set the input measurement uncertainties and process noises for the kalman filter.  These are all in the “stats” section of the input configuration file.  Even if these are all set to correctly match your actual configuration, there will be additional errors in these estimates caused by non-linearities in the system, non-gaussian distributions, and time-correlated measurements among other things.

So, let’s do a little analysis to get a feel for how useful these estimates are.  We’ll start with the above data set which includes eight hours of measurements from a stationary u-blox M8T receiver and a CORS reference station 8 km away.  I enabled fix-and-hold for ambiguity resolution with relatively low tracking gain (pos2-varholdamb=0.1).  I ran both static and kinematic solutions on the data, then turned off ambiguity resolution and re-ran the solutions to get examples of both fixed and float solutions for static and kinematic modes.

After running the solutions, I pulled the solution files into matlab for plotting and analysis.  Since the rover was stationary and I knew it’s precise location I was able to easily calculate the true errors.  I then plotted for each solution point, the absolute value of the errors and three times the standard deviation estimate for each point, similar to the above RTKPLOT plot.  The raw data is in E/N/U coordinates but I combined the East and North values into a single horizontal error and error estimate.  After finding that in some cases the error estimates were too low, I also plotted a line using double the error estimate, to see if that might be a usable value .  In the title of each plot I’ve included the percent of samples that were inside the error lines, the first number is for the undoubled estimate, the second is for the doubled estimate.  I also made one more modification to the error estimates by limiting them to a minimum value.   In the case of the static solutions, the RTKLIB error estimate will continue to decrease almost all the way to zero but this is not realistic since there are errors that are not visible to the solution.  I arbitrarily limited each horizontal axis standard deviation to no less than 5 mm, and the vertical axis to 1 cm.   I don’t have good justification for these particular numbers but do believe there needs to be some limits set.

For a perfect Gaussian distribution, plus or minus three standard deviations should include 99.7% of the data.  Given that these are not perfect distributions and will also contain outliers, I would consider the estimates useful if more than 95% of the data fell within them.

Here are the plots for the above data set run with static solutions, float on the left, and only the fixed values of the solution with ambiguity resolution enabled on the right.  The blue line is the actual error, the red line is the RTKLIB estimate, and the yellow line is double that.  The top plots are for the horizontal axes and the bottom plots for the vertical axis.  In the static cases, all the error lines dropped below the minimum estimate values I set above fairly quickly, so only the initial convergence of the float solution was really of any interest.   Still the error estimates in that region look somewhat reasonable, although the undoubled estimates are clearly optimistic. The undoubled estimates (red) are not visible on the plots where both estimates have dropped below the minimum and they get overwritten by the doubled estimate.

stdev8

Next are the same plots for the kinematic solutions.  Just to confuse you, I have accidentally put the float solution on the right this time.  Again, the solution with ambiguity resolution enabled (on the left) only includes points that were fixed.  These are more interesting than the previous plots since they are not dominated by the arbitrary minimum error estimate limits I added.  Looking at the float solution first, the undoubled estimates again look too optimistic with only 92.2% and 75.2% of the data within that limit.  At 100% and 99.6% the doubled values (yellow lines) appear to be better estimates.  For the fixed values on the left however the undoubled estimate percentages and plot lines appear to be fairly reasonable.

stdev7

In one last example, I used a different data set, this one is one of the sample data sets on my website which was taken with two M8T receivers, one on each end of a kayak out on the ocean.  In this case we know that the distance between the two receivers will remain constant so we can use that information to do a similar analysis as above.  Because the kayak is moving in all three axes with the waves we can not separate the horizontal and vertical components but can do an actual error to estimated error comparison for the three axes combined.

The float solution is back on the left again, just the fixed values from the ambiguity resolution enabled solution on the right.  Based on the calculated percentages and the shapes of the curves, it seems fairly reasonable to again choose the doubled estimates for the float solution and the undoubled estimates for the fixed values.  Even with the doubling, the percent of solution values within three standard deviations is still only 88.5% which is rather low but most of the outliers were in the initial convergence where we might expect more issues.

stdev6

So, based on these few examples I do see correlation between the RTKLIB error estimates and the actual errors, not as much as I would have liked, but there is some.   Maybe these adjustments I made would hold up for other cases as well, but I would not have a lot of confidence without trying more examples first.

Clearly these error estimates can not be taken at face value.  Do they have any value?  It probably depends on what you are trying to do with them.  If you are just trying to get a rough idea of the accuracy of the measurements, especially if it is in a statistical sense, and you have done some previous analysis with similar data sets, then you can most likely derive some value from them.  If the absolute accuracy of a single measurement is important to you then you will probably need to find another solution.

What about trying to adjust the input configuration parameters (measurement and process noises) to make the accuracy estimates more accurate?  You may be able to make small improvements but I suspect they will not be significant enough to avoid post-solution adjustments.  You will also find that adjusting these parameters will affect the quality of the solution and it will be difficult to optimize for both.

I am interested, though, if anyone has any ideas for simple (or at least only moderately complicated) code changes that could be made to RTKLIB to improve these estimates or any other ideas on how to improve them.

 

 

 

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.

RTKLIB on a drone with u-blox M8T receivers

Drones are a popular application for RTKLIB and quite a few readers have shared their drone-collected data sets with me, usually with questions on how they can get better solutions. In many cases, the quality of this data has been fairly poor and it has been difficult to get satisfactory results. I was curious to understand why this environment tends to be so challenging since in theory a drone should have more open skies than just about any other application.

To do an experiment, I bought an inexpensive consumer drone from Amazon. I chose the X8C from Syma since it is beginner model and a little larger than some options. I figured the larger size should make it better able to carry some extra weight.

After a few practice flights to get the hang of flying it, I used some duct tape and double-sided foam adhesive to attach a u-blox antenna and 90 mm diameter ground plane to the top of the drone and a u-blox M8T receiver with my custom CHIP data logger underneath where the camera usually goes. I used the landing gear as a spool to wind the unnecessary five meters of antenna cable which was the heaviest part of the whole setup. From a weight perspective, the Emlid Reach units would have been a better choice, but I wanted to collect data from the Galileo constellation of satellites as well as GPS and GLONASS so I used my CSG receiver with the newer 3.0 firmware. I used a second CSG receiver mounted on top of my car as the base station.  Here’s a stock photo of the drone on the left and after my modifications on the right.

drone1drone2a

Although the drone was able to lift the extra weight fairly easily, it seemed to affect the stability of the flight control system and after a few minutes the prop motors would start to fight each other. At that point the drone would start to descend even at full throttle and the drone would land hard enough to usually bounce on its side or back. Still I was able to make a number of short flights which were adequate for testing purposes.

Here’s the observation data for the first set of flights, base station on the left and drone on the right. Red ticks are cycle-slips and gray ticks are half-cycle ambiguities. Ideally, the drone data would look as clean as the base but as you can see it is significantly worse and it turned out to be unusable for any sort of reliable position solution.  The regions without cycle-slips in the drone observations are the times in between flights in which the drone is sitting on the ground.

drone3

Clearly, while the drone is flying, something is interfering with the GPS receiver or antenna, most likely either EMI or mechanical vibration. I could have used a fancy test stand and RF sniffer to try and locate the source of interference but since this blog is focused on low-cost solutions I just used some duct tape, a steel bar, and the RTKLIB code instead.

I used two types of duct tape, both the polyester/fabric type that everyone calls duct tape, and also the metal foil type that is actually used to repair or install ducts. I first used the non-metal duct tape to securely attach the landing gear to the heavy steel bar. The steel bar was convenient because it was easy to attach but anything heavy enough to prevent the drone lifting off under full throttle would work fine.

I then started an instance of RTKNAVI on my laptop and connected it to the receiver on the drone.  The goal was to simulate a complete drone flight while the drone was sitting on the ground and at the same time watch the RTKNAVI observations to detect any degradation of the measurements.  I used a wireless connection but a USB cable would have worked too.

Unfortunately RTKNAVI won’t plot the observation data real-time, but by selecting the tiny “RTK Monitor” box in the bottom left corner of the main RTKNAVI screen, then choosing “Obs Data” from the menu, I was able to get a continuously updating listing of the observations.  Cycle-slips show up as non-zero values in the first column with the I heading. I chose a location outdoors with open enough skies that any degradation in the observation data would be obvious.

drone4

I first observed the cycle-slip column with the drone powered down to verify I wasn’t getting any cycle-slips on all but the lowest elevation satellites. I then continued to observe the cycle-slip column while sequencing through the steps required to fly the drone. I first powered on the drone, then powered on the transmitter, then issued the calibration/connection sequence, then turned on the throttle to low. So far, so good, no sign of cycle-slips. I then started moving the joysticks to issue steering commands which caused the motors to change speeds. All of a sudden I started getting cycle-slips, the more aggressive the steering commands, the more cycle-slips I saw. Aggressive changes in throttle also caused cycle-slips but full throttle with no adjustments or steering commands was fine.

Next I moved just the antenna, then just the receiver away from the drone while issuing steering commands. Moving the antenna away had no effect but moving the receiver away eliminated the cycle-slips.

At this point my guess was that the interference was coming from the relatively high power switching in the motor control circuits and that the antenna ground plane was shielding the antenna from this interference but nothing was shielding the receiver. To test this theory, I attached a layer of the metal duct tape to the bottom of the drone to act as a shield between the drone controller board and the receiver.  I then re-attached the receiver to the bottom of the drone and re-ran the experiment. This time there were almost no cycle-slips even with the most aggressive steering.

I then removed the steel bar and ran a second set of short flights with the layer of metal tape still in place. I was a little concerned that the new shield would interfere with commands sent from the transmitter to the drone so I first tested everything while still on the ground and then kept the drone fairly close during the flight. Fortunately I didn’t see any sign of commands not getting through.

The drone data looked much cleaner in this flight!  Unfortunately, this time the base data was no good with many simultaneous cycle-slips throughout the observation data. At this point I realized that I had placed the base station receiver directly on the top of the car when collecting the data which was very hot at the time. Usually I keep the receiver in the car to avoid this and only place the antenna on the roof. I have seen this kind of severe temperature effects cause simultaneous cycle-slips before but never to this extent. Again the data was completely unusable.

So, back out there again for a third round of flights. This time, everything looked much better. I still saw a few cycle-slips, especially when first applying the throttle at take-off, so my shielding was not perfect but a dramatic improvement over the first flight. The plots below show the results. The top two plots are position solutions for the z-axis. The top plot is with continuous ambiguity resolution and the middle plot is with fix-and-hold enabled. The bottom plot is the drone observation data.

drone5

I made three adjustments to the input configuration file from what I would normally use for my car based measurements.  First of all, since the drones have very open skies, I adjusted the minimum elevation angles from 15 degrees to 10 degrees.   Then, after plotting and observing the accelerations from an initial solution, I increased the vertical acceleration dynamics estimate (stats-prnaccelv) from 0.25 to 1.0.  Finally, because I was seeing slightly higher position variances in the initial solution than I usually do, I adjusted the position variance AR threshold (pos2-arthres1) from 0.004 to 0.1  Both of these last two changes would make sense if the level of vibration were higher in the drone than I am used to seeing, which is quite likely.

Each time the drone landed/crashed due to the unstable flight control system it would bounce to the side or upside-down and that is what is causing the cycle-slips and switch from fix to float at the end of each flight. As you can see though in every case I quickly get another fix after I put the drone upright again. The fixes are solid enough to hold through the entire flight even in continuous mode for all but one of the flights. With fix-and-hold enabled all flights maintained 100% fix rate. The data is as good as or better than similar experiments where I have mounted the rover on top of a car.

This is not surprising since the skies are more open in this experiment. Having over twenty satellites available for ambiguity resolution also helped. I used all the satellites (GPS/GLONASS/Galileo/SBAS) for ambiguity resolution and took advantage of the new feature in the demo5 b26 code that cycles through all the satellites and will throw a single one out if it is preventing a fix. This will automatically occur anytime the number of satellites available for ambiguity resolution is greater than the config parameter “pos2-mindropsats” which defaults to twenty.

I have added the raw data and the configuration file to the  sample data set section at rtkexplorer.com

I imagine different drones will have different issues and not all will be as easy to fix as this one, but the method described here or something similar should be helpful any time drone data is not looking as clean as the base station data.

The fix I chose was very easy to implement but a better fix would probably have been to wrap just the receiver in a shield rather than placing a shield between the control board and the receiver. This would protect the receiver better and avoid affecting commands sent from the transmitter.  In fact, based on these results, I suspect shielding the GPS receiver on a drone is always a good idea.

Zero baseline experiment

I’ve been busy with some consulting projects recently so it’s been a while since my last post but I’m finally caught up and had some time to write something.  I thought I would describe an experiment I did to both try out the “fixed” mode in RTKLIB and also provide some insight into the composition of the errors in the pseudorange and carrier phase measurements in the u-blox M8T receiver.

The “fixed” mode is an alternative to “static” or “kinematic” in which the exact rover location is specified as well as the base position and remains fixed.  The residual errors are then calculated  from the actual position rather than the measured position.  I describe it in a little more detail in this post.  It is intended to be used as a tool to characterize and analyze the residual errors in the pseudorange and carrier phase measurements.

The basic idea in this experiment was to connect two M8T receivers to a single antenna and then compare residuals between the two receivers.  I first looked at the solution using one receiver as base and the other as rover (the zero baseline case) and then compared solutions between each receiver and a local CORS reference station about 8 km away.

The M8T is typically setup to use an active antenna for which it provides power on the antenna input.  I was concerned about connecting the two antenna power feeds together, so to avoid this, I added a 47 pf capacitor in series in one of the antenna feeds to act as a DC block.  In the photo below, the capacitor is inside the metal tape wrapped around a male to male SMA adapter.  I cut the adapter in half, soldered the capacitor to each end, then wrapped it in metal tape as a shield.

zeroBL

The receivers are from CSG and each one is connected to a Next Thing CHIP single board computer, which logs the data and transmits it over wireless to my laptop.  They are very similar to the Raspberry Pi data loggers I described in a previous post, but the on-board wireless makes them more convenient to use.  At $9 each, they are also quite affordable, especially since they do not need micro SD cards like the Raspberry Pi Zeros.  They also have a built-in LiPo battery connector which can be convenient for providing power., although they can also be powered over the USB connectors.  They are also linux based, so setting them up is very similar to the instructions in my Raspberry Pi post.

I first looked at the zero baseline case where I used one receiver as base and the other as rover.  In this case the two receivers are seeing exactly the same signal from the single antenna.  Any error contributions from the satellites, atmosphere, or antenna should cancel and the only contributor to the residual errors should be from the receivers.

I collected about an hour of measurement data from my back patio.  It is next to the house and nearby trees so as usual, the data quality is only mediocre and will include both some multipath and signal attenuation.  I prefer to look at less than perfect data because that is where the challenges are, not in the perfect data sets collected in wide-open skies.

Here are the residuals for a high elevation, high signal strength GPS satellite.  Standard deviations are 0.24 meters for the pseudorange and 0.0008 meters for the carrier phase.

zeroBL1

For a lower elevation GPS satellite with low and varying signal strength, the standard deviations increased to 0.46 meters for the pseudorange and 0.0017 meters for the carrier phase.  Notice how the residuals increase as the signal strength decreases as you would expect.

 

zeroBL2

The GLONASS satellites had noticeably higher residuals.  Here is an example of a satellite with high elevation and reasonable signal strength.  The standard deviations were 1.02 meters for pseudorange and 0.0039 meters for carrier phase, more than twice the GPS residuals.

zeroBL3

I’m not quite sure how relevant it is, but the ratio between the pseudorange residuals and carrier phase residuals in each case is roughly 300, the same value I have found works best for “eratio1”, the config file input parameter that specifies the ratio between the two.

RTKLIB also estimates the standard devations of the GLONASS satellites measurements at 1.5 times the standard deviations of the GPS satellites which is less than the difference I see in the example above.

However, my numbers are for only the receiver components of the measurement errors, I’m not sure exactly which components the RTKLIB config parameters are intended to include.

For the second experiment, I calculated solutions for both receivers relative to a CORS reference station about 8 km away.  In this case, I was curious to see how close the two solutions are as they will have common satellite, atmospheric, and antenna errors but will differ in their receiver errors.  The plot below shows the residuals for a GPS satellite from each solution plotted on top of each other.  As you can see the errors are quite a bit larger than before and the correlation between the two receivers is very high.  Based on the frequency of the errors, I suspect they are dominated by multipath which will vary roughly sinusoidally as the direct path and reflected path go in and out of phase with each other.

I found it quite impressive to see how repeatable the errors are between the two solutions.  It indicates, at least at this distance, that the errors from the receiver are small compared to the other errors in the system.zeroBL4

Again, the GLONASS results were not as good as the GPS results and include a DC shift in the carrier phase that I’m not sure exactly what the cause is.

zeroBL5

I haven’t spent a lot of time trying to figure out how to best use the information in these plots but in particular I found the similarity between the two receiver solutions in the longer baseline experiment quite encouraging.  If the errors are dominated by multipath as I expect, then the baseline length isn’t that relevant and I would expect to see similar results with shorter baselines.  If that’s true, then it may be possible to derive information about the receiver’s environment from the multipath data.  People do this with more expensive dual frequency receivers to monitor things like tides and ground moisture content.  It would be interesting to see if it can be done with these low cost receivers.  Or maybe it already has been done …