Robustness, Calibration, and Safe Control › Fallback Policies and Runtime Assurance
World Models HandbookAll chapters Robustness, Calibration, and Safe Control › Fallback Policies and Runtime AssuranceOne section · Sections in this chapter5 / 8 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
The architecture we now describe has a history in safety-critical control under various names; a standard formulation is the Simplex pattern. Split the controller into two parts:
- A performance controller, which may be arbitrarily complex, learned, and unverified. It is the thing that does the task well.
- A safety controller (the fallback), which is simple enough to be analyzed, tested exhaustively, or verified. It is the thing that keeps the system inside the safe set.
A monitor decides which controller is in charge. A formal safety result needs more than a simple controller and a threshold: the initial condition must admit a safe continuation, the decision module must be correct, and switching must preserve that continuation under the declared disturbances and timing. A permanently safe command sequence and correct decision module are explicit assumptions in the Black-Box Simplex formulation. This relocates the verification burden rather than removing it. A finite simulation of our proportional-derivative fallback is evidence about tested episodes, not certification.
The sections that follow name the important parameters: the declared parameter bounds , the innovation threshold , the fallback tail length, and the CVaR level together with the number of draws and candidates.
Given a fallback controller , we want to know which initial states are guaranteed to stay safe under that controller. The recoverable set answers this question: it is the set of states from which can keep the system inside the safe set forever:
where:
- : the initial state
- : position and velocity under the fallback rollout
- : the safe position set (in our example, )
- : the fallback (safety) controller
For a specified plant, disturbance model, and fallback, the monitor should preserve membership in . Under uncertainty the definition must quantify over all allowed disturbances and parameter trajectories as well. Outside this particular fallback's recoverable set, its guarantee is unavailable; another controller may still succeed. Checking a finite horizon or a finite grid does not establish the infinite-time property in the definition. The set is useful precisely because it states which continuation and assumptions must be proved.
For our bounded position envelope and nondegenerate Gaussian velocity innovation, an all-draw robust recoverable set is empty: from any finite state and applied command, an innovation large enough to leave the envelope in the next step has positive probability. A nonempty deterministic invariant argument would require a different, explicitly bounded disturbance model. A probabilistic safety criterion is another option, but is not the all-disturbance definition above.
A monitor that does not use the learned model
The monitor should not assume that accurate training predictions imply a valid safety model under shift. Learned models can participate in a certificate when their error is bounded under defensible assumptions; otherwise a model-only safety check can share the planner's blind spots. Our small damping shift changed empirical coverage modestly, not catastrophically, but that result still does not establish future safety. The toy screen below uses a separate declared scenario to illustrate this separation of responsibilities.
We can posit a separate parameter scenario to illustrate the architecture. Its settings are not independently verified bounds on a physical plant, so calling the scenario conservative does not establish containment. In our example, we use
where:
- : stiffness, the restoring force per unit displacement
- : viscous damping, the drag proportional to velocity
- : actuator gain, how much acceleration one unit of command produces
- : dry friction, a constant drag opposing motion
These lower limits alone do not define a finite parameter box or prove a worst-case trajectory. Our code fixes stiffness and friction and selects damping/gain endpoints greedily along one trajectory. Its choices are illustrative engineering settings, not verified physical bounds. Greedy outward acceleration need not maximize the eventual peak because it changes subsequent velocity and position. The resulting value is a scenario peak, not an enclosure of all reachable states.
For a bounded uncertainty set , a disturbance set , and known initial state , a formal endpoint reachable set would be
where:
- : the worst-case forward reachable set of positions after steps from state
- : the position at the end of the horizon
- : position and velocity at step of the rollout
- : stiffness, damping, gain, and friction parameter tuple
- : the box of declared parameter bounds
- : the fallback action at step
Here is the discrete plant transition with parameter tuple and disturbance ; states the permitted disturbances. Safety over the horizon needs every intermediate reachable set, not only , to lie inside the safe envelope. State-estimation error requires an initial set rather than a single . Infinite-time assurance additionally needs a terminal invariant continuation, and a physical plant requires inter-sample and latency analysis. Gaussian process noise in our simulation is unbounded, so no finite deterministic disturbance envelope covers every draw. A bounded-noise proof would describe a different explicit disturbance model, or a probabilistic result with a stated failure level. None is proved by the scenario screen below.
A second monitor: prediction consistency
A complementary signal comes from innovation monitoring: compare predicted and observed next states after an action, normalized by predictive standard deviation. This is a reactive diagnostic, not a reachable-set certificate. The toy combines it with a finite scenario screen; a certified architecture would replace that screen with a justified enclosure and safe continuation test.
where:
- : the state dimension (here , for position and velocity)
- : the -th component of the observed next state
- : the -th component of the model's predicted mean next state
- : the model's predicted variance for the -th component
- : the root-mean-square standardized innovation; under correct componentwise zero means and variances, , not generally
The threshold trades sensitivity against false alarms. Changed dynamics may increase the statistic, but benign noise can also trigger it and small changes may remain undetected. This root statistic is not a chi-square innovation test: the position and velocity innovations are correlated by construction, and we do not whiten their full covariance. The code uses a single-transition threshold and a lower reset threshold, not a smoothed window, formal sequential detector, or calibrated false-alarm probability. The earlier filtering material provides context for residual diagnostics, not a guarantee for this heuristic.
Two details matter. The statistic needs an observed transition, so it cannot prevent harm during that first transition. Its scale also depends on the predictive variance, so overestimated variance can hide errors and underestimated variance can create false alarms. There is no universal one- or two-step detection bound here. Logging innovations, threshold crossings, and selected actions is necessary to distinguish detection from scenario-triggered handover.
The two monitors are complementary:
- The consistency monitor is inexpensive and reactive. It needs at least one observed transition and may miss a shift indefinitely.
- A certified reachability monitor can reject a proposal before execution, provided its enclosure and timing assumptions hold. Our finite scenario screen has this prospective timing but not that certification.
A design may combine these signals, but combining heuristics does not produce a proof. A sound safety condition must remain enforced even when residuals look benign; an innovation test should not override it merely to improve performance. The two signals address different evidence, and their switching logic needs explicit analysis. In the experiment the shield checks the candidate sequence followed by a fallback tail in one deterministic scenario and also responds to innovation threshold crossings.
# Illustrative parameters for one adverse deterministic schedule, not an
# exhaustive reachable-set calculation or a validated physical envelope.
K_MIN, C_MIN, GAIN_MIN, GAIN_MAX, FRIC_MIN = 0.80, 0.00, 0.90, 1.10, 0.0
C_MAX = 1.10
Z_THRESHOLD = 2.5
FALLBACK_TAIL = 30
def fallback_action(state, kp=3.5, kd=3.0, u_max=U_FALLBACK):
"""Proportional-derivative regulator. No learned component, full authority."""
p, v = float(state[0]), float(state[1])
return float(np.clip(-kp * p - kd * v, -u_max, u_max))
def scenario_peak(state, action_fn, steps):
"""Peak along one adverse deterministic parameter schedule, not a bound."""
p, v = float(state[0]), float(state[1])
peak = abs(p)
for t in range(steps):
u = float(action_fn(t, (p, v)))
c = C_MIN if p * v > 0.0 else C_MAX # least damping when escaping
gain = GAIN_MAX if np.sign(p) * u > 0.0 else GAIN_MIN # weakest brake
acc = -K_MIN * p - c * v - FRIC_MIN * np.sign(v) + gain * u
v = v + DT * acc
p = p + DT * v
peak = max(peak, abs(p))
return peak
def monitor_ok(state, planned_actions, horizon):
"""Finite-horizon scenario screen; omits process noise and is not certified."""
def policy(t, s):
return planned_actions[t] if t < horizon else fallback_action(s)
return scenario_peak(state, policy, horizon + FALLBACK_TAIL) <= P_LIMITThe declared scenario includes zero damping, but it omits process noise and searches neither all parameter paths nor all disturbance paths. It can trigger unnecessary fallback or accept an unsafe plan. The finite tail is thirty steps, not an invariant-set proof. The shield remains useful as an executable architecture example precisely when these limitations are visible; calling it conservative is not evidence that its peak upper-bounds the actual plant.
Running the shield
We run expected-cost MPC, CVaR MPC, and shielded MPC in nominal and zero-damping environments. Episodes start near the envelope with outward velocity, creating a useful braking stress test. Braking is not necessary in every nominal episode: restoring force and damping can already keep some noise-free trajectories inside. Comparing these controllers measures their combined behavior; it does not isolate manual braking from luck or prove which component caused an improvement.
def run_controller(mode, params, s0, n_steps, env_rng, plan_rng, horizon=8):
p, v = float(s0[0]), float(s0[1])
prev_state, prev_action = np.array([p, v]), 0.0
distrust = False
violations, shield_steps, cost = 0, 0, 0.0
trace = np.empty((n_steps + 1, 2))
shield_flag = np.zeros(n_steps + 1, dtype=bool)
trace[0] = (p, v)
for t in range(n_steps):
state = np.array([p, v])
if mode == "shield" and t > 0:
mu_i, var_i, _ = predict(
members, np.array([[prev_state[0], prev_state[1], prev_action]])
)
z = float(
np.sqrt(np.mean((state - prev_state - mu_i[0]) ** 2 / var_i[0]))
)
if z > Z_THRESHOLD:
distrust = True
elif (
z < 1.0
and scenario_peak(
state, lambda tt, s: fallback_action(s), FALLBACK_TAIL
)
<= P_LIMIT
):
distrust = False
planned = plan(
state,
plan_rng,
mode=("cvar" if mode == "cvar" else "mean"),
horizon=horizon,
return_sequence=True,
)
use_fallback = mode == "shield" and (
distrust or not monitor_ok(state, planned, horizon)
)
if use_fallback:
u = fallback_action(state)
shield_steps += 1
else:
u = float(planned[0])
prev_state, prev_action = state, u
p, v = simulate(params, (p, v), [u], env_rng, SIGMA_P)[1]
over = max(0.0, abs(p) - SOFT_LIMIT)
cost += (
W_P * p * p + W_V * v * v + W_U * u * u + BARRIER_WEIGHT * over**2
)
if abs(p) > P_LIMIT:
violations += 1
trace[t + 1] = (p, v)
shield_flag[t] = use_fallback
return dict(
cost=cost,
violations=violations,
shield_steps=shield_steps,
trace=trace,
shield=shield_flag,
)
NOMINAL_ENV = (1.00, 0.90, 1.00, 0.0)
SHIFTED_ENV = (1.00, 0.00, 1.00, 0.0)
RT_STEPS = 45
RT_MODES = ["mean", "cvar", "shield"]
rt_rng = np.random.default_rng(77)
EPISODES_RT = []
for _ in range(6):
p0 = rt_rng.uniform(0.25, 0.32) * rt_rng.choice([-1.0, 1.0])
v0 = np.sign(p0) * rt_rng.uniform(0.78, 0.88)
EPISODES_RT.append((p0, v0))
rt_rows, rt_traces = [], {}
for env_name, params in (
("nominal", NOMINAL_ENV),
("damping shift", SHIFTED_ENV),
):
for mode in RT_MODES:
plan_rng = np.random.default_rng(1000)
for i, (p0, v0) in enumerate(EPISODES_RT):
env_rng = np.random.default_rng(500 + i)
res = run_controller(
mode, params, (p0, v0), RT_STEPS, env_rng, plan_rng
)
rt_rows.append(
dict(
env=env_name,
mode=mode,
cost=res["cost"],
viol=res["violations"],
peak=float(np.abs(res["trace"][:, 0]).max()),
shield=res["shield_steps"],
)
)
if i == 0:
rt_traces[(env_name, mode)] = resenvironment controller violations peak |p| mean cost shield steps nominal mean 7 0.650 4.38 0.0 nominal cvar 7 0.667 4.53 0.0 nominal shield 0 0.541 2.99 2.0 damping shift mean 103 0.947 18.65 0.0 damping shift cvar 115 0.972 20.42 0.0 damping shift shield 2 0.604 5.52 6.3
The printed rows pair each environment with each controller and report the total violations, the worst peak position, the mean episode cost, and the mean number of shield steps.
Three columns carry the message. The violations column counts the number of simulated steps in which exceeded the limit. The peak column is how far the worst episode got. The shield steps column counts how often the fallback was in charge. Together they describe the answer to the central question of the chapter: what did the system lose by trusting the learned model, and what did it pay to stop trusting it?
The executed nominal rows have 7, 7, and 0 violating steps for expected-cost, CVaR, and shielded MPC; shifted rows have 103, 115, and 2. The shifted shield's maximum position magnitude is 0.604, above the 0.600 limit. It reduces violations here but does not eliminate them. The shield also has stronger actuator authority than the learned planners, so the reduction cannot be attributed solely to monitoring. Matched seeds pair process noise, not later states. These finite results establish neither invariant safety nor a detection delay.
The shield steps column measures fallback usage. Frequent nominal handovers can reflect the aggressive initial conditions, scenario screen, or innovation false alarms; they do not prove a threshold is too tight. No handover under a shift is not necessarily an error if the proposed actions remain safe. Tune performance only after defining and validating the safety condition, and keep separate counts for each trigger to understand its contribution. The present table is an empirical tradeoff summary, not a soundness test.

Vertical shading marks action intervals during which the fallback was selected, including prospective scenario rejections and reactive innovation triggers. This first shifted episode illustrates the combined controller, not a certified recoverable set or a universal detection time. To isolate mechanisms, an additional ablation would compare each trigger separately and equalize actuator authority. Safety analysis must also account for untested initial states, longer horizons, process-noise tails, estimation errors, and switching delays.
