GEOM-300 · Lesson 7 of 12 · 21 min

Carrier phase and ambiguity resolution

The canal's control network needed relative accuracies of about 5 mm horizontally and 10 mm vertically between points a few kilometres apart, because the canal drops only 0.25 m per kilometre and the hydraulic design was sensitive to the grades. No code measurement can deliver that. Ruth Albrecht set up static sessions of two hours on each pair of points and explained to Leah Tran that the whole method depends on one property of the carrier phase: it measures range in units of 19 cm, and if the receiver can work out exactly how many whole wavelengths separate it from each satellite, its millimetre precision becomes millimetre accuracy. Finding those whole numbers is ambiguity resolution, and this lesson is about how it is done and how to tell when it has gone wrong.

The carrier phase observation

In cycles, the carrier phase measured by receiver \(r\) from satellite \(s\) on one frequency is

\[\phi_r^s = \frac{1}{\lambda}\big(\rho_r^s - I_r^s + T_r^s\big) + f\,(dt_r - dt^s) + N_r^s + \delta_r - \delta^s + \varepsilon\]

where \(\lambda\) and \(f\) are the wavelength and frequency, \(N\) is the integer ambiguity and \(\delta\) are phase hardware delays in cycles. A receiver can measure \(\phi\) to about a hundredth of a cycle, two millimetres, but every term except the noise has to be known or eliminated before that precision can be used. Relative positioning eliminates most of them by differencing observations from two receivers that track the same satellites at the same time.

Single, double and triple differences

The single difference between receivers \(A\) and \(B\) for satellite \(j\), \(\phi_{AB}^j = \phi_B^j - \phi_A^j\), cancels the satellite clock and the satellite hardware delay, and largely cancels orbit and atmospheric errors when the receivers are close. It still contains both receiver clocks. The double difference subtracts two single differences to satellites \(j\) and \(k\):

\[\phi_{AB}^{jk} = \phi_{AB}^k - \phi_{AB}^j = \frac{1}{\lambda}\big(\rho_{AB}^{jk} - I_{AB}^{jk} + T_{AB}^{jk}\big) + N_{AB}^{jk} + \varepsilon_{AB}^{jk}\]

Both receiver clocks and all receiver hardware delays cancel, because they are the same for satellites \(j\) and \(k\) at each receiver. What remains is the double-differenced range, small residual atmospheric terms that grow with the baseline length, noise, and the double-differenced ambiguity, which is an integer because it is a sum and difference of four integers. Double differences are the standard observable of baseline processing: a session with \(n\) satellites provides \(n - 1\) independent double differences per epoch, all usually referred to one reference satellite, often the highest.

A diagram with two receivers A and B on the ground and two satellites j and k above them. Four signal lines connect each receiver to each satellite. Boxes beside the diagram list what each difference removes: the single difference between receivers removes the satellite clock and satellite biases; the double difference between satellites removes the receiver clocks and receiver biases; the triple difference between epochs removes the constant ambiguities.
Differencing carrier phases. Each difference removes a group of errors; double differences keep the integer ambiguity and remove all clocks.

The triple difference subtracts double differences at consecutive epochs. Because the ambiguity is constant while tracking continues, it cancels, leaving only the change in geometry. Triple differences give a rough, ambiguity-free solution useful as a starting point and are sensitive to cycle slips, which appear as an isolated spike, so they are used to find and repair slips before the main solution.

The program below builds phase observations for two receivers and two satellites with large clock errors and arbitrary integer ambiguities, and confirms that after double differencing the phase minus the geometric term is exactly the integer combination of ambiguities.

Double differences cancel clocks; rounding, bootstrapping and integer search compared on simulated float ambiguities.
# Double differences cancel clocks; then fix the float ambiguities to integers
import math, random, itertools
random.seed(11)
lam = 0.1903                                   # L1 wavelength, m

