# How Loosely Coupled INS/GNSS Integration Works

> An inertial measurement unit tells you how the vehicle moved; a satellite receiver tells you where it is. This lecture builds the filter that combines them in the simplest architecture that works: loosely coupled integration, where the receiver's own position and velocity solution is differenced against the inertial one and that difference is handed to an error-state extended Kalman filter. It starts from the mechanization equations and the drift they inherit, follows a fifteen-state error vector through prediction and correction, shows why the measurement matrix is almost the identity, and watches an accelerometer bias being calibrated while the vehicle drives. It closes on the trade: modularity, a small state and a cheap update, against a filter that has nothing at all to say when fewer than four satellites are in view.

- Canonical watch page: [How Loosely Coupled INS/GNSS Integration Works](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works)
- Publisher: [Academa, Inc.](https://academa.ai)
- Subject: Engineering
- Published: 2026-09-02T18:55:30.761Z
- Updated: 2026-09-02T18:55:30.761Z
- Duration: PT834S (13 minutes 54 seconds)
- Chapters: 4
- Views: 5
- Language: en-US
- Access: Free
- Video stream: [HLS content](https://academa.ai/media/l/01M1HNTW2WGTP67D71P8AJMPH6/0/dark/master.m3u8)
- Embed: [Player](https://academa.ai/embed/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works)
- Audiovisual record: [Semantic JSON](https://academa.ai/media/l/01M1HNTW2WGTP67D71P8AJMPH6/0/semantic.json)
- Thumbnail: [Image](https://academa.ai/media/l/01M1HNTW2WGTP67D71P8AJMPH6/0/dark/poster.jpg)

## Description

How an error-state Kalman filter fuses an inertial solution with a GNSS fix: mechanization, drift, innovation, and the four-satellite floor.

## Chapters

- [00:00–03:36.529 · Two Instruments, Two Kinds of Error](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=0)
- [03:36.529–07:8.827 · The Architecture, and the Error State](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=216.52920833333332)
- [07:8.827–10:55.256 · The Correction Loop](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=428.8265833333333)
- [10:55.256–13:54 · Strengths, and the Four-Satellite Floor](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333)

## Transcript

### [00:00 · Two Instruments, Two Kinds of Error](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=0)

Here is the problem this lecture is about. A vehicle has to report where it is and how fast it is going, continuously, at high rate, for an hour, in open sky and under a bridge. Two instruments can answer that, and each of them fails in a way the other one does not. The first is an inertial measurement unit. Three accelerometers and three gyroscopes, bolted to the vehicle frame, reporting specific force and angular rate in their own body axes, several hundred times a second. Nothing in that list refers to the world outside the vehicle. Mechanization is the arithmetic that turns those two signals into a navigation solution. Integrate angular rate to keep attitude. Rotate the measured force into navigation axes, add gravity back, and integrate to get velocity. Integrate once more to get position. Every one of those integrals also integrates the sensor's own errors, and that is the whole trouble. A constant accelerometer bias, half a milli-g, say, becomes a velocity error that grows linearly and a position error that grows as one half b t squared. Here is what that costs, drawn against time in seconds, with metres of position error up the side. It is smooth, and it is quiet, and it climbs: past ten metres, past twenty metres, and it never comes back down. So an unaided inertial system is superb over seconds and useless over minutes. And notice which part is bad. The shape of the trajectory is excellent; it is the absolute placement that slides away. The second instrument does the opposite. A satellite receiver measures its distance to every satellite it can see, and with four or more of those distances it solves directly for three coordinates of position, and for its own clock offset, which is the fourth unknown. What comes out is an absolute fix: position, and usually velocity, expressed in an earth-fixed frame and referred to nothing but the satellites. It arrives slowly by inertial standards, one to ten times a second. And it is noisy. Receiver noise, unmodelled atmospheric delay, and signals that arrive after bouncing off a building, which is what multipath means, all move the reported fix by metres from one epoch to the next. Here it is on the same axes. But watch what it does not do. It wanders, and it keeps wandering about the same level, under about five metres, and it does not care whether you have been driving for one minute or five hours. Its error is bounded. The inertial error is not. Put them side by side and the pattern is almost too convenient. The inertial unit is fast, smooth and locally accurate, and it drifts. The receiver is slow and noisy, and it does not drift. One more line matters later. The inertial unit needs nothing outside the vehicle at all, while the receiver needs a clear view of at least four satellites, and that is the one place the scheme we are about to build gives up. So neither instrument is the answer; the pair is. And this is what the pair can do: an error that is smooth and fast like the inertial solution, and bounded like the satellite one. Building that blue curve is the whole of this lecture.

### [03:36.529 · The Architecture, and the Error State](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=216.52920833333332)

So we build the pair. Loosely coupled integration is one particular way of wiring them together, and it is the one to meet first, because every piece of it can be bought, tested and replaced on its own. The top row is the inertial chain. The measurement unit hands its samples to the mechanization we just wrote down, and out comes a continuous solution: position, velocity and attitude, at the full sensor rate. Underneath, and quite separately, sits the receiver. It tracks whatever satellites it can see and solves its own navigation problem, on its own schedule, and what leaves it is a computed fix. Now the filter. It does not sit in the signal path at all. Both solutions are handed to it, and what it estimates is not where the vehicle is, but how wrong the inertial solution has become. Its measurement is therefore a difference. Take the inertial position and velocity, subtract the position and velocity the receiver reported, and what is left is error: the inertial system's error, plus the receiver's noise. And the corrections travel back up the same interface. The estimated error is written into the mechanization, and the estimated sensor biases are subtracted from the incoming samples, so the errors the filter is linearising about stay small. The word loosely is a statement about that interface. What crosses between the two systems is a finished navigation solution, six numbers. The individual satellite ranges never leave the receiver, and the receiver never hears about the inertial unit. Why estimate the error rather than the state? Look at what the error is. Here is the true path of the vehicle in grey, and here is the path the mechanization computed, in red. The shapes agree very well. The placement does not. The difference between those two paths is small, it is slowly varying, and to first order it obeys linear dynamics. That is the whole reason for the indirect formulation: the vehicle's motion is thoroughly nonlinear, but its error is not. So we do not ask the filter for the vehicle's position. We ask it for fifteen numbers that say how wrong the inertial solution is: three of position, three of velocity, three of attitude, and six sensor biases, three per triad. Those fifteen errors evolve according to a matrix F built from the current attitude, the current specific force and the bias models, plus process noise for everything F leaves out. That is the propagation half of the filter. Now the measurement. It is the inertial solution minus the receiver's solution, and nothing else. Write each of them as the truth plus its own error, and the truth cancels. What is left is the position and velocity part of the error state, minus the receiver's noise. So the measurement matrix is almost embarrassingly simple: identity on six of the fifteen states, zero on the other nine. That is the entire measurement model of a loosely coupled filter. And notice what is not in there. No satellite geometry, no ranges, no clock. All of that stayed inside the receiver, which is exactly what makes this scheme modular, and also exactly what will limit it.

### [07:8.827 · The Correction Loop](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=428.8265833333333)

Now the filter itself. It alternates between two steps, and the interesting thing about this architecture is how little happens in the first of them. Between fixes there is no measurement, so nothing corrects anything at all. The mechanization runs on at full rate, the error grows exactly as it did unaided, and all the filter can do is keep track of how uncertain that growing solution has become. The prediction is the ordinary Kalman one, on the error state. Because the last correction was written straight into the mechanization, the error estimate starts each interval at zero. The transition matrix over one interval is the identity plus F delta t, and the covariance is pushed through it and grown by the process noise. Watch the picture while that runs. Nothing on it improves. Between fixes, a loosely coupled system is an unaided inertial system with a growing covariance attached to it. Then a fix arrives, and everything happens at once. The innovation is the difference we built a moment ago, less whatever the filter already expected that difference to be. Here it expected zero, so the innovation is the raw difference. The gain weighs the two sides against each other. The middle term, S, is how large a difference we should have expected, given our own uncertainty and the receiver's noise. When the receiver is noisy and the filter is confident, the correction is small. When the inertial solution has been coasting a long time, it is large. The correction is applied to the whole error state, not only to the six states we measured. Position error is observed directly. Attitude error and the gyro biases are not, and they are estimated anyway, because the covariance says they are correlated with what we did measure. And the covariance shrinks, which is the part that matters most. The filter is now more certain than it was, and the next coasting interval starts from a smaller number. Then it all repeats. And here is what to watch across several cycles: the teeth are getting shorter. Nearly nine metres on the first, under six on the next, then four. Each fix does more than reset the error; it also improves the estimate of the biases that were making it grow. That improvement deserves its own picture. This is the filter's estimate of one accelerometer bias against time, in milli-g, with the true value dashed across it at eight. It starts at zero, because we knew nothing, and it walks up to the truth over a minute or two of driving. A bias on an accelerometer produces a velocity error that grows in a particular direction, and every fix reports that direction again. So the filter is calibrating the instrument while the vehicle drives. Which brings us to where the correction is actually applied, and there are two choices. In the feedback configuration the estimate is written into the mechanization: position, velocity and attitude are overwritten, the estimated biases are subtracted from the incoming samples, and the error estimate is then reset to zero. In the feedforward configuration the mechanization is left running untouched, and the correction is added to its output instead. That is easier to bolt onto an existing box, but the inertial solution keeps drifting underneath, so the errors the filter linearised about stop being small. Feedback keeps them small. So the loop is four words: coast, compare, correct, calibrate. And note where the navigation solution comes from. It is produced entirely by the mechanization; the filter never computes a position, only a correction to one.

### [10:55.256 · Strengths, and the Four-Satellite Floor](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333)

Two things left: what this arrangement buys, and the one place it stops working. The second is easier to see, so start there. On the left, the number of satellites the receiver can use; on the right, the error of the integrated solution over the same half minute. With six satellites in view the fixes keep arriving, once a second, and the error stays well under five metres: the sawtooth we have just been watching, on a coarser scale. Then the vehicle turns into a street with tall buildings on both sides, and the usable count falls to three. Four independent ranges are needed for three coordinates and the clock offset, so with three the receiver publishes nothing at all. And a loosely coupled filter has nothing to do with three ranges. Its measurement is a position and velocity solution, and there is no solution, so there is no update: no innovation, no gain, no correction. The filter coasts, and what you are watching is once again the unaided inertial error. Ten seconds of that, and the solution is nearly twenty metres out. Then the street opens, the satellites come back, and the very first fix pulls the whole thing down again. The recovery is immediate: the filter kept a valid covariance the whole way through the gap, so it knows exactly how little to trust itself. So here is the trade, and it is a clear one. On the gain side: the receiver is a box you can buy, qualify and replace, and the filter never touches its internals. The measurement model is six states of identity, so the code is small and the update is cheap. And you have two solutions that can check each other. On the other side: the receiver has already filtered its own output, so consecutive fixes are correlated and the noise covariance you assume is optimistic. The fix is old when it arrives, so it must be time-tagged and applied to the instant it belongs to. And below four satellites there is no measurement at all. None of that is a reason to avoid the architecture. It is a reason to know which failure you are buying. This filter is exactly as available as the receiver's position solution, and no more. If you need aiding below four satellites, you need a different interface, and that is what a tightly coupled design is for. So, the whole thing in one line. The navigation solution is the mechanization's own, corrected by an estimate of its own error, and that estimate is driven by nothing more than the difference between two independent solutions to the same problem. The inertial unit supplies continuity, smoothness and rate. The receiver supplies an absolute reference. And the error-state filter in between carries the calibration from one fix to the next, which is why the solution keeps its accuracy through the ten seconds when nobody is checking it.

## About Academa, Inc.

Academa makes technical knowledge easier to understand through visual lectures and lets learners request new lecture videos on the topics they need.

## Complete audiovisual record

Immutable source: [semantic.json](https://academa.ai/media/l/01M1HNTW2WGTP67D71P8AJMPH6/0/semantic.json)

Record version: 1. Render attempt: 0.

### How to read this timeline

Each scene owns its object identifiers. A beat's board is the complete board when listed, empty when marked empty, and unchanged from the nearest earlier listed board in the same scene when marked unchanged. Action times are absolute positions in the published video.

### Scene 1: [Two Instruments, Two Kinds of Error](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=0)

Span: 00:00–03:36.529 (0s–216.52920833333332s).

#### Objects

- clock: a VariableNumber (initial\_value=6.0, format\_spec='.0f')
- compare: a Table \[text\] that says "property INS GNSS rate high low short term smooth noisy long term drifts bounded needs sky view no yes" (rows=(('property', 'INS', 'GNSS'), ('rate', 'high', 'low'), ('short …, header=True)
- drift: a Math \[text\] that says "$epsilon\_upright("pos") = frac(1, 2) b thin t^2$"
- error\_axes: an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0)
- fused\_curve: a FunctionPlot \[blue\] drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0))
- gnss\_curve: a FunctionPlot \[green\] labelled "upright("GNSS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0))
- gnss\_def: a Panel that says "A receiver measures its range to four or more satellites and solves for three coordinates of position and its own clock offset."
- gnss\_out: a Math \[text\] that says "$arrow(p)\_upright("gnss"), quad arrow(v)\_upright("gnss")$"
- gnss\_rate: a Math \[text\] that says "$f\_upright("gnss") approx 1 - 10 thin upright("Hz")$"
- heading\_pair: a Heading that says "Complementary Errors"
- imu\_out: a Math \[text\] that says "$arrow(f)\_upright("b"), quad arrow(omega)\_upright("b")$"
- ins\_curve: a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0))
- ins\_now: a PlotPoint \[yellow\] labelled "0 thin upright("m")" drawn in error\_axes (target='ins\_curve', x=\<VariableNumber clock = 60.0\>)
- mechanization: a Derivation \[text\] that says "$dot(arrow(psi)) &= arrow(omega)\_upright("b") \\ dot(arrow(v)) &= R(arrow(psi)) arrow(f)\_upright("b") + arrow(g) \\ dot(arrow(p)) &= arrow(v)$"
- metres: a VariableNumber (initial\_value=0.2, format\_spec='.0f')
- point: a Point \[yellow\] drawn in error\_axes (location=(60.0, 21.6))
- question: a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"

#### Beats

##### [00:00](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=0)

Narration: Here is the problem this lecture is about. A vehicle has to report where it is and how fast it is going, continuously, at high rate, for an hour, in open sky and under a bridge. Two instruments can answer that, and each of them fails in a way the other one does not.

Board: Empty.

Actions:
- [00:00](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=0): question is shown on the screen, written out.
- [00:17.45](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=17.4495): question moves to a new place on the board.

##### [00:18.649](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=18.6495)

Narration: The first is an inertial measurement unit. Three accelerometers and three gyroscopes, bolted to the vehicle frame, reporting specific force and angular rate in their own body axes, several hundred times a second. Nothing in that list refers to the world outside the vehicle.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"

Actions:
- [00:26.393](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=26.392999999999997): imu\_out is shown on the screen, written out.

##### [00:37.001](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=37.001000000000005)

Narration: Mechanization is the arithmetic that turns those two signals into a navigation solution. Integrate angular rate to keep attitude. Rotate the measured force into navigation axes, add gravity back, and integrate to get velocity. Integrate once more to get position.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"; imu\_out — a Math \[text\] that says "$arrow(f)\_upright("b"), quad arrow(omega)\_upright("b")$"

Actions:
- [00:44.466](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=44.466): mechanization is shown on the screen, written out.
- [00:51.014](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=51.014): mechanization is shown on the screen, written out.
- [00:53.998](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=53.998000000000005): mechanization is shown on the screen, written out.

##### [00:55.585](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=55.584500000000006)

Narration: Every one of those integrals also integrates the sensor's own errors, and that is the whole trouble. A constant accelerometer bias, half a milli-g, say, becomes a velocity error that grows linearly and a position error that grows as one half b t squared.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [00:55.585](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=55.584500000000006): error\_axes is shown on the screen, written out.
- [01:10.62](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=70.62): drift is shown on the screen, written out.

##### [01:13.17](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=73.17)

Narration: Here is what that costs, drawn against time in seconds, with metres of position error up the side. It is smooth, and it is quiet, and it climbs: past ten metres, past twenty metres, and it never comes back down.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"; imu\_out — a Math \[text\] that says "$arrow(f)\_upright("b"), quad arrow(omega)\_upright("b")$"; drift — a Math \[text\] that says "$epsilon\_upright("pos") = frac(1, 2) b thin t^2$"; error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0)

Actions:
- [01:15.132](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=75.132): ins\_curve is shown on the screen, drawn.
- [01:20.345](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=80.345): ins\_now is shown on the screen, written out.
- [01:22.795](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=82.795): ins\_now is redrawn as the numbers it depends on change.
- [01:22.795](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=82.795): clock ticks to 60.0.
- [01:22.795](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=82.795): metres ticks to 21.6.

##### [01:28.945](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=88.9445)

Narration: So an unaided inertial system is superb over seconds and useless over minutes. And notice which part is bad. The shape of the trajectory is excellent; it is the absolute placement that slides away.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"; imu\_out — a Math \[text\] that says "$arrow(f)\_upright("b"), quad arrow(omega)\_upright("b")$"; drift — a Math \[text\] that says "$epsilon\_upright("pos") = frac(1, 2) b thin t^2$"; error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0); ins\_curve — a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); ins\_now — a PlotPoint \[yellow\] labelled "0 thin upright("m")" drawn in error\_axes (target='ins\_curve', x=\<VariableNumber clock = 60.0\>)

Actions:
- [01:42.064](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=102.06400000000002): point is shown on the screen, grown.
- [01:44.072](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=104.07202525252526): point is hidden from the screen.

##### [01:44.576](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=104.5755)

Narration: The second instrument does the opposite. A satellite receiver measures its distance to every satellite it can see, and with four or more of those distances it solves directly for three coordinates of position, and for its own clock offset, which is the fourth unknown.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [01:48.964](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=108.96400000000003): drift is hidden from the screen — left the board.
- [01:48.964](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=108.96400000000003): imu\_out is hidden from the screen — left the board.
- [01:48.964](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=108.96400000000003): mechanization is hidden from the screen — left the board.
- [01:48.964](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=108.96400000000003): gnss\_def is shown on the screen, written out.

##### [02:1.151](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=121.15100000000001)

Narration: What comes out is an absolute fix: position, and usually velocity, expressed in an earth-fixed frame and referred to nothing but the satellites. It arrives slowly by inertial standards, one to ten times a second.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"; error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0); ins\_curve — a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); ins\_now — a PlotPoint \[yellow\] labelled "0 thin upright("m")" drawn in error\_axes (target='ins\_curve', x=\<VariableNumber clock = 60.0\>); gnss\_def — a Panel that says "A receiver measures its range to four or more satellites and solves for three coordinates of position and its own clock offset."

Actions:
- [02:2.486](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=122.48600000000002): gnss\_out is shown on the screen, written out.
- [02:12.158](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=132.15800000000002): gnss\_rate is shown on the screen, written out.

##### [02:16.74](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=136.73950000000002)

Narration: And it is noisy. Receiver noise, unmodelled atmospheric delay, and signals that arrive after bouncing off a building, which is what multipath means, all move the reported fix by metres from one epoch to the next. Here it is on the same axes.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"; error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0); ins\_curve — a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); ins\_now — a PlotPoint \[yellow\] labelled "0 thin upright("m")" drawn in error\_axes (target='ins\_curve', x=\<VariableNumber clock = 60.0\>); gnss\_def — a Panel that says "A receiver measures its range to four or more satellites and solves for three coordinates of position and its own clock offset."; gnss\_out — a Math \[text\] that says "$arrow(p)\_upright("gnss"), quad arrow(v)\_upright("gnss")$"; gnss\_rate — a Math \[text\] that says "$f\_upright("gnss") approx 1 - 10 thin upright("Hz")$"

Actions:
- [02:31.218](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=151.21800000000005): gnss\_curve is shown on the screen, drawn.

##### [02:33.954](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=153.954)

Narration: But watch what it does not do. It wanders, and it keeps wandering about the same level, under about five metres, and it does not care whether you have been driving for one minute or five hours. Its error is bounded. The inertial error is not.

Board: question — a Panel that says "A vehicle must report its position and velocity continuously, at high rate, for an hour. Which instrument would you trust?"; error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0); ins\_curve — a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); ins\_now — a PlotPoint \[yellow\] labelled "0 thin upright("m")" drawn in error\_axes (target='ins\_curve', x=\<VariableNumber clock = 60.0\>); gnss\_def — a Panel that says "A receiver measures its range to four or more satellites and solves for three coordinates of position and its own clock offset."; gnss\_out — a Math \[text\] that says "$arrow(p)\_upright("gnss"), quad arrow(v)\_upright("gnss")$"; gnss\_rate — a Math \[text\] that says "$f\_upright("gnss") approx 1 - 10 thin upright("Hz")$"; gnss\_curve — a FunctionPlot \[green\] labelled "upright("GNSS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0))

