Programování a elektronika - úvahy

TrueFuse 2F: Measuring the Port Instead of Trusting It

NNeil Bowen17 min čtení

The third part of the altitude fusion filter behind AltimeterCloud and our altimeters. A port coefficient measured rather than assumed, a slew witness taught to look both ways, an ejection charge that reads the wrong way up, and the same law ported into two firmwares that could not be built more differently.

In September we published the story of TrueFuse 2E: two hundred and one flights run through every candidate change, a slew witness for the notches the hold detector could not see, and a port to the Nano that had to be identical rather than similar. That article ends by admitting what was still owed: one real flight through the bridge. This one starts there, and it is about a different kind of idea from the two before it.

2C and 2E both treat the port error the same way. They know the barometer over-reads while the rocket is fast, so they schedule around it: hand the estimate to the accelerometer while the air is moving past the port, hand it back when the rocket slows and the pressure can be believed again. That works, and it is most of why the filter exists. But it never asks how big the error actually was. 2F is the first revision that measures it.

A port that reads below the pad

Flight 2886 is a Nano on a 400 Hz log, and it does something a pressure sensor should not be able to do. A second and a quarter after launch, with the rocket eighty-five metres up and climbing hard, the barometer reads thirty metres below the pad. Then it unwinds, races back up, overshoots and settles. The raw peak is 277.84 m. 2E, carrying the climb on the accelerometer and handing back to a barometer that is still recovering, calls the apogee 279.72 m: two metres above anything the sensor ever recorded.

Nothing in 2E is wrong on that flight. The hand-over happens where it should, the trend sensor does its job, and the answer is out by less than one percent. But the error has a shape, and the shape is the same on every flight that shows it: the pressure lags on the way up in proportion to how fast the rocket is going, and everything downstream inherits that lag.

Flight 2886. The port unwinds thirty metres below the pad while the rocket is climbing. 2E carries the climb and hands back to a recovering barometer. 2F measures what the port was doing and corrects the pressure it hands back to.

Measuring the port instead of trusting it

A port error is not noise and it is not a bias. It is a pressure effect that scales with dynamic pressure, so it scales with the square of airspeed. That is a testable statement, and it means the error has a coefficient with units: metres of altitude error per metre per second squared.

2F measures that coefficient on every flight. Starting a hundred milliseconds after burnout and running for four hundred more, the filter takes its own inertial altitude, subtracts the raw pressure altitude, and divides by the square of its own velocity. It needs at least ten samples in the window and a velocity above thirty metres per second, and it will not measure while the trend sensor owns the output. The answer is a trimmed mean, with the highest and lowest tenth thrown away, so one corrupt sample landing in the window cannot set the coefficient for a whole flight. On 2886 it comes out at 0.0178 metres per (metre per second) squared, which is a hundred and seventy-eight metres of error at a hundred metres per second. That is not a tuning constant we picked. It is a measurement of that airframe, that port and that flight.

Where that window sits took longer to settle than anything else in 2F, and it is worth showing why, because both ends of it are pinned by real flights. It cannot start at rest, because the error scales with v squared and before the rocket moves there is nothing there to measure: the lead is zero and so is the divisor. It cannot sit on burnout either, because burnout is where the motor comes off pressure and washes the port, and a coefficient measured there reads high. And it cannot move out into the coast, which is the answer we tried first and threw away. On 2886 the coefficient settles to a clean plateau about seven hundred milliseconds after burnout and a window there looked obviously right. On other flights the same window reads several times what the earlier one does. A plateau that is stable on one flight is a trap on another, and the reason why turned out to be worth a section of its own.

Is it even a port error?

That last point is worth more than the window it settled, because it exposed something the filter had not been asking. The coefficient is a ratio, and a ratio can always be computed. Whether the thing you are dividing is the error you think it is, is a separate question.

The physics gives a clean test. A port error is caused by air moving past a hole, so it must vanish when the rocket stops. Plot the fuse's lead over the barometer against the square of the speed, and a real port error is a line heading for the origin, with a slope that is the coefficient. Anything that does not run to the origin is something else wearing the same clothes.

The lead against v squared. 2886 falls away with the speed and heads for the origin, which is what a port error has to do, and the slope is its coefficient. 2858's lead sits at about twenty-three metres while the rocket slows from eighty-five metres per second to twenty-five, so whatever it is, it is not caused by airspeed.

Most flights fail that test, and 2858 is a typical one. Its lead sits at about twenty-three metres while the rocket slows from eighty-five metres per second to twenty-five, and a lead that does not care how fast the rocket is going cannot have been caused by how fast the rocket is going. The window measures a small positive coefficient on it, which is arithmetically correct and physically meaningless, and the number grows as the flight goes on, because a fixed offset divided by a collapsing v squared always does. That is the same fact as the coast plateau reading several times too high, seen from the other side, and we only joined the two together while drawing the chart above.

