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.

 

 

 

 

 

Advertisements

Exploring moving-base solutions

Recently, I’ve had several questions about moving-base solutions so that will be the topic for this post.

As you might guess from the name, a moving-base solution differs from the more common fixed-based solutions in that the base station is allowed to move in addition to the rover.   Although it could be used to track the distance between two moving rovers it is more commonly used in a configuration with two receivers attached to a single rover and used to determine heading. Since the receivers remain at a fixed distance from each other, the solution in this case becomes a circle with a radius equal to the distance between the receivers.  The location on this circle corresponds to the rover’s heading which is easily calculated using a four quadrant arctan of the x and y components of the position.  I also used moving base solutions in several of my earliest posts because the circular nature of the solution makes it easier to verify the solution and to measure errors.  Since all solution points should be on the circle, any deviation from the circle can be assumed to be error.

To be more exact, everywhere I mention “circle” above I really should say “sphere” instead since the solution has three dimensions, but if the rover is ground-based, the movements in the z-axis will be relatively small and for simplicity we can assume it is a circle.

In fixed-base solutions, the measurement rate of the base station is often lower than the rover both because it’s location is not changing and also because the base data often has to be transmitted over a data link which may be bandwidth limited.  In a moving-base solution, since both receivers are moving, and there is usually no need for a data link since they are both attached to the same rover, it makes sense to use the same data rate for both receivers.

For this exercise, I chose to use a data set I discussed previously in my “M8N vs M8T” series of posts.  It consists of two receivers, an M8N and an M8T, on top of a moving car and another M8T receiver used as a fixed base station.  The car drives on roads with a fairly open sky view for up to a couple kilometers away from the base station.  The base station is located next to some sheds and a tree, so is not ideal, but still has fairly open skies.  All three receivers  ran at 5 Hz sampling rate and both moving receivers have some missing samples.  I’m not sure exactly why this is, it may be because I used a single laptop to collect both data streams.  Regardless of where they come from, I have found occasional missing samples are fairly common whenever I collect data at higher sample rates and believe the solution should be robust enough to handle them.  The rover M8T data also has a simultaneous cycle-slip type receiver glitch near the beginning of the data as described in my last post.  Overall, I would consider this a moderately challenging data set but those are often the best kind for testing the limits of RTKLIB.

union1

Having data from three receivers gives us the luxury of being able to calculate three different solutions (base->rover1, base->rover2, and rover1->rover2) and then compare results between them.  Since the first two solutions are fixed-base and the third is a moving-base, it also allows us to validate the moving-base solution using a combination of the two fixed-base solutions.

To start with, let’s calculate solutions for the distance between each moving receiver relative to the fixed base station using the demo5 code and my standard config files for the M8N and M8T receivers.  The only difference between the two config files is that the GLONASS ambiguity resolution (gloarmode) is set to “fix-and-hold” for the M8N config file and to “on” for the M8T config file for reasons explained in previous posts.   I’ve also done the conversion from raw data to RINEX observation files with the TRK_MEAS and STD_SLIP receiver options set to 2 and 4 respectively, again for reasons previously explained.  I set the solution mode to “static-start” since I knew the data set started with the rover stationary for long enough to get a first fix but I also could have used “kinematic” mode.

Subtracting the two fixed-base solutions gives us the distance between the two rover receivers which should be equal to a moving-base solution calculated directly between the two rovers.  The only difference is that the errors will be larger in the difference of two solutions than they will be in the direct solution because the errors in the combined solutions will accumulate.

Here are the positions and ground track for the difference between the two solutions, using the “1-2” plotting option in RTKPLOT.  As expected we get a circle for the ground track.  From the radius of the circle we can tell that the two rovers were about 15 cm apart.  Usually you would put the two receivers as far apart as possible, since the errors in the heading will decrease as the distance between the rovers increases but in this case I hadn’t intended to use the results this way so had placed the rovers closer together.  Still, it might be representative of a configuration on a small drone or other small rover.

movebase5

Next let’s try to calculate the solution directly between the two moving receivers.  RTKLIB does have a special “moving-base” mode but we won’t use this yet.  The “kinematic” solution calculates the distance between the two rovers regardless of the location of the base, so for now we can ignore the fact that the base is moving.  This will breakdown eventually if the rover gets too far from the base but since in this data set the rover is only a couple kilometers from the base at its farthest point we should be OK.

