Skip to the content
FixTheRobot Explore Robotics / UAV / Module 2 / M2-T1

UAV Systems Engineering · Module 2

M2-T1: GNSS fundamentals

Four satellites, four unknowns: derive the pseudorange equation, solve it by Gauss–Newton, and see why geometry matters as much as signal.

  • Lesson 1 of 16
  • UAV Navigation and GNSS-Denied Operations
  • Established engineering
  • About 6 minutes to read

GNSS is the aerial robot’s global reference: the only sensor that does not drift. To design a system that survives its loss you first need to know what it actually measures, how accurate that is, and what can break it.

Learning objectives

After this lesson, you should be able to:

  • Write the pseudorange measurement equation and name its terms.
  • Explain why four satellites are required for a 3-D position and clock solution.
  • Solve for position and clock bias with Gauss–Newton least squares.
  • Interpret dilution of precision (DOP) as a geometry factor on position error.

Conceptual explanation

Each GNSS satellite broadcasts its position and the time at which it sent the signal. The receiver subtracts this from its own clock to get a travel time, multiplied by the speed of light: the pseudorange. It is “pseudo” because the receiver’s clock is cheap and wrong by an unknown amount, which adds the same error to every range.

Pseudorange positioningFour satellites at known positions each broadcast a time stamp. The receiver measures pseudoranges, each equal to the true range plus a common receiver clock error expressed as distance. Four unknowns (x, y, z and the clock bias) need four pseudoranges.SV1SV2SV3SV4 receiver: unknowns x, y, z, and clock bias b ρ_i = ‖s_i − r‖ + c·b + ε_i one clock bias for every satellite
Each pseudorange is a distance to a known point plus a common clock term. Four unknowns need four equations.

A receiver therefore estimates four numbers: three position coordinates and the receiver clock bias. With more satellites in view the system is over-determined and solved by least squares.

Animation of a satellite signal travelling to a receiver. A wavefront leaves the satellite and reaches the receiver after about 67 milliseconds. A plot shows the range error caused by a receiver clock error growing linearly, about 300 metres for each microsecond, with a moving point that sweeps the clock error from 0 to 1 microsecond.
GNSS measures signal travel time and multiplies by the speed of light. A receiver clock that is wrong by one microsecond shifts every pseudorange by about 300 m, so the clock error is solved together with position, which is why four satellites are needed. Satellite altitude about 20 200 km (GPS). (Looping, about 5 seconds; drawn and computed for this course with illustrative values.)

Engineering intuition

Three known distances would fix a point in 3-D if the clock were perfect. The clock error shifts every range by the same amount, so a fourth satellite is needed to find it. Position accuracy then depends on two things: the accuracy of each range (the user equivalent range error) and the geometry of the satellites. Satellites clustered in one part of the sky give nearly parallel lines of sight and a poorly conditioned solution; spread-out satellites give a well-conditioned one. DOP summarises that conditioning.

Vertical accuracy is worse than horizontal accuracy because all satellites are above the horizon: no satellite constrains the solution from below.

Mathematical formulation

For satellite ii at known position sis_{i} and receiver at unknown position rr with clock bias bb (in seconds), the pseudorange is:

Pseudorange equation
ρi=∥si−r∥+c b+εi\rho_i = \lVert\mathbf s_i - \mathbf r\rVert + c\,b + \varepsilon_i
ρi\rho _{i}
measured pseudorange (m).
sis_{i}, rr
satellite and receiver positions in the same Earth-fixed frame.
cc
speed of light, 299 792 458 m/s.
bb
receiver clock bias; cc bb is the same distance error for every satellite.
εi\varepsilon _{i}
remaining errors: satellite clock and orbit, ionosphere and troposphere delay, multipath, receiver noise (lesson M2-T4).

Linearise about an estimate (r^\hat{r}, b^\hat{b}): with unit line-of-sight vectors ui=(si−r^)/∥si−r^∥u_{i}=(s_{i}-\hat{r})/\Vert s_{i}-\hat{r}\Vert ,