Actions:
- [02:39.631](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=159.631): The segment (0.0, 5.0) to (60.0, 5.0) in error\_axes is lit up.
- [02:47.131](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=167.131): error\_axes: retire a lit segment (unemphasize\_line).
- [02:50.579](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=170.5795): error\_axes moves to a new place on the board.
- [02:50.579](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=170.5795): gnss\_def is hidden from the screen — left the board.
- [02:50.579](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=170.5795): gnss\_out is hidden from the screen — left the board.
- [02:50.579](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=170.5795): gnss\_rate is hidden from the screen — left the board.
- [02:50.579](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=170.5795): question is hidden from the screen — left the board.

##### [02:51.18](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=171.17950000000002)

Narration: Put them side by side and the pattern is almost too convenient. The inertial unit is fast, smooth and locally accurate, and it drifts. The receiver is slow and noisy, and it does not drift.

Board: error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0); ins\_curve — a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); ins\_now — a PlotPoint \[yellow\] labelled "0 thin upright("m")" drawn in error\_axes (target='ins\_curve', x=\<VariableNumber clock = 60.0\>); gnss\_curve — a FunctionPlot \[green\] labelled "upright("GNSS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0))

Actions:
- [02:51.18](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=171.17950000000002): heading\_pair is shown on the screen, written out.
- [02:51.18](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=171.17950000000002): ins\_now is hidden from the screen.
- [02:53.292](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=173.29200000000003): compare is shown on the screen, written out.
- [02:57.101](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=177.10100000000003): compare is shown on the screen, written out.
- [02:57.612](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=177.61200000000002): compare is shown on the screen, written out.
- [02:59.806](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=179.80600000000004): compare is shown on the screen, written out.