The only change I made to the config file from the previous M8N run for this run was to reduce the acceleration input parameters “stats-prnaccelh” and “stats-prnaccelv” which are used to describe the acceleration characteristics of the rover in the horizontal and vertical directions relative to the base.  In the fixed-base solution, these need to include both the linear accelerations and rotational accelerations since the rover is moving and the base is fixed, but in the moving-base solution, since we care only about differential acceleration between the receivers, we can ignore the linear accelerations and include only the rotational accelerations.  I just used a rough guess and reduced the numbers from (1,0.25) to (0.25,0.1) but I could have found more exact numbers by looking at the acceleration plot of an initial run of the solution.

Here’s the solution using this configuration.  It looks reasonable except for the occasional large spikes.

movebase2

After a little debugging, I found that the spikes were occurring wherever there was a missing sample in the base data.  When this occurs, RTKLIB just uses the previous base sample.  This works fine when the base is not moving, but in this case that’s no longer true, and the previous base measurements are not good estimates of the current position.  We can tell RTKLIB to skip these measurements by setting the maximum age of differential to something less than one sample time.  This is done with the “pos2-maxage” input parameter.  I set it to 0.1 which is half of one sample time.

With this change, I got the following solution for the position.  Much better!

movebase3

The ground track for this solution is shown below on the right, on the left is the previous ground track derived by subtracting the two fixed-base solutions.  As expected, the solutions look very similar except the moving-base solution has smaller errors which appear as deviations from a perfect circle.

movebase1

To further validate this solution we can compare the heading calculated from the moving-base position with the heading determined from the velocity vector of the fixed-base solution.  This wouldn’t work if the rover were a boat, drone, or person, but in the case of a car there are no external lateral drifts and the car will move in the direction it is pointed (unless it’s in reverse of course).   This won’t work if the velocity is zero or near zero but for reasonably high velocities we should get a good match.  The top plot below shows the difference between the two.  The blue line is for all velocities and the red is for when the velocity drops below 5 m/s.  The bottom plot shows the distance from the base to the rover.

movebase4

As expected, the errors are large when the velocities are low but we get a good match otherwise.  There also appears to be no correlation between the errors and the base to rover distance which suggests we are well below the maximum base to rover distance before we start to see issues with our assumption that the base did not move.

Overall, this solution looks excellent, with 100% fix and based on deviations from the circle, very small errors.  In fact, I recommend this configuration over the RTKLIB “moving-base” solution if you are able to live within the maximum baseline constraints.  I don’t know how large that is, but it looks like it may be significantly larger than 2 kilometers which is probably large enough for most applications.

In the next post I will explore what happens when the RTKLIB solution mode is set to “movingbase” in more detail but for now let me bring up just one of its effects since it is something we can also do here without invoking “movingbase” mode and it may have some benefit.

RTKLIB uses an extended kalman filter which is designed to handle non-linearities in the system by linearizing around the current operating point.  This generally works quite well but as the system becomes more non-linear, the errors introduced by this approximation grow larger.  One way to deal with this is to run multiple iterations of the kalman filter every measurement sample to converge on the correct answer.  As we get closer to the correct answer, we will operate closer to the point around which the system has been linearized and the errors will be smaller.  There is an input parameter in RTKLIB called “pos2-niter” that specifies the number of filter iterations for each sample.  The default value is one but when “posmode” is set to “movingbase” two iterations are automatically added to whatever this value is set to.  In the default case, we would get three iterations every sample instead of one.  Since the kalman filter assumes all velocities are linear and in the moving-base case we have been looking at, they are all rotational and non-linear, it might make sense to do this.  In my example, the sample rate is quite high relative to the rate of rotation and I found it did not help, but in other cases where the rate of rotation is higher relative to the sample rate, it might be a good idea.

So, let me finish by summarizing the changes I recommend for moving-base solutions.

  1.  Set measurement sample rate for both rover and base to the same value
  2. Leave “pos1-posmode” set to “kinematic” or “static-start”
  3. Set “pos2-maxage” to half the sample time (e.g 0.1 for 5 samples/sec)
  4. Reduce “stats-prnaccelh” and “stats-prnaccelv” to reflect differential accelearation
  5. Experiment with increasing “pos2-niter” from 1 to 3