Linearised least squares
Δρ=H Δx,Δρi=ρi−(∥si−r^∥+c b^)\Delta\boldsymbol\rho = \mathbf H\,\Delta\mathbf x, \qquad \Delta\rho_i = \rho_i - \left(\lVert\mathbf s_i - \hat{\mathbf r}\rVert + c\,\hat b\right)
Geometry matrix
Hi=[−ui⊤1],Δx=[Δrc Δb]\mathbf H_i = \begin{bmatrix}-\mathbf u_i^{\top} & 1\end{bmatrix}, \qquad \Delta\mathbf x = \begin{bmatrix}\Delta\mathbf r\\ c\,\Delta b\end{bmatrix}
Least-squares step
Δx=(H⊤H)−1H⊤Δρ\Delta\mathbf x = (\mathbf H^{\top}\mathbf H)^{-1}\mathbf H^{\top}\Delta\boldsymbol\rho
Iterate r̂ ← r̂ + Δr until Δx is small (Gauss–Newton).

With independent range errors of standard deviation σ\sigma , the covariance of the solution is σ2(H⊤H)−1\sigma ^{2}(H^{\top}H)^{-1}. The dilution of precision is built from the diagonal of (H⊤H)−1(H^{\top}H)^{-1}:

Dilution of precision
GDOP=trace⁡ ⁣((H⊤H)−1)\mathrm{GDOP} = \sqrt{\operatorname{trace}\!\left((\mathbf H^{\top}\mathbf H)^{-1}\right)}
PDOP is the position part; HDOP and VDOP are the horizontal and vertical parts.
position error (1σ)≈DOP×σrange\text{position error } (1\sigma) \approx \mathrm{DOP}\times\sigma_{\text{range}}

Architecture and data flow

Antenna → RF front-end → tracking loops (per satellite) → pseudorange and carrier-phase measurements → navigation solution (position, velocity, time) with quality indicators (satellite count, DOP, accuracy estimates, fix type) → autopilot. The autopilot should consume the receiver’s quality indicators, not only the position: they are what lets a monitor decide to stop trusting GNSS (lesson M8-T11).

Real-world UAV applications

  • Absolute position reference for navigation, geofencing and return-to-home.
  • Bounding drift of inertial and visual odometry in a GNSS-aided estimator.
  • Time reference: GNSS provides time for sensor synchronisation (lesson M7-T8).
  • Pre-flight go/no-go: required satellite count, HDOP and fix type before arming.

Implementation example

This runs as shown. It builds a synthetic constellation, simulates pseudoranges with a 100 km clock-bias-equivalent and noise, solves by Gauss–Newton, and computes DOP.

import numpy as np
rng = np.random.default_rng(1)
c = 299_792_458.0
R_orbit = 26_560e3                                      # GPS-like orbital radius (m), illustrative geometry
truth = np.array([6_371e3, 0.0, 0.0]); b_true = 1e-4    # receiver on the "equator" (m), clock bias 0.1 ms
az_el = [(0, 80), (90, 35), (180, 25), (270, 40), (45, 55)]   # satellite directions (deg): azimuth, elevation

def sat_pos(az, el):
    az, el = np.radians(az), np.radians(el)
    up = truth / np.linalg.norm(truth); east = np.array([0, 1.0, 0]); north = np.cross(up, east)
    d = np.cos(el) * (np.cos(az) * north + np.sin(az) * east) + np.sin(el) * up
    # ray from the receiver along d meets the orbit sphere:
    t = -truth @ d + np.sqrt((truth @ d) ** 2 - truth @ truth + R_orbit ** 2)
    return truth + t * d

S = np.array([sat_pos(a, e) for a, e in az_el])
sigma = 3.0                                              # per-satellite range error, m
rho = np.linalg.norm(S - truth, axis=1) + c * b_true + sigma * rng.standard_normal(len(S))

x = np.array([6_000e3, 100e3, -100e3, 0.0])              # initial guess [r, c*b]: ~400 km off
for _ in range(10):
    rng_hat = np.linalg.norm(S - x[:3], axis=1)
    u = (S - x[:3]) / rng_hat[:, None]
    H = np.hstack([-u, np.ones((len(S), 1))])
    dx, *_ = np.linalg.lstsq(H, rho - (rng_hat + x[3]), rcond=None)
    x = x + dx
    if np.linalg.norm(dx) < 1e-6: break