##### [03:5.631](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=185.6305)

Narration: One more line matters later. The inertial unit needs nothing outside the vehicle at all, while the receiver needs a clear view of at least four satellites, and that is the one place the scheme we are about to build gives up.

Board: error\_axes — an Axes (x\_range=(0.0, 60.0), y\_range=(0.0, 25.0), x\_ticks\_every=10.0); ins\_curve — a FunctionPlot \[red\] labelled "upright("INS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); gnss\_curve — a FunctionPlot \[green\] labelled "upright("GNSS")" drawn in error\_axes (function=\<function\>, x\_range=(0.0, 60.0)); heading\_pair — a Heading that says "Complementary Errors"

Actions:
- [03:13.293](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=193.293): compare is shown on the screen, written out.

##### [03:19.768](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=199.768)

Narration: So neither instrument is the answer; the pair is. And this is what the pair can do: an error that is smooth and fast like the inertial solution, and bounded like the satellite one. Building that blue curve is the whole of this lecture.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [03:26.78](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=206.78): fused\_curve is shown on the screen, drawn.
- [03:35.488](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=215.4875416666667): compare is hidden from the screen — left the board.
- [03:35.488](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=215.4875416666667): error\_axes is hidden from the screen — left the board.
- [03:35.488](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=215.4875416666667): ins\_curve is hidden from the screen — error\_axes left the board.
- [03:35.488](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=215.4875416666667): gnss\_curve is hidden from the screen — error\_axes left the board.
- [03:35.488](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=215.4875416666667): fused\_curve is hidden from the screen — error\_axes left the board.
- [03:35.488](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=215.4875416666667): heading\_pair is hidden from the screen — left the board.

### Scene 2: [The Architecture, and the Error State](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=216.52920833333332)

Span: 03:36.529–07:8.827 (216.52920833333332s–428.8265833333333s).

#### Objects

- correction\_up: a Vector \[yellow\] labelled "delta hat(arrow(x))" drawn in plan (start=(7.4, 2.0), end=(7.4, 5.0))
- dynamics: a Math \[text\] that says "$dot(delta arrow(x)) = F thin delta arrow(x) + arrow(w)$"
- ekf\_box: a Polygon \[yellow\] drawn in plan (vertices=((4.6, 0.8), (8.6, 0.8), (8.6, 2.0), (4.6, 2.0)), filled=False)
- ekf\_name: a Math \[yellow\] that says "$upright("error-state EKF")$" drawn in plan
- fix\_a: a Point \[green\] drawn in map\_axes (location=(3.1, 2.66))
- fix\_b: a Point \[green\] drawn in map\_axes (location=(5.42, 2.2))
- fix\_c: a Point \[green\] drawn in map\_axes (location=(7.9, 1.36))
- fix\_in: a Vector \[green\] labelled "arrow(x)\_upright("gnss")" drawn in plan (start=(3.2, 1.4), end=(4.6, 1.4))
- gnss\_box: a Polygon \[green\] drawn in plan (vertices=((0.3, 0.8), (3.2, 0.8), (3.2, 2.0), (0.3, 2.0)), filled=False)
- gnss\_name: a Math \[green\] that says "$upright("GNSS receiver")$" drawn in plan
- h\_def: a Math \[text\] that says "$H = mat(I, 0, 0, 0, 0; 0, I, 0, 0, 0)$"
- head\_arch: a Heading that says "Loosely Coupled: The Wiring"
- head\_err: a Heading that says "Why the Filter Estimates the Error"
- head\_meas: a Heading that says "The Measurement Model"
- imu\_box: a Polygon \[blue\] drawn in plan (vertices=((0.3, 5.0), (2.7, 5.0), (2.7, 6.2), (0.3, 6.2)), filled=False)
- imu\_link: a Vector \[blue\] drawn in plan (start=(2.7, 5.6), end=(3.8, 5.6))
- imu\_name: a Math \[blue\] that says "$upright("IMU")$" drawn in plan
- innovation: an Arrow \[yellow\] labelled "arrow(z)" drawn in map\_axes (start=(9.152, 2.135), end=(7.9, 1.36))
- ins\_box: a Polygon \[blue\] drawn in plan (vertices=((3.8, 5.0), (8.0, 5.0), (8.0, 6.2), (3.8, 6.2)), filled=False)
- ins\_down: a Vector \[blue\] labelled "arrow(x)\_upright("ins")" drawn in plan (start=(5.2, 5.0), end=(5.2, 2.0))
- ins\_here: a Point \[red\] drawn in map\_axes (location=(9.152, 2.135))
- ins\_name: a Math \[blue\] that says "$upright("INS mechanization")$" drawn in plan
- ins\_path: a ParametricCurve \[red\] labelled "upright("INS")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0))
- item1: a Text \[text\] that says "An INS mechanization, running at IMU rate."
- item2: a Text \[text\] that says "An independent receiver, reporting its own position and velocity."
- item3: a Text \[text\] that says "A filter whose states are the INS errors."
- item4: a Text \[text\] that says "A measurement built by differencing the two solutions."
- item5: a Text \[text\] that says "Corrections fed back into the mechanization and the IMU."
- map\_axes: an Axes (x\_range=(0.0, 11.0), y\_range=(0.0, 6.0), aspect=(11.0, 6.0))
- measurement: a Derivation \[text\] that says "$arrow(z) &= arrow(x)\_upright("ins") - arrow(x)\_upright("gnss") \\ &= (arrow(x) + delta arrow(x)) - (arrow(x) + arrow(n)) \\ &= delta arrow(x)\_(p, v) - arrow(n) \\ &= H thin delta arrow(x) - arrow(n)$"
- out\_box: a Polygon \[blue\] drawn in plan (vertices=((9.6, 5.0), (12.4, 5.0), (12.4, 6.2), (9.6, 6.2)), filled=False)
- out\_link: a Vector \[blue\] drawn in plan (start=(8.0, 5.6), end=(9.6, 5.6))
- out\_name: a Math \[blue\] that says "$upright("PVA")$" drawn in plan
- plan: a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0))
- state\_vec: a Math \[text\] that says "$delta arrow(x) = mat(delta arrow(p); delta arrow(v); delta arrow(psi); arrow(b)\_a; arrow(b)\_g)$"
- true\_path: a ParametricCurve \[gray\] labelled "upright("truth")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0))

#### Beats

##### [03:36.529](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=216.52920833333332)

Narration: So we build the pair. Loosely coupled integration is one particular way of wiring them together, and it is the one to meet first, because every piece of it can be bought, tested and replaced on its own.

Board: Empty.

Actions:
- [03:36.529](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=216.52920833333332): head\_arch is shown on the screen, written out.
- [03:41.405](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=221.40520833333332): plan is shown on the screen, written out.

##### [03:49.413](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=229.4127083333333)

Narration: The top row is the inertial chain. The measurement unit hands its samples to the mechanization we just wrote down, and out comes a continuous solution: position, velocity and attitude, at the full sensor rate.

Board: plan — a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0)); head\_arch — a Heading that says "Loosely Coupled: The Wiring"