The filter does not currently run that test. It measures the coefficient inside a window and then relies on the five conditions below to keep it out of trouble, and on the flights we have that is enough. Asking the lead to prove it scales with v squared before the coefficient is believed at all is the obvious next mechanism, and it is on the list rather than in the code.

When it does not fire

Having a coefficient is the easy half. Using it is where the work goes, because a number measured during one part of the flight only means anything while the same physics applies. The correction is added to the pressure at the hand-over, and only when five things are true at once: the rocket is climbing, the top has not been reached, no bridge is open, the raw is below the fuse's own line, and the trend sensor has been quietly in track for a full second since the last time it held. It is also capped so that it can only ever move the correction and never the pressure itself.

On most flights it never fires. Some measure a coefficient at or below zero, which means the barometer was not lagging in the way the mechanism exists to fix: on 2836 it sits around minus 0.02 for the whole climb, and nothing is measured and nothing is applied. Others measure something that is not a port error at all, as above, and the conditions keep it out of the trace. 2F is then identical to 2E, sample for sample. A mechanism that knows when to leave well alone is worth as much as one that knows when to act, and it is a good deal easier to show.

A witness that looks both ways

2E's slew witness is the purest piece of physics in the filter: over any forty milliseconds, the barometer may not honestly fall further than the vehicle could have moved, plus the sensor's own measured noise. When it falls further than that, the fall did not happen, and a bridge opens on the trend the barometer was following.

The obvious thing, once you have written it down, is that the same argument runs upward. A barometer may not honestly rise faster than the vehicle can climb either.

An ejection charge produces both. On flight 2895 the charge pressurises the airframe, the port sees the pressure rise, and the altitude dives sixty-five metres in thirty milliseconds: the signature everyone knows, and worth 7.8 hPa at the sensor. On flight 2888 the same event goes the other way. The pressure at the port falls by about a third of a millibar, and the trace climbs two and a half metres over seventy-three milliseconds before decaying back. Two and a half metres is nothing on the climb and everything at the top, where the vehicle is at its slowest, and 2E takes the hat as the apogee.

What we believe is happening, and we should be honest that this is a reading of one flight rather than something we have proven: the altimeter on 2888 was in its own bay, sealed from the ejection charge, so it never saw the overpressure at all. What it saw was the joint letting go. Gas leaving the tube with the charge in it rushes past the outside of the ebay, and flow across a static port lowers the pressure there. The sensor reads that as height.

Three things in the log support it, and none of them proves it. The board temperature moves three hundredths of a degree across the whole event, so the sensor being heated by the gas is not the explanation. The barometer is demonstrably capable of rendering a violent event, since on 2895 it turns in seventeen metres inside a single two and a half millisecond sample, so 2888's seventy-three millisecond rise is a real seventy-three millisecond flow rather than a spike smoothed by the sensor's own filter. And the size fits weak coupling: a third of a millibar is what about seven metres per second of flow across the hole would do, which is a small share of what is coming out of that joint, and a small share is what a separate bay with its ports away from the break should feel.

What would settle it is the fleet rather than the physics. If every hat comes from an airframe whose altimeter bay is sealed from the ejection volume, and every dive from one where it is not, the mechanism is confirmed by construction. That is a column we have not added to the battery yet.

Two and a half metres in seventy-three milliseconds is an apparent climb of thirty-four metres per second, at a moment when the rocket is doing almost nothing. That is why this needs a physics test rather than an outlier test: it is smooth, it lasts thirty samples, and no despike would ever call it a glitch. It is only impossible if you know how fast the vehicle could have been going.

The useful part is that the filter does not need to know which way it will go. A rise the vehicle could not have made is as impossible as a fall it could not have made, and it is refused by the same argument. On a rise, the bridge that opens is built differently: it anchors on a straight line fitted through the three hundred milliseconds of raw ending just before the rise, and then it coasts on gravity alone rather than on the accelerometer, because an accelerometer inside an airframe that has just fired a charge is not a witness worth having. It releases when the raw comes back within two metres of the arc and stays there.

The same event with both signs. 2895 dives sixty-five metres when the charge pressurises the airframe. 2888 rises two and a half metres when the pressure at the port falls instead, and that hat becomes 2E's apogee. 2F carries a gravity arc across it.

The hold that has to be refused

One more mechanism came straight out of 2886, and it is the smallest and the least obvious of them. When the port unwinds far enough to read below the pad, the trend sensor sees the recovery as an artifact and tries to hold across it. It is doing exactly what it was built to do, and it is wrong, because the thing it is holding across is the barometer coming back to the truth rather than leaving it.

So 2F carries one flag. If the raw has been more than ten metres below the pad at any point after launch, the trend sensor may not open a hold for the first three seconds of the flight. After that the flag stops mattering, because a port that is going to unwind has done it by then. It is a narrow rule and it earns its place on exactly the flights that need it.

