The physics of the Roadster wall-flip simulation

Report on sim/wall_flip_sim.py, written 2026-10-17. Every number on this page comes from the code, from a run of it, or from PROJECT.html. Code links go to the file on GitHub, by line. Other pages: videos, 3D replay, development journey.

The problem. On 2026-10-15 a Tesla Roadster drove up a curved wall, rode a 170° overhang upside down, let go, rolled upright in the air and landed on cold-gas thrusters. No source publishes the wall size, the car mass or the thrust. The broadcast shows only a few gauges: pitch, altitude, downforce and G. This page shows how the simulation turns those gauge readings and a few press facts into a complete, checkable physical model.

How to read it. Part 1 derives each equation from first principles. After each derivation, a teal box says the same thing in plain words and names the code line. Part 2 lists every number, with its status. Part 3 compares the result with the HUD and lists what the model cannot show. Part 4 analyses the flip itself: the release from the ceiling and the half-roll, with one model for all forces.

Status tags used in Part 2: measured read from the video; published stated by Tesla or the press; derived calculated from other numbers; est. an estimate (an assumption).

Part 1: the theory

0. Setting: clocks, axes, symbols

Clock. All times are seconds on the VideoFromSpace clock (eqOfmtTJD1A). The PCMag clip runs 61.35 s later: PCMag time = sim time + 61.35 s. The header of data/hud_wall_flip.csv still says 61.0 s. That value is old. The gauge readings corrected it to 61.35 s on 2026-10-16.

World axes. \(x\) is horizontal, along the wall's plane. \(x = 0\) is the foot of the curve. The car starts at negative \(x\), climbs toward positive \(x\), and the overhang carries it back over negative \(x\). \(y\) points to the side, and \(z\) points up. The flight model keeps the car in the plane \(y = 0\) (see Known limits).

Body axes. \(x_b\) points forward, \(y_b\) left and \(z_b\) up, from the car's centre of gravity (CG). The rotation matrix \(R\) takes a body vector into world axes: \(\mathbf{v}_{\text{world}} = R\,\mathbf{v}_b\).

Altitude. The HUD ALTITUDE is the CG height above its height when parked. The sim stores the CG at \(z = h + h_{cg}\), with \(h_{cg} = 0.45\) m.

SymbolMeaningUnit
\(m\)Car mass: dry mass plus the gas left in the tankkg
\(g_0\)Standard gravity, 9.80665m/s²
\(\mathbf{g}\)Gravity vector \((0, 0, -g_0)\)m/s²
\(s\)Distance travelled along the wall (track length)m
\(\theta\)Pitch: angle of the track to the horizontal (0° road, 90° vertical, 170° ceiling)rad
\(h\)HUD altitude of the CGm (HUD shows ft; 1 ft = 0.3048 m)
\(\kappa\)Curvature of the track, \(d\theta/ds\)1/m
\(\mathbf{p}, \mathbf{v}\)CG position and velocity, world axesm, m/s
\(q, R\)Attitude as a unit quaternion and as a rotation matrix—
\(\boldsymbol{\omega}\)Angular velocity, body axesrad/s
\(I\)Inertia tensor, body axes, diagonalkg·m²
\(P, T, v\)Tank gas pressure, temperature, specific volume \(V/m_{gas}\)Pa, K, m³/kg
\(f_i\)Thrust of nozzle \(i\), \(i = 1 \dots 10\)N

1. Rebuilding the wall from the HUD

No source gives the wall dimensions. During the first, slow climb (0:05.5–0:27 in VideoFromSpace), the HUD shows PITCH \(\theta\) and ALTITUDE \(h\). These two gauges are enough to rebuild the shape of the CG path.

Step 1: the slope relation. Let the car move a short distance \(ds\) along the track at pitch \(\theta\). The CG then rises \(dh = \sin\theta\,ds\) and moves \(dx = \cos\theta\,ds\) sideways. Divide the two to remove \(ds\):

$$\frac{dx}{dh} = \frac{\cos\theta}{\sin\theta} \quad\Longrightarrow\quad x(\theta) = \int \frac{dh}{\tan\theta} \approx \sum_k \frac{\Delta h_k}{\tan\bar\theta_k}$$

Here \(\bar\theta_k\) is the mid-point pitch of step \(k\). The code steps \(\theta\) from 0° to 170° in 0.1° steps.

Step 2: the entry curve. Near \(\theta = 0\), \(\tan\theta \to 0\). A 0.1 ft read error in \(h\) then gives a large error in \(x\). So the code drops readings below 20° and uses a circle there. A circle of radius \(R\) that starts flat on the road has \(h = R(1-\cos\theta)\). The least-squares radius minimises \(\sum_i \left[h_i - R(1-\cos\theta_i)\right]^2\). Set the derivative with respect to \(R\) to zero:

$$R = \frac{\sum_i h_i\,(1-\cos\theta_i)}{\sum_i (1-\cos\theta_i)^2}$$

The sum uses the readings between 20° and 80° (27.6° to 76.4°). The result is \(R = 8.656\) m.

Step 3: the blend. Above the circle, a shape-preserving cubic (PCHIP) passes through the readings \(h(\theta)\). Between 20° and 40°, a linear weight \(w = (\theta - 20°)/20°\) moves from the circle to the data: \(h = (1-w)\,R(1-\cos\theta) + w\,h_{\text{PCHIP}}(\theta)\).

Step 4: the ceiling. From the first 170° reading, the pitch gauge stays at 170°. The code makes the rest a straight line at 170°. It must reach the release altitude \(z_{rel}\), which is the lag-corrected HUD altitude at 52.25 s (§10). Its length is

$$L = \frac{z_{rel} - z_{170}}{\sin 170°} + L_{lip}$$

\(L_{lip}\) is the extra ceiling past the release point: 1.5 m in the default hud variant, 0 m in the short variant. Last, the code adds 40 m of flat road in front of the foot and integrates the arc length \(s = \int\sqrt{dx^2 + dz^2}\).

In plain words. If you know how steep the track is and how much the car climbed, you know how far it moved sideways. The code adds up those small sideways steps. Where the track is nearly flat, the method is too sensitive to reading errors, so a circle fills that part. The upside-down ceiling is a straight line.
sim/wall_flip_sim.py:101–133 build_wall()

2. Motion on the wall

On the wall, the model does not predict the motion. It reads the motion from the HUD of the flip run and then computes the forces that this motion needs. This is an inverse (kinematic) model.

Altitude to track position. On the wall, \(dh/ds = \sin\theta > 0\) for \(0 \lt \theta \lt 180°\). So \(h(s)\) increases strictly and has an inverse \(s(h)\). Each lag-corrected HUD altitude gives one track position.

Start position from the G gauge. The car starts from rest at 45.65 s, when G steps from 1.0 to 1.1. The altitude stays below 0.1 ft until 46.3 s. On a flat road, the accelerometer measures the vector difference of the car's acceleration \(a\) and gravity. Its size is \(\sqrt{a^2 + g_0^2}\). So

$$G = \frac{\sqrt{a^2 + g_0^2}}{g_0} \quad\Longrightarrow\quad a = g_0\sqrt{G^2 - 1} = g_0\sqrt{1.1^2 - 1} = 0.458\,g_0$$

With constant acceleration for 0.65 s (45.65 to 46.3 s), the car travels \(\tfrac12 \cdot 0.46\,g_0 \cdot 0.65^2 = 0.95\) m. The code puts the start that far before the point where the altitude first reads 0.1 ft.

Smoothing. The readings \(s_i\) are noisy, and the loads need the second derivative. A smoothing spline \(f(t)\) minimises

$$\sum_i \bigl(s_i - f(t_i)\bigr)^2 + \lambda \int f''(t)^2\,dt, \qquad \lambda = 2\times10^{-3}$$