Actions:
- [03:50.98](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=230.9802083333333): plan moves to a new place on the board.
- [03:50.98](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=230.9802083333333): item1 is shown on the screen, written out.
- [03:52.849](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=232.8492083333333): imu\_box is shown on the screen, written out.
- [03:52.849](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=232.8492083333333): imu\_name is shown on the screen, written out.
- [03:53.534](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=233.5342083333333): imu\_link is shown on the screen, written out.
- [03:54.637](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=234.63720833333332): ins\_box is shown on the screen, written out.
- [03:54.637](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=234.63720833333332): ins\_name is shown on the screen, written out.
- [03:57.029](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=237.02920833333332): out\_link is shown on the screen, written out.
- [03:59.409](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=239.4092083333333): out\_box is shown on the screen, written out.
- [03:59.409](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=239.4092083333333): out\_name is shown on the screen, written out.

##### [04:4.839](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=244.83870833333333)

Narration: Underneath, and quite separately, sits the receiver. It tracks whatever satellites it can see and solves its own navigation problem, on its own schedule, and what leaves it is a computed fix.

Board: item1 — a Text \[text\] that says "An INS mechanization, running at IMU rate."; plan — a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0)); head\_arch — a Heading that says "Loosely Coupled: The Wiring"; imu\_box — a Polygon \[blue\] drawn in plan (vertices=((0.3, 5.0), (2.7, 5.0), (2.7, 6.2), (0.3, 6.2)), filled=False); imu\_name — a Math \[blue\] that says "$upright("IMU")$" drawn in plan; imu\_link — a Vector \[blue\] drawn in plan (start=(2.7, 5.6), end=(3.8, 5.6)); ins\_box — a Polygon \[blue\] drawn in plan (vertices=((3.8, 5.0), (8.0, 5.0), (8.0, 6.2), (3.8, 6.2)), filled=False); ins\_name — a Math \[blue\] that says "$upright("INS mechanization")$" drawn in plan; out\_link — a Vector \[blue\] drawn in plan (start=(8.0, 5.6), end=(9.6, 5.6)); out\_box — a Polygon \[blue\] drawn in plan (vertices=((9.6, 5.0), (12.4, 5.0), (12.4, 6.2), (9.6, 6.2)), filled=False); out\_name — a Math \[blue\] that says "$upright("PVA")$" drawn in plan

Actions:
- [04:7.66](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=247.66020833333332): item2 is shown on the screen, written out.
- [04:9.099](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=249.0992083333333): gnss\_box is shown on the screen, written out.
- [04:9.099](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=249.0992083333333): gnss\_name is shown on the screen, written out.

##### [04:18.105](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=258.10520833333334)

Narration: Now the filter. It does not sit in the signal path at all. Both solutions are handed to it, and what it estimates is not where the vehicle is, but how wrong the inertial solution has become.

Board: item1 — a Text \[text\] that says "An INS mechanization, running at IMU rate."; item2 — a Text \[text\] that says "An independent receiver, reporting its own position and velocity."; plan — a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0)); head\_arch — a Heading that says "Loosely Coupled: The Wiring"; imu\_box — a Polygon \[blue\] drawn in plan (vertices=((0.3, 5.0), (2.7, 5.0), (2.7, 6.2), (0.3, 6.2)), filled=False); imu\_name — a Math \[blue\] that says "$upright("IMU")$" drawn in plan; imu\_link — a Vector \[blue\] drawn in plan (start=(2.7, 5.6), end=(3.8, 5.6)); ins\_box — a Polygon \[blue\] drawn in plan (vertices=((3.8, 5.0), (8.0, 5.0), (8.0, 6.2), (3.8, 6.2)), filled=False); ins\_name — a Math \[blue\] that says "$upright("INS mechanization")$" drawn in plan; out\_link — a Vector \[blue\] drawn in plan (start=(8.0, 5.6), end=(9.6, 5.6)); out\_box — a Polygon \[blue\] drawn in plan (vertices=((9.6, 5.0), (12.4, 5.0), (12.4, 6.2), (9.6, 6.2)), filled=False); out\_name — a Math \[blue\] that says "$upright("PVA")$" drawn in plan; gnss\_box — a Polygon \[green\] drawn in plan (vertices=((0.3, 0.8), (3.2, 0.8), (3.2, 2.0), (0.3, 2.0)), filled=False); gnss\_name — a Math \[green\] that says "$upright("GNSS receiver")$" drawn in plan

Actions:
- [04:18.825](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=258.8252083333333): item3 is shown on the screen, written out.
- [04:21.089](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=261.0892083333333): ekf\_box is shown on the screen, written out.
- [04:21.089](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=261.0892083333333): ekf\_name is shown on the screen, written out.
- [04:22.726](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=262.7262083333333): ins\_down is shown on the screen, written out.
- [04:23.037](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=263.0368262195122): fix\_in is shown on the screen, written out.

##### [04:31.162](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=271.1622083333333)

Narration: Its measurement is therefore a difference. Take the inertial position and velocity, subtract the position and velocity the receiver reported, and what is left is error: the inertial system's error, plus the receiver's noise.

Board: item1 — a Text \[text\] that says "An INS mechanization, running at IMU rate."; item2 — a Text \[text\] that says "An independent receiver, reporting its own position and velocity."; item3 — a Text \[text\] that says "A filter whose states are the INS errors."; plan — a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0)); head\_arch — a Heading that says "Loosely Coupled: The Wiring"; imu\_box — a Polygon \[blue\] drawn in plan (vertices=((0.3, 5.0), (2.7, 5.0), (2.7, 6.2), (0.3, 6.2)), filled=False); imu\_name — a Math \[blue\] that says "$upright("IMU")$" drawn in plan; imu\_link — a Vector \[blue\] drawn in plan (start=(2.7, 5.6), end=(3.8, 5.6)); ins\_box — a Polygon \[blue\] drawn in plan (vertices=((3.8, 5.0), (8.0, 5.0), (8.0, 6.2), (3.8, 6.2)), filled=False); ins\_name — a Math \[blue\] that says "$upright("INS mechanization")$" drawn in plan; out\_link — a Vector \[blue\] drawn in plan (start=(8.0, 5.6), end=(9.6, 5.6)); out\_box — a Polygon \[blue\] drawn in plan (vertices=((9.6, 5.0), (12.4, 5.0), (12.4, 6.2), (9.6, 6.2)), filled=False); out\_name — a Math \[blue\] that says "$upright("PVA")$" drawn in plan; gnss\_box — a Polygon \[green\] drawn in plan (vertices=((0.3, 0.8), (3.2, 0.8), (3.2, 2.0), (0.3, 2.0)), filled=False); gnss\_name — a Math \[green\] that says "$upright("GNSS receiver")$" drawn in plan; ekf\_box — a Polygon \[yellow\] drawn in plan (vertices=((4.6, 0.8), (8.6, 0.8), (8.6, 2.0), (4.6, 2.0)), filled=False); ekf\_name — a Math \[yellow\] that says "$upright("error-state EKF")$" drawn in plan; ins\_down — a Vector \[blue\] labelled "arrow(x)\_upright("ins")" drawn in plan (start=(5.2, 5.0), end=(5.2, 2.0)); fix\_in — a Vector \[green\] labelled "arrow(x)\_upright("gnss")" drawn in plan (start=(3.2, 1.4), end=(4.6, 1.4))

Actions:
- [04:32.927](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=272.92720833333334): item4 is shown on the screen, written out.

##### [04:46.136](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=286.1357083333333)

Narration: And the corrections travel back up the same interface. The estimated error is written into the mechanization, and the estimated sensor biases are subtracted from the incoming samples, so the errors the filter is linearising about stay small.

Board: item1 — a Text \[text\] that says "An INS mechanization, running at IMU rate."; item2 — a Text \[text\] that says "An independent receiver, reporting its own position and velocity."; item3 — a Text \[text\] that says "A filter whose states are the INS errors."; item4 — a Text \[text\] that says "A measurement built by differencing the two solutions."; plan — a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0)); head\_arch — a Heading that says "Loosely Coupled: The Wiring"; imu\_box — a Polygon \[blue\] drawn in plan (vertices=((0.3, 5.0), (2.7, 5.0), (2.7, 6.2), (0.3, 6.2)), filled=False); imu\_name — a Math \[blue\] that says "$upright("IMU")$" drawn in plan; imu\_link — a Vector \[blue\] drawn in plan (start=(2.7, 5.6), end=(3.8, 5.6)); ins\_box — a Polygon \[blue\] drawn in plan (vertices=((3.8, 5.0), (8.0, 5.0), (8.0, 6.2), (3.8, 6.2)), filled=False); ins\_name — a Math \[blue\] that says "$upright("INS mechanization")$" drawn in plan; out\_link — a Vector \[blue\] drawn in plan (start=(8.0, 5.6), end=(9.6, 5.6)); out\_box — a Polygon \[blue\] drawn in plan (vertices=((9.6, 5.0), (12.4, 5.0), (12.4, 6.2), (9.6, 6.2)), filled=False); out\_name — a Math \[blue\] that says "$upright("PVA")$" drawn in plan; gnss\_box — a Polygon \[green\] drawn in plan (vertices=((0.3, 0.8), (3.2, 0.8), (3.2, 2.0), (0.3, 2.0)), filled=False); gnss\_name — a Math \[green\] that says "$upright("GNSS receiver")$" drawn in plan; ekf\_box — a Polygon \[yellow\] drawn in plan (vertices=((4.6, 0.8), (8.6, 0.8), (8.6, 2.0), (4.6, 2.0)), filled=False); ekf\_name — a Math \[yellow\] that says "$upright("error-state EKF")$" drawn in plan; ins\_down — a Vector \[blue\] labelled "arrow(x)\_upright("ins")" drawn in plan (start=(5.2, 5.0), end=(5.2, 2.0)); fix\_in — a Vector \[green\] labelled "arrow(x)\_upright("gnss")" drawn in plan (start=(3.2, 1.4), end=(4.6, 1.4))

Actions:
- [04:46.832](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=286.8322083333333): item5 is shown on the screen, written out.
- [04:51.302](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=291.3022083333333): correction\_up is shown on the screen, written out.

##### [05:1.608](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=301.6082083333333)

Narration: The word loosely is a statement about that interface. What crosses between the two systems is a finished navigation solution, six numbers. The individual satellite ranges never leave the receiver, and the receiver never hears about the inertial unit.