These recommendations are based on my fairly limited experience with moving-base solutions so if anybody else has other recommendations, please respond in the Comments section.

I have added the data set I used here to the data sets available for download on rtkexplorer.com for anyone who would like to experiment further with this data.

In the next post, I will talk more about what happens when “pos1-posmode” is set to “movingbase”.

 

 

Raw Residuals Analysis and Measurement Quality

A couple posts back I mentioned that it should be fairly easy to measure the solution residuals in order to validate or disprove my somewhat arbitrary choice to increase the “stats-eratio1” input parameter from its default value of 100 to 300. So, I decided to go ahead and do it. Like many things, it turned out to be not quite as easy or as definitive as I had hoped it would be, but I will share in this post what I found.

For those of you who don’t have the definitions of all 99 different RTKLIB input options at the tips of your fingers, eratio1 is basically an estimate of how much more accurate the receiver’s carrier-phase measurements are than the pseudorange measurements. Specifically it is defined as the ratio of the standard deviations of the two. The standard deviations of the measurements are used by the kalman filter to weight the relative importance of each measurement.

RTKLIB has a couple of features that will help do this analysis. First of all, the residuals for each satellite for each epoch are recorded in the stats file. The residuals are the difference between the estimated distance from the receiver to each satellite (range) and the actual range measurements after adjusting them to remove errors. There are separate residuals recorded for both the pseudorange and the carrier-phase measurements.

What we are interested in is the measurement errors rather than the measurement residuals, which are slightly different from each other. The residuals are calculated as the difference from the estimated ranges while the errors are calculated as the difference from the actual ranges. The estimated ranges in this case are derived from a best fit of the measurement data .

Fortunately, RTKLIB has a solution mode we haven’t talked about before, the “Fixed” mode which is specifically intended for doing this sort of residual analysis. It is similar to static in that it is assumed that the rover is stationary.  In this mode, however, we give RTKLIB the exact locations of both the base and the rover and it then calculates the residuals based on the inputted rover location rather than the estimated rover positions.  The position output does not vary from sample to sample as it does in “Static” mode and remains fixed at the value specified in the input parameters.  In reality I’m not sure how much difference this makes for the level of analysis we are doing here. I actually ran the experiment twice, once in “Fixed” mode and once in “Static” mode and got fairly similar answers. The results I show here though are all from the “Fixed” mode solution.

To collect some data for this experiment, I set up three receivers within a couple of meters of each other, two M8T receivers and one M8N receiver. I chose a location fairly close to a house and also close to several trees to replicate a less than ideal situation since I’d like to optimize the input parameters for a more challenging environment. There is more margin in ideal conditions so tuning of the input parameters should be less critical then. I collected roughly four hours of measurements at a one second sample rate from each of three receivers and also pulled the same four hours of data from a nearby CORS reference station. This gave me several combinations of different receiver combinations and baselines to include in the analysis.

RTKLIB estimates measurement uncertainties as a function of satellite elevation and satellite system so I split my data up that way as well. I won’t bother to label each line in the plots below but each line represents one satellite system and one combination of receivers. The upper plot is for a short baseline, and the lower plot is for a long baseline. The x-axis represents satellite elevation. Each point is the standard deviation of errors from all epochs from all satellites in that system over a range of five degrees of elevation. The data below 15 degrees is not very relevant to this experiment since I usually set the elevation threshold to throw out those measurements. There is no SBAS data in the long baseline plots because the CORS station does not include the SBAS satellites.

residual1

So how we do interpret this data. As you can see from the plots, the ratio of the standard deviations varies from roughly 100 to 300 most of the time. That doesn’t help a lot since the purpose of this experiment was to help decide between 100 and 300. Maybe it should make everybody happy since if you like 100, you can probably use this data to justify that number and if you like 300, you could use this data to justify that instead. Still I find it useful to know neither answer is terribly wrong and that it is probably OK to adjust the value within this range to what you find works best. Sometimes in cases like this it makes sense to use a conservative value which could be defined as either 100 or 300, and sometimes it makes sense to use a mean, which in this case would be about 200.

I will probably change my default setting from 300 to 200 and use that unless I find that causes a degradation in my results.

