The Engineer and the Trainee: Adaptive MPC Guiding and Shielding Laya

Two of my recent lander experiments kept nagging at me. In One Lander, Three Controllers, an adaptive MPC learned its engine during the flight and landed through a power loss with no training data at all. In Lunar Laya, a small decision model on Apple MLX turned a text description of the flight into structured choices, but the text carried hints from a fixed feedback law that assumed a healthy engine. Cut the engine power and that model crashed every time, faithfully following bad advice. So I asked the obvious question: what happens if the engineer writes the hints for the trainee? The result is Lunar MPC + Laya.

Distilled Laya proposing commands from telemetry while adaptive MPC vetoes unsafe ones, landing through a 60% engine loss

An actual recorded flight. Laya proposes every command from telemetry alone; adaptive MPC vetoes about one in three. The engine loses 60% of its thrust at ten seconds, the estimate drops to 40%, and the lander touches down at seventy.

The engineer and the trainee

The game is the same arcade-style lander from Lunar Laya: three pads on bumpy terrain, a tilt control, an engine with off, half and full, and one decision every fifth of a second. Land upright, slowly, inside a pad, before the fuel runs out. The twist is an unannounced fault: partway through the flight the main engine loses 30% or 60% of its power, and the pilot is never told.

MPC is the engineer. It has the physics written down. Before every move it simulates thousands of command sequences three seconds ahead, picks the cheapest, executes only the first command, and replans. It also compares what it predicted with what actually happened and updates its estimate of engine strength by recursive least squares. Nobody trained it; I wrote its cost function by hand, and I ported it from the Box2D world of the earlier post to the arcade physics here.

Laya is the trainee. It reads a sentence like “Altitude 200 m, vertical velocity −8 m/s, tilt 3 degrees” and answers two multiple-choice questions: which way to tilt, how much engine. It learned from examples. It has no idea what gravity is.

Three ways they work together

1. The engineer whispers to the trainee. Laya's prompt already ended with a requested rotation and power. I swapped the source of that request from the fixed feedback law to MPC's first planned command, and changed nothing else: same weights, same prompt template, byte for byte. With the old requests, Laya landed 17 of 30 flights through a 30% power loss and 0 of 30 through a 60% loss. With MPC's requests, 30 of 30 in both. Same brain, better advice. The interesting detail is that MPC's adaptation now reaches the language model through the words in the prompt. Laya never sees the fault; it sees requests that already account for it.

2. The engineer checks the trainee's work. The original Lunar Laya overrode the model every time it disagreed with guidance. That is safe but leaves the model no room. Here the shield is predictive: MPC forces Laya's proposal as the first command of a second beam search and compares the best achievable cost with its own plan. Only a proposal that is predicted to be worse gets replaced. Laya keeps its independence; physics keeps a veto.

And here is the honest part. With the original checkpoint the shield never fired. Not once in 28,026 decisions. That model was fine-tuned to follow its prompt's request, and it follows it perfectly, so its flights are identical to MPC's own. Worse, when I appended a single sentence to the prompt with the engine estimate, request following collapsed to zero and every flight was lost. The checkpoint is welded to its training template. Useful to know before anyone puts a language model in a control loop.

3. The trainee learns from the engineer, then flies with a safety net. So I trained a second checkpoint. Same base model, same recipe as the first post, three RTX PRO 6000 GPUs, about seven minutes. This time the teacher was adaptive MPC, the rollouts included both fault levels, and the requested labels were removed from the prompt entirely. Laya has to decide from telemetry.

PilotNominalThrust ×0.7Thrust ×0.4Laya's choice kept
Distilled Laya, alone0/300/300/30
Distilled Laya + MPC shield30/3030/3030/30about two thirds

Alone, it cannot land a single flight. Validation accuracy was 80% per question, which sounds fine until you remember that one wrong command moves the ship slightly off the teacher's trajectory, the next state is less familiar, and agreement with MPC falls to 10–18%. That is the textbook behaviour-cloning failure, reproduced on my desk. With the shield on, the same weights land 90 of 90, and roughly two thirds of the commands that actually fly the ship are Laya's own. That is the first configuration where the fused pilot is neither controller alone.

Why bother, if the engineer alone can land?

Because the engineer can only do what its rules say. Its preferences are numbers in a cost function. It cannot be taught from examples, cannot take an instruction in plain language, and cannot tell you how confident it is. The trainee can do all three. What I want is a pilot with the trainee's flexibility and the engineer's guarantee that physics gets the last word. That pilot now exists and lands. It just needs the engineer to step in less often.

Try it in the browser

I ported the physics and the MPC to VanillaJS so you can fly it: click anywhere in the sky to place the lander, pick a pad, add a fault, and launch. A Node check verifies that the JavaScript reproduces every command of six Python-recorded flights. With the local Python server running, the same page flies both Laya checkpoints live on MLX and replays every recorded decision with the model's probabilities, MPC's request, Laya's proposal, and whether the shield fired.

The usual caveats apply. The beam search is incomplete, the cost weights were hand-tuned on ten development seeds, the evaluation is ten held-out seeds per pad, and some starts are unrecoverable for every pilot, including MPC. The shield can only be as good as MPC's own plan.

Next is the obvious one: roll out the shielded pilot, relabel every visited state with MPC, and retrain, so the trainee learns from the neighbourhood of its own mistakes. If that raises the raw landing count above zero and cuts the override rate, the loop is working. Source, docs, measured results and the browser lab are all at github.com/mraad/lunar-mpc-laya. More to come.

Comments

Popular posts from this blog

How to use Esri Flex API on Android and iPhone

Weighted Map Feature Clustering With Attributes

Augmented Reality, iPhone and ArcGIS Server