Board: item1 — a Text \[text\] that says "An INS mechanization, running at IMU rate."; item2 — a Text \[text\] that says "An independent receiver, reporting its own position and velocity."; item3 — a Text \[text\] that says "A filter whose states are the INS errors."; item4 — a Text \[text\] that says "A measurement built by differencing the two solutions."; item5 — a Text \[text\] that says "Corrections fed back into the mechanization and the IMU."; plan — a Figure (x\_range=(0.0, 13.0), y\_range=(0.0, 7.0), aspect=(13.0, 7.0)); head\_arch — a Heading that says "Loosely Coupled: The Wiring"; imu\_box — a Polygon \[blue\] drawn in plan (vertices=((0.3, 5.0), (2.7, 5.0), (2.7, 6.2), (0.3, 6.2)), filled=False); imu\_name — a Math \[blue\] that says "$upright("IMU")$" drawn in plan; imu\_link — a Vector \[blue\] drawn in plan (start=(2.7, 5.6), end=(3.8, 5.6)); ins\_box — a Polygon \[blue\] drawn in plan (vertices=((3.8, 5.0), (8.0, 5.0), (8.0, 6.2), (3.8, 6.2)), filled=False); ins\_name — a Math \[blue\] that says "$upright("INS mechanization")$" drawn in plan; out\_link — a Vector \[blue\] drawn in plan (start=(8.0, 5.6), end=(9.6, 5.6)); out\_box — a Polygon \[blue\] drawn in plan (vertices=((9.6, 5.0), (12.4, 5.0), (12.4, 6.2), (9.6, 6.2)), filled=False); out\_name — a Math \[blue\] that says "$upright("PVA")$" drawn in plan; gnss\_box — a Polygon \[green\] drawn in plan (vertices=((0.3, 0.8), (3.2, 0.8), (3.2, 2.0), (0.3, 2.0)), filled=False); gnss\_name — a Math \[green\] that says "$upright("GNSS receiver")$" drawn in plan; ekf\_box — a Polygon \[yellow\] drawn in plan (vertices=((4.6, 0.8), (8.6, 0.8), (8.6, 2.0), (4.6, 2.0)), filled=False); ekf\_name — a Math \[yellow\] that says "$upright("error-state EKF")$" drawn in plan; ins\_down — a Vector \[blue\] labelled "arrow(x)\_upright("ins")" drawn in plan (start=(5.2, 5.0), end=(5.2, 2.0)); fix\_in — a Vector \[green\] labelled "arrow(x)\_upright("gnss")" drawn in plan (start=(3.2, 1.4), end=(4.6, 1.4)); correction\_up — a Vector \[yellow\] labelled "delta hat(arrow(x))" drawn in plan (start=(7.4, 2.0), end=(7.4, 5.0))

Actions:
- [05:9.097](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=309.0972083333333): ins\_down is indicated — a transient flash.
- [05:9.358](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=309.35769630584184): fix\_in is indicated — a transient flash.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): head\_arch is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): item1 is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): item2 is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): item3 is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): item4 is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): item5 is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): plan is hidden from the screen — left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): imu\_box is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): imu\_name is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): imu\_link is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): ins\_box is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): ins\_name is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): out\_link is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): out\_box is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): out\_name is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): gnss\_box is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): gnss\_name is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): ekf\_box is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): ekf\_name is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): ins\_down is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): fix\_in is hidden from the screen — plan left the board.
- [05:16.411](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=316.4112083333333): correction\_up is hidden from the screen — plan left the board.

##### [05:17.611](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=317.6112083333333)

Narration: Why estimate the error rather than the state? Look at what the error is. Here is the true path of the vehicle in grey, and here is the path the mechanization computed, in red. The shapes agree very well. The placement does not.

Board: Empty.

Actions:
- [05:17.611](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=317.6112083333333): head\_err is shown on the screen, written out.
- [05:21.117](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=321.1172083333333): map\_axes is shown on the screen, written out.
- [05:24.693](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=324.6932083333333): true\_path is shown on the screen, drawn.
- [05:28.211](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=328.2112083333333): ins\_path is shown on the screen, drawn.

##### [05:33.281](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=333.28070833333334)

Narration: The difference between those two paths is small, it is slowly varying, and to first order it obeys linear dynamics. That is the whole reason for the indirect formulation: the vehicle's motion is thoroughly nonlinear, but its error is not.

Board: map\_axes — an Axes (x\_range=(0.0, 11.0), y\_range=(0.0, 6.0), aspect=(11.0, 6.0)); head\_err — a Heading that says "Why the Filter Estimates the Error"; true\_path — a ParametricCurve \[gray\] labelled "upright("truth")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); ins\_path — a ParametricCurve \[red\] labelled "upright("INS")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0))

Actions:
- [05:33.803](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=333.80320833333326): The segment (5.5, 2.093) to (6.045, 2.517) in map\_axes is lit up.
- [05:42.766](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=342.7662083333333): map\_axes: retire a lit segment (unemphasize\_line).

##### [05:49.96](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=349.9602083333333)

Narration: So we do not ask the filter for the vehicle's position. We ask it for fifteen numbers that say how wrong the inertial solution is: three of position, three of velocity, three of attitude, and six sensor biases, three per triad.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [05:54.988](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=354.9882083333333): map\_axes moves to a new place on the board.
- [05:54.988](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=354.9882083333333): state\_vec is shown on the screen, written out.
- [05:58.656](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=358.65620833333327): state\_vec (the "delta arrow(p)" part) is emphasized.
- [06:2.755](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=362.7552083333333): state\_vec (the "arrow(b)\_a" part) is emphasized.
- [06:2.755](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=362.7552083333333): state\_vec (the "delta arrow(p)" part) is no longer emphasized.

##### [06:6.455](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=366.4547083333333)

Narration: Those fifteen errors evolve according to a matrix F built from the current attitude, the current specific force and the bias models, plus process noise for everything F leaves out. That is the propagation half of the filter.

Board: state\_vec — a Math \[text\] that says "$delta arrow(x) = mat(delta arrow(p); delta arrow(v); delta arrow(psi); arrow(b)\_a; arrow(b)\_g)$"; map\_axes — an Axes (x\_range=(0.0, 11.0), y\_range=(0.0, 6.0), aspect=(11.0, 6.0)); head\_err — a Heading that says "Why the Filter Estimates the Error"; true\_path — a ParametricCurve \[gray\] labelled "upright("truth")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); ins\_path — a ParametricCurve \[red\] labelled "upright("INS")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0))

Actions:
- [06:6.455](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=366.4547083333333): state\_vec (the "arrow(b)\_a" part) is no longer emphasized.
- [06:9.357](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=369.35720833333335): dynamics is shown on the screen, written out.
- [06:21.211](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=381.2107083333333): map\_axes moves to a new place on the board.
- [06:21.211](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=381.2107083333333): dynamics is hidden from the screen — left the board.
- [06:21.211](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=381.2107083333333): head\_err is hidden from the screen — left the board.
- [06:21.211](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=381.2107083333333): state\_vec is hidden from the screen — left the board.

##### [06:21.811](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=381.8107083333333)

Narration: Now the measurement. It is the inertial solution minus the receiver's solution, and nothing else. Write each of them as the truth plus its own error, and the truth cancels.

Board: map\_axes — an Axes (x\_range=(0.0, 11.0), y\_range=(0.0, 6.0), aspect=(11.0, 6.0)); true\_path — a ParametricCurve \[gray\] labelled "upright("truth")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); ins\_path — a ParametricCurve \[red\] labelled "upright("INS")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0))

Actions:
- [06:21.811](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=381.8107083333333): head\_meas is shown on the screen, written out.
- [06:25.119](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=385.1192083333333): fix\_a is shown on the screen, written out.
- [06:25.119](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=385.1192083333333): measurement is shown on the screen, written out.
- [06:25.275](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=385.2745045631358): fix\_b is shown on the screen, written out.
- [06:25.43](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=385.42980079293835): fix\_c is shown on the screen, written out.
- [06:28.568](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=388.5682083333333): measurement is shown on the screen, written out.
- [06:32.538](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=392.5382083333333): measurement is shown on the screen, written out.

##### [06:34.23](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=394.2297083333333)

Narration: What is left is the position and velocity part of the error state, minus the receiver's noise. So the measurement matrix is almost embarrassingly simple: identity on six of the fifteen states, zero on the other nine. That is the entire measurement model of a loosely coupled filter.

Board: map\_axes — an Axes (x\_range=(0.0, 11.0), y\_range=(0.0, 6.0), aspect=(11.0, 6.0)); true\_path — a ParametricCurve \[gray\] labelled "upright("truth")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); ins\_path — a ParametricCurve \[red\] labelled "upright("INS")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); head\_meas — a Heading that says "The Measurement Model"; fix\_a — a Point \[green\] drawn in map\_axes (location=(3.1, 2.66)); fix\_b — a Point \[green\] drawn in map\_axes (location=(5.42, 2.2)); fix\_c — a Point \[green\] drawn in map\_axes (location=(7.9, 1.36))

Actions:
- [06:35.692](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=395.6922083333333): ins\_here is shown on the screen, written out.
- [06:36.006](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=396.0061544506075): innovation is shown on the screen, written out.
- [06:42.066](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=402.0662083333333): measurement is shown on the screen, written out.
- [06:44.678](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=404.6782083333333): h\_def is shown on the screen, written out.
- [06:49.798](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=409.7982083333333): A box is drawn around h\_def.

##### [06:53.615](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=413.6147083333333)

Narration: And notice what is not in there. No satellite geometry, no ranges, no clock. All of that stayed inside the receiver, which is exactly what makes this scheme modular, and also exactly what will limit it.