Below I have also plotted the standard deviations for the two measurements since they are of interest as well, particularly the carrier-phase numbers since RTKLIB also estimates those based on the input parameters stats-errphase, stats-errphaseel and stats-errphasebl. I will leave analysis of this data to a future post as well as looking at independent estimates that are made by the Ublox receivers themselves.

residual2

residual3

In order to avoid cluttering the discussion above I left out some of the details of calculating the standard deviations, particularly the handling of non-zero means. The errors in the measurements range in frequency from very low to high. The very low frequency or possibly DC errors do not average to zero in four hours and show up as non-zero means over the full data set. I removed these means since I felt they were caused by factors not relevant to this experiment and they do not affect the standard deviations anyways. Other errors are higher frequency and do average to zero over the length of time each satellite spanned five degrees of elevation. Since this was the bucket size of my analysis, I did not need to do any mean adjustment for these.

There are also errors that are slowly varying and while they average out to zero over the full four hours, do not average to zero over the five degree buckets. These errors get under-estimated in the standard deviation since the slicing of the errors into five degree segments effectively acts as a high-pass filter to the standard deviation calculation. To compensate for this effect, instead of calculating the standard deviation of [x], I used [x -x]. For a zero-mean population the two calculations will give identical results but for a non-zero mean population, the second calculation will give a better estimate of what the standard deviation would have been without the high-pass filtering. The reason I removed the means of the full data set as described above is that even though they don’t affect the normal standard deviation measurement they would have affected this modified calculation.

I don’t believe any of these adjustments significantly affected the result, but I do believe they should improve its accuracy. This is somewhat subjective though and another person’s analysis would probably be at least slightly different.

RTKLIB: Customizing the input configuration file

[Update 4/21/17: Added updates for new features through Demo5 B26B as well as additional info on existing features]

One of the nice things about RTKLIB is that it is extremely configurable and has a whole slew of input options available. Unfortunately these can be a bit overwhelming at times, especially for someone new to the program. The RTKLIB manual does briefly explain what each option does, but even with this information it can be difficult to know how best to choose values for some of the parameters.

I won’t try to give a comprehensive explanation of all the input options here, but will explain the ones I have found useful to adjust in my experiments and include a little about why I chose the values I did. I describe them as they appear in the configuration file rather than how they appear in the RTKNAVI GUI menu but the comments apply to both. I created this list by comparing my latest config files to the default config file and noting which settings were different. The values in the list below are the values I use in my config file for a 5 Hz rover measurement rate.  The same config files can be used for either RTKNAVI, RTKPOST, or RNX2RTKP.

The settings and options highlighted in blue below are available only in my demo code and not in the release code but otherwise much of what I describe below will apply to either code.  Most of my work is done with Ublox M8N and M8T receivers with short baselines and these settings will more directly apply to those combinations but should be useful at least as a starting point for other scenarios.

SETTING1:

pos1-posmode = static, kinematic, static-start, movingbase, fixed

If the rover is stationary, use “static”. If it is moving, “kinematic” or “static-start”. I always require the rover to be stationary long enough to get first fix, in which case “static-start” usually works better because it take advantage of the knowledge that the rover is not moving initially. Use “movingbase” if the base is moving as well as the rover. In this case be sure to set “pos2-baselen” and “pos2-basesig” as well. Use “fixed” if you know the rover’s exact location and are only interested in analyzing the residuals.

pos1-frequency = l1

L1 for single frequency receivers,  L1+L2 if the rover is dual frequency

pos1-soltype = forward, backward, combined

This is the direction in time that the kalman filter is run. For real-time processing, “forward” is your only choice. For post-processing, “combined” first runs the filter forward, then backwards and combines the results. For each epoch, if both directions have a fix, then the combined result is the average of the two with a fixed status unless the difference between the two is too large in which case the status will be float. If only one direction has a fix, that value will be used and the status will be fixed. If both directions are float then the average will be used and the status will be float. Results are not always better with combined because a false fix when running in either direction will usually cause the combined result to be float and incorrect. The primary advantage of combined is that it will usually give you fixed status right to the beginning of the data while the forward only solution will take some time to converge. The 2.4.3 code resets the bias states before starting the backwards run to insure independent solutions. The demo5 code doesn’t reset the bias states to avoid having to lock back up when the rover is moving.  I only use the “backward” setting for debug when I am having trouble getting an initial fix and want to know what the correct satellite phase-biases are.