# 1. Clock terms vanish in a double difference
rho = {("B", 1): 20512345.678, ("B", 2): 21877001.234, ("R", 1): 20512301.112, ("R", 2): 21877050.991}
dt_rx = {"B": 3.1e-4, "R": -7.4e-5}; dt_sat = {1: 2.2e-5, 2: -1.6e-5}; c = 299792458.0
N = {("B", 1): 107791234, ("B", 2): 114962875, ("R", 1): 107791001, ("R", 2): 114963140}
phase = {k: rho[k] / lam + c * (dt_rx[k[0]] - dt_sat[k[1]]) / lam + N[k] for k in rho}   # cycles
dd_obs = (phase["R", 2] - phase["B", 2]) - (phase["R", 1] - phase["B", 1])
dd_geom = ((rho["R", 2] - rho["B", 2]) - (rho["R", 1] - rho["B", 1])) / lam
dd_N = (N["R", 2] - N["B", 2]) - (N["R", 1] - N["B", 1])
print("double-difference phase minus geometry:", round(dd_obs - dd_geom, 6), "cycles; integer ambiguity", dd_N)

# 2. Float solution of three double-difference ambiguities and its covariance (cycles^2)
true = [4, -7, 12]
Q = [[0.090, 0.071, 0.052], [0.071, 0.081, 0.047], [0.052, 0.047, 0.065]]
L = [[0.0] * 3 for _ in range(3)]               # Cholesky factor to draw correlated errors
for i in range(3):
    for j in range(i + 1):
        s = sum(L[i][k] * L[j][k] for k in range(j))
        L[i][j] = math.sqrt(Q[i][i] - s) if i == j else (Q[i][j] - s) / L[j][j]
def inv3(A):
    a, b, c_, d, e, f, g, h, i = A[0] + A[1] + A[2]
    det = a * (e * i - f * h) - b * (d * i - f * g) + c_ * (d * h - e * g)
    return [[(e * i - f * h) / det, (c_ * h - b * i) / det, (b * f - c_ * e) / det],
            [(f * g - d * i) / det, (a * i - c_ * g) / det, (c_ * d - a * f) / det],
            [(d * h - e * g) / det, (b * g - a * h) / det, (a * e - b * d) / det]]
W = inv3(Q)
def norm(x, z): d = [a - b for a, b in zip(x, z)]; return sum(d[i] * W[i][j] * d[j] for i in range(3) for j in range(3))

def bootstrap(x):
    x = list(x); out = []
    for i in range(3):          # fix one ambiguity, then condition the rest on it
        zi = round(x[i]); out.append(zi); delta = x[i] - zi
        for j in range(i + 1, 3):
            x[j] -= Q[j][i] / Q[i][i] * delta
    return out

def search(x):
    cands = itertools.product(*[range(round(v) - 2, round(v) + 3) for v in x])
    best = sorted(cands, key=lambda z: norm(x, z))[:2]
    return list(best[0]), norm(x, best[1]) / norm(x, best[0])

ok = {"rounding": 0, "bootstrapping": 0, "integer search": 0}; accepted = wrong_accepted = 0
for t in range(2000):
    g = [random.gauss(0, 1) for _ in range(3)]
    x = [true[i] + sum(L[i][k] * g[k] for k in range(3)) for i in range(3)]
    ok["rounding"] += [round(v) for v in x] == true
    ok["bootstrapping"] += bootstrap(x) == true
    z, ratio = search(x); ok["integer search"] += z == true
    if ratio > 3.0:
        accepted += 1; wrong_accepted += z != true
for k, v in ok.items():
    print(k.ljust(15), "success rate", format(100 * v / 2000, "5.1f"), "%")
print("ratio test > 3 accepted", format(100 * accepted / 2000, "4.1f"), "% of epochs;", wrong_accepted, "wrong fixes accepted")
Output
double-difference phase minus geometry: 498.0 cycles; integer ambiguity 498
rounding        success rate  84.5 %
bootstrapping   success rate  88.8 %
integer search  success rate  93.5 %
ratio test > 3 accepted 71.5 % of epochs; 10 wrong fixes accepted

The float solution

With the double-differenced ambiguities treated as real-valued unknowns, a least-squares adjustment of all epochs estimates the baseline components and the ambiguities together. This is the float solution. Its baseline is good to a few centimetres to a decimetre after an hour on a short baseline, but it converges slowly, because the ambiguities are only separated from the coordinates by the slow change of satellite geometry. The float ambiguities are correlated with each other and with the coordinates, often strongly. Their covariance matrix is the key to the next step.

