TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
Optional: Aerodynamics and the Analytical Solution

This reading develops the cornering and braking models introduced in Chapter 3. Start with the pictures and the interpretations. The calculus section is optional; you can use its result without following every derivation step.

We are solving a model, not finding the universally shortest braking distance in TORCS. Assume straight-line braking on a level surface, constant effective grip and mass over the manoeuvre, and aerodynamic forces proportional to speed squared. The tyres must retain positive normal load; with lift, require \(mg+k_Lv^2>0\) over the interval. Real tyre behaviour, load transfer, banking, and actuator response still matter when driving.

1. Drag and downforce do different jobs

Drag acts against motion and directly helps remove kinetic energy. Downforce adds normal load at the tyres; in our simple friction model that increases the force they can transmit. It is not another backward force.

Wings can produce a force toward the ground. Flow beneath the car can also produce downforce, often called ground effect. Ride height changes that underbody flow, so the same car's aerodynamic behaviour can change as its suspension moves.

Side view showing backward aerodynamic drag and downward aerodynamic load as distinct forces

We collect the aerodynamic properties into two coefficients:

Frozen aerodynamic model

\[ F_D=k_Dv^2,\qquad F_L=k_Lv^2. \]

Positive \(k_L\) means downforce; negative \(k_L\) means lift.

Symbol Meaning Unit
\(k_D\) Drag-force coefficient including density and area kg/m
\(k_L\) Downforce coefficient including the chosen aerodynamic state kg/m
\(m\) Current mass used by the model kg
\(\mu\) Effective tyre/surface grip estimate Dimensionless

These \(k\) values are not the dimensionless textbook coefficients \(C_D\) and \(C_L\). For the familiar body-drag model, \(k_D=\tfrac12\rho C_D A\): dynamic pressure \(\tfrac12\rho v^2\), area, and shape together determine the force. Here \(\rho\) is air density in kg/m³, \(A\) is reference area in m², and \(C_D\) is the dimensionless drag coefficient.

2. Cornering with downforce

The normal load is now approximated by \(mg+k_Lv^2\). Repeating the inward-force balance from Chapter 3 gives:

\[\begin{aligned} \frac{mv^2}{R} &\leq \mu(mg+k_Lv^2),\\ v^2\left(1-\frac{\mu k_LR}{m}\right) &\leq \mu gR. \end{aligned} \]

For a positive denominator:

Aerodynamic cornering estimate

\[ v_{\mathrm{corner}}= \sqrt{\frac{\mu gR}{1-\mu k_LR/m}}. \]

Unlike the no-aerodynamics case, mass no longer cancels out.

Calculated cornering curves with and without downforce, both subject to a finite target cap

With downforce, the estimate increases. With lift, it decreases. If \(k_L>0\) and \(R\geq m/(\mu k_L)\), the denominator is zero or negative. The force inequality then supplies no finite speed bound under this model. It does not prove a real car can take the bend at any speed.

The implementation returns the gearing/redline search bound in that case, rather than dividing by zero or taking a square root of a negative number. For negative \(k_L\), it also keeps the cap below the model's loss-of-normal-load speed \(\sqrt{mg/(-k_L)}\). The ordinary corner margin still applies.

3. Add aerodynamic work to braking

The tyres can provide a braking force of approximately \(\mu(mg+k_Lv^2)\), and drag contributes \(k_Dv^2\). The total opposing force is:

\[ F_{\mathrm{brake}}(v)=\mu mg+(\mu k_L+k_D)v^2. \]

The energy difference is equal to the work over braking distance \(d\):

\[\frac{m}{2}(v_{\mathrm{in}}^2-v_{\mathrm{out}}^2) =\mu mgd+(\mu k_L+k_D)\int_0^d v(s)^2\,ds. \]

The integral is necessary because speed changes along the braking path. Using the starting speed throughout would overestimate the aerodynamic contribution.

For compact notation, define:

\[ a_0=\mu g,\qquad b=\frac{\mu k_L+k_D}{m}. \]

Then the deceleration magnitude is \(a(v)=a_0+bv^2\). The units are m/s² for \(a_0\) and 1/m for \(b\). We assume \(a_0>0\) and require positive deceleration throughout the speed interval. The usual downforce-and-drag case has \(b\geq0\).

4. A useful conservative approximation

For \(b\geq0\), deceleration is weakest at the final speed. Pretend that this weaker value applies throughout the braking manoeuvre:

One-interval distance estimate

\[ d_{\mathrm{bound}}= \frac{v_{\mathrm{in}}^2-v_{\mathrm{out}}^2} {2(a_0+bv_{\mathrm{out}}^2)}. \]