pos1-elmask = 15 (degrees)

Minimum satellite elevation for use in calculating position. I usually set this to 15 degrees to reduce the chance of bringing multipath into the solution but this setting will be dependent on the rover environment. The more open the sky view, the lower this value can be set to.

pos1-snrmask-r = off, pos1-snrmask-b = off,on

Minimum satellite SNR for rover (_r) and base(_b) for use in calculating position. Can be a more effective criteria for eliminating poor satellites than elevation because it is a more direct measure of signal quality but the optimal value will vary with receiver type and antenna type so I leave it off most of the time to avoid the need to tune it for each application.

pos1-snrmask_L1 =35,35,35,35,35,35,35,35,35

Set SNR thresholds for each five degrees of elevation. I usually leave all values the same and pick something between 35 and 38 db depending on what the nominal SNR is. These values are only used if pos1-snrmask_x is set to on

pos1-dynamics = on

Enabling rover dynamics adds velocity and acceleration states to the kalman filter for the rover. It will improve “kinematic” and “static-start” results, but will have little or no effect on “static” mode. The release code will run noticeably slower with dynamics enabled but the demo5 code should be OK. Be sure to set “prnaccelh” and “prnaccelv” appropriately for your rover acceleration characteristics.  Rover dynamics is not compatible with “moving-base” mode, so turn it off when using that mode.

pos1-posopt1 = off, on (Sat PCV)

Set whether the satellite antenna phase center variation is used or not. Leave it off for RTK but you set it for PPP. If set to on, you need to specify the satellite antenna PCV file in the files parameters.

pos1-posopt2 = off, on (Rec PCV)

Set whether the receiver antenna phase center variations are used or not. If set to on, you need to specify the receiver antenna PCV file in the files parameters and the type of receiver antenna for base and rover in the antenna section. Only survey grade antennas are included in the antenna file available from IGS so only use this if your antenna is in the file. It primarily affects accuracy in the z-axis so it can be important if you care about height. You can leave this off if both antennas are the same since they will cancel.

pos1-posopt5 = off, on (RAIM FDE)

If the residuals for any satellite exceed a threshold, that satellite is excluded. This will only exclude satellites with very large errors but requires a fair bit of computation so I usually leave this disabled.

pos1-exclsats=

If you know a satellite is bad you can exclude it from the solution by listing it here. I only use this in rare cases for debugging if I suspect a satellite is bad.

pos1-navsys = 7, 15,

I always include GLONASS and SBAS sats, as more information is generally better.  If using the newer 3.0 u-blox firmware with the M8T I also enable Galileo

 

SETTING2:

pos2-armode = continuous, fix-and-hold

Integer ambiguity resolution method. I like to think of continuous mode as an acquisition mode and fix-and-hold as a tracking mode. I normally use continuous mode for static solutions and fix-and-hold for moving rovers but if the raw measurement quality is good enough to maintain ambiguity resolution when the rover is moving then it is probably better to use continuous mode for moving rovers as well. This will avoid the risk of locking on to a false fix. If in continuous mode, a false fix will usually drop out fairly quickly but fix-and-hold will track a false fix for much longer. If “armode” is not set to “fix-and-hold” then any of the options below that refer to holds don’t apply, including pos2-gloarmode.

pos2-varholdamb=0.001, 1.0 (meters)

Starting with the demo5 b26b code, the tracking gain for fix-and-hold can be adjusted with this parameter. It is actually a variance rather than a gain, so larger values will give lower gain. 0.001 is the default value, anything over 100 will have very little effect. This value is used as the variance for the pseudo-measurements generated during a hold which provide feedback to drive the bias states in the kalman filter towards integer values.  I find that values from 0.1 to 1.0 provides enough gain to assist with tracking while still avoiding tracking of false fixes in most cases.

pos2-gloarmode = on, fix-and-hold

Integer ambiguity resolution for the GLONASS sats.  If your receivers are identical, you can usually set this to “on” which is the preferred setting since it will allow the GLONASS sats to be used for integer ambiguity resolution during the initial acquire. If your receivers are different or you are using two u-blox M8N receivers you will need to null out the inter-channel biases with this parameter set to “fix-and-hold” if you want to include the GLONASS satellites in the AR solution. In this case the GLONASS sats will not be used for inter-channel ambiguity resolution until after the inter-channel biases have been calibrated which begins after the first hold. There is an “autocal” option as well, but I have never been able to make this work.