Board: map\_axes — an Axes (x\_range=(0.0, 11.0), y\_range=(0.0, 6.0), aspect=(11.0, 6.0)); true\_path — a ParametricCurve \[gray\] labelled "upright("truth")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); ins\_path — a ParametricCurve \[red\] labelled "upright("INS")" drawn in map\_axes (function=\<function\>, t\_range=(0.0, 8.0)); h\_def — a Math \[text\] that says "$H = mat(I, 0, 0, 0, 0; 0, I, 0, 0, 0)$"; head\_meas — a Heading that says "The Measurement Model"; fix\_a — a Point \[green\] drawn in map\_axes (location=(3.1, 2.66)); fix\_b — a Point \[green\] drawn in map\_axes (location=(5.42, 2.2)); fix\_c — a Point \[green\] drawn in map\_axes (location=(7.9, 1.36)); ins\_here — a Point \[red\] drawn in map\_axes (location=(9.152, 2.135)); innovation — an Arrow \[yellow\] labelled "arrow(z)" drawn in map\_axes (start=(9.152, 2.135), end=(7.9, 1.36))

Actions:
- [07:4.586](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=424.5862083333333): innovation is indicated — a transient flash.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): h\_def is hidden from the screen — left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): head\_meas is hidden from the screen — left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): map\_axes is hidden from the screen — left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): true\_path is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): ins\_path is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): fix\_a is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): fix\_b is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): fix\_c is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): ins\_here is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): innovation is hidden from the screen — map\_axes left the board.
- [07:7.785](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=427.7849166666667): measurement is hidden from the screen — left the board.

### Scene 3: [The Correction Loop](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=428.8265833333333)

Span: 07:8.827–10:55.256 (428.8265833333333s–655.2562083333333s).

#### Objects

- bias\_axes: an Axes (x\_range=(0.0, 120.0), y\_range=(0.0, 10.0), x\_ticks\_every=30.0)
- bias\_curve: a FunctionPlot \[blue\] labelled "hat(b)\_a" drawn in bias\_axes (function=\<function\>, x\_range=(0.0, 120.0))
- err\_axes: an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 10.0), x\_ticks\_every=5.0)
- f\_bias: a Math \[text\] that says "$arrow(f)\_upright("c") = arrow(f) - hat(arrow(b))\_a$"
- f\_reset: a Math \[text\] that says "$delta hat(arrow(x)) arrow.l 0$"
- f\_state: a Math \[text\] that says "$arrow(x) arrow.l arrow(x) - delta hat(arrow(x))$"
- head\_apply: a Heading that says "Where the Correction Goes"
- head\_predict: a Heading that says "Between Fixes: Predict"
- head\_update: a Heading that says "At a Fix: Correct"
- loop: a Panel that says "Feedback: the correction is written into the mechanization and the estimate is reset. Feedforward: the mechanization runs untouched and the correction is applied to its output."
- point: a Point \[yellow\] drawn in err\_axes (location=(4.5, 7.34))
- point\_2: a Point \[yellow\] drawn in err\_axes (location=(5.0, 0.45))
- point\_3: a Point \[yellow\] drawn in bias\_axes (location=(10.0, 2.6))
- point\_4: a Point \[yellow\] drawn in bias\_axes (location=(100.0, 7.88))
- predict: a Derivation \[text\] that says "$delta arrow(x)^- &= 0 \\ Phi &approx I + F thin Delta t \\ P^- &= Phi thin P thin Phi^upright("T") + Q$"
- predict\_note: a Text \[text\] that says "Between fixes the filter tracks only how uncertain the solution has become."
- progress: a VariableNumber (initial\_value=0.2)
- rider: a PlotPoint \[yellow\] drawn in err\_axes (target='sawtooth', x=\<VariableNumber progress = 30.0\>)
- sawtooth: a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>))
- truth\_line: a Line \[gray\] labelled "b\_a" drawn in bias\_axes (start=(0.0, 8.0), end=(120.0, 8.0), dashed=True)
- update: a Derivation \[text\] that says "$arrow(y) &= arrow(z) - H thin delta arrow(x)^- \\ S &= H thin P^- H^upright("T") + R \\ K &= P^- H^upright("T") S^(-1) \\ delta hat(arrow(x)) &= delta arrow(x)^- + K arrow(y) \\ P^+ &= (I - K H) thin P^-$"

#### Beats

##### [07:8.827](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=428.8265833333333)

Narration: Now the filter itself. It alternates between two steps, and the interesting thing about this architecture is how little happens in the first of them.

Board: Empty.

Actions:
- [07:8.827](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=428.8265833333333): head\_predict is shown on the screen, written out.
- [07:12.275](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=432.2745833333333): err\_axes is shown on the screen, written out.

##### [07:18.703](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=438.7030833333333)

Narration: Between fixes there is no measurement, so nothing corrects anything at all. The mechanization runs on at full rate, the error grows exactly as it did unaided, and all the filter can do is keep track of how uncertain that growing solution has become.

Board: err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 10.0), x\_ticks\_every=5.0); head\_predict — a Heading that says "Between Fixes: Predict"

Actions:
- [07:18.703](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=438.7030833333333): sawtooth is shown on the screen, written out.
- [07:19.283](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=439.28285317186493): rider is shown on the screen, written out.
- [07:26.366](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=446.3655833333333): sawtooth is redrawn as the numbers it depends on change.
- [07:26.366](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=446.3655833333333): rider is redrawn as the numbers it depends on change.
- [07:26.366](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=446.3655833333333): progress ticks to 2.6.

##### [07:34.094](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=454.0940833333333)

Narration: The prediction is the ordinary Kalman one, on the error state. Because the last correction was written straight into the mechanization, the error estimate starts each interval at zero. The transition matrix over one interval is the identity plus F delta t, and the covariance is pushed through it and grown by the process noise.

Board: err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 10.0), x\_ticks\_every=5.0); head\_predict — a Heading that says "Between Fixes: Predict"; sawtooth — a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); rider — a PlotPoint \[yellow\] drawn in err\_axes (target='sawtooth', x=\<VariableNumber progress = 30.0\>)

Actions:
- [07:44.009](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=464.0085833333333): err\_axes moves to a new place on the board.
- [07:44.009](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=464.0085833333333): predict is shown on the screen, written out.
- [07:45.414](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=465.4135833333333): predict is shown on the screen, written out.
- [07:50.058](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=470.0575833333333): predict is shown on the screen, written out.
- [07:51.718](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=471.7175833333333): sawtooth is redrawn as the numbers it depends on change.
- [07:51.718](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=471.7175833333333): rider is redrawn as the numbers it depends on change.
- [07:51.718](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=471.7175833333333): progress ticks to 4.9.
- [07:52.229](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=472.2285833333333): predict\_note is shown on the screen, written out.

##### [07:54.187](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=474.1870833333333)

Narration: Watch the picture while that runs. Nothing on it improves. Between fixes, a loosely coupled system is an unaided inertial system with a growing covariance attached to it.

Board: predict\_note — a Text \[text\] that says "Between fixes the filter tracks only how uncertain the solution has become."; err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 10.0), x\_ticks\_every=5.0); head\_predict — a Heading that says "Between Fixes: Predict"; sawtooth — a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); rider — a PlotPoint \[yellow\] drawn in err\_axes (target='sawtooth', x=\<VariableNumber progress = 30.0\>)

Actions:
- [07:57.241](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=477.2405833333333): point is shown on the screen, grown.
- [07:59.948](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=479.94754347460474): point is hidden from the screen.
- [08:5.17](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=485.1700833333333): head\_predict is hidden from the screen — left the board.
- [08:5.17](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=485.1700833333333): predict is hidden from the screen — left the board.
- [08:5.17](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=485.1700833333333): predict\_note is hidden from the screen — left the board.

##### [08:5.77](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=485.77008333333333)

Narration: Then a fix arrives, and everything happens at once. The innovation is the difference we built a moment ago, less whatever the filter already expected that difference to be. Here it expected zero, so the innovation is the raw difference.

Board: err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 10.0), x\_ticks\_every=5.0); sawtooth — a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); rider — a PlotPoint \[yellow\] drawn in err\_axes (target='sawtooth', x=\<VariableNumber progress = 30.0\>)

Actions:
- [08:5.77](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=485.77008333333333): head\_update is shown on the screen, written out.
- [08:6.385](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=486.3845833333333): sawtooth is redrawn as the numbers it depends on change.
- [08:6.385](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=486.3845833333333): rider is redrawn as the numbers it depends on change.
- [08:6.385](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=486.3845833333333): progress ticks to 5.6.
- [08:8.324](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=488.3235833333333): point\_2 is shown on the screen, grown.
- [08:9.752](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=489.7515833333333): update is shown on the screen, written out.
- [08:10.701](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=490.7009006747486): point\_2 is hidden from the screen.

##### [08:20.22](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=500.2200833333333)

Narration: The gain weighs the two sides against each other. The middle term, S, is how large a difference we should have expected, given our own uncertainty and the receiver's noise. When the receiver is noisy and the filter is confident, the correction is small. When the inertial solution has been coasting a long time, it is large.

Board: err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 10.0), x\_ticks\_every=5.0); sawtooth — a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); rider — a PlotPoint \[yellow\] drawn in err\_axes (target='sawtooth', x=\<VariableNumber progress = 30.0\>); head\_update — a Heading that says "At a Fix: Correct"

Actions:
- [08:23.692](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=503.6915833333333): update is shown on the screen, written out.
- [08:33.828](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=513.8275833333333): update is shown on the screen, written out.

##### [08:40.615](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=520.6150833333334)

Narration: The correction is applied to the whole error state, not only to the six states we measured. Position error is observed directly. Attitude error and the gyro biases are not, and they are estimated anyway, because the covariance says they are correlated with what we did measure.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [08:41.707](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=521.7065833333332): update is shown on the screen, written out.

##### [08:57.783](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=537.7830833333333)

Narration: And the covariance shrinks, which is the part that matters most. The filter is now more certain than it was, and the next coasting interval starts from a smaller number.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [08:59.026](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=539.0255833333333): update is shown on the screen, written out.
- [09:4.668](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=544.6675833333333): sawtooth is redrawn as the numbers it depends on change.
- [09:4.668](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=544.6675833333333): rider is redrawn as the numbers it depends on change.
- [09:4.668](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=544.6675833333333): progress ticks to 9.8.

##### [09:8.089](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=548.0885833333333)