err = np.linalg.norm(x[:3] - truth)
Q = np.linalg.inv(H.T @ H)
pdop = np.sqrt(np.trace(Q[:3, :3]))
print(f"position error {err:.1f} m, clock bias error {(x[3]/c - b_true)*1e9:.1f} ns, PDOP {pdop:.2f}")
assert err < 30 and pdop < 5 and abs(x[3] / c - b_true) < 1e-7

# poor geometry: all satellites near one direction -> much larger DOP
S2 = np.array([sat_pos(a, e) for a, e in [(0, 60), (10, 62), (350, 58), (5, 65), (20, 60)]])
u = (S2 - truth) / np.linalg.norm(S2 - truth, axis=1)[:, None]
H2 = np.hstack([-u, np.ones((5, 1))]); pdop2 = np.sqrt(np.trace(np.linalg.inv(H2.T @ H2)[:3, :3]))
print("clustered satellites PDOP:", round(pdop2, 1)); assert pdop2 > 3 * pdop
Gauss–Newton pseudorange solution and DOP. Satellite directions are synthetic.

Common engineering mistakes

Treating position as the only output

The receiver also reports velocity (from Doppler), time and accuracy estimates; ignoring quality indicators removes your best integrity signal.

Assuming more satellites always means better accuracy

Geometry and error quality matter. Low-elevation satellites carry more atmospheric and multipath error.

Using GNSS height as precise altitude above ground

Vertical error is larger than horizontal and the height is above an ellipsoid or geoid, not above ground.

Ignoring receiver update rate and latency

A 5 Hz fix with 100–200 ms latency is stale at 15 m/s: model the delay in the estimator.

Failure modes

Failure modes, symptoms and causes
Failure modeHow it shows upLikely cause
Poor geometryLarge reported DOP, jumping positionSatellites blocked by buildings or terrain, leaving a narrow cone of sky
Receiver cold startNo fix for tens of seconds after power-upAlmanac or ephemeris unavailable; wait for a fix before arming
Fix type degradationReceiver drops from RTK fixed to float or to a plain 3-D fixLost corrections or too few satellites, reducing accuracy from centimetres to metres
Antenna interferenceLow carrier-to-noise ratio, intermittent fixInterference from companion computer, USB 3 or camera electronics near the antenna

Debugging approach

  1. Log satellite count, HDOP/VDOP, fix type and the receiver’s horizontal accuracy estimate alongside the position.
  2. Plot carrier-to-noise density (C/N0) per satellite: a low value on all satellites points to antenna placement or interference.
  3. Compare against a second receiver or a surveyed point on the ground before flying.
  4. Move the antenna away from the companion computer and USB 3 cables, and re-check C/N0.

Practical exercises

  1. Show that three pseudoranges leave a one-parameter family of solutions when the clock bias is unknown.
  2. Compute HDOP and VDOP for the code example and explain why VDOP is larger.
  3. Change the constellation so that all satellites are above 70∘70^{\circ} elevation. What happens to the DOP?
  4. If σrange=3 m\sigma _{\text{range}}=3\,\mathrm{m} and PDOP = 2, what is the expected position error?

Interview questions

Write an answer in your own words, then reveal the model answer. Nothing is sent anywhere.

Question 1

Why do you need four satellites for a 3-D fix?

Model answer

There are four unknowns: xx, yy, zz and the receiver clock bias. Each pseudorange gives one equation, so four are needed; more make the problem over-determined and allow least-squares and integrity checks.

Question 2

What does DOP tell you?

Model answer

How satellite geometry amplifies range errors into position errors: position error ≈ DOP × range error. It is a property of geometry, independent of signal quality.

Question 3

Why is GNSS vertical accuracy worse than horizontal?

Model answer

All satellites are above the horizon, so no line of sight constrains the vertical solution from below; VDOP is therefore larger than HDOP.

References and further reading

Primary papers, official documentation and standards. Each claim above that is specific to a tool or version points here.

What’s next

Mark this lesson

Saved in this browser and synced to your account when you are signed in.

Next lesson

M2-T2: GPS, GLONASS, Galileo and BeiDou

Compare the four constellations and the benefit of multi-constellation receivers.