pos2-gainholdamb=0.01

Starting with the demo5 b26b code, the gain of the inter-channel bias calibration for the GLONASS satellites can be adjusted with this parameter. Although not fully tested, the hope is that in addition, this parameter in conjunction with pos2-varholdamb will enable the possibility to null out the inter-channel biases for the GLONASS satellites when the tracking effect of fix-and-hold on the GPS satellites is not desired (i.e.. effectively continuous mode). This would be done by setting pos2-gainholdamb to a nominal value and setting pos2-varholdamb to a very large variance to push it’s tracking gain to near zero.

pos2-arthres = 3

This is the threshold used to determine if there is enough confidence in the ambiguity resolution solution to declare a fix. It is the ratio of the squared residuals of the second-best solution to the best solution. I generally always leave this at the default value of 3.0 and adjust all the other parameters to work around this one. Although a larger AR ratio indicates higher confidence than a low AR ratio, there is not a fixed relationship between the two. The larger the errors in the kalman filter states, the lower the confidence in that solution will be for a given AR ratio. Generally the errors in the kalman filter will be largest when it is first converging so this is the most likely time to get a false fix. Reducing pos2-arthers1 can help avoid this.  A larger number of satellites used for AR will increase the confidence level for a given threshold, so in theory at least, it makes sense to increase this if you are typically working with a larger number of satellites than normal.

pos2-arfilter = on

Setting this to on will qualify new sats or sats recovering from a cycle-slip. If a sat significantly degrades the AR ratio when it is first added, its use for ambiguity resolution will be delayed. Turning this on should allow you to reduce “arlockcnt” which serves a similar purpose but with a blind delay count.

pos2-arthres1 = 0.004

Integer ambiguity resolution is delayed until the variance of the position state has reached this threshold. It is intended to avoid false fixes before the bias states in the kalman filter have had time to converge. It is particularly important to set this to a relatively low value if you have set eratio1 to values larger than 100 or are using a single constellation solution. If you see AR ratios of zero extending too far into your solution, you may need to increase this value since it means ambiguity resolution has been disabled because the threshold has not been met yet. I find 0.004 to 0.10 usually works well for me but if your measurements are lower quality you may need to increase this to avoid overly delaying first fix or losing fix after multiple cycle slips have occurred.

pos2-arthres2, pos2-arthres3, pos2-arthres4

Defined but not used anywhere in the code, best to remove these from your config file

pos2-arlockcnt = 0, 5  

Number of samples to delay a new sat or sat recovering from a cycle-slip before using it for integer ambiguity resolution. Avoids corruption of the AR ratio from including a sat that hasn’t had time to converge yet. Use in conjunction with “arfilter”. Note that the units are in samples, not units of time, so it must be adjusted if you change the rover measurement sample rate.  I usually set this to zero for u-blox receivers which are very good at flagging questionable observations but set it to at least five for other receivers.

pos2-minfixsats = 4

Minimum number of sats necessary to get a fix. Used to avoid false fixes from a very small number of satellites, especially during periods of frequent cycle-slips.

pos2-minholdsats = 5

Minimum number of sats necessary to hold an integer ambiguity result. Used to avoid false holds from a very small number of satellites, especially during periods of frequent cycle-slips.

pos2-mindropsats = 10

Minimum number of sats necessary to enable exclusion of a single satellite from ambiguity resolution each epoch.  In each epoch a different satellite is excluded.  If excluding the satellite results in a significant improvement in the AR ratio, then that satellite is removed from the list of satellites used for AR.

pos2-rcvstds = on,off

Enabling this feature causes the the measurement variances for the raw pseudorange and phase measurement observations to be adjusted based on the standard deviation of the measurements as reported by the receiver. This feature is currently only supported for u-blox receivers. The adjustment in variance is in addition to adjustments made for satellite elevation based on the stats-errphaseel parameter.  I generally get better results with this turned off.

pos2-arelmask = 15

Functionally no different from the default of zero, since elevations less than “elmask” will not be used for ambiguity resolution but I changed it to avoid confusion.

pos2-arminfix = 100  (20*sample rate)