Fixing ambiguities to integers

If the float ambiguities are close enough to their true integer values, fixing them to those integers and re-solving for the coordinates collapses the uncertainty of the baseline to the level of the phase noise, a few millimetres. This is the fixed solution. The difficulty is deciding which integers are correct. Three strategies of increasing sophistication are used.

Rounding each float ambiguity to the nearest integer ignores the correlations and works only when each ambiguity's standard deviation is well below a cycle. Bootstrapping fixes the ambiguities one at a time, most precise first, and after each fix updates the remaining float values using their correlation with the one just fixed; it is better than rounding and simple to compute. Integer least squares finds the vector of integers that minimizes the weighted distance to the float solution,

\[\check{\mathbf{z}} = \arg\min_{\mathbf{z} \in \mathbb{Z}^n} (\hat{\mathbf{a}} - \mathbf{z})^{\mathsf T}\, \mathbf{Q}_{\hat a}^{-1} (\hat{\mathbf{a}} - \mathbf{z})\]

and is optimal in the sense that it maximizes the probability of fixing correctly. Searching all integer vectors naively is slow when the float ambiguities are strongly correlated, because the search space is a long, thin ellipsoid. The LAMBDA method, published by Peter Teunissen in 1993, transforms the ambiguities by an integer-preserving transformation that decorrelates them, making the search space nearly spherical and the search fast, then transforms the answer back. It is used, in one form or another, in almost every precise GNSS processor.

The simulation in the program draws 2000 float solutions for three correlated double-differenced ambiguities with standard deviations of about 0.25 to 0.30 cycles and correlations near 0.8. Rounding succeeds 84.5 % of the time, bootstrapping 88.8 % and integer search 93.5 %. Even the best method fails on one epoch in fifteen, which is why ambiguity resolution needs validation.

Validation: is the fix right?

A wrong fix is worse than no fix. The coordinates are then biased by a multiple of the wavelength projected onto the baseline, typically several centimetres to decimetres, while the solution reports millimetre precision. Validation tests compare the best integer candidate with the second best. The most widely used is the ratio test: the ratio of the weighted squared distance of the second-best candidate to that of the best must exceed a threshold, commonly 2 or 3. A large ratio means the best candidate is clearly better than any alternative. In the simulation a threshold of 3 accepted 71.5 % of epochs and let through ten wrong fixes out of 2000 trials; a higher threshold would reject more wrong fixes at the cost of accepting fewer correct ones. More rigorous approaches use fixed failure-rate thresholds derived from the success rate computed from the float covariance.

Other practical checks follow. The fixed solution's residuals should be small and random, with a reference variance near one. Repeating the session at a different time, with different satellites, should give the same baseline within a few millimetres. And the baselines of a closed loop of points should sum to nearly zero. Ruth's rule for the canal network was that no baseline was accepted on its fixed solution alone: each point had to be connected by at least two independent baselines, observed in sessions at least a few hours apart.

Making ambiguities easier: wide lanes and multiple frequencies

The difficulty of fixing depends on the ratio of the uncertainty to the wavelength. The wide-lane combination of L1 and L2 has an 86 cm wavelength, and of L1 and L5 75 cm, so its ambiguities are easy to fix, often from a few epochs of the Melbourne–Wübbena combination, which is free of geometry and ionosphere. Once the wide-lane ambiguity \(N_1 - N_2\) is known, the remaining ambiguity can be fixed using the ionosphere-free combination, whose effective wavelength is then about 10.7 cm, the narrow lane. This cascade is standard in long-baseline and PPP processing. With three frequencies, an extra-wide-lane combination of L2 and L5 has a wavelength of almost 6 m and can be fixed almost instantaneously, which shortens convergence further.

Worked problem

Wide-lane ambiguity from the Melbourne–Wübbena combination

Over 200 epochs, the double-differenced Melbourne–Wübbena combination for one pair of satellites on L1 and L2 averages 5.1752 m, with a standard deviation of the mean of 0.012 m. The wide-lane wavelength is \(\lambda_{WL} = c/(f_1 - f_2) = 0.8619\) m. Find the wide-lane ambiguity and judge whether it can be fixed.

