Introduction to RTKLIB ambiguity fixing mode and partial ambiguity fixing technology (with source code, based on RTKLIB)

Brief description of ambiguity fixation

From the point of view of the name, the pseudo-range is actually a distance, although the "distance" contains errors and large random noise; but when the receiver tracks the carrier for the first time, it can only know its initial phase clearly, and the phase in the signal propagation process There is no way to know the number of cycles clearly, and this number of cycles is the ambiguity we want to determine.

Although the pseudo-range accuracy is relatively low, multi-epoch filtering and even single-epoch solution with enough satellites can also reach the threshold of fixed ambiguity. The ambiguity of station-satellite double-difference can eliminate most of the errors. For example, inter-station single-difference can eliminate most of the atmospheric error and satellite orbit and clock errors; inter-satellite single-difference can eliminate errors related to hardware channel delay. The ambiguity after double difference has recovered its integer characteristics. If you use lambda search and pass the ratio test, you can calculate the fixed ambiguity solution by back substitution, achieving centimeter positioning accuracy.

But considering the transformation of the reference satellite, we do not directly estimate the double-difference ambiguity when estimating the parameters. As in the design in rtklib, the inter-station single-difference ambiguity is estimated in the state quantity, and the inter-satellite single-difference is performed when the ambiguity is fixed.

Ambiguity fixed mode and implementation in rtklib

There are three ambiguity fixation modes in rtklib:

continuous

Personally call it filter mode

This is a classic mode, basically mentioned in the kalman filtering papers, all of which are in this mode. That is, no cycle-slip ambiguity of adjacent epochs gives a minimal process noise. But if you use this mode to run the dynamic data collected by yourself, you will find that the fixed rate is not stable, sometimes it may be relatively high, but in most cases the fixed rate may be relatively low. For example, in the picture below, using the playground data collected by a classmate, there is no occlusion, and all systems are turned on and only the first frequency point is used to participate in positioning. The fixation rate is only 1.3%, which is unbelievably low. Even if the second and third frequency points are added, the fixed rate is still not optimistic. Why this mode is so bad, the possible reason is that rtklib data preprocessing is not perfect, and the accuracy of floating point solution is very poor.

instantaneous

single epoch mode

In this mode, there is no correlation between the ambiguities of adjacent epochs. If the positioning mode does not select the PVA mode, there is no correlation between all the state quantities of adjacent epochs, that is, each epoch performs a least square, and then directly Go try to fix the blurriness. The advantage of the single epoch mode is that the results of this epoch are only related to the current epoch, and there is no need to consider the problem of cycle slip processing or filter divergence. Of course, it is only related to the current epoch, which is also its disadvantage, and the correlation between epochs is not fully utilized. The configuration is exactly the same as that in the previous section, except that the fuzzy fixed mode is changed, and the fuzzy fixed rate reaches an astonishing 94%.

fix and hold

hold mode

This mode is based on the filtering mode. If the ambiguity is fixed correctly, it will constrain the fixed ambiguity to the floating-point filter. Of course, if the ambiguity is wrongly fixed, it will cause a large deviation in the floating-point solution, resulting in a long-term failure to fix.

partial ambiguity fixation

Part of the ambiguity is fixed. In fact, it has nothing to do with the fixed mode mentioned in the previous section. Any mode can use partial ambiguity to fix. If you are familiar with rtklib, you know that when the ambiguity is fixed, you can directly search the full set of ambiguity. If it fails the ratio test, it will be judged that the fixation failed, the fixation process will end, and then the floating-point solution of the ambiguity will be output.

Of course, we can filter the satellites participating in the fixation by setting the altitude angle of the satellites participating in the fixation in the configuration file, but an epoch will still only try to fix once, and some ambiguity fixation techniques are performed multiple times in an epoch The attempt of ambiguity fixation further improves the success rate of ambiguity fixation by optimizing the ambiguity subset.

The process is as follows:

If we think that satellites with higher satellite altitude angles have higher ambiguity accuracy and higher probability of being fixed successfully, then when selecting a fixed ambiguity subset, the satellites with higher satellite altitude angles can be deleted last, giving priority to Delete satellites with lower altitude angles. The principle is very simple. The implementation based on rtklib requires familiarity with its fixed process, especially the implementation process of inter-station single-difference ambiguity transfer station-satellite double-difference ambiguity, which will not be expanded here.

Code

First, in the ssat_t structure, add the following identifiers for each frequency of a single satellite to select ambiguity subsets.