In the energy picture, this approximation replaces the area under \(v(s)^2\) by the smaller rectangle \(v_{\mathrm{out}}^2d\):

The area under squared speed during braking, compared with a smaller rectangle at the final squared speed

Underestimating the aerodynamic braking work produces a longer estimated distance. It is an upper bound within this model, not a guarantee about the complete simulator. If a signed coefficient gives \(b<0\), the weaker endpoint is instead the initial speed; the code uses the weaker of both endpoints.

Select BrakingModel::AeroBound in speed.cpp to try this model.

5. Refine the estimate numerically

A single rectangle can be crude over a large speed change. Divide the interval into smaller pieces and add their braking distances.

The code uses \(u=v^2\), with equally spaced boundaries \(u_0,\ldots,u_N\) from \(v_{\mathrm{out}}^2\) to \(v_{\mathrm{in}}^2\). Each piece contributes:

\[\Delta d_i= \frac{u_{i+1}-u_i}{2\min(a_0+bu_i,\ a_0+bu_{i+1})}, \qquad d_N=\sum_{i=0}^{N-1}\Delta d_i. \]

This keeps the conservative endpoint idea, but follows the changing deceleration more closely. With zero aerodynamic contribution, every subdivision gives the same constant-deceleration result.

Select BrakingModel::AeroNumerical, then try NUMERICAL_INTERVALS values of 1, 4, 8, and 32 in braking.cpp. More intervals reduce approximation error but cost more computation. No single interval count is equally accurate for every speed range and coefficient choice. Simpson or Romberg integration is another possible numerical approach; it does not automatically retain this upper-bound property.

6. Optional derivation: solve the model analytically

This is the complete analytical route. Only this section needs differential and integral calculus. Our initial condition is \(v(0)=v_{\mathrm{in}}\).

Step 1 — express deceleration per distance

From the force balance:

\[ \frac{dv}{dt}=-(a_0+bv^2). \]

Since \(ds/dt=v\), the chain rule gives:

\[ v\frac{dv}{ds}=-(a_0+bv^2). \]

Equivalently, differentiating the work-energy equation gives \(d(\tfrac12mv^2)/ds=-m(a_0+bv^2)\). These are the same model.

Step 2 — use squared speed

Let \(u=v^2\). Then \(du/ds=2v\,dv/ds\), so:

\[ \frac{du}{ds}=-2(a_0+bu). \]

Step 3 — integrate and apply the starting condition

For \(b\ne0\), separate the variables:

\[\begin{aligned} \int_{v_{\mathrm{in}}^2}^{u(s)}\frac{du}{a_0+bu}&=-2\int_0^s ds,\\ \frac{1}{b}\ln\left(\frac{a_0+bu(s)}{a_0+bv_{\mathrm{in}}^2}\right)&=-2s. \end{aligned} \]

Rearranging gives the squared-speed profile:

\[ v(s)^2= \left(v_{\mathrm{in}}^2+\frac{a_0}{b}\right)e^{-2bs}-\frac{a_0}{b}. \]

Use the nonnegative square root for forward speed. This profile describes the braking motion only until the car stops; extending it beyond that point would eventually produce a negative squared speed.

Step 4 — solve for the desired final speed

Set \(v(d)=v_{\mathrm{out}}\) and solve for \(d\):

Exact distance for this braking model

\[ \boxed{ d=\frac{1}{2b}\ln\left( \frac{a_0+bv_{\mathrm{in}}^2}{a_0+bv_{\mathrm{out}}^2} \right)}. \]

For \(v_{\mathrm{in}}\geq v_{\mathrm{out}}\geq0\) and positive deceleration throughout, the distance is nonnegative. The expression also works for a negative \(b\) while that domain condition holds. The code refuses a finite distance if deceleration reaches zero or becomes negative in the interval. The logarithm's argument is dimensionless, and \(1/(2b)\) supplies metres.

Step 5 — recover the simple formula

When \(b=0\), the differential equation becomes \(du/ds=-2a_0\). Therefore:

\[ v(s)^2=v_{\mathrm{in}}^2-2a_0s, \qquad d=\frac{v_{\mathrm{in}}^2-v_{\mathrm{out}}^2}{2a_0}. \]

This is exactly the main chapter's constant-deceleration model. The logarithmic formula approaches this result as \(b\to0\).

7. Turn the result into reliable code

Directly subtracting nearly equal squared speeds and then taking a logarithm of a number nearly equal to one loses precision. The implementation in braking.cpp uses the equivalent expressions:

\[\begin{aligned} \Delta u &=(v_{\mathrm{in}}-v_{\mathrm{out}})(v_{\mathrm{in}}+v_{\mathrm{out}}),\\ z&=\frac{b\Delta u}{a_0+bv_{\mathrm{out}}^2},\\ d&=\frac{\operatorname{log1p}(z)}{2b}. \end{aligned} \]