Speed is \(v = f'(t)\) and acceleration along the track is \(a = f''(t)\). The code samples them every 0.01 s from 44.0 s to the release at 52.25 s. Before 45.65 s it sets \(v = a = 0\).

In plain words. The HUD says how high the car was at each moment. The rebuilt wall says where on the track that height is. A smooth curve through those points gives the speed and the acceleration.
sim/wall_flip_sim.py:173–186 wall_phase(), start position at line 179, spline at line 182

3. Loads on the wall: tyres, suction, G, power

Path frame. At pitch \(\theta\), the unit tangent along the track and the unit normal away from the surface (the car's "up") are

$$\hat{\mathbf t} = (\cos\theta,\ 0,\ \sin\theta), \qquad \hat{\mathbf n} = (-\sin\theta,\ 0,\ \cos\theta)$$

Acceleration on a curved path. Differentiate the velocity \(\mathbf v = v\,\hat{\mathbf t}\). Because \(d\hat{\mathbf t}/ds = \kappa\,\hat{\mathbf n}\) and \(ds/dt = v\):

$$\mathbf a = \dot v\,\hat{\mathbf t} + v\,\frac{d\hat{\mathbf t}}{dt} = a\,\hat{\mathbf t} + v^2\kappa\,\hat{\mathbf n}$$

The second term is the centripetal acceleration. On the concave wall it points away from the surface, into the car's "up" direction.

Forces. Five forces act on the car: tyre traction \(F_t\,\hat{\mathbf t}\); the surface's push \(N\,\hat{\mathbf n}\) with \(N \ge 0\); suction \(-F_s\,\hat{\mathbf n}\), which pulls the car onto the surface; gravity \(m\mathbf g\); and air drag \(-D\,\hat{\mathbf t}\) with \(D = \tfrac12\rho\,(C_dA)_x\,v^2\). Gravity along the two directions is \(m\mathbf g\cdot\hat{\mathbf t} = -mg_0\sin\theta\) and \(m\mathbf g\cdot\hat{\mathbf n} = -mg_0\cos\theta\). Newton's second law along each direction gives

$$\text{along } \hat{\mathbf t}:\quad m a = F_t - m g_0\sin\theta - D \quad\Longrightarrow\quad F_t = m a + m g_0 \sin\theta + D$$ $$\text{along } \hat{\mathbf n}:\quad m v^2\kappa = N - F_s - m g_0\cos\theta \quad\Longrightarrow\quad N = m v^2\kappa + m g_0\cos\theta + F_s$$

Friction limit. The tyres can transmit at most \(\mu N\): \(|F_t| \le \mu N\). Put in \(N\) and solve for the suction:

$$F_s \;\ge\; \frac{|F_t|}{\mu} - m v^2\kappa - m g_0\cos\theta \qquad\Longrightarrow\qquad F_{s,\min} = \max\!\Bigl(0,\ \frac{|F_t|}{\mu} - m v^2\kappa - m g_0\cos\theta\Bigr)$$

On the ceiling, \(\theta = 170°\) and \(\cos\theta = -0.985\). The last term then becomes \(+0.985\,mg_0\): suction must first cancel almost all of the car's weight, and then supply the normal load for traction.

Accelerometer. An accelerometer measures the specific force \(\mathbf a - \mathbf g\), not \(\mathbf a\). At rest it reads \((0, 0, g_0)\), that is 1 G. The model's G gauge is

$$G = \frac{\lvert a\,\hat{\mathbf t} + v^2\kappa\,\hat{\mathbf n} - \mathbf g\rvert}{g_0}$$

Power. The power at the wheels is \(P_w = F_t\,v\).

In plain words. The tyres must push the car up the slope, accelerate it and beat the air. A tyre can only push as hard as it is pressed onto the surface, times the friction coefficient. Upside down, gravity pulls the car away, so the suction fans must press the car on. The model computes the least suction that still lets the tyres grip.
sim/wall_flip_sim.py:187–199: tyre force line 193, minimum suction line 194, G lines 195–196, power line 199

4. Free flight: the rigid body

After release at 52.25 s, the car is a free rigid body with six degrees of freedom (DOF): three of position and three of attitude. The initial state is the last wall state: position \(\mathbf p\), velocity \(v\,\hat{\mathbf t}\), attitude from the path frame \(R = [\hat{\mathbf t},\ \hat{\mathbf n}\times\hat{\mathbf t},\ \hat{\mathbf n}]\), and \(\boldsymbol\omega = 0\).

Translation (Newton). With all non-gravity forces collected in \(\mathbf F_{ng}\) (world axes):

$$m\,\dot{\mathbf v} = \mathbf F_{ng} + m\,\mathbf g, \qquad \dot{\mathbf p} = \mathbf v, \qquad \mathbf F_{ng} = R\,(\mathbf F_{thrust} + \mathbf F_{drag}) + \mathbf F_{contact}$$

The mass falls as gas leaves: \(m = m_{dry} + m_{gas}(t)\). For a body that ejects mass, the thrust force \(\mathbf F_{thrust}\) already contains the momentum carried away by the gas. So \(m\dot{\mathbf v} = \mathbf F\) holds with the current mass and no extra \(\dot m\,\mathbf v\) term.

Rotation (Euler). The angular momentum in body axes is \(I\boldsymbol\omega\). Its rate in an inertial frame, written in rotating body axes, is \(I\dot{\boldsymbol\omega} + \boldsymbol\omega\times I\boldsymbol\omega\). That rate equals the applied moment \(\mathbf M\):

$$I\,\dot{\boldsymbol\omega} = \mathbf M - \boldsymbol\omega\times I\boldsymbol\omega$$

Attitude (quaternions). A unit quaternion \(q = (w, x, y, z)\) stores the attitude without the singularities of Euler angles. With \(\boldsymbol\omega\) in body axes, its rate is

$$\dot q = \tfrac12\, q \otimes (0, \boldsymbol\omega)$$

where \(\otimes\) is the quaternion product. The rotation matrix follows from \(q\):

$$R(q) = \begin{pmatrix} 1-2(y^2+z^2) & 2(xy - wz) & 2(xz + wy) \\ 2(xy + wz) & 1-2(x^2+z^2) & 2(yz - wx) \\ 2(xz - wy) & 2(yz + wx) & 1-2(x^2+y^2) \end{pmatrix}$$

Integration. The step is \(\Delta t = 1\) ms, semi-implicit Euler: first \(\mathbf v\) and \(\boldsymbol\omega\), then \(\mathbf p\) and \(q\) with the new rates. After each step the code divides \(q\) by its norm, so it stays a unit quaternion. Over 5.75 s that is 5,750 steps.

In plain words. In the air, the car obeys two laws. Force changes its speed. Moment (twist) changes its spin. The spin is stored as a quaternion, a four-number form of attitude that never locks up. The code advances time in 1 ms steps.
sim/wall_flip_sim.py:289–302 integration; 145–154 quaternion ↔ matrix; 210–213 initial state

5. Forces in flight: nozzles, drag, wheels

Nozzle wrench. Nozzle \(i\) sits at body position \(\mathbf r_i\) and pushes along the unit body direction \(\mathbf d_i\) with thrust \(f_i \ge 0\). Its force is \(f_i\mathbf d_i\) and its moment about the CG is \(\mathbf r_i \times f_i\mathbf d_i\). All ten nozzles together give a six-component wrench, linear in the thrusts:

$$\begin{pmatrix}\mathbf F_{thrust} \\ \mathbf M_{thrust}\end{pmatrix} = B\,\mathbf f, \qquad B = \begin{pmatrix} \mathbf d_1 & \cdots & \mathbf d_{10} \\ \mathbf r_1\times\mathbf d_1 & \cdots & \mathbf r_{10}\times\mathbf d_{10} \end{pmatrix} \in \mathbb R^{6\times10}$$

Drag. The code uses a separate drag area on each body axis \(j\):

$$F_{drag,j} = -\tfrac12\,\rho\,(C_dA)_j\,\lvert v_{b,j}\rvert\,v_{b,j}, \qquad \mathbf v_b = R^{\mathsf T}\mathbf v$$

Wheels. Each of the four wheels is a contact point \(\mathbf r_w = (\pm\tfrac{WB}2,\ \pm\tfrac{TR}2,\ -(h_{cg}+\delta_0))\) in body axes. \(\delta_0 = mg_0/(4k) = 72.0\) mm is the static spring deflection. When the world height \(z_w\) of a wheel point is below 0, the ground pushes up with a spring-damper force, and friction acts on the sliding velocity \(\mathbf v_t\):

$$N = \max\bigl(0,\ -k\,z_w - c\,\dot z_w\bigr), \qquad \mathbf F_{fric} = -\mathbf v_t\,\min\!\Bigl(5000,\ \frac{\mu N}{\lvert\mathbf v_t\rvert}\Bigr)$$

At low sliding speed, friction acts as a 5,000 N·s/m damper. At higher speed, it is Coulomb friction of size \(\mu N\). The damper part removes the jump at \(\mathbf v_t = 0\), which a 1 ms integrator cannot handle. Each wheel force also gives a moment \(R^{\mathsf T}\bigl((R\mathbf r_w)\times\mathbf F\bigr)\) in body axes.

In plain words. Each jet pushes the car and also twists it, more so when it sits far from the centre. One 6×10 table holds both effects for all ten jets. Air drag grows with the square of speed. The wheels are springs with shock absorbers that work only when they touch the ground.
sim/wall_flip_sim.py:58–70 nozzles and \(B\); 243–254 wheels; 287–291 thrust, drag, sum

6. The gas: Abel-Noble tank and blowdown

Why not the ideal gas law. The ideal gas law \(Pv = RT\) treats molecules as points. At 690 bar, nitrogen molecules fill a real part of the volume, and the gas is stiffer than the ideal law says. The Abel-Noble equation removes a co-volume \(b\) per kilogram from the space the molecules can move in:

$$P\,(v - b) = R\,T, \qquad v = \frac{V}{m_{gas}}$$

The compressibility factor is \(Z = Pv/(RT) = 1 + bP/(RT)\). With \(b = 8.0\times10^{-4}\) m³/kg, at 690 bar and 293 K, \(Z = 1.635\). The code comment says the co-volume was fitted to \(Z = 1.65\) for N₂ at 690 bar. The value this \(b\) gives at 293 K is 1.635, which is 0.9% lower.

Start state. 250 kg in 0.600 m³ gives \(v_0 = 2.4\times10^{-3}\) m³/kg. Then \(P_0 = RT/(v_0 - b) = 296.8\times293/(1.6\times10^{-3}) = 543.5\) bar. The ideal law would give 362 bar.

Blowdown. Follow the gas that stays in the tank. Its specific volume grows as gas leaves. The first law for one kilogram is \(du = \delta q - P\,dv\). For an Abel-Noble gas, internal energy depends on \(T\) only, because \((\partial u/\partial v)_T = T(\partial P/\partial T)_v - P = TR/(v-b) - P = 0\). So \(du = c_v\,dT\). With no heat flow:

$$c_v\,dT = -\frac{RT}{v - b}\,dv \quad\Longrightarrow\quad \frac{dT}{T} = -(\gamma - 1)\,\frac{d(v-b)}{v-b} \quad\Longrightarrow\quad T\,(v-b)^{\gamma-1} = \text{const}$$

This uses \(R/c_v = \gamma - 1\). The tank wall gives heat back to the cold gas, so the real process lies between adiabatic (\(n = \gamma = 1.4\)) and isothermal (\(n = 1\)). The code uses the polytropic form with \(n = 1.25\):

$$T_{k+1} = T_k \left(\frac{v_k - b}{v_{k+1} - b}\right)^{n-1}$$

Each step removes \(\dot m\,\Delta t\) of gas (§7) and then updates \(T\) and \(P\).

In plain words. At 543 bar the gas is so dense that its molecules take up real space, so the pressure is 50% higher than the simple gas law says. When gas leaves, the gas that stays expands and cools, and the pressure falls faster than the mass. Heat from the tank wall slows the cooling. The exponent \(n\) sets how much.
sim/wall_flip_sim.py:81–97 Tank: pressure line 87, blowdown line 96

7. The nozzle: thrust and mass flow

Choked flow. At a pressure ratio of hundreds to one, the flow at the nozzle throat reaches the speed of sound. The mass flow then depends only on the tank state and the throat area \(A^*\). For an ideal gas with isentropic flow from the tank to the throat:

$$\dot m = \frac{P\,A^*}{c^*}, \qquad c^* = \frac{\sqrt{R\,T}}{\Gamma}, \qquad \Gamma = \sqrt{\gamma}\left(\frac{2}{\gamma+1}\right)^{\frac{\gamma+1}{2(\gamma-1)}}$$

For \(\gamma = 1.4\), \(\Gamma = 0.6847\). The code writes the same quantity as \(c^* = \sqrt{\gamma RT}/\Gamma'\) with \(\Gamma' = \sqrt{\gamma}\,\Gamma = 0.8102\). At 293 K, \(c^* = 430.7\) m/s.

Thrust. The thrust coefficient \(C_f\) collects the exit speed and the exit pressure terms: \(F = C_f\,P\,A^*\). Divide the two relations to remove \(A^*\) and \(P\):

$$\dot m = \frac{F}{C_f\,c^*}, \qquad c_{\text{eff}} = C_f\,c^* = 1.6 \times 430.7 = 689.1\ \text{m/s}$$

Pressure limit. With a fixed throat, \(F \propto P\). So each nozzle's maximum thrust falls with the tank pressure: \(F_{\max,i}(P) = F_{\max,i}^{(0)}\,P/P_0\). The valve can only reduce the thrust below that limit.

Throat sizes (derived). From \(A^* = F_{\max}^{(0)}/(C_f P_0)\): rear 230 mm² (17.1 mm diameter), corner lift 402 mm² (22.6 mm), front 172 mm² (14.8 mm). At full pressure one lift nozzle uses 50.8 kg/s.

In plain words. A cold-gas jet is a hole that the gas leaves at the speed of sound. A bigger hole or a higher pressure gives more thrust and uses gas faster. Each newton of thrust uses gas at 1/689 kg/s. As the tank empties, every jet gets weaker.
sim/wall_flip_sim.py:78 \(\Gamma'\); 89–93 \(c^*\) and \(\dot m\); 278 pressure limit

8. The flight controller

The demo car was autonomous, so the model flies it with a controller, not a human. The controller runs at 100 Hz (every 10th 1 ms step). It has three references and two feedback laws.

Reference 1: height. \(z_r(t)\) is a smoothing spline (\(\lambda = 10^{-3}\)) through the lag-corrected HUD altitude plus \(h_{cg}\), from 52.20 s on.

Reference 2: horizontal braking. The car leaves the lip with horizontal speed \(v_{x0}\). The controller brakes it to zero by \(T_b = 55.0\) s with a minimum-jerk profile. Let \(u = (t - T_{rel})/(T_b - T_{rel})\), clipped to [0, 1], and

$$S(u) = 10u^3 - 15u^4 + 6u^5, \qquad \dot x_r = v_{x0}\bigl(1 - S(u)\bigr), \qquad x_r = x_0 + v_{x0}(T_b - T_{rel})\int_0^u \bigl(1 - S(u')\bigr)\,du'$$

\(S\) goes from 0 to 1 with zero slope and zero curvature at both ends, so the braking starts and ends without a jerk. Because \(\int_0^1 (1 - S)\,du = \tfrac12\), the braking distance is \(v_{x0}(T_b - T_{rel})/2\).

Reference 3: attitude. The car must half-roll from upside down to upright, between \(t_0 = 52.35\) s and \(t_1 = 53.10\) s, and lose its 10° release pitch by 53.40 s:

$$R_r(t) = R_{up}\;R_y\!\Bigl(\theta_0\bigl(1 - S(u_p)\bigr)\Bigr)\;R_x\!\Bigl(\pi\bigl(1 - S(u_r)\bigr)\Bigr), \qquad u_r = \frac{t - t_0}{t_1 - t_0}, \quad u_p = \frac{t - t_0}{t_1 + 0.3 - t_0}$$

\(R_{up} = \mathrm{diag}(-1, -1, 1)\) is upright with the nose toward \(-x\). \(\theta_0 = -10°\) is the release pitch as a rotation about \(y\).

Feedback law 1: position. The wanted acceleration is the reference acceleration plus proportional-derivative (PD) corrections:

$$a_{x} = \ddot x_r + 4(x_r - x) + 4(\dot x_r - \dot x), \qquad a_{y} = 4(0 - y) + 4(0 - \dot y)$$ $$a_{z} = \begin{cases} \ddot z_r + 9(z_r - z) + 4.2(\dot z_r - \dot z), & t \ge T_{burn} = 53.95\ \text{s} \\ -g_0, & t \lt T_{burn} \end{cases}$$

A PD law \(\ddot e + k_d\dot e + k_p e = 0\) has natural frequency \(\omega_n = \sqrt{k_p}\) and damping ratio \(\zeta = k_d/(2\omega_n)\). Horizontal: \(\omega_n = 2\) rad/s, \(\zeta = 1.0\). Vertical: \(\omega_n = 3\) rad/s, \(\zeta = 0.7\). Before the burn, \(a_z = -g_0\) asks for zero vertical non-gravity force: the car falls free. The jets still fire for the roll and the braking, so a small vertical thrust can remain. The required non-gravity force in body axes is

$$\mathbf F_b = R^{\mathsf T}\,m\,(\mathbf a_{des} - \mathbf g)$$

Feedback law 2: attitude. The attitude error is the rotation from the reference to the actual attitude, \(R_e = R_r^{\mathsf T}R\). For a rotation by angle \(\phi\) about unit axis \(\mathbf k\), \(\tfrac12(R_e - R_e^{\mathsf T}) = \sin\phi\,[\mathbf k]_\times\). So the vector

$$\mathbf e = \tfrac12\,\bigl(R_e - R_e^{\mathsf T}\bigr)^{\vee} = \sin\phi\;\mathbf k$$

is a small-angle rotation error (\(^\vee\) takes the three entries of a skew matrix). The reference rate comes from \([\boldsymbol\omega_r]_\times = R_r^{\mathsf T}\dot R_r\), by a central difference over ±0.01 s. The wanted moment is

$$\mathbf M_b = I\bigl(-36\,\mathbf e - 8.4\,(\boldsymbol\omega - \boldsymbol\omega_r)\bigr) + \boldsymbol\omega\times I\boldsymbol\omega$$

That is \(\omega_n = 6\) rad/s and \(\zeta = 0.7\) on each axis. The last term cancels the gyroscopic term of Euler's equation (§4).

In plain words. The controller has a plan for height (follow the HUD), for forward speed (brake smoothly to a stop by 55.0 s) and for attitude (roll over in 0.75 s). Each 10 ms it compares the car with the plan and asks for a force and a twist that close the gap, like a spring with a shock absorber. Until 53.95 s it lets the car fall freely.
sim/wall_flip_sim.py:204–228 references; 265–277 feedback laws; 167–169 \(S(u)\)

9. The valve allocator

The controller asks for a wrench \(\mathbf w = (\mathbf F_b, \mathbf M_b)\): six numbers. There are ten thrusts, each between 0 and its pressure limit. The allocator finds the thrusts that come closest:

$$\min_{\mathbf f}\ \bigl\lVert W\,(B\mathbf f - \mathbf w)\bigr\rVert^2 + \varepsilon^2\lVert\mathbf f\rVert^2 \quad \text{subject to}\quad 0 \le f_i \le F_{\max,i}(P)$$

\(W = \mathrm{diag}(10^{-3}, 10^{-3}, 10^{-3}, 3\times10^{-3}, 3\times10^{-3}, 3\times10^{-3})\) per N and per N·m: one N·m of moment error counts 3 times as much as one N of force error. \(\varepsilon = 10^{-5}\) is a small penalty that picks the lowest total thrust when several answers fit equally. SciPy's lsq_linear solves this bounded-variable least-squares problem.

Valves. A valve does not open at once. The actual thrust follows the command with a first-order lag:

$$\tau\,\dot f_i = f_{cmd,i} - f_i, \qquad \tau = 20\ \text{ms}$$

and is clipped to \([0, F_{\max,i}(P)]\).

Landing cut. When the wheels carry more than half the weight for more than 0.05 s, all commands go to zero and stay there.

In plain words. Jets can only push, and each has a limit. When the wish is more than the jets can give, the allocator picks the best compromise and treats twist errors as more serious than force errors. Valves take about 20 ms to follow.
sim/wall_flip_sim.py:278–282 allocator; 284–286 valves; 257–263 landing cut

10. The HUD lag: a free-fall fit

The first full run failed its own check (sensitivity). One cause: the HUD altitude is late. The G gauge drops from 1.0 to 0.4 between 52.2 and 52.3 s, but the altitude keeps rising until 52.6–52.7 s. A car in free fall after release can rise only for \(v_{z0}/g_0\), about 0.14 s.

Model. Before release, the CG climbs the straight 170° ceiling at a constant vertical speed \(v_{z0}\). After release it falls freely. The HUD shows this height \(\ell\) seconds late. With \(\tau = t - \ell - T_{rel}\):

$$\hat h(t) = z_0 + v_{z0}\,\tau - \tfrac12\,g_0\,\max(\tau, 0)^2$$

A parabola alone has only two free parameters, so it cannot separate \(\ell\) from \(z_0\) and \(v_{z0}\). The kink at \(\tau = 0\), where the straight climb changes to the parabola, fixes \(\ell\). The fit uses the 18 HUD readings from 52.2 to 53.95 s, before the burn.

Result. \(\ell = 0.337\) s, \(v_{z0} = 1.329\) m/s, \(z_0 = 20.768\) m, rms residual 1.258 ft. Check: the sim's release state is 8.139 m/s along a 170° ceiling, so \(v_{z0} = 8.139\sin10° = 1.413\) m/s, 6% above the fit. The code uses \(\ell = 0.30\) s. The second stunt's HUD showed about 0.2 s. The record gives no other reason for 0.30 s in place of 0.34 s.

In plain words. A car that lets go of a ceiling can only drift up for a moment before it falls. The HUD altitude kept climbing for 0.4 s, so the gauge is late. Fitting a fall curve to the gauge gives a delay of 0.34 s. The sim shifts all HUD altitudes 0.30 s earlier.
sim/wall_flip_sim.py:51 HUD_LAG; 136–138 applied to all HUD altitudes; fit in out/physics/make_charts.py (the fit code was not in the repository before)

11. Fit metrics and the self-check

The report compares the sim with the HUD on the HUD's own sample times:

The run stops with an error unless all seven checks pass: apex within 1.5 ft of the HUD; touchdown within 0.4 s; altitude RMSE under 2.5 ft; landing tilt under 10°; gas used between 0 and 250 kg; wall clearance over 0.1 m; no body corner more than 0.05 m below the ground.

sim/wall_flip_sim.py:340–373 report; 399–408 self-check; 314–329 clearance

Part 2: the numbers

Sources: PROJECT.html §3–§8 and the source table in the README. "Derived" values were calculated for this report by out/physics/make_charts.py or by the sim run.

The car

QuantityValueStatusBasisCode
Wet mass2,350 kgderivedHUD DOWNFORCE peak 4,700 kg ÷ "up to 2 G" suction (event)line 334
Dry mass2,100 kgderivedWet mass minus 250 kg of gas. Compare: base target under 1,700 kg (Top Gear)line 29
Wheelbase2.825 mpublishedTop Gear (Tesla engineer)line 39
Track (wheel spacing)1.70 mest.—line 39
Width2.00 mpublishedTop Gearline 40
Length, height4.70 m, 1.15 mest.Not publishedline 40
CG height at rest0.45 mest.—line 38
Inertia roll / pitch / yaw650 / 2,900 / 3,200 kg·m²est.Check: a uniform solid box of 4.70 × 2.00 × 1.15 m and 2,350 kg gives 1,042 / 4,585 / 5,109. The estimates are 62–63% of that, which fits mass placed low and central.line 37
Suspension, per wheel80 kN/m, 6 kN·s/mest.Gives 1.86 Hz, damping ratio 0.44, static deflection 72.0 mm (derived)line 41
Tyre friction μ1.1est.—line 42
Drag areas x / y / z0.7 / 2.0 / 8.0 m²est.Air density 1.2 kg/m³lines 43–44
Drive powerover 1 MWpublishedTop Gear. Not used by the sim; compared with the computed wheel power—
Suction available4,700 kgfmeasuredHUD DOWNFORCE peak in the first climbline 45

The wall (ramp)

QuantityValueStatusBasis
Profile readingsPitch, altitude, downforce at 2 Hz, 0.1-unit precisionmeasureddata/wall_profile_hud.csv, VideoFromSpace 5.5–27.0 s
Entry circle radius (CG path)8.656 mderivedLeast squares, 27.6°–76.4° (§1)
Vertical pointCG altitude 9.38 m, 14.26 m of track from the footderivedPROJECT.html §3
Overhang90° → 170° while the altitude goes 9.4 → 19.2 mmeasuredHUD
CeilingStraight at 170°measuredPitch gauge stays at 170° from 63.1 to 69.1 ft
Release CG altitude20.696 mderivedLag-corrected HUD altitude at 52.25 s
Track length, foot to release38.727 mderivedSim release_track_s_m
Ceiling past the release (to the lip)1.5 m (hud) or 0 m (short)est.Evidence for each in PROJECT.html §9
Horizontal extent (CG path)20.18 m (hud), 18.70 m (short)derivedSim runs
Width3.3 mmeasuredFrame PCMag 1:44, car width 2.0 m as the scale
Top surface height at releaseabout 21.6 mderived20.70 m + about 0.9 m CG to surface upside down (est.); PROJECT.html §3

The nozzles

Ten nozzles: 4 rear main, 4 corner lift, 2 front for braking and yaw (event, Top Gear, TechCrunch). The force per nozzle is not published. Body axes: x forward, y left, z up, from the CG.

GroupPositions (m)Thrust directionMax thrust at full tankStatusThroat (derived)
Rear main ×4x = −2.30, y = ±0.45, ±0.15, z = −0.10(1, 0, 0), forward20 kN eachpublished total "over 80 kN"; split est.230 mm², 17.1 mm
Corner lift ×4x = ±1.40, y = ±0.85, z = −0.20(0, 0, 1), up35 kN each (140 kN; 6.07 g at 2,350 kg)derived: the least size that gives the 3.3 g burn at 54.4 s and a hover at the end402 mm², 22.6 mm
Front ×2x = 2.20, y = ±0.70, z = −0.10(−cos 20°, ∓sin 20°, 0): aft and inward15 kN eachderived size; 20° angle est.172 mm², 14.8 mm
PositionsAll est. from the car size
Valve lag20 ms first-orderest.
Thrust coefficient \(C_f\)1.6 (expanded nozzle, about 500:1 pressure ratio)est.

Code: sim/wall_flip_sim.py:58–66, \(C_f\) line 36, valve lag line 46.

The tank and the gas

QuantityValueStatusBasis
Volume0.600 m³ (two pressure vessels)publishedEvent
Gas mass250 kgpublishedEvent: "about 250 kilos of air"
GasN₂: R = 296.8 J/(kg·K), γ = 1.4publishedTop Gear says nitrogen, the event says air; R differs by under 3%
Start temperature293 Kest.—
Abel-Noble co-volume b8.0 × 10⁻⁴ m³/kgderivedFitted to Z ≈ 1.65 at 690 bar; gives 1.635 at 293 K
Rated pressureabout 690 bar (10,000 psi)publishedTop Gear, Thrust version
Start pressure543.5 barderived§6
Polytropic exponent n1.25est.Middle of 1.2–1.3 for fast pressure-vessel blowdown; sensitivity
c*, effective exhaust speed430.7 m/s, 689.1 m/s at 293 Kderived§7

Timing and the controller

QuantityValueStatusBasis
Clock offsetPCMag = sim + 61.35 smeasuredGauge readings in both videos; the CSV header value 61.0 s is old
Start from rest45.65 smeasuredHUD G 1.0 → 1.1
Release \(T_{rel}\)52.25 smeasuredHUD G 1.0 → 0.4 between 52.2 and 52.3 s
Half-roll window52.35 → 53.10 smeasuredVideoFromSpace frames at 10 fps: leaves the lip 52.3, on its side 52.6–52.7, upright 53.1
Burn start \(T_{burn}\)53.95 smeasuredHUD G 0.9 → 1.7. Shot B shows lift jets at 53.45 s (see limits)
Braking done \(T_b\)55.0 sest.The car hovers at about 10 ft from 54.8 to 55.2 s
HUD altitude lag0.30 sderivedFree-fall fit gives 0.337 s (§10)
Position gains (x, y)\(k_p = 4\ \text{s}^{-2}\), \(k_d = 4\ \text{s}^{-1}\)est.\(\omega_n = 2\) rad/s, \(\zeta = 1.0\)
Height gains\(k_p = 9\ \text{s}^{-2}\), \(k_d = 4.2\ \text{s}^{-1}\)est.\(\omega_n = 3\) rad/s, \(\zeta = 0.7\)
Attitude gains\(k_R = 36\ \text{s}^{-2}\), \(k_\omega = 8.4\ \text{s}^{-1}\)est.\(\omega_n = 6\) rad/s, \(\zeta = 0.7\)
Controller rate, step100 Hz, 1 msest.—

Part 3: results against the HUD

Run of 2026-10-17, default hud overhang. The self-check passes.

QuantitySimulationHUD (observed)
Apex68.46 ft at 52.39 s68.0 ft at 52.30 s (lag-corrected)
Touchdown56.17 s56.30 s (56.6 s minus the 0.30 s lag)
Altitude RMSE in flight2.09 ftFloor: the free-fall fit alone leaves 1.26 ft
G RMSE, wall / flight0.26 g / 0.60 g—
Peak G in the landing burn3.65 g at 54.04 s3.3 g at 54.4 s
Peak G in flight, overall3.78 g at 56.19 s (wheels touch down)—
Release state8.139 m/s along 170°: \(v_x = -8.015\), \(v_z = 1.413\) m/s; x = −10.45 m—
Gas used58.6 kg before the burn (roll, braking), 191.8 kg in total, 58.2 kg left—
Tank pressure543.5 bar → 338.9 bar at the burn → 58.6 bar at the end—
Landing pointx = −21.47 m, y = 0.00 m, tilt 0.0°Not measurable
Closest body corner to the wall0.50 m—
Lowest body corner0.058 m above the ground—

A check on the braking. §8 gives a braking distance of \(v_{x0}(T_b - T_{rel})/2 = -8.015 \times 2.75 / 2 = -11.02\) m. The release is at x = −10.45 m, so the car should stop at −21.47 m. The sim lands at x = −21.47 m.

Until 2026-10-18, PROJECT.html §8 listed the first passing run: 2.04 ft, 3.90 g, 187.8 kg, 0.59 m, touchdown 56.19 s. Those values are from before the half-roll window changed from 52.45/53.35 s to 52.35/53.10 s on 2026-10-16 (§9 of that page). python check.py found them; §8 now shows the current run. This page uses the current code.

The wall

Wall profile in the x-z plane with the CG path, the surface, pitch markers at 30 to 170 degrees and the release point
Fig. 1. The rebuilt wall. Teal: the CG path from the HUD (§1). Orange: the surface, 0.45 m below the CG path along the normal. The release point (pink) is 10.45 m behind the foot, with the CG 21.21 m above the road. The overhang reaches back over the approach road.
Three panels against time on the wall: speed, minimum suction against the 4,700 kgf available, and wheel power
Fig. 2. On the wall (§2, §3). The grey band from 51.31 s is the 170° ceiling, where the HUD resolution makes speed and acceleration unreliable.

Reading Fig. 2. The speed is about 6.8 m/s in the entry curve and falls to 4.6 m/s on the overhang (49.0–50.5 s). Up to 51.0 s the minimum suction peaks at 3,779 kgf, against 4,700 kgf available: 80% of it. The median from 48.5 to 51.0 s is 1,989 kgf. Wheel power up to 51.0 s peaks at 207 kW, against more than 1,000 kW published. So suction, not motor power, limits the climb.

Why the suction curve is a saw. The swings come from the acceleration \(a = f''(t)\), not from the wall. Example: the HUD altitude jumps from 48.1 to 50.6 ft between 50.2 and 50.3 s. After the 0.30 s lag shift, \(a\) rises to 6.4 m/s² at 49.8 s and falls to −3.2 m/s² at 50.0 s. The suction need follows: 3,779 kgf, then 1,579 kgf.

The ceiling values are noise. On a 170° ceiling, one 0.1 ft altitude step is 0.176 m of track. The sim's peaks there, 5,003 kgf of suction at 51.40 s (speed 10.14 m/s, acceleration 10.62 m/s²), 294 kW and 10.46 m/s, are in this band. They are not physical results. PROJECT.html §4.1 gives the typical overhang need as about 3,300 kgf and the peak power as about 190 kW; those values were sampled every 0.5 s.

Altitude and G

Altitude against time: HUD readings, HUD shifted by 0.30 s, the sim, and the free-fall fit
Fig. 3. CG altitude. Orange dots: the HUD as read. Thin orange: the HUD shifted 0.30 s earlier. Teal: the sim. Purple dashes: the free-fall fit of §10 with its 0.337 s lag removed.

Reading Fig. 3. On the wall, the sim leads the raw HUD by the lag, by design. In flight the sim follows the shifted HUD. The largest gap is in the fall: from 53.1 to 53.4 s (lag-corrected) the sim is 5.3 to 6.3 ft below the shifted HUD.

G against time: HUD G-FORCE readings and the sim specific force
Fig. 4. Accelerometer reading. Orange: HUD G-FORCE. Teal: the sim's specific force divided by \(g_0\).

Reading Fig. 4. On the wall, the sim's G swings by about ±0.5 g around the HUD. The cause is the same acceleration noise as in Fig. 2. In free fall the sim reads 0.0 to 1.4 g; the HUD reads 0.2 to 0.6 g. The sim spikes at 52.6 s and 53.1 s are the lift pairs that start and stop the roll. Both curves rise at about 53.95 s. The sim peaks at once, 3.65 g at 54.04 s; the HUD peaks at 3.3 g at 54.4 s. The spike of 3.78 g at 56.19 s is the wheel impact at touchdown.

Tank and nozzles

Tank pressure and gas mass against time after release
Fig. 5. Tank blowdown (§6). Pressure falls faster than the gas mass, because the gas also cools.

Reading Fig. 5. The run uses 76.7% of the gas (191.8 of 250 kg), but the pressure falls by 89% (543.5 to 58.6 bar). At touchdown each nozzle can give only 11.3% of its full-tank thrust.

Ten nozzle thrusts against time in three panels: rear, corner lift, front, each with the pressure limit
Fig. 6. The ten nozzle commands as thrust ÷ full-tank maximum. The grey dashes are the pressure limit \(P/P_0\): no line can go above it.

Reading Fig. 6. Before the burn, the front pair brakes the forward speed and the lift pairs make the roll: first the right pair (FR, RR), then the left pair (FL, RL) to stop it. The outer rear nozzles fire one at a time (rear0 at y = +0.45 m, rear3 at y = −0.45 m). One-sided, they give a yaw moment and some forward push. From 53.95 s the four lift nozzles run at or near the pressure limit until about 55.0 s, then below it for the hover. The burn is limited by pressure, which is why the lift nozzles had to be 35 kN each (sensitivity).

Sensitivity findings

Each row changes one input and reruns the flight (current code, same wall phase). Pass/fail uses the self-check limits: touchdown within 0.4 s of 56.30 s, altitude RMSE under 2.5 ft.

CaseTouchdownAlt. RMSEGas usedEnd pressurePeak GCheck
n = 1.4 (no heat from the tank wall)55.38 s3.10 ft170.6 kg72.3 bar4.11fails (touchdown, RMSE)
n = 1.25 (used)56.17 s2.09 ft191.8 kg58.6 bar3.78passes
n = 1.1 (nearly isothermal)56.25 s2.03 ft187.8 kg82.9 bar3.89passes
First-guess nozzles: lift 4 × 20 kN, front 2 × 8 kN54.78 s4.20 ft115.7 kg192.7 bar9.81fails (touchdown, RMSE)
short overhang (lip at the release point)56.17 s2.19 ft191.9 kg58.5 bar3.79passes (apex 68.23 ft, clearance 0.51 m)

Known limits

  1. Planar flight (y = 0). In shot B and in the replay R1, the real car drifts to +y (screen left). The model keeps it in the plane. A two-camera triangulation of the real path failed its gate (car rms ≤ 5 px in both views; best result 76 px in R1, 50 px in B). Per the owner's rule, the sim was not refitted.
  2. The wall phase is kinematic. The motion on the wall is read from the HUD, not predicted. The loads inherit the gauge noise: the 5,003 kgf suction, the 294 kW power and the 10.46 m/s speed on the ceiling are artefacts. The speed also jumps from 0 to 1.52 m/s at 45.65 s, because the code sets \(v = 0\) before that time while the spline already moves.
  3. Overhang length. Two variants. Shot B wall-edge fits favour the hud length (median rms 3.09 px at +1.5 m against 3.23 px at 0 m). The image at PCMag 113.6 s (= 52.25 s) shows the car at or past the lip, which favours short.
  4. G gauge timing. The model takes the G gauge as not lagged. Shot B shows the lift jets at 53.45 s, 0.5 s before the HUD G rise that sets \(T_{burn}\) = 53.95 s. Either the G gauge also lags, or the jets start before G rises.
  5. Constant inertia and CG. 191.8 kg of gas leaves, 8.2% of the wet mass. The mass in Newton's law falls, but the inertia and the CG position do not change.
  6. Simple nozzle model. \(c^*\) uses the ideal-gas choking relation at the tank temperature; the throat gas at about half the tank pressure is still dense. \(C_f\) is a constant 1.6, although the exit pressure ratio falls from about 540 to 58 during the run. One lumped tank, no pipe losses.
  7. No reference feed-forward for spin rate. The attitude law uses \(\boldsymbol\omega_r\) but not \(\dot{\boldsymbol\omega}_r\).
  8. Altitude zero. The first climb reached 69.1 ft; the flip run let go at 67.8 ft after lag correction. The altitude zero can differ by about 1.3 ft between runs.
  9. Gauge readings. All HUD values were read by eye: 0.1 ft and 0.1 g steps at 10 Hz (flip run) and 2 Hz (first climb).
  10. Roll tracking. The sim's half-roll lags its reference by about 0.1 s and overshoots upright by 34.3° (Part 4, §4.6).
  11. Estimates. Mass, inertia, \(C_f\), n, the gains and the nozzle positions are estimates. The lift and front nozzle sizes were derived to fit the observed flight. They are consistent with the data, not measured.

Part 4: the flip

The problem. For about one second the car does three things that no other phase of the stunt combines. It hangs upside down under a 170° ceiling, held there only by suction. It lets go. Then, in free fall, it turns 180° about its own long axis and arrives upright before the landing burn. The car has no wings and no rudder. Ten cold-gas jets that can only push, gravity and the air are the only things that can turn it. This part asks which of those forces does the work, how large each one is, and what the turn costs.

Window. From 51.31 s (the track reaches 170°, the car is inverted and the suction holds it) to 53.95 s (the landing burn starts). Before the window, the car climbs the curved overhang. After it, the burn of §8 stops the fall.

Method. Part 4 is an analysis of the existing sim, not a change to it. sim/wall_flip_sim.py and its self-check are unchanged. Section 4.3 writes one equation set for the whole window, with every force and moment. The terms that the sim leaves out are then evaluated along the sim's own trajectory, so that each one has a size. The script out/physics/flip.py prints every number in this part.

4.0 Timeline and symbols

Time (s)EventSource
51.31The track reaches 170°. From here the ceiling is straight.Wall rebuild (§1) and the lag-corrected HUD altitude
52.25Release: the car leaves the ceiling at 8.139 m/s along the 170° line.HUD G 1.0 → 0.4 between 52.2 and 52.3 s
52.35 → 53.10Half-roll window: inverted → uprightVideo frames at 10 fps: leaves the lip 52.3, on its side 52.6–52.7, upright 53.1
53.40The −10° release pitch is gone in the referenceReference design (§8)
53.95Landing burn startsHUD G 0.9 → 1.7

Symbols added in this part:

SymbolMeaningUnit
\(\varphi\)Roll angle about the body \(x_b\) axis. \(\varphi = 180°\) is upside down, \(\varphi = 0\) is upright. The script reads it from the rotation matrix as \(\varphi = \operatorname{atan2}(R_{32}, R_{33})\).rad (shown in °)
\(p, q, r\)Body angular rates about \(x_b, y_b, z_b\): roll, pitch, yaw. \(\boldsymbol\omega = (p, q, r)\).rad/s
\(I_{xx}, I_{yy}, I_{zz}\)Moments of inertia: 650, 2,900, 3,200 (est.)kg·m²
\(d\)Lateral distance from the CG to the line of the lift nozzles, 0.85 mm
\(T\)Duration of the half-roll, \(t_1 - t_0 = 0.75\) ss
\(F_s\), \(N\)Suction force and surface push on the ceiling (§3)N
\(\mathbf J\)Linear impulse \(\int \mathbf F\,dt\)N·s
Eight rear-view panels of the car from 52.20 to 53.90 s: inverted under the ceiling, rolling with the right lift jets, on its side, braked by the left lift jets past upright, and upright before the burn
Fig. 7. The flip seen from behind (sim, hud overhang). Screen right is \(+y\). Arrows: the thrust of the two lift nozzles on one side (front + rear corner), drawn on the body \(z_b\) axis. Blue bands: the exhaust, opposite to the thrust. Dot: the roof. Panels 3 and 5 are the peaks of the two thrust pulses; panel 4 is the instant \(\varphi = 90°\).

4.1 Before: riding the ceiling

The force balance upside down. On the straight ceiling, the curvature is \(\kappa = 0\). The normal equation of §3 then has no centripetal term:

$$N = F_s + m g_0\cos\theta = F_s - 0.985\,m g_0 \qquad (\theta = 170°)$$

The surface can only push, so \(N \ge 0\). The suction must first carry 98.5% of the weight, 2,314 kgf, before it presses the tyres on at all. The tyres must then carry the along-track load \(F_t = m a + m g_0\sin\theta + D\).

Worked case: the least suction at constant speed. Take \(a = 0\) at the release speed \(v = 8.139\) m/s. The drag is \(D = \tfrac12\rho\,(C_dA)_x v^2 = 27.8\) N, so \(F_t = 4{,}030\) N. With \(\mu = 1.1\):

$$F_{s,\min} = \frac{|F_t|}{\mu} - m g_0\cos\theta = 26{,}359\ \text{N} = 2{,}688\ \text{kgf}$$

That is 57% of the 4,700 kgf that the HUD showed as the peak downforce. The ceiling values of the sim's \(F_{s,\min}\) in Fig. 2 are larger, but they come from gauge noise in \(a\) (Part 3).

No spin at the start. On the curved overhang the car pitches at \(\dot\theta = v\kappa\); its largest value from 50.0 s to 51.31 s is 38.2°/s in the sim. On the straight ceiling \(\kappa = 0\), so \(\dot\theta = 0\). A car that lets go of a straight ceiling therefore starts its flight with \(\boldsymbol\omega = 0\), which is the sim's initial condition (§4). Any turn after the release must come from a moment applied in the air.

The accelerometer cannot see the suction. While the car is attached at \(a = 0\), the non-gravity force is \((N - F_s)\,\hat{\mathbf n} + (F_t - D)\,\hat{\mathbf t} = m g_0\cos\theta\,\hat{\mathbf n} + m g_0\sin\theta\,\hat{\mathbf t}\), whose size is \(m g_0\). The G gauge reads 1.0 for any suction above the minimum. It drops only when the car leaves the surface and the contact force goes to zero. So the G step from 1.0 to 0.4 between 52.2 and 52.3 s dates the separation, not the moment the suction was switched off. The HUD reads 1.0–1.1 g from 51.3 to 52.2 s, in agreement.

In plain words. Upside down, the suction has to hold up almost the whole car before the tyres can grip. At a steady 8 m/s it needs about 2,700 kgf, a bit more than half of what the fans gave. The ceiling is straight, so the car is not turning when it lets go. The G gauge stays at 1 G while the car hangs on, whatever the suction does, and falls only when the car comes off.
sim/wall_flip_sim.py:193–194 tyre force and minimum suction; 210–213 initial flight state

4.2 Letting go: separation from the ceiling

The condition. When the suction falls below \(0.985\,mg_0 + |F_t|/\mu\), the tyres slip; when it falls below \(0.985\,mg_0\), the push \(N\) reaches zero and the car leaves. The sim models this as an instant switch at \(T_{rel} = 52.25\) s.

The gap. After release, gravity has a part \(g_0|\cos\theta| = 0.985\,g_0\) along the normal away from the ceiling and a part \(g_0\sin\theta = 0.174\,g_0\) against the motion along it. With no thrust, the gap below the plane of the ceiling grows as

$$h_{gap}(\tau) = h_0 + \tfrac12\,(0.985\,g_0)\,\tau^2, \qquad \tau = t - T_{rel}$$

where \(h_0 = 0.120\) m is the distance from the body to the surface at release in the sim's box model. The free-fall part reaches 0.5 m after \(\tau = 0.322\) s. The sim's own gap, which includes the roll, is 0.170 m at 52.35 s, 0.312 m at 52.45 s and 0.485 m at 52.55 s.

How much ceiling is left. In the hud variant the wall ends 1.5 m past the nominal release point. The smoothing spline of §2 puts the sim's car 0.392 m past that point at 52.25 s, so only 1.108 m of ceiling is ahead of the CG. Solving \(1.108 = v\tau - \tfrac12(0.174\,g_0)\tau^2\) gives \(\tau = 0.138\) s: the CG passes the lip at 52.388 s, when the free-fall gap is 0.092 m. The rear bumper, 2.35 m behind the CG, passes it at 52.696 s. In the short variant the lip is at the release point: the CG passes it at 52.25 s and the rear bumper at 52.548 s. Fig. 8 shows the hud case.

Side view of the end of the ceiling with the hud and short lips and the car outline at 52.25, 52.40, 52.55 and 52.70 s, with lift exhaust lines
Fig. 8. Side view of the release. Grey: the ceiling surface; triangles: the two lip positions. Teal: the car's body box every 0.15 s, with its CG. Blue: lift-nozzle exhaust while the nozzle gives more than 2 kN. At 52.40 s the rear right exhaust (RR) points at the last part of the hud ceiling (§4.9).

A check the self-check skips. The wall-clearance check of §11 starts 0.3 s after the release, because the car starts on the surface. Over the skipped 0.3 s, the smallest body-to-ceiling gap in the sim is 0.120 m, at 52.25 s itself. The gap only grows after that, also during the start of the roll. No contact is hidden in the skipped window.

In plain words. When the suction stops, the car falls away from the ceiling almost as fast as it would fall from a roof. It travels about 1.1 m more under the ceiling (in the longer-ceiling version), then it is past the edge. By then the gap is under 10 cm, so the roll must not start much earlier.
sim/wall_flip_sim.py:48 T_RELEASE; 55 LIP_EXT; 322 clearance check starts at +0.3 s

4.3 One model for the whole window

The phases before and after the release use one rigid body with one set of equations. Only the active forces change. Let \(c(t) = 1\) while the car touches the ceiling and \(c(t) = 0\) after it leaves. In world axes:

$$m\,\dot{\mathbf v} = m\mathbf g + R\bigl(B_F\,\mathbf f + \mathbf F_{aero} + \Delta\mathbf F_{jet}\bigr) + c(t)\bigl[(N - F_s)\,\hat{\mathbf n} + (F_t - D)\,\hat{\mathbf t}\bigr]$$

and in body axes:

$$I\,\dot{\boldsymbol\omega} + \boldsymbol\omega\times I\boldsymbol\omega = B_M\,\mathbf f + \mathbf M_{aero} + \Delta\mathbf M_{jet} + c(t)\,\mathbf M_{contact}$$

\(B_F\) and \(B_M\) are the force and moment rows of the nozzle matrix \(B\) (§5). The contact obeys the complementarity conditions

$$h_{gap} \ge 0, \qquad N \ge 0, \qquad h_{gap}\,N = 0$$

that is, either the car touches and the surface pushes, or there is a gap and no push. The aerodynamic terms are

$$\mathbf F_{aero} = -\tfrac12\rho\,(C_dA)\,\lvert\mathbf v_b\rvert\,\mathbf v_b, \qquad \mathbf M_{aero} = \mathbf r_{cp}\times\mathbf F_{aero} + M_{damp}(p, V)\,\mathbf e_x$$

with \(\mathbf r_{cp}\) the offset of the centre of pressure from the CG and \(M_{damp}\) the roll damping (§4.8). \(\Delta\mathbf F_{jet}\), \(\Delta\mathbf M_{jet}\) are the forces that the jets induce on the body through the surrounding air: entrainment in free air and suction near a surface (§4.9). The table lists which terms the sim contains.

TermIn the sim?Where its size is shown
Gravity, thrust \(B\mathbf f\), gyroscopic \(\boldsymbol\omega\times I\boldsymbol\omega\)Yes§4.4, §4.6
Drag \(\mathbf F_{aero}\) on three body axesYes§4.8
Contact \(c(t)\): suction, surface push, tractionBefore release only, as a prescribed (kinematic) path; the release is an instant switch§4.1, §4.2
Aero moment \(\mathbf r_{cp}\times\mathbf F_{aero}\)No (\(\mathbf r_{cp} = 0\))§4.8
Aero roll damping \(M_{damp}\)No§4.8
Jet-induced \(\Delta\mathbf F_{jet}, \Delta\mathbf M_{jet}\)No§4.8, §4.9
Mass and inertia change as gas leavesMass yes; inertia noKnown limits 5
In plain words. One pair of equations covers the whole flip: force changes the speed, moment changes the spin. While the car touches the ceiling, the surface and the suction are two more forces. When it lets go, they switch off. Everything else (jets, air, gravity) acts all the time. The sim contains the large terms; the rest of this part measures the small ones.
sim/wall_flip_sim.py:287–296 forces, drag and the Euler step

4.4 The half-roll as a rigid-body problem

The roll equation. Take the \(x_b\) row of Euler's equation:

$$I_{xx}\,\dot p = M_x - (I_{zz} - I_{yy})\,q\,r$$

The sim's peak \(|q| = 0.321\) rad/s and \(|r| = 0.279\) rad/s give a gyroscopic term of at most 15.3 N·m. That is 0.059% of the peak jet moment, so in practice \(I_{xx}\dot p = M_x\). With \(\varphi\) as defined in §4.0 and small pitch, \(\dot\varphi \approx p\).

Proposition 1 (peak rate and acceleration of the half-roll). Let the roll follow \(\varphi(t) = \pi\,\bigl(1 - S(u)\bigr)\) with \(u = (t - t_0)/T\) and the minimum-jerk curve \(S(u) = 10u^3 - 15u^4 + 6u^5\) of §8. Then the largest roll rate and roll acceleration are

$$\lvert\dot\varphi\rvert_{\max} = \frac{15\pi}{8\,T} = 7.854\ \text{rad/s}, \qquad \lvert\ddot\varphi\rvert_{\max} = \frac{10\sqrt3}{3}\,\frac{\pi}{T^2} = 32.25\ \text{rad/s}^2 \qquad (T = 0.75\ \text{s})$$

Proof. \(\dot\varphi = -\pi S'(u)/T\) and \(\ddot\varphi = -\pi S''(u)/T^2\), with \(S'(u) = 30u^2(1-u)^2\), \(S''(u) = 60u - 180u^2 + 120u^3\) and \(S'''(u) = 60 - 360u + 360u^2\). \(S'\) is largest where \(S'' = 0\) inside \((0,1)\): \(u = \tfrac12\), \(S'(\tfrac12) = 30/16 = 15/8 = 1.875\). \(|S''|\) is largest where \(S''' = 0\): \(u = (3 \mp \sqrt3)/6\), where \(|S''| = 10\sqrt3/3 = 5.7735\). Multiply by \(\pi/T\) and \(\pi/T^2\). ∎

The moment and the thrust it needs. The moment at the peak is \(I_{xx}\,\ddot\varphi_{\max} = 650 \times 32.25 = 20.96\) kN·m. The lift nozzles push along \(z_b\) at \(y = \pm d\), so a nozzle of thrust \(f\) gives a roll moment \(\pm d f\). Two nozzles on one side give the moment with \(f = M/(2d) = 12.33\) kN each, which is 35% of their 35 kN rating. The angular impulse to reach the peak rate is \(I_{xx}\dot\varphi_{\max} = 5{,}105\) N·m·s for each half of the roll.

The estimate that sets it. \(I_{xx} = 650\) kg·m² is an estimate (Part 2). The thrust need scales with it:

\(I_{xx}\) (kg·m²)Peak thrust per nozzlePair force as specific forceOpen-loop sideways speed (§4.5)
4007.59 kN0.66 g1.06 m/s
650 (used)12.33 kN1.07 g1.72 m/s
1,042 (uniform box)19.76 kN1.72 g2.75 m/s
In plain words. To turn the car over in 0.75 s with a smooth start and stop, the spin must reach about 7.9 rad/s (450°/s) halfway. The hardest push comes about a fifth of the way in and again a fifth from the end. Two jets on one side give that push at about a third of their power. A heavier-to-turn car needs proportionally more.
sim/wall_flip_sim.py:49 roll window; 218–220 R_ref; 37 inertia

4.5 Jets that only push: the roll throws the car sideways

A wing can make a pure moment. A set of push-only jets cannot always do so. For the lift nozzles the cost is unavoidable.

Proposition 2 (a roll moment needs a net push). Let the four lift nozzles have thrusts \(f_i \ge 0\) along \(z_b\) at \(y = \pm d\). Their roll moment \(M_x\) and their total force \(F_z\) along \(z_b\) satisfy \(F_z \ge |M_x|/d\).

Proof. \(M_x = d\,(f_{FL} + f_{RL} - f_{FR} - f_{RR})\). By the triangle inequality and \(f_i \ge 0\), \(|M_x| \le d\,(f_{FL} + f_{RL} + f_{FR} + f_{RR}) = d\,F_z\). Equality holds when one side is off. ∎

The other jets do not escape this: the rear and front nozzles push in the \(x_b y_b\) plane, and their roll arm is at most 0.034 m per newton (the front pair), which gives at most 438 N·m in the sim, 1.7% of the peak jet moment.

Where the push goes. In world axes, the body \(z_b\) axis at roll angle \(\varphi\) (pitch neglected) is \((0,\ \sin\varphi,\ \cos\varphi)\). The sim confirms it: at \(\varphi = 90°\) (52.80 s) the world \(y\) part of \(z_b\) is +0.999. During the whole roll \(0 \lt \varphi \lt \pi\), so \(\sin\varphi \gt 0\): every pulse, the one that starts the spin and the one that stops it, pushes toward \(+y\).

Proposition 3 (the sideways impulse of the half-roll). With the least jet forces of Proposition 2 and the roll of Proposition 1, the impulse of the lift jets is

$$J_y = \frac{I_{xx}}{d}\int_{t_0}^{t_1}\lvert\ddot\varphi\rvert\sin\varphi\,dt = 4{,}038\ \text{N·s}, \qquad J_z = \frac{I_{xx}}{d}\int_{t_0}^{t_1}\lvert\ddot\varphi\rvert\cos\varphi\,dt = 0$$

Proof. By Proposition 2, the least body-\(z\) force is \(I_{xx}|\ddot\varphi|/d\), and its world direction is \((0, \sin\varphi, \cos\varphi)\). The minimum-jerk curve is symmetric about the midpoint: \(S(1-u) = 1 - S(u)\), so \(\varphi(t_0 + t_1 - t) = \pi - \varphi(t)\) and \(|\ddot\varphi|\) takes the same value at \(t\) and \(t_0 + t_1 - t\). Under this reflection \(\cos\varphi\) changes sign and \(\sin\varphi\) does not. So the \(z\) integral is zero and the \(y\) integral is twice its first half. The value 4,038 N·s is the numerical integral. ∎

The size. \(J_y/m = 1.72\) m/s. Without a sideways correction, the car would drift 0.64 m by the end of the roll and 2.11 m by the burn. The vertical parts cancel: the first pulse pushes down (body \(z_b\) points down while inverted) and the second pushes up. Their magnitudes add up to 5.11 m/s of velocity change, all spent to turn the car.

What the sim does with it. The sim's controller holds \(y = 0\) (§8). Fig. 11 (bottom) shows the result: the sim's \(v_y\) still reaches +0.987 m/s at 52.96 s, the controller then pulls it back to −0.521 m/s at 53.34 s, and the largest offset is 0.333 m. The open-loop line rises to 1.72 m/s and stays there.

Link to the video. In shot B and in the replay R1, the real car drifts to \(+y\) (screen left) (Known limits 1). The model gives a mechanism with that sign, if the real car rolled the same way as the sim (roof toward \(+y\) at mid-roll). The 10 fps roll frames are too small to show the roof side, so the roll direction of the real car is not measured. The triangulation that would measure the drift failed its gate.

In plain words. The jets can push but cannot pull. To start the spin, the jets on one side fire; to stop it, the jets on the other side fire. Both pushes have a sideways part in the same direction, because the car is on its side between them. So a jet roll also throws the car sideways, about 1.7 m/s here. The real car did drift sideways. The sim's autopilot fights the drift and keeps the car on its line.
sim/wall_flip_sim.py:60–66 nozzle positions and directions; 267–268 sideways law \(a_y\)

4.6 What the sim's roll did

Roll angle, roll rate and roll acceleration against time, sim against the minimum-jerk reference, with the video observations
Fig. 9. The half-roll. Teal: the sim. Purple dashes: the reference of §8. Orange bar and dot: the video (on its side 52.6–52.7 s, upright 53.1 s).

Reading Fig. 9. The reference meets the video: it passes 90° at 52.725 s and is upright at 53.10 s. The sim does not follow the reference closely. It passes 90° at 52.800 s, 0.075 s after the reference and 0.10 s after the end of the video's "on its side" interval. It passes upright at 53.00 s, overshoots to −34.3° at 53.18 s, and is still at −3.0° at 53.60 s. At 53.10 s, when the video shows the car upright, the sim is at −28.9°. Its peak roll rate is 9.02 rad/s against 7.854 rad/s, and its peak roll acceleration 39.8 rad/s² against 32.25 rad/s².

The cause. The attitude law of §8 has a natural frequency of 6 rad/s and damping 0.7, and it uses the reference rate \(\boldsymbol\omega_r\) but not the reference acceleration \(\dot{\boldsymbol\omega}_r\) (Known limits 7). The moment therefore rises only after an attitude error has built up, so the roll starts late, and the error then drives an overshoot. The valve lag of 20 ms adds to the delay. A feed-forward moment \(I\dot{\boldsymbol\omega}_r\) is the standard fix. It is not applied here, because this part does not change the sim. The landing tilt is still 0.0°.

Top: jet roll moment and I times roll acceleration against time. Bottom: magnitudes of jet, aero damping, gyroscopic and centre-of-pressure moments on a log scale
Fig. 10. Roll moment budget. Top: the jet moment and \(I_{xx}\dot p\) from the attitude record. Bottom, log scale: the size of each term in the roll equation.

Reading Fig. 10. The jet moment peaks at 26.0 kN·m and \(I_{xx}\dot p\) at 25.9 kN·m; the two curves lie on each other. This checks that the recorded attitude obeys the roll equation with no hidden term. The first pulse (FR + RR) peaks at 24.9 kN at 52.640 s (FR 13.4 kN, RR 11.5 kN, limit 33.0 kN), at \(\varphi = 157°\). The second pulse (FL + RL) peaks at 30.1 kN at 53.060 s (FL 15.5 kN, RL 14.6 kN), at \(\varphi = -21°\), that is, after the car has already rolled past upright. The lower panel shows that the jet moment is 2 to 3 orders of magnitude larger than every other term during the roll.

In plain words. The planned roll matches the video. The sim's autopilot follows it about 0.1 s late, turns too far (34.3° past upright) and needs half a second to settle. The cause is a simple feedback law with no "look-ahead" term. The jets supply all of the twist; nothing else comes close.
sim/wall_flip_sim.py:277 attitude law; 46 valve lag

4.7 The G gauge during the roll

Top: four lift-nozzle thrusts and the pressure limit. Middle: sim specific force against HUD G. Bottom: sideways speed, sim against open loop
Fig. 11. Forces in the flip. Top: the four lift nozzles and their pressure limit. Middle: the sim's specific force against the HUD G gauge. Bottom: sideways speed \(v_y\), the sim against the open-loop result of §4.5.

Fig. 11 (middle) shows a clear difference. During the roll, 52.35–53.10 s, the HUD shows 0.2–0.4 g; the sim shows 0.00–1.40 g. The roll pulses cause the sim's two humps.

Proposition 4 (a bound on the roll inertia from the gauge). Suppose the gauge shows the unfiltered size of the specific force, and the roll moment comes from the lift jets. A rest-to-rest turn by \(\pi\) in time \(T\) needs a peak \(|\ddot\varphi| \ge 4\pi/T^2\). If the gauge never exceeds \(G_{\max}\) during the roll, then

$$I_{xx} \le \frac{G_{\max}\,g_0\,m\,d\,T^2}{4\pi}$$

Proof. The rate starts and ends at zero, so it rises to some peak \(\dot\varphi_{pk}\) and falls back. Let \(\alpha = \max|\ddot\varphi|\). The rate cannot exceed \(\alpha t\) from the start or \(\alpha(T - t)\) from the end, so the angle turned is at most \(\int_0^T \alpha\min(t, T-t)\,dt = \alpha T^2/4\). It must equal \(\pi\), so \(\alpha \ge 4\pi/T^2\). By Proposition 2 the lift-jet force along \(z_b\) is then at least \(I_{xx}\alpha/d\) at that instant. The other jets push in the \(x_b y_b\) plane, which is perpendicular to \(z_b\), so they cannot reduce the size of the specific force. Hence \(G_{\max}\,g_0 \ge I_{xx}\alpha/(m d)\). Drag along \(z_b\) is at most 327 N in the roll, 1.4% of the weight; the bound neglects it. ∎

The numbers. With \(G_{\max} = 0.4\), \(T = 0.75\) s: \(I_{xx} \le 351\) kg·m². If the roll took \(T = 0.85\) s (one more video frame), \(I_{xx} \le 451\) kg·m². For the minimum-jerk shape itself, the bound is 243 kg·m². The estimate is 650 kg·m², and a uniform box of the car's size and mass gives 1,042 kg·m². So at least one of these is true:

  1. The G gauge does not show the unfiltered specific force. It may be filtered or averaged. The HUD altitude is already known to lag by 0.30 s (§10).
  2. The roll inertia is at most about half of the estimate (351 / 650 = 54%).
  3. Part of the roll comes from something other than the lift jets, for example a moment applied before the car leaves the ceiling.

An example of the third case: if one side's suction let go first, the still-attached wheel line would act as a hinge. Gravity's normal part about that line, \(0.985\,mg_0 \times d = 19.3\) kN·m, would then start the roll with \(8.22\) rad/s² (inertia about the hinge 2,348 kg·m²) and no jet force. The record has no evidence for or against this.

In plain words. If the jets alone turned the car, the G gauge should have jumped to about 1 G twice during the roll. It stayed at 0.2–0.4 G. Either the gauge smooths its value, or the car is much easier to turn than estimated, or something else helped start the roll.
Computed in out/physics/flip.py (HUD readings from data/hud_wall_flip.csv)

4.8 Aerodynamics along the sim's path

Dynamic pressure. The airspeed is 8.13 m/s at release and 14.10 m/s at the burn. So \(q = \tfrac12\rho V^2\) goes from 39.6 Pa to 119.2 Pa. For scale, the car's weight spread over its 9.40 m² plan area is 2,452 Pa. The air is weak during the flip.

Drag (in the sim). The largest drag force in the window is 929 N, 4.03% of the weight, at the burn, when the car falls fastest. During the roll the drag is at most 327 N.

Roll damping (not in the sim). A rolling car moves its floor, roof and sides through the air. Two simple models bound the moment.

  1. Cross-flow. A strip of the plan at lateral position \(y\) moves at \(p\,y\) normal to itself and feels a pressure \(\tfrac12\rho\,C_{D}\,(py)^2\). The moment of all strips is
$$M_{cf} = \tfrac12\rho\,L\,p\lvert p\rvert\left[C_{Dz}\frac{(W/2)^4}{2} + C_{Dy}\frac{(H/2)^4}{2}\right]$$

since \(\int_{-a}^{a} y^2|y|\,dy = a^4/2\). The drag coefficients come from the sim's own drag areas: \(C_{Dz} = 8.0/(L W) = 0.851\) and \(C_{Dy} = 2.0/(L H) = 0.370\). This gives \(M_{cf} = 1.257\,p|p|\) N·m.

  1. Slender wing. In the forward flow \(V\), a strip at \(y\) sees an angle of attack \(py/V\). Slender-wing theory gives a lift slope \(C_{L\alpha} = \pi A/2\) with aspect ratio \(A = W/L = 0.426\), so \(C_{L\alpha} = 0.668\). The moment is
$$M_{sw} = \tfrac12\rho V^2 C_{L\alpha}\,L\int_{-W/2}^{W/2}\frac{p y}{V}\,y\,dy = \tfrac12\rho\,C_{L\alpha}\,L\,\frac{2}{3}\Bigl(\frac W2\Bigr)^3\,V p = 1.257\,V p\ \text{N·m}$$

On the sim's path the peaks are 102 N·m and 119 N·m: 0.39% and 0.46% of the peak jet moment. If no controller corrected it, the sum of the two would change the roll angle by 2.51° over the roll. The two constants are equal by coincidence of the numbers, not by a physical rule.

Centre-of-pressure offset (not in the sim). The sim puts the aerodynamic force at the CG. Each 0.1 m of offset adds a moment of \(0.1\,|\mathbf F_{aero}|\): at most 93 N·m in the window, 0.36% of the jet peak, or 0.032 rad/s² in pitch.

Jet-induced lift loss in free air (not in the sim). A jet drags the nearby air with it, which lowers the pressure on the body around the nozzle. Kuhn, Bellavia, Corsiglia and Wardwell (NASA TM 102268, 1991, p. 5) give, for open air,

$$\frac{\Delta L_\infty}{T} = K_\infty\sqrt{\frac{S}{A_j}}\left(\frac{\Sigma\pi d}{d_e}\right)^{1.58}\mathrm{NPR}^{-0.5}, \qquad K_\infty = -0.00010$$

with \(S\) the plan area, \(A_j\) the total jet area, \(\Sigma\pi d\) the total jet perimeter, \(d_e\) the diameter of one jet with the total area, and NPR the nozzle pressure ratio. For one active pair (two jets), \(\Sigma\pi d/d_e = \sqrt2\,\pi\). The jet diameter is not known. The throat is 22.6 mm; ideal expansion from NPR 536 to 1 bar gives an exit Mach number of 5.01, an area ratio of 25.2 and an exit of 114 mm. The result is \(\Delta L_\infty/T = -0.10\%\) to \(-0.55\%\), at most 131 N on a 24 kN pair. The suckdown data in the 1985 survey were taken at NPR 1.45–2.4 (NASA TM 86825, Figs. 3 and 9); here the NPR is 435–536, 181 to 370 times larger. Take the value as an order of magnitude only.

Horizontal bar chart on a log scale of the peak size of seven small terms as a percentage of weight or of the peak jet roll moment
Fig. 12. The small terms on the sim's own path. Force terms as a percentage of the weight; moment terms as a percentage of the peak jet roll moment (26.0 kN·m). Each label says whether the sim contains the term.
In plain words. At 8–14 m/s the air pushes on the car with about 4% of its weight. The air also resists the spin, but with about 0.5% of what the jets apply. The sim leaves those out, and they would change the roll by about 2.5° if nobody corrected it. The jet-induced suction in open air is smaller still.
sim/wall_flip_sim.py:43 drag areas; 290 drag force

4.9 The jets and the ceiling

Where the exhaust goes. The lift nozzles push along \(+z_b\), so their exhaust leaves along \(-z_b\). Upside down, \(-z_b\) points up, at the ceiling. The sim's first lift thrust above 0.5 kN comes at 52.400 s, when the CG is at \(x = -11.66\) m, already 0.2 m past the hud lip (\(x = -11.46\) m). The rear nozzles are 1.4 m behind the CG, so the rear right nozzle (RR) is still under the ceiling.

The geometry in the sim. In the hud variant, the axis of the RR exhaust meets the ceiling from 52.40 to 52.56 s, at 0.36–0.87 m from the nozzle, with up to 9.5 kN of thrust. In the short variant it meets the ceiling only from 52.40 to 52.42 s, with at most 1.2 kN. No other lift nozzle points at the ceiling while it fires.

The physics. A jet that hits a nearby surface spreads along it as a wall jet. The wall jet drags air out of the gap between the body and the surface, and the low pressure in the gap pulls the body toward the surface ("suckdown"). Here the surface is the ceiling, so the pull is upward, against the RR thrust, which pushes the car down and starts the roll. The pull therefore reduces both the push and the roll moment of RR. For a single jet in hover over a large ground board, Wyatt's correlation (Kuhn and Eshleman, NASA TM 86825, 1985, Fig. 2) is

$$\frac{\Delta L}{T} = -0.012\left(\frac{h}{D - d}\right)^{-2.3}$$

where \(h\) is the height of the plan surface above the ground, \(D\) the effective diameter of the plan, and \(d\) the jet diameter. Its plotted data span \(h/(D - d) \approx 0.17\) to 1.5. For the car, \(D \approx 3.46\) m (circle of equal area) and \(d = 0.114\) m, so the range is \(h = 0.57\) to 5.02 m. At \(h = 0.57\) m, the correlation gives a loss of 70% of the jet thrust. The real gap during the event is 0.12 to 0.49 m, below the fitted range, where the formula gives more than 100%. The correlation cannot give a size here, for three reasons:

  1. It is for a hovering body over a still surface. Here the car slides along the ceiling at 8 m/s and falls away from it.
  2. It is for a large ground board. The ceiling is 3.3 m wide, less than the plan diameter of 3.46 m, and it ends at the lip, 1.22 m from the RR nozzle at 52.40 s.
  3. The gap is below the fitted range, and the NPR (435–536) is 181 to 370 times the 1.45–2.4 of the survey's data.

A scale for the effect. At the bottom of its range the correlation gives 70% of the thrust, and at \(h = 0.49\) m it gives 100%. So take full cancellation of the RR thrust as the scale: while its axis meets the ceiling, the RR impulse is 769 N·s, or 0.327 m/s of speed. Its roll part is 654 N·m·s, 12.8% of the angular impulse of one half of the roll. This is the only aerodynamic term in the window that could matter at the 10% level, and it is the only one that depends on the overhang variant: the hud ceiling exposes it for 0.16 s, the short ceiling for 0.02 s.

In plain words. When the first jets fire, the car is upside down, so they blow up at the last part of the ceiling. A jet blowing at a nearby wall sucks the body toward that wall. Here that would pull against the jet that starts the roll. Standard formulas for this effect do not fit a car sliding past a narrow ceiling edge. If it cancelled that jet completely, it would take away about one eighth of the start-up spin, and only with the longer ceiling.
Computed in out/physics/flip.py; ceiling geometry from sim/wall_flip_sim.py:314–320

4.10 After: into the burn, and what the model captures

Into the burn. By 53.40 s the release pitch of −10° is gone in the reference (the sim shows +0.87°). At 53.90 s the sim is upright within 2°. From release to the burn, the jets use 58.6 kg of gas. By thrust impulse, the front pair (braking and yaw) takes 48%, the lift nozzles (the roll and its correction) 42%, and the rear nozzles 10%. At 53.95 s the four lift nozzles open together for the burn of §8.

What the model captures.

What it misses, and where it is discussed.

Reproduce

python sim/wall_flip_sim.py — runs both phases in about 3 s, prints the report, writes out/replay_data.js and runs the self-check. Add short for the short overhang (this also rewrites out/replay_data.js).

python out/physics/make_charts.py — about 30 s. Imports the sim module (the same code and data that write out/replay_data.js), prints every derived number on this page, the free-fall fit and the sensitivity table, and writes the six PNG charts in out/physics/.

python out/physics/flip.py — about 5 s. Part 4: imports the sim module without changing it, prints every number of Part 4 and writes the six flip_*.png figures.

Charts: matplotlib; colours checked for colour-blind separation on the dark card colour. Math: KaTeX 0.16.9 (needs internet).