Narration: Then it all repeats. And here is what to watch across several cycles: the teeth are getting shorter. Nearly nine metres on the first, under six on the next, then four. Each fix does more than reset the error; it also improves the estimate of the biases that were making it grow.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [09:9.32](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=549.3195833333333): sawtooth is redrawn as the numbers it depends on change.
- [09:9.32](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=549.3195833333333): rider is redrawn as the numbers it depends on change.
- [09:9.32](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=549.3195833333333): progress ticks to 30.0.
- [09:26.525](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=566.5250833333333): err\_axes is hidden from the screen — left the board.
- [09:26.525](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=566.5250833333333): sawtooth is hidden from the screen — err\_axes left the board.
- [09:26.525](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=566.5250833333333): rider is hidden from the screen — err\_axes left the board.
- [09:26.525](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=566.5250833333333): head\_update is hidden from the screen — left the board.
- [09:26.525](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=566.5250833333333): update is hidden from the screen — left the board.

##### [09:27.725](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=567.7250833333333)

Narration: That improvement deserves its own picture. This is the filter's estimate of one accelerometer bias against time, in milli-g, with the true value dashed across it at eight.

Board: Empty.

Actions:
- [09:27.725](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=567.7250833333333): head\_apply is shown on the screen, written out.
- [09:30.5](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=570.4995833333332): bias\_axes is shown on the screen, written out.
- [09:31.452](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=571.4515833333332): bias\_curve is shown on the screen, drawn.
- [09:36.619](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=576.6185833333333): truth\_line is shown on the screen, written out.

##### [09:38.971](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=578.9710833333334)

Narration: It starts at zero, because we knew nothing, and it walks up to the truth over a minute or two of driving. A bias on an accelerometer produces a velocity error that grows in a particular direction, and every fix reports that direction again. So the filter is calibrating the instrument while the vehicle drives.

Board: bias\_axes — an Axes (x\_range=(0.0, 120.0), y\_range=(0.0, 10.0), x\_ticks\_every=30.0); head\_apply — a Heading that says "Where the Correction Goes"; bias\_curve — a FunctionPlot \[blue\] labelled "hat(b)\_a" drawn in bias\_axes (function=\<function\>, x\_range=(0.0, 120.0)); truth\_line — a Line \[gray\] labelled "b\_a" drawn in bias\_axes (start=(0.0, 8.0), end=(120.0, 8.0), dashed=True)

Actions:
- [09:42.594](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=582.5935833333333): point\_3 is shown on the screen, grown.
- [09:43.729](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=583.7294305879091): point\_3 is hidden from the screen.
- [09:54.645](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=594.6445833333333): point\_4 is shown on the screen, grown.
- [09:55.84](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=595.8402962360713): point\_4 is hidden from the screen.

##### [09:58.263](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=598.2630833333333)

Narration: Which brings us to where the correction is actually applied, and there are two choices. In the feedback configuration the estimate is written into the mechanization: position, velocity and attitude are overwritten, the estimated biases are subtracted from the incoming samples, and the error estimate is then reset to zero.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [10:2.257](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=602.2565833333333): bias\_axes moves to a new place on the board.
- [10:2.257](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=602.2565833333333): loop is shown on the screen, written out.
- [10:4.103](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=604.1025833333333): loop (the "Feedback" part) is emphasized.
- [10:10.895](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=610.8945833333333): f\_state is shown on the screen, written out.
- [10:13.322](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=613.3215833333334): f\_bias is shown on the screen, written out.
- [10:17.072](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=617.0715833333334): f\_reset is shown on the screen, written out.

##### [10:19.064](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=619.0640833333333)

Narration: In the feedforward configuration the mechanization is left running untouched, and the correction is added to its output instead. That is easier to bolt onto an existing box, but the inertial solution keeps drifting underneath, so the errors the filter linearised about stop being small. Feedback keeps them small.

Board: loop — a Panel that says "Feedback: the correction is written into the mechanization and the estimate is reset. Feedforward: the mechanization runs untouched and the correction is applied to its output."; f\_state — a Math \[text\] that says "$arrow(x) arrow.l arrow(x) - delta hat(arrow(x))$"; f\_bias — a Math \[text\] that says "$arrow(f)\_upright("c") = arrow(f) - hat(arrow(b))\_a$"; f\_reset — a Math \[text\] that says "$delta hat(arrow(x)) arrow.l 0$"; bias\_axes — an Axes (x\_range=(0.0, 120.0), y\_range=(0.0, 10.0), x\_ticks\_every=30.0); head\_apply — a Heading that says "Where the Correction Goes"; bias\_curve — a FunctionPlot \[blue\] labelled "hat(b)\_a" drawn in bias\_axes (function=\<function\>, x\_range=(0.0, 120.0)); truth\_line — a Line \[gray\] labelled "b\_a" drawn in bias\_axes (start=(0.0, 8.0), end=(120.0, 8.0), dashed=True)

Actions:
- [10:19.738](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=619.7375833333333): loop (the "Feedback" part) is no longer emphasized.
- [10:19.738](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=619.7375833333333): loop (the "Feedforward" part) is emphasized.
- [10:36.225](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=636.2245833333334): loop (the "Feedforward" part) is no longer emphasized.

##### [10:38.659](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=638.6585833333334)

Narration: So the loop is four words: coast, compare, correct, calibrate. And note where the navigation solution comes from. It is produced entirely by the mechanization; the filter never computes a position, only a correction to one.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [10:52.695](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=652.6945833333333): f\_state is indicated — a transient flash.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): bias\_axes is hidden from the screen — left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): bias\_curve is hidden from the screen — bias\_axes left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): truth\_line is hidden from the screen — bias\_axes left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): f\_bias is hidden from the screen — left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): f\_reset is hidden from the screen — left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): f\_state is hidden from the screen — left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): head\_apply is hidden from the screen — left the board.
- [10:54.215](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=654.2145416666667): loop is hidden from the screen — left the board.

### Scene 4: [Strengths, and the Four-Satellite Floor](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333)

Span: 10:55.256–13:54.224 (655.2562083333333s–834.2237916666667s).

#### Objects

- closing: a Panel that says "The inertial unit supplies continuity and rate, the receiver supplies an absolute reference, and the error-state filter carries the calibration from one fix to the next."
- err\_axes: an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 22.0), x\_ticks\_every=10.0)
- err\_curve: a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>))
- err\_rider: a PlotPoint \[yellow\] drawn in err\_axes (target='err\_curve', x=\<VariableNumber progress = 30.0\>)
- error\_label: a Tex \[text\] that says "Position error"
- gain\_label: a Tex \[text\] that says "What you gain"
- give\_label: a Tex \[text\] that says "What you give up"
- head\_close: a Heading that says "The Whole Thing in One Line"
- head\_gap: a Heading that says "When the Fixes Stop"
- head\_trade: a Heading that says "The Trade"
- limits: a Block \[text\] that says "Fixes are correlated: the receiver filtered them first. Latency: the fix must be tagged and applied to the right instant. Below four satellites, no measurement at all. A tightly coupled filter would still use the ranges it has."
- point: a Point \[yellow\] drawn in err\_axes (location=(22.0, 18.9))
- progress: a VariableNumber (initial\_value=0.3)
- sat\_axes: an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 8.0), x\_ticks\_every=10.0)
- sat\_curve: a FunctionPlot \[green\] drawn in sat\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>))
- sat\_rider: a PlotPoint \[yellow\] drawn in sat\_axes (target='sat\_curve', x=\<VariableNumber progress = 30.0\>)
- sky\_label: a Tex \[text\] that says "Satellites in view"
- strengths: a Block \[text\] that says "The receiver is a box you can buy, qualify and replace. The measurement model is six states of identity. A small state and one update per fix: cheap to run. Two solutions that can check each other."
- summary: a Math \[text\] that says "$hat(arrow(x)) = arrow(x)\_upright("ins") - delta hat(arrow(x))$"
- threshold: a Line \[yellow\] labelled "4" drawn in sat\_axes (start=(0.0, 4.0), end=(30.0, 4.0), dashed=True)

#### Beats

##### [10:55.256](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333)

Narration: Two things left: what this arrangement buys, and the one place it stops working. The second is easier to see, so start there. On the left, the number of satellites the receiver can use; on the right, the error of the integrated solution over the same half minute.

Board: Empty.

Actions:
- [10:55.256](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333): head\_gap is shown on the screen, written out.
- [10:55.256](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333): sky\_label is shown on the screen, written out.
- [10:55.256](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.2562083333333): error\_label is shown on the screen, written out.
- [10:55.871](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.8712083333334): sat\_axes is shown on the screen, written out.
- [10:55.871](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=655.8712083333334): sat\_curve is shown on the screen, written out.
- [10:56.553](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=656.5525988194807): sat\_rider is shown on the screen, written out.
- [11:7.621](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=667.6212083333334): err\_axes is shown on the screen, written out.
- [11:7.621](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=667.6212083333334): err\_curve is shown on the screen, written out.
- [11:8.016](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=668.0159958772061): err\_rider is shown on the screen, written out.

##### [11:12.169](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=672.1687083333334)

Narration: With six satellites in view the fixes keep arriving, once a second, and the error stays well under five metres: the sawtooth we have just been watching, on a coarser scale.

Board: sky\_label — a Tex \[text\] that says "Satellites in view"; sat\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 8.0), x\_ticks\_every=10.0); error\_label — a Tex \[text\] that says "Position error"; err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 22.0), x\_ticks\_every=10.0); head\_gap — a Heading that says "When the Fixes Stop"; sat\_curve — a FunctionPlot \[green\] drawn in sat\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); sat\_rider — a PlotPoint \[yellow\] drawn in sat\_axes (target='sat\_curve', x=\<VariableNumber progress = 30.0\>); err\_curve — a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); err\_rider — a PlotPoint \[yellow\] drawn in err\_axes (target='err\_curve', x=\<VariableNumber progress = 30.0\>)