std::log1p(z) computes \(\ln(1+z)\) accurately for small \(z\). The code handles \(b=0\) explicitly and uses the small- \(z\) expansion \(\ln(1+z)/z=1-z/2+O(z^2)\) for very small terms. Equal speeds return zero.

Select BrakingModel::AeroAnalytical to use this implementation. For all optional models, the planner searches for the largest allowed approach speed whose calculated braking distance fits the available distance. That bounded search also works with the numerical approximation.

Equation-generated braking distances comparing no aerodynamics, one interval, eight intervals, and the analytical model

For \(b\geq0\), the no-aero estimate is longest, the one-interval aero estimate is shorter, and the analytical distance is shorter still. Subdivision approaches the analytical curve. At high speeds the opposing aerodynamic force grows with \(v^2\) too, so the distance no longer follows the simple quadratic growth of the no-aero model. This explains why the aerodynamic braking curves in the graph grow more slowly at high speeds.

The graph uses the printed illustrative coefficients. It is not a measurement of a particular TORCS car, and an exact model calculation does not promise a better lap time on every run.

For the same illustrative coefficients, slowing from 30 m/s to 15 m/s gives:

Calculation Distance
No aerodynamic contribution 56.25 m
One-interval aerodynamic bound 52.33 m
Eight conservative intervals 48.08 m
Analytical aerodynamic solution 47.51 m

This connects the worked example in the main chapter with the successive improvements. The difference between the last two rows is approximation error within the same model, not a difference between two measured laps.

The full distance depends on both speeds. The contour map below shows that two-variable dependence on a flat, labelled grid:

Analytical braking-distance contours over initial and final speed; the diagonal marks zero required braking

Pick an initial speed on the horizontal axis and a final speed on the vertical axis. The labelled contours show the model distance in metres. At or above the equal-speed diagonal, slowing down is unnecessary; that does not mean changing to a higher speed takes no time or distance.

8. Where the car coefficients come from

SpeedDriver::configure reads the current car parameter handle once per session. The helper follows the present force-model conventions, using both wings:

\[\begin{aligned} H&=1.5\sum_{i=1}^{4}h_i, & f_h&=2e^{-3H^4},\\ q_j&=1.23 A_j\sin\alpha_j,\\ k_L&=f_h(c_{\mathrm{front}}+c_{\mathrm{rear}})+4\sum_j q_j,\\ k_D&=0.645 C_x A_{\mathrm{front}}+\sum_j q_j. \end{aligned} \]

  • \(h_i\) are the configured ride heights, in metres.
  • \(f_h\) is the ride-height factor used for the body's ground-effect contribution.
  • \(A_j\) and \(\alpha_j\) are each wing's area and angle; angles returned in internal units are radians.
  • The sums over \(j\) include front and rear wings; \(q_j\) is that wing's contribution to the drag coefficient in this frozen model.
  • \(c_{\mathrm{front}}\) and \(c_{\mathrm{rear}}\) are the body's configured lift/downforce coefficients in the simulator's convention.
  • 0.645 corresponds to the body's density factor in the force model. The wing and ride-height constants are empirical model coefficients with the implied unit conversions; they are not universal laws of aerodynamics.

We freeze ride height and wing state at the configured values. During driving, pitch, suspension motion, airflow direction, damage, and other cars can change the actual forces. The current mass is updated as dryMass + car->_fuel, matching the mass term used by the simulator rather than introducing a second fuel-density conversion. As fuel is used, the same aerodynamic force acts on less mass, changing the cornering and braking estimates.

The driver additionally uses planning reserves. Its effective grip combines the lowest configured tyre coefficient with the relevant surface coefficient and GRIP_RESERVE. For braking, BRAKE_USAGE scales both \(a_0\) and \(b\); for cornering, CORNER_MARGIN reduces the model speed. The distance margins remain active even with the analytical model.

Aerodynamic cornering is enabled in the supplied speed.cpp. Set AERO_CORNERS = false to compare the gravity-only model, then restore true. Compare one change at a time, then restore the defaults if the simple steering cannot follow the more ambitious targets.

What the model leaves out

The derivation does not fully describe front/rear load transfer, brake balance, load-sensitive tyre grip, tyre temperature and wear, changing ride height, wheel rotational energy, road gradient, or combined braking and cornering. Some forces also depend on airflow and vehicle orientation rather than forward speed alone. Those are reasons to retain margins and observe the car.

The analytical result is exact within its assumptions. Numerical agreement checks the mathematics; driving checks whether the approximation is useful.

Return to Chapter 3, or visit Questions and feedback.