{"version":1,"lectureId":"01M1HNTW2WGTP67D71P8AJMPH6","attempt":0,"publication":{"slug":"how-loosely-coupled-ins-gnss-integration-works","title":"How Loosely Coupled INS/GNSS Integration Works","subject":"engineering","summary":"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.","metaDescription":"How an error-state Kalman filter fuses an inertial solution with a GNSS fix: mechanization, drift, innovation, and the four-satellite floor.","transcript":"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. 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. 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. 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.","watch":{"version":1,"scenes":[{"title":"Two Instruments, Two Kinds of Error","start":0,"end":216.52920833333332,"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":[{"start":0,"say":"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.","live":[],"does":[[0,"question is shown on the screen, written out."],[17.4495,"question moves to a new place on the board."]]},{"start":18.6495,"say":"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.","live":["question"],"does":[[26.392999999999997,"imu_out is shown on the screen, written out."]]},{"start":37.001000000000005,"say":"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.","live":["question","imu_out"],"does":[[44.466,"mechanization is shown on the screen, written out."],[51.014,"mechanization is shown on the screen, written out."],[53.998000000000005,"mechanization is shown on the screen, written out."]]},{"start":55.584500000000006,"say":"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.","live":null,"does":[[55.584500000000006,"error_axes is shown on the screen, written out."],[70.62,"drift is shown on the screen, written out."]]},{"start":73.17,"say":"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.","live":["question","imu_out","drift","error_axes"],"does":[[75.132,"ins_curve is shown on the screen, drawn."],[80.345,"ins_now is shown on the screen, written out."],[82.795,"ins_now is redrawn as the numbers it depends on change."],[82.795,"clock ticks to 60.0."],[82.795,"metres ticks to 21.6."]]},{"start":88.9445,"say":"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.","live":["question","imu_out","drift","error_axes","ins_curve","ins_now"],"does":[[102.06400000000002,"point is shown on the screen, grown."],[104.07202525252526,"point is hidden from the screen."]]},{"start":104.5755,"say":"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.","live":null,"does":[[108.96400000000003,"drift is hidden from the screen — left the board."],[108.96400000000003,"imu_out is hidden from the screen — left the board."],[108.96400000000003,"mechanization is hidden from the screen — left the board."],[108.96400000000003,"gnss_def is shown on the screen, written out."]]},{"start":121.15100000000001,"say":"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.","live":["question","error_axes","ins_curve","ins_now","gnss_def"],"does":[[122.48600000000002,"gnss_out is shown on the screen, written out."],[132.15800000000002,"gnss_rate is shown on the screen, written out."]]},{"start":136.73950000000002,"say":"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.","live":["question","error_axes","ins_curve","ins_now","gnss_def","gnss_out","gnss_rate"],"does":[[151.21800000000005,"gnss_curve is shown on the screen, drawn."]]},{"start":153.954,"say":"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.","live":["question","error_axes","ins_curve","ins_now","gnss_def","gnss_out","gnss_rate","gnss_curve"],"does":[[159.631,"The segment (0.0, 5.0) to (60.0, 5.0) in error_axes is lit up."],[167.131,"error_axes: retire a lit segment (unemphasize_line)."],[170.5795,"error_axes moves to a new place on the board."],[170.5795,"gnss_def is hidden from the screen — left the board."],[170.5795,"gnss_out is hidden from the screen — left the board."],[170.5795,"gnss_rate is hidden from the screen — left the board."],[170.5795,"question is hidden from the screen — left the board."]]},{"start":171.17950000000002,"say":"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.","live":["error_axes","ins_curve","ins_now","gnss_curve"],"does":[[171.17950000000002,"heading_pair is shown on the screen, written out."],[171.17950000000002,"ins_now is hidden from the screen."],[173.29200000000003,"compare is shown on the screen, written out."],[177.10100000000003,"compare is shown on the screen, written out."],[177.61200000000002,"compare is shown on the screen, written out."],[179.80600000000004,"compare is shown on the screen, written out."]]},{"start":185.6305,"say":"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.","live":["error_axes","ins_curve","gnss_curve","heading_pair"],"does":[[193.293,"compare is shown on the screen, written out."]]},{"start":199.768,"say":"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.","live":null,"does":[[206.78,"fused_curve is shown on the screen, drawn."],[215.4875416666667,"compare is hidden from the screen — left the board."],[215.4875416666667,"error_axes is hidden from the screen — left the board."],[215.4875416666667,"ins_curve is hidden from the screen — error_axes left the board."],[215.4875416666667,"gnss_curve is hidden from the screen — error_axes left the board."],[215.4875416666667,"fused_curve is hidden from the screen — error_axes left the board."],[215.4875416666667,"heading_pair is hidden from the screen — left the board."]]}]},{"title":"The Architecture, and the Error State","start":216.52920833333332,"end":428.8265833333333,"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":[{"start":216.52920833333332,"say":"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.","live":[],"does":[[216.52920833333332,"head_arch is shown on the screen, written out."],[221.40520833333332,"plan is shown on the screen, written out."]]},{"start":229.4127083333333,"say":"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.","live":["plan","head_arch"],"does":[[230.9802083333333,"plan moves to a new place on the board."],[230.9802083333333,"item1 is shown on the screen, written out."],[232.8492083333333,"imu_box is shown on the screen, written out."],[232.8492083333333,"imu_name is shown on the screen, written out."],[233.5342083333333,"imu_link is shown on the screen, written out."],[234.63720833333332,"ins_box is shown on the screen, written out."],[234.63720833333332,"ins_name is shown on the screen, written out."],[237.02920833333332,"out_link is shown on the screen, written out."],[239.4092083333333,"out_box is shown on the screen, written out."],[239.4092083333333,"out_name is shown on the screen, written out."]]},{"start":244.83870833333333,"say":"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.","live":["item1","plan","head_arch","imu_box","imu_name","imu_link","ins_box","ins_name","out_link","out_box","out_name"],"does":[[247.66020833333332,"item2 is shown on the screen, written out."],[249.0992083333333,"gnss_box is shown on the screen, written out."],[249.0992083333333,"gnss_name is shown on the screen, written out."]]},{"start":258.10520833333334,"say":"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.","live":["item1","item2","plan","head_arch","imu_box","imu_name","imu_link","ins_box","ins_name","out_link","out_box","out_name","gnss_box","gnss_name"],"does":[[258.8252083333333,"item3 is shown on the screen, written out."],[261.0892083333333,"ekf_box is shown on the screen, written out."],[261.0892083333333,"ekf_name is shown on the screen, written out."],[262.7262083333333,"ins_down is shown on the screen, written out."],[263.0368262195122,"fix_in is shown on the screen, written out."]]},{"start":271.1622083333333,"say":"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.","live":["item1","item2","item3","plan","head_arch","imu_box","imu_name","imu_link","ins_box","ins_name","out_link","out_box","out_name","gnss_box","gnss_name","ekf_box","ekf_name","ins_down","fix_in"],"does":[[272.92720833333334,"item4 is shown on the screen, written out."]]},{"start":286.1357083333333,"say":"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.","live":["item1","item2","item3","item4","plan","head_arch","imu_box","imu_name","imu_link","ins_box","ins_name","out_link","out_box","out_name","gnss_box","gnss_name","ekf_box","ekf_name","ins_down","fix_in"],"does":[[286.8322083333333,"item5 is shown on the screen, written out."],[291.3022083333333,"correction_up is shown on the screen, written out."]]},{"start":301.6082083333333,"say":"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.","live":["item1","item2","item3","item4","item5","plan","head_arch","imu_box","imu_name","imu_link","ins_box","ins_name","out_link","out_box","out_name","gnss_box","gnss_name","ekf_box","ekf_name","ins_down","fix_in","correction_up"],"does":[[309.0972083333333,"ins_down is indicated — a transient flash."],[309.35769630584184,"fix_in is indicated — a transient flash."],[316.4112083333333,"head_arch is hidden from the screen — left the board."],[316.4112083333333,"item1 is hidden from the screen — left the board."],[316.4112083333333,"item2 is hidden from the screen — left the board."],[316.4112083333333,"item3 is hidden from the screen — left the board."],[316.4112083333333,"item4 is hidden from the screen — left the board."],[316.4112083333333,"item5 is hidden from the screen — left the board."],[316.4112083333333,"plan is hidden from the screen — left the board."],[316.4112083333333,"imu_box is hidden from the screen — plan left the board."],[316.4112083333333,"imu_name is hidden from the screen — plan left the board."],[316.4112083333333,"imu_link is hidden from the screen — plan left the board."],[316.4112083333333,"ins_box is hidden from the screen — plan left the board."],[316.4112083333333,"ins_name is hidden from the screen — plan left the board."],[316.4112083333333,"out_link is hidden from the screen — plan left the board."],[316.4112083333333,"out_box is hidden from the screen — plan left the board."],[316.4112083333333,"out_name is hidden from the screen — plan left the board."],[316.4112083333333,"gnss_box is hidden from the screen — plan left the board."],[316.4112083333333,"gnss_name is hidden from the screen — plan left the board."],[316.4112083333333,"ekf_box is hidden from the screen — plan left the board."],[316.4112083333333,"ekf_name is hidden from the screen — plan left the board."],[316.4112083333333,"ins_down is hidden from the screen — plan left the board."],[316.4112083333333,"fix_in is hidden from the screen — plan left the board."],[316.4112083333333,"correction_up is hidden from the screen — plan left the board."]]},{"start":317.6112083333333,"say":"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.","live":[],"does":[[317.6112083333333,"head_err is shown on the screen, written out."],[321.1172083333333,"map_axes is shown on the screen, written out."],[324.6932083333333,"true_path is shown on the screen, drawn."],[328.2112083333333,"ins_path is shown on the screen, drawn."]]},{"start":333.28070833333334,"say":"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.","live":["map_axes","head_err","true_path","ins_path"],"does":[[333.80320833333326,"The segment (5.5, 2.093) to (6.045, 2.517) in map_axes is lit up."],[342.7662083333333,"map_axes: retire a lit segment (unemphasize_line)."]]},{"start":349.9602083333333,"say":"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.","live":null,"does":[[354.9882083333333,"map_axes moves to a new place on the board."],[354.9882083333333,"state_vec is shown on the screen, written out."],[358.65620833333327,"state_vec (the \"delta arrow(p)\" part) is emphasized."],[362.7552083333333,"state_vec (the \"arrow(b)_a\" part) is emphasized."],[362.7552083333333,"state_vec (the \"delta arrow(p)\" part) is no longer emphasized."]]},{"start":366.4547083333333,"say":"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.","live":["state_vec","map_axes","head_err","true_path","ins_path"],"does":[[366.4547083333333,"state_vec (the \"arrow(b)_a\" part) is no longer emphasized."],[369.35720833333335,"dynamics is shown on the screen, written out."],[381.2107083333333,"map_axes moves to a new place on the board."],[381.2107083333333,"dynamics is hidden from the screen — left the board."],[381.2107083333333,"head_err is hidden from the screen — left the board."],[381.2107083333333,"state_vec is hidden from the screen — left the board."]]},{"start":381.8107083333333,"say":"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.","live":["map_axes","true_path","ins_path"],"does":[[381.8107083333333,"head_meas is shown on the screen, written out."],[385.1192083333333,"fix_a is shown on the screen, written out."],[385.1192083333333,"measurement is shown on the screen, written out."],[385.2745045631358,"fix_b is shown on the screen, written out."],[385.42980079293835,"fix_c is shown on the screen, written out."],[388.5682083333333,"measurement is shown on the screen, written out."],[392.5382083333333,"measurement is shown on the screen, written out."]]},{"start":394.2297083333333,"say":"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.","live":["map_axes","true_path","ins_path","head_meas","fix_a","fix_b","fix_c"],"does":[[395.6922083333333,"ins_here is shown on the screen, written out."],[396.0061544506075,"innovation is shown on the screen, written out."],[402.0662083333333,"measurement is shown on the screen, written out."],[404.6782083333333,"h_def is shown on the screen, written out."],[409.7982083333333,"A box is drawn around h_def."]]},{"start":413.6147083333333,"say":"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.","live":["map_axes","true_path","ins_path","h_def","head_meas","fix_a","fix_b","fix_c","ins_here","innovation"],"does":[[424.5862083333333,"innovation is indicated — a transient flash."],[427.7849166666667,"h_def is hidden from the screen — left the board."],[427.7849166666667,"head_meas is hidden from the screen — left the board."],[427.7849166666667,"map_axes is hidden from the screen — left the board."],[427.7849166666667,"true_path is hidden from the screen — map_axes left the board."],[427.7849166666667,"ins_path is hidden from the screen — map_axes left the board."],[427.7849166666667,"fix_a is hidden from the screen — map_axes left the board."],[427.7849166666667,"fix_b is hidden from the screen — map_axes left the board."],[427.7849166666667,"fix_c is hidden from the screen — map_axes left the board."],[427.7849166666667,"ins_here is hidden from the screen — map_axes left the board."],[427.7849166666667,"innovation is hidden from the screen — map_axes left the board."],[427.7849166666667,"measurement is hidden from the screen — left the board."]]}]},{"title":"The Correction Loop","start":428.8265833333333,"end":655.2562083333333,"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":[{"start":428.8265833333333,"say":"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.","live":[],"does":[[428.8265833333333,"head_predict is shown on the screen, written out."],[432.2745833333333,"err_axes is shown on the screen, written out."]]},{"start":438.7030833333333,"say":"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.","live":["err_axes","head_predict"],"does":[[438.7030833333333,"sawtooth is shown on the screen, written out."],[439.28285317186493,"rider is shown on the screen, written out."],[446.3655833333333,"sawtooth is redrawn as the numbers it depends on change."],[446.3655833333333,"rider is redrawn as the numbers it depends on change."],[446.3655833333333,"progress ticks to 2.6."]]},{"start":454.0940833333333,"say":"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.","live":["err_axes","head_predict","sawtooth","rider"],"does":[[464.0085833333333,"err_axes moves to a new place on the board."],[464.0085833333333,"predict is shown on the screen, written out."],[465.4135833333333,"predict is shown on the screen, written out."],[470.0575833333333,"predict is shown on the screen, written out."],[471.7175833333333,"sawtooth is redrawn as the numbers it depends on change."],[471.7175833333333,"rider is redrawn as the numbers it depends on change."],[471.7175833333333,"progress ticks to 4.9."],[472.2285833333333,"predict_note is shown on the screen, written out."]]},{"start":474.1870833333333,"say":"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.","live":["predict_note","err_axes","head_predict","sawtooth","rider"],"does":[[477.2405833333333,"point is shown on the screen, grown."],[479.94754347460474,"point is hidden from the screen."],[485.1700833333333,"head_predict is hidden from the screen — left the board."],[485.1700833333333,"predict is hidden from the screen — left the board."],[485.1700833333333,"predict_note is hidden from the screen — left the board."]]},{"start":485.77008333333333,"say":"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.","live":["err_axes","sawtooth","rider"],"does":[[485.77008333333333,"head_update is shown on the screen, written out."],[486.3845833333333,"sawtooth is redrawn as the numbers it depends on change."],[486.3845833333333,"rider is redrawn as the numbers it depends on change."],[486.3845833333333,"progress ticks to 5.6."],[488.3235833333333,"point_2 is shown on the screen, grown."],[489.7515833333333,"update is shown on the screen, written out."],[490.7009006747486,"point_2 is hidden from the screen."]]},{"start":500.2200833333333,"say":"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.","live":["err_axes","sawtooth","rider","head_update"],"does":[[503.6915833333333,"update is shown on the screen, written out."],[513.8275833333333,"update is shown on the screen, written out."]]},{"start":520.6150833333334,"say":"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.","live":null,"does":[[521.7065833333332,"update is shown on the screen, written out."]]},{"start":537.7830833333333,"say":"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.","live":null,"does":[[539.0255833333333,"update is shown on the screen, written out."],[544.6675833333333,"sawtooth is redrawn as the numbers it depends on change."],[544.6675833333333,"rider is redrawn as the numbers it depends on change."],[544.6675833333333,"progress ticks to 9.8."]]},{"start":548.0885833333333,"say":"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.","live":null,"does":[[549.3195833333333,"sawtooth is redrawn as the numbers it depends on change."],[549.3195833333333,"rider is redrawn as the numbers it depends on change."],[549.3195833333333,"progress ticks to 30.0."],[566.5250833333333,"err_axes is hidden from the screen — left the board."],[566.5250833333333,"sawtooth is hidden from the screen — err_axes left the board."],[566.5250833333333,"rider is hidden from the screen — err_axes left the board."],[566.5250833333333,"head_update is hidden from the screen — left the board."],[566.5250833333333,"update is hidden from the screen — left the board."]]},{"start":567.7250833333333,"say":"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.","live":[],"does":[[567.7250833333333,"head_apply is shown on the screen, written out."],[570.4995833333332,"bias_axes is shown on the screen, written out."],[571.4515833333332,"bias_curve is shown on the screen, drawn."],[576.6185833333333,"truth_line is shown on the screen, written out."]]},{"start":578.9710833333334,"say":"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.","live":["bias_axes","head_apply","bias_curve","truth_line"],"does":[[582.5935833333333,"point_3 is shown on the screen, grown."],[583.7294305879091,"point_3 is hidden from the screen."],[594.6445833333333,"point_4 is shown on the screen, grown."],[595.8402962360713,"point_4 is hidden from the screen."]]},{"start":598.2630833333333,"say":"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.","live":null,"does":[[602.2565833333333,"bias_axes moves to a new place on the board."],[602.2565833333333,"loop is shown on the screen, written out."],[604.1025833333333,"loop (the \"Feedback\" part) is emphasized."],[610.8945833333333,"f_state is shown on the screen, written out."],[613.3215833333334,"f_bias is shown on the screen, written out."],[617.0715833333334,"f_reset is shown on the screen, written out."]]},{"start":619.0640833333333,"say":"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.","live":["loop","f_state","f_bias","f_reset","bias_axes","head_apply","bias_curve","truth_line"],"does":[[619.7375833333333,"loop (the \"Feedback\" part) is no longer emphasized."],[619.7375833333333,"loop (the \"Feedforward\" part) is emphasized."],[636.2245833333334,"loop (the \"Feedforward\" part) is no longer emphasized."]]},{"start":638.6585833333334,"say":"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.","live":null,"does":[[652.6945833333333,"f_state is indicated — a transient flash."],[654.2145416666667,"bias_axes is hidden from the screen — left the board."],[654.2145416666667,"bias_curve is hidden from the screen — bias_axes left the board."],[654.2145416666667,"truth_line is hidden from the screen — bias_axes left the board."],[654.2145416666667,"f_bias is hidden from the screen — left the board."],[654.2145416666667,"f_reset is hidden from the screen — left the board."],[654.2145416666667,"f_state is hidden from the screen — left the board."],[654.2145416666667,"head_apply is hidden from the screen — left the board."],[654.2145416666667,"loop is hidden from the screen — left the board."]]}]},{"title":"Strengths, and the Four-Satellite Floor","start":655.2562083333333,"end":834.2237916666667,"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":[{"start":655.2562083333333,"say":"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.","live":[],"does":[[655.2562083333333,"head_gap is shown on the screen, written out."],[655.2562083333333,"sky_label is shown on the screen, written out."],[655.2562083333333,"error_label is shown on the screen, written out."],[655.8712083333334,"sat_axes is shown on the screen, written out."],[655.8712083333334,"sat_curve is shown on the screen, written out."],[656.5525988194807,"sat_rider is shown on the screen, written out."],[667.6212083333334,"err_axes is shown on the screen, written out."],[667.6212083333334,"err_curve is shown on the screen, written out."],[668.0159958772061,"err_rider is shown on the screen, written out."]]},{"start":672.1687083333334,"say":"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.","live":["sky_label","sat_axes","error_label","err_axes","head_gap","sat_curve","sat_rider","err_curve","err_rider"],"does":[[674.4902083333334,"sat_curve is redrawn as the numbers it depends on change."],[674.4902083333334,"sat_rider is redrawn as the numbers it depends on change."],[674.4902083333334,"err_curve is redrawn as the numbers it depends on change."],[674.4902083333334,"err_rider is redrawn as the numbers it depends on change."],[674.4902083333334,"progress ticks to 11.6."]]},{"start":683.3452083333334,"say":"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.","live":null,"does":[[688.4542083333333,"sat_curve is redrawn as the numbers it depends on change."],[688.4542083333333,"sat_rider is redrawn as the numbers it depends on change."],[688.4542083333333,"err_curve is redrawn as the numbers it depends on change."],[688.4542083333333,"err_rider is redrawn as the numbers it depends on change."],[688.4542083333333,"progress ticks to 14.5."],[690.1022083333334,"threshold is shown on the screen, written out."]]},{"start":698.4347083333333,"say":"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.","live":["sky_label","sat_axes","error_label","err_axes","head_gap","sat_curve","sat_rider","err_curve","err_rider","threshold"],"does":[[713.1092083333333,"sat_curve is redrawn as the numbers it depends on change."],[713.1092083333333,"sat_rider is redrawn as the numbers it depends on change."],[713.1092083333333,"err_curve is redrawn as the numbers it depends on change."],[713.1092083333333,"err_rider is redrawn as the numbers it depends on change."],[713.1092083333333,"progress ticks to 22.0."]]},{"start":718.2367083333334,"say":"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.","live":null,"does":[[721.0112083333333,"point is shown on the screen, grown."],[722.9120062898264,"point is hidden from the screen."],[723.2872083333334,"sat_curve is redrawn as the numbers it depends on change."],[723.2872083333334,"sat_rider is redrawn as the numbers it depends on change."],[723.2872083333334,"err_curve is redrawn as the numbers it depends on change."],[723.2872083333334,"err_rider is redrawn as the numbers it depends on change."],[723.2872083333334,"progress ticks to 30.0."],[736.8132083333334,"err_axes is hidden from the screen — left the board."],[736.8132083333334,"err_curve is hidden from the screen — err_axes left the board."],[736.8132083333334,"err_rider is hidden from the screen — err_axes left the board."],[736.8132083333334,"error_label is hidden from the screen — left the board."],[736.8132083333334,"head_gap is hidden from the screen — left the board."],[736.8132083333334,"sat_axes is hidden from the screen — left the board."],[736.8132083333334,"sat_curve is hidden from the screen — sat_axes left the board."],[736.8132083333334,"sat_rider is hidden from the screen — sat_axes left the board."],[736.8132083333334,"threshold is hidden from the screen — sat_axes left the board."],[736.8132083333334,"sky_label is hidden from the screen — left the board."]]},{"start":738.0132083333333,"say":"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.","live":[],"does":[[738.0132083333333,"head_trade is shown on the screen, written out."],[738.0132083333333,"gain_label is shown on the screen, written out."],[742.0302083333333,"strengths is shown on the screen, written out."],[745.2582083333334,"strengths (the \"buy, qualify and replace\" part) is emphasized."],[751.4232083333334,"strengths (the \"buy, qualify and replace\" part) is no longer emphasized."],[751.4232083333334,"strengths (the \"six states of identity\" part) is emphasized."],[757.4252083333333,"strengths (the \"check each other\" part) is emphasized."],[757.4252083333333,"strengths (the \"six states of identity\" part) is no longer emphasized."]]},{"start":759.1397083333334,"say":"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.","live":["gain_label","strengths","head_trade"],"does":[[759.1397083333334,"give_label is shown on the screen, written out."],[759.1397083333334,"strengths (the \"check each other\" part) is no longer emphasized."],[759.7892083333334,"limits is shown on the screen, written out."],[764.8052083333333,"limits (the \"correlated\" part) is emphasized."],[771.3882083333334,"limits (the \"Latency\" part) is emphasized."],[771.3882083333334,"limits (the \"correlated\" part) is no longer emphasized."],[774.7322083333333,"limits (the \"Below four satellites\" part) is emphasized."],[774.7322083333333,"limits (the \"Latency\" part) is no longer emphasized."]]},{"start":778.3852083333334,"say":"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.","live":["gain_label","strengths","give_label","limits","head_trade"],"does":[[796.0672083333334,"limits (the \"Below four satellites\" part) is no longer emphasized."],[796.0672083333334,"limits (the \"tightly coupled\" part) is emphasized."],[798.0762083333334,"gain_label is hidden from the screen — left the board."],[798.0762083333334,"give_label is hidden from the screen — left the board."],[798.0762083333334,"head_trade is hidden from the screen — left the board."],[798.0762083333334,"limits is hidden from the screen — left the board."],[798.0762083333334,"strengths is hidden from the screen — left the board."],[798.0762083333334,"limits (the \"tightly coupled\" part) is no longer emphasized."]]},{"start":799.2762083333333,"say":"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.","live":[],"does":[[799.2762083333333,"head_close is shown on the screen, written out."],[805.1162083333334,"summary is shown on the screen, written out."],[810.1892083333333,"A box is drawn around summary."]]},{"start":814.5162083333333,"say":"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.","live":["summary","head_close"],"does":[[815.0852083333334,"closing is shown on the screen, written out."],[825.4522083333334,"closing (the \"calibration\" part) is emphasized."],[832.932125,"closing (the \"calibration\" part) is no longer emphasized."],[833.182125,"closing is hidden from the screen — left the board."],[833.182125,"head_close is hidden from the screen — left the board."],[833.182125,"summary is hidden from the screen — left the board."]]}]}]},"durationSeconds":834,"chapters":[{"title":"Two Instruments, Two Kinds of Error","startSeconds":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. 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."},{"title":"The Architecture, and the Error State","startSeconds":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. 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."},{"title":"The Correction Loop","startSeconds":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. 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."},{"title":"Strengths, and the Four-Satellite Floor","startSeconds":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. 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."}]}}