Actions:
- [11:14.49](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=674.4902083333334): sat\_curve is redrawn as the numbers it depends on change.
- [11:14.49](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=674.4902083333334): sat\_rider is redrawn as the numbers it depends on change.
- [11:14.49](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=674.4902083333334): err\_curve is redrawn as the numbers it depends on change.
- [11:14.49](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=674.4902083333334): err\_rider is redrawn as the numbers it depends on change.
- [11:14.49](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=674.4902083333334): progress ticks to 11.6.

##### [11:23.345](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=683.3452083333334)

Narration: Then the vehicle turns into a street with tall buildings on both sides, and the usable count falls to three. Four independent ranges are needed for three coordinates and the clock offset, so with three the receiver publishes nothing at all.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [11:28.454](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=688.4542083333333): sat\_curve is redrawn as the numbers it depends on change.
- [11:28.454](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=688.4542083333333): sat\_rider is redrawn as the numbers it depends on change.
- [11:28.454](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=688.4542083333333): err\_curve is redrawn as the numbers it depends on change.
- [11:28.454](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=688.4542083333333): err\_rider is redrawn as the numbers it depends on change.
- [11:28.454](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=688.4542083333333): progress ticks to 14.5.
- [11:30.102](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=690.1022083333334): threshold is shown on the screen, written out.

##### [11:38.435](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=698.4347083333333)

Narration: And a loosely coupled filter has nothing to do with three ranges. Its measurement is a position and velocity solution, and there is no solution, so there is no update: no innovation, no gain, no correction. The filter coasts, and what you are watching is once again the unaided inertial error.

Board: sky\_label — a Tex \[text\] that says "Satellites in view"; sat\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 8.0), x\_ticks\_every=10.0); error\_label — a Tex \[text\] that says "Position error"; err\_axes — an Axes (x\_range=(0.0, 30.0), y\_range=(0.0, 22.0), x\_ticks\_every=10.0); head\_gap — a Heading that says "When the Fixes Stop"; sat\_curve — a FunctionPlot \[green\] drawn in sat\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); sat\_rider — a PlotPoint \[yellow\] drawn in sat\_axes (target='sat\_curve', x=\<VariableNumber progress = 30.0\>); err\_curve — a FunctionPlot \[blue\] drawn in err\_axes (function=\<function\>, x\_range=(0.0, \<VariableNumber progress = 30.0\>)); err\_rider — a PlotPoint \[yellow\] drawn in err\_axes (target='err\_curve', x=\<VariableNumber progress = 30.0\>); threshold — a Line \[yellow\] labelled "4" drawn in sat\_axes (start=(0.0, 4.0), end=(30.0, 4.0), dashed=True)

Actions:
- [11:53.109](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=713.1092083333333): sat\_curve is redrawn as the numbers it depends on change.
- [11:53.109](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=713.1092083333333): sat\_rider is redrawn as the numbers it depends on change.
- [11:53.109](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=713.1092083333333): err\_curve is redrawn as the numbers it depends on change.
- [11:53.109](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=713.1092083333333): err\_rider is redrawn as the numbers it depends on change.
- [11:53.109](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=713.1092083333333): progress ticks to 22.0.

##### [11:58.237](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=718.2367083333334)

Narration: Ten seconds of that, and the solution is nearly twenty metres out. Then the street opens, the satellites come back, and the very first fix pulls the whole thing down again. The recovery is immediate: the filter kept a valid covariance the whole way through the gap, so it knows exactly how little to trust itself.

Board: Unchanged from the preceding beat in this scene.

Actions:
- [12:1.011](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=721.0112083333333): point is shown on the screen, grown.
- [12:2.912](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=722.9120062898264): point is hidden from the screen.
- [12:3.287](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=723.2872083333334): sat\_curve is redrawn as the numbers it depends on change.
- [12:3.287](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=723.2872083333334): sat\_rider is redrawn as the numbers it depends on change.
- [12:3.287](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=723.2872083333334): err\_curve is redrawn as the numbers it depends on change.
- [12:3.287](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=723.2872083333334): err\_rider is redrawn as the numbers it depends on change.
- [12:3.287](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=723.2872083333334): progress ticks to 30.0.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): err\_axes is hidden from the screen — left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): err\_curve is hidden from the screen — err\_axes left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): err\_rider is hidden from the screen — err\_axes left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): error\_label is hidden from the screen — left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): head\_gap is hidden from the screen — left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): sat\_axes is hidden from the screen — left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): sat\_curve is hidden from the screen — sat\_axes left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): sat\_rider is hidden from the screen — sat\_axes left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): threshold is hidden from the screen — sat\_axes left the board.
- [12:16.813](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=736.8132083333334): sky\_label is hidden from the screen — left the board.

##### [12:18.013](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=738.0132083333333)

Narration: So here is the trade, and it is a clear one. On the gain side: the receiver is a box you can buy, qualify and replace, and the filter never touches its internals. The measurement model is six states of identity, so the code is small and the update is cheap. And you have two solutions that can check each other.

Board: Empty.

Actions:
- [12:18.013](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=738.0132083333333): head\_trade is shown on the screen, written out.
- [12:18.013](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=738.0132083333333): gain\_label is shown on the screen, written out.
- [12:22.03](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=742.0302083333333): strengths is shown on the screen, written out.
- [12:25.258](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=745.2582083333334): strengths (the "buy, qualify and replace" part) is emphasized.
- [12:31.423](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=751.4232083333334): strengths (the "buy, qualify and replace" part) is no longer emphasized.
- [12:31.423](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=751.4232083333334): strengths (the "six states of identity" part) is emphasized.
- [12:37.425](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=757.4252083333333): strengths (the "check each other" part) is emphasized.
- [12:37.425](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=757.4252083333333): strengths (the "six states of identity" part) is no longer emphasized.

##### [12:39.14](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=759.1397083333334)

Narration: On the other side: the receiver has already filtered its own output, so consecutive fixes are correlated and the noise covariance you assume is optimistic. The fix is old when it arrives, so it must be time-tagged and applied to the instant it belongs to. And below four satellites there is no measurement at all.

Board: gain\_label — a Tex \[text\] that says "What you gain"; strengths — a Block \[text\] that says "The receiver is a box you can buy, qualify and replace. The measurement model is six states of identity. A small state and one update per fix: cheap to run. Two solutions that can check each other."; head\_trade — a Heading that says "The Trade"

Actions:
- [12:39.14](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=759.1397083333334): give\_label is shown on the screen, written out.
- [12:39.14](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=759.1397083333334): strengths (the "check each other" part) is no longer emphasized.
- [12:39.789](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=759.7892083333334): limits is shown on the screen, written out.
- [12:44.805](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=764.8052083333333): limits (the "correlated" part) is emphasized.
- [12:51.388](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=771.3882083333334): limits (the "Latency" part) is emphasized.
- [12:51.388](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=771.3882083333334): limits (the "correlated" part) is no longer emphasized.
- [12:54.732](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=774.7322083333333): limits (the "Below four satellites" part) is emphasized.
- [12:54.732](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=774.7322083333333): limits (the "Latency" part) is no longer emphasized.

##### [12:58.385](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=778.3852083333334)

Narration: None of that is a reason to avoid the architecture. It is a reason to know which failure you are buying. This filter is exactly as available as the receiver's position solution, and no more. If you need aiding below four satellites, you need a different interface, and that is what a tightly coupled design is for.

Board: gain\_label — a Tex \[text\] that says "What you gain"; strengths — a Block \[text\] that says "The receiver is a box you can buy, qualify and replace. The measurement model is six states of identity. A small state and one update per fix: cheap to run. Two solutions that can check each other."; give\_label — a Tex \[text\] that says "What you give up"; limits — a Block \[text\] that says "Fixes are correlated: the receiver filtered them first. Latency: the fix must be tagged and applied to the right instant. Below four satellites, no measurement at all. A tightly coupled filter would still use the ranges it has."; head\_trade — a Heading that says "The Trade"

Actions:
- [13:16.067](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=796.0672083333334): limits (the "Below four satellites" part) is no longer emphasized.
- [13:16.067](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=796.0672083333334): limits (the "tightly coupled" part) is emphasized.
- [13:18.076](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=798.0762083333334): gain\_label is hidden from the screen — left the board.
- [13:18.076](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=798.0762083333334): give\_label is hidden from the screen — left the board.
- [13:18.076](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=798.0762083333334): head\_trade is hidden from the screen — left the board.
- [13:18.076](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=798.0762083333334): limits is hidden from the screen — left the board.
- [13:18.076](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=798.0762083333334): strengths is hidden from the screen — left the board.
- [13:18.076](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=798.0762083333334): limits (the "tightly coupled" part) is no longer emphasized.

##### [13:19.276](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=799.2762083333333)

Narration: So, the whole thing in one line. The navigation solution is the mechanization's own, corrected by an estimate of its own error, and that estimate is driven by nothing more than the difference between two independent solutions to the same problem.

Board: Empty.

Actions:
- [13:19.276](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=799.2762083333333): head\_close is shown on the screen, written out.
- [13:25.116](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=805.1162083333334): summary is shown on the screen, written out.
- [13:30.189](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=810.1892083333333): A box is drawn around summary.

##### [13:34.516](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=814.5162083333333)

Narration: The inertial unit supplies continuity, smoothness and rate. The receiver supplies an absolute reference. And the error-state filter in between carries the calibration from one fix to the next, which is why the solution keeps its accuracy through the ten seconds when nobody is checking it.

Board: summary — a Math \[text\] that says "$hat(arrow(x)) = arrow(x)\_upright("ins") - delta hat(arrow(x))$"; head\_close — a Heading that says "The Whole Thing in One Line"

Actions:
- [13:35.085](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=815.0852083333334): closing is shown on the screen, written out.
- [13:45.452](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=825.4522083333334): closing (the "calibration" part) is emphasized.
- [13:52.932](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=832.932125): closing (the "calibration" part) is no longer emphasized.
- [13:53.182](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=833.182125): closing is hidden from the screen — left the board.
- [13:53.182](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=833.182125): head\_close is hidden from the screen — left the board.
- [13:53.182](https://academa.ai/@yong/lectures/how-loosely-coupled-ins-gnss-integration-works?t=833.182125): summary is hidden from the screen — left the board.