Number of consecutive fix samples needed to hold the ambiguities. Increasing this is probably the most effective way to reduce false holds, but will also increase time to first hold. Note that this value also needs to be adjusted if the rover measurement sample rate changes.

pos2-elmaskhold = 15

Functionally no different from the default of zero, since elevations less than “elmask” will not be used for holding ambiguity resolution results but I changed it to avoid confusion.

pos2-aroutcnt = 100 (20*sample rate)

Number of consecutive missing samples that will cause the ambiguities to be reset. Again, this value needs to be adjusted if the rover measurement sample rate changes.

pos2-maxage = 100

Maximum delay between rover measurement and base measurement (age of differential) in seconds. This usually occurs because of missing measurements from a misbehaving radio link. I’ve increased it from the default because I found I was often still getting good results even when this value got fairly large, assuming the dropout occurred after first fix-and-hold.

pos2-rejionno = 1000

Reject a measurement if its pre-fit residual is greater than this value in meters. I have found that RTKLIB does not handle outlier measurements well, so I set this large enough to effectively disable it. There was a recent bug fix in the release code related to outliers but even with this fix I found that I got better results with a larger value.

 

OUTPUT:

out-solformat = enu, llh, xyz

I am usually interested in relative distances between rover and base, so set this to “enu”. If you are interested in absolute locations, set this to “llh” but make sure you set the exact base location in the “ant2” settings. Be careful with this setting if you need accurate z-axis measurements. Only the llh format will give you a constant z-height if the rover is at constant altitude. “Enu” and “xyz” are cartesian coordinates and so the z-axis follows a flat plane, not the curvature of the earth. This can lead to particularly large errors if the base station is located farther from the rover since the curvature will increase with distance.

out-outhead = on

No functional difference to the solution, just output more info to the result file.

out-outopt = on

No functional difference to the solution, just output more info to the result file.

out-outstat = residual

No functional difference to the solution, just output residuals to a file. The residuals can be very useful for debugging problems with a solution.

stats-eratio1 = 300

Ratio of the standard deviations of the pseudorange measurements to the carrier-phase measurements. I have found a larger value works better for low-cost receivers, but that the default value of 100 often work better for more expensive receivers since they have less noisy pseudorange measurements. Larger values tend to cause the kalman filter to converge faster and leads to faster first fixes but it also increases the chance of a false fix. If you increase this value, you should set pos2-arthres1 low enough to prevent finding fixes before the kalman filter has had time to converge. I believe increasing this value has a similar effect to increasing the time constant on a pseudorange smoothing algorithm in that it filters out more of the higher frequencies in the pseudorange measurements while maintaining the low frequency components.

stats-prnaccelh = 1.0

If receiver dynamics are enabled, use this value to set the standard deviation of the rover receiver acceleration in the horizontal components. This value should include accelerations at all frequencies, not just low frequencies. It should characterize any movements of the rover antenna, not just movements of the complete rover so it may be larger than you think. It will include accelerations from vibration, bumps in the road, etc as well as the more obvious rigid-body accelerations of the whole rover.

stats-prnaccelv = 0.25

The comments about horizontal accelerations apply even more to the vertical acceleration component since in many applications the intentional accelerations will all be in the horizontal components. It is best to derive this value from actual GPS measurement data rather than expectations of the rigid-body rover. It is better to over-estimate these values than to under-estimate them.

ant2-postype = rinexhead, llh, single

This is the location of the base station antenna. If you are only interested in relative distance between base and rover this value does not need to be particularly accurate. For post-processing I usually use the approximate base station location from the RINEX file header. If you want absolute position in your solution, then the base station location must be much more accurate since any error in that will add to your rover position error. If I want absolute position, I first process the base station data against a nearby reference station to get the exact location, then use the ”llh” or “xyz”option to specify that location. For real-time processing, I use the “single” option which uses the single solution from the data to get a rough estimate of base station location.

ant2-maxaveep = 1

Specifies the number of samples averaged to determine base station location if “postype” is set to “single”. I set this to one to prevent the base station position from varying after the kalman filter has started to converge since that seems to cause long times to first fix. In most cases for post-processing, the base station location will come from the RINEX file header and so you will not use this setting. However if you are working with RTCM files you may need this even for post-processing.

Please help me update this list if you have had success adjusting other options or using different settings for these options, or if you disagree with any of my suggestions. I will treat this as a working document and continue to update it as I learn more.