uint8_t amb_flag[NFREQ]; /* ambiguity fix flag (0/1:no need to fix,2:try to fix,3: fix ref sat 4: fix) */
double amb_weight[NFREQ]; /* ambiguity weight for partial ambiguity resolution  */

At the same time, the altitude angle of the satellite is used for filling, and considering that the first frequency point observations of most consumer modules are relatively sufficient, we increase the weight of the first frequency point and delete the ambiguity information of other frequency points first. .

static void fillup_amb_weight_flag(rtk_t *rtk)
{
    int i, j, na = rtk->na;
    for (i = 0; i < MAXSAT; i++)
    {
        /* check the system to fix */
        int sys = satsys(i+1, NULL);
        if (sys == SYS_GLO && rtk->opt.glomodear == 0)
        {
            continue;
        }
        if (sys == SYS_CMP && rtk->opt.bdsmodear == 0)
        {
            continue;
        }
        for (j = 0; j < NFREQ; j++)
        {
            if (rtk->x[na + j * MAXSAT + i] == 0.0 ||
                !rtk->ssat[i].vsat[j] || !rtk->ssat[i].half[j])
            {
                continue;
            }
            if (rtk->ssat[i].lock[j] < 0 || (rtk->ssat[i ].slip[j] & 2) ||
                rtk->ssat[i].azel[1] < rtk->opt.elmaskar)
            {
                continue;
            }
            /* We simply use the elevation as the amb weight, future extend to other feature */
            rtk->ssat[i].amb_weight[j] = rtk->ssat[i].azel[1] * R2D;
            if (j == 0)
            {
                /* give more weight to L1 frequency */
                rtk->ssat[i].amb_weight[j] += 35.0;
            }
            rtk->ssat[i].amb_flag[j] = 2;
        }
    }
}

The main logic of adding partial ambiguity, the logic will call the original resamb_LAMBDA function of rtklib, the code is as follows:

/* partial resolve integer ambiguity by LAMBDA ---------------------------------------*/
static int resamb_partial(rtk_t *rtk, double *bias, double *xa) 
{
    int i, j;

    /* reset the ambiguity flag and weight */
    for (i = 0; i < MAXSAT; i++)
    {
        for (j = 0; j < NFREQ; j++)
        {
            rtk->ssat[i].amb_flag[j] = 0;
            rtk->ssat[i].amb_weight[j] = 0.0;
        }
    }
    fillup_amb_weight_flag(rtk);
    
    /* iteration for partial resolution */
    int nb = 0;
    while ((nb = resamb_LAMBDA(rtk, bias, xa)) <= 0)
    {
        /* find the min amb weight and mark */
        double min_weight = 999.9;
        int sat_idx = -1, freq_idx = -1;
        for (i = 0; i < MAXSAT; i++)
        {
            for (j = 0; j < NFREQ; j++)
            {
                if (rtk->ssat[i].amb_flag[j] >= 2)
                {
                    if(rtk->ssat[i].amb_weight[j] < min_weight)
                    {
                        min_weight = rtk->ssat[i].amb_weight[j];
                        sat_idx = i;
                        freq_idx = j;
                    }
                }
            }
        }
        if(sat_idx >=0 && freq_idx >= 0)
        {
            rtk->ssat[sat_idx].amb_flag[freq_idx] = 1;
        }

        /* check if have enough satellites to fix */
        if (sat_num_of_to_fix(rtk) <= 5)
        {
            return 0;
        }
    }
    return nb;
}
Of course, the ddidx function in the resamb_LAMBDA function has been changed to:
/* index for SD to DD transformation matrix D 
 * in this function, we use the ssat->amb_flag and ->amb_weight to 
 * select the ref satellite and to select the ambiguity subset to fix
 * */
static int ddidx_with_amb_weight_flag(rtk_t *rtk, int *ix)

For the implementation of this function, see the source code.

Test Results

Using the configuration of the instantaneous mode in the previous section, turn on the logic of partial ambiguity fixation, and the fixation rate increases from 94% to close to 99%.

the code

The background of the official account replies to git to obtain the address of the code cloud. After cloning to the local, please switch to the rtk branch to view.

No public

Sometimes codes or resources are placed on the personal official account. If you have any questions, you can reply in the background of the official account, and the answer is faster. Welcome to pay attention to GNSS and automatic driving

Guess you like

Origin blog.csdn.net/dong20081991/article/details/129223718