The 2E machine with the parts added in 2F marked. Everything not marked is 2E with its rules unchanged.

What was tried and left out

The 2E article made the point that withdrawing a change is a normal outcome. 2F kept the habit.

A cap on the downward bridge, seeding its ceiling from the velocity at the moment it opened, was tried and taken out: on flight 2836 it read the notch itself into the slope it was fitting, which is the same failure the 2E article describes for a bridge that seeds its velocity from the era's own witness. Two guards on the pad, one capping how long a hold could last there and one abandoning the fusion entirely when the IMU had nothing usable to say, both fired on real flights whose pads were simply moving, and both came out. And the coast window for the coefficient, described above, which was measured on one flight, looked right, and was withdrawn when a second flight was run through it. The code carries the flight number that killed each of them, as it does for the ideas 2E buried.

Getting it onto both devices

The porting rule has not moved: the device runs the same law, not a resemblance of it. This time there were two ports to do, into two firmwares that are not built the same way, and the difference between them turned out to be the interesting part of the whole revision.

The Nano runs its fusion at save, with the whole flight in an array. That port is the 2E body with the 2F additions transcribed statement for statement. The Mercury runs its fusion live, one sample at a time inside the flight loop, and that is where each addition had to be taken one at a time and asked whether it is even possible.

Four of them are causal as written and went straight across: the coefficient, the correction, the refused hold and the upward bridge all read only the past and act forward. One is inert, because a rule the live filter already has produces the same schedule by another route. And one cannot exist live at all. 2F can unwind a false trigger, going back over the samples it printed between a launch it no longer believes and the moment it changed its mind, and rewriting them to pressure. On the website and on the Nano those samples are still in an array and can be rewritten. On a Mercury they have already gone to flash. A filter that cannot revise its own past simply cannot have that mechanism, and pretending otherwise would have been the kind of resemblance the porting rule exists to prevent.

Both ports were then run against the reference on the same logs, sample by sample. The Mercury's live fusion differs from the website's by 1.4 mm at its worst sample out of 11,889 on 2886, a mean of three hundredths of a millimetre, with the coefficient agreeing to four decimal places and the apogee identical. The Nano's sits on its own saved column to two millimetres.

Flight 2886 through all three. The lower panel is the Mercury's live fusion against the website's, before the post pass.

Which instant counts as zero

Here is the one worth writing down, because it is the sort a test catches and a read-through never does.

The refused hold asks two questions about time: has the raw been below the pad since launch, and are we still inside the first three seconds of the flight. In the save-time filter that is trivial, because its clock starts at launch. In the live filter the clock starts when the filter does, which is whenever the device powered up, and on the log we tested with that was eight seconds before the rocket left the rail. Both tests were therefore asked against the wrong origin: the flag could be raised while the board sat on the pad, and the refusal could never fire once the flight had actually started.

The result was an apogee of 300.62 m on a flight that went to 274. It was found by running 2886 through the live path and laying it against the same log through the save-time path, and it was two lines to fix. Ports between two forms of the same law fail at the seams rather than in the maths, and the seams are always something as dull as which instant counts as zero.

The flight the last article was waiting for

The 2E piece closed by admitting that the bridge and the holds had never run on a device with a real ejection charge behind them. They had run, in code identical to four decimal places, on the two hundred flights that had one, but not live on hardware.

They have now. A small flight on a B motor, in too much wind to fly anything bigger, saved by a Nano running 1.64 with 2F active: burnout stamped at 939 ms, apogee 67.80 m, the charge at 5.05 seconds, and the trend sensor bridging sixty-three metres of ejection dive in the middle of it. Rerun on the desktop through the same firmware headers, the device's saved column comes back to sixteen millimetres. That is the answer the last article owed, and it is also the flight in the figure above that dives rather than rises.

What is next

The same order as always: better evidence first, cleverer maths second. The v squared test for the coefficient, described above, so that a lead has to prove what it is before it is corrected for. Sample times to a tenth of a millisecond on both sides, still. A quicker barometer, still, after a flight campaign rather than before one. On the Nano, the save itself: a maximum length log at 400 Hz spends most of its filtering time on samples recorded after the rocket had already landed, and bounding the passes at touchdown is worth more than any amount of arithmetic tuning.

And the honest gap in this article: 2F has been checked flight by flight against the reference and it has flown, but it has not been through the full battery the way 2E was. Until it has, the raw column in every log is untouched by any of this, as it has been since the beginning, so the evidence to judge the answer ships inside every flight.

TrueFuse 2F revision 3 and TruePath revision 6 are what the website runs, and what Nano firmware 1.64 and Mercury firmware 2.50 carry. On a flight logged by firmware older than that, the site offers TrueFuse 2F and 2F with TruePath as chart overlays, because the altitude column in those logs predates the filter. On newer firmware the column already is this curve, so no overlay is drawn.