Show solution
  1. \[N_{WL} = \frac{\overline{MW}}{\lambda_{WL}} = \frac{5.1752}{0.8619} = 6.0044\ \text{cycles}\]
  2. \[\sigma_{N_{WL}} = \frac{0.012}{0.8619} = 0.014\ \text{cycles}\]
  3. \[|6.0044 - 6| = 0.004 \ll 0.25 \;\Rightarrow\; N_{WL} = 6\]

Answer: The float value is within 0.004 cycles of an integer and its standard deviation is only 0.014 cycles, so the wide-lane ambiguity is fixed confidently to 6. The long wide-lane wavelength is what makes this so easy compared with the 19 cm L1 wavelength.

Special cases

GLONASS FDMA signals complicate double differences, because each satellite has a different wavelength: the double difference no longer contains a pure integer unless the single-difference ambiguity of the reference satellite is known, and receiver inter-frequency biases differ between brands. Software handles this with calibrated biases or by fixing only part of the GLONASS ambiguities. Galileo, BeiDou and GPS CDMA signals have no such problem, and modern processors often fix them first. Mixing receiver brands at the two ends of a baseline can also cause quarter-cycle or half-cycle offsets between signal components; RTCM messages and processing software correct these when the receiver and antenna are described correctly.

When some ambiguities are poorly determined, for example those of low or recently risen satellites, partial ambiguity resolution fixes only a subset that passes validation and leaves the rest float. This is common in RTK and PPP, where it shortens the time to a usable solution.

Common mistakes

  • MistakeAccepting a fixed solution because the software reports one.

    InsteadCheck ratio or failure rate, residuals and independent repeats; wrong fixes look precise.

  • MistakeRounding strongly correlated ambiguities.

    InsteadUse integer least squares, as in LAMBDA, or at least bootstrapping.

  • MistakeUsing triple differences for the final solution.

    InsteadThey remove ambiguities and lose strength; use them to detect slips and to start the solution.

  • MistakeAssuming GLONASS double-differenced ambiguities are integers.

    InsteadFDMA wavelengths differ by satellite; inter-frequency biases must be handled.

  • MistakeExpecting a fix on a long baseline in minutes.

    InsteadResidual ionosphere grows with baseline length and slows or prevents fixing; use longer sessions or wide-lane strategies.

Summary and key terms

  • Carrier phase is precise to millimetres but ambiguous by an integer number of cycles.
  • Single differences remove satellite clocks; double differences also remove receiver clocks and keep an integer ambiguity.
  • Triple differences remove ambiguities and expose cycle slips.
  • Float solutions treat ambiguities as real numbers; fixed solutions constrain them to integers.
  • Integer least squares, implemented efficiently by LAMBDA, maximizes the probability of a correct fix.
  • Validation by ratio test, residuals and independent repeats guards against wrong fixes.
  • Wide-lane combinations with long wavelengths make ambiguity resolution easier.
Double difference
A difference of observations between two receivers and two satellites that cancels all clock errors.
Float solution
A solution in which ambiguities are estimated as real numbers.
Fixed solution
A solution in which ambiguities are constrained to integer values.
LAMBDA
Least-squares Ambiguity Decorrelation Adjustment, an efficient method for integer least-squares ambiguity resolution.
Ratio test
A validation test comparing the fit of the second-best and best integer candidates.
Wide lane
A phase combination with a long effective wavelength that eases ambiguity resolution.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. How many independent double differences does one epoch with 11 satellites provide?

    Show answer

    10.

  2. Which differences remove the satellite clock?

    Show answer

    The single difference between receivers, and therefore the double difference.

  3. The best candidate has a weighted distance of 1.8 and the second 7.9. Is the ratio test passed at 3?

    Show answer

    Ratio 4.4 > 3: passed.

  4. A wrong fix of one cycle on L1 is projected half onto the baseline. What bias results?

    Show answer

    About 0.5 × 19 cm ≈ 9.5 cm.

  5. What is the wavelength of the extra-wide lane L2 − L5?

    Show answer

    c / (1227.60 − 1176.45) MHz = 5.86 m.

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz