Normal and tangential coordinates

In the normal and tangential coordinate system, the (vector) equation of motion

\[ \sum \mathbf{F} = m \mathbf{a} \]

decomposes into the three scalar equations for the tangential (\(t\)), normal (\(n\)), and binormal (\(b\)) directons:

\[\begin{split} \begin{align} \sum F_t &= m a_t = m \dot{v} = m \ddot{s} \\ \sum F_n &= m a_n = m \frac{v^2}{\rho} \\ \sum F_b &= m a_b = 0 \;, \end{align} \end{split}\]

where \(F_i\) is a force in the \(i\) direction, \(m\) is the particle mass, \(v\) is the velocity, and \(\rho\) is the radius of curvature.

The tangential acceleration \(a_t\) is positive or negative in the direction of motion, the normal acceleration \(a_n\) is always positive in the normal direction, and the binormal acceleration \(a_b\) is always zero, because motion lies in the plane formed by the normal and tangential directions.

Example: race car at banking angle (no friction)

A Formula 1 race car of mass \(m\) = 740 kg is traveling on a track at constant velocity \(v\) = 60 m/s, where the radius of curvature is \(\rho\) = 400 m. What is the banking angle \(\theta\) necessary for the car to avoid sliding as it goes around this curve?

First, let’s draw a free-body diagram for the car:

Now, write the three scalar equations of motion for the car. The equation in the tangential direction does not really tell us much, since the car is moving at a constant speed in its direction of motion:

\[ \sum F_t = m a_t = m \dot{v} = 0 \;. \]

In the normal direction, the only force is the normal component of the resultant force:

\[\begin{split} \begin{align} \sum F_n &= m a_n \\ N_C \sin \theta &= m \frac{v^2}{\rho} \end{align} \end{split}\]

and in the binormal direction, we have both the component of the resultant force and also the car’s weight, but the binormal acceleration is zero:

\[\begin{split} \begin{align} \sum F_b &= m a_b = 0 \\ N_C \cos \theta - m g &= 0 \\ \rightarrow N_C \cos \theta &= m g \end{align} \end{split}\]

If we divide the latter equation from the former, we can solve for the banking angle:

\[\begin{split} \begin{align} \frac{N_C \sin \theta}{N_C \cos \theta} &= \frac{m v^2 / \rho}{mg} \\ \tan \theta &= \frac{v^2}{\rho g} \\ \therefore \theta &= \tan^{-1} \left(\frac{v^2}{\rho g} \right) \end{align} \end{split}\]

For the parameters given:

import numpy as np

mass = 740 # kg
velocity = 60 # m/s
rho = 400 # m
g = 9.81 # m/s^2

theta = np.arctan(velocity**2 / (rho * g))
print(f'theta ={theta * 180/np.pi: .2f}°')
theta = 42.53°

Example: race car at banking angle (with friction)

Now, consider the same situation, but account for the effect of friction, which will counter the car’s motion in the outward direction. What is the new banking angle needed to avoid the car sliding in this case? Assume the coefficient of static friction is \(\mu_s = 0.2\).

mu = 0.2

In this case, we now have to account for components of the friction force in the normal and binormal directions, where the friction force is

\[ f = \mu_s N_C \;. \]

In the normal direction, we have

\[\begin{split} \begin{align} \sum F_n &= m a_n \\ N_C \sin \theta + f \cos \theta &= m \frac{v^2}{\rho} \end{align} \end{split}\]

and in the binormal direction

\[\begin{split} \begin{align} \sum F_b &= m a_b = 0 \\ N_C \cos \theta - f \sin \theta - m g &= 0 \\ \rightarrow N_C \cos \theta - f \sin \theta &= m g \end{align} \end{split}\]

Combining the two equations (again, by dividing the first by the second) and recalling that \(f = \mu_s N_c\):

\[\begin{split} \begin{align} \frac{N_C \sin \theta + f \cos \theta}{N_C \cos \theta - f \sin \theta} &= \frac{m v^2 / \rho}{m g} \\ \frac{\sin \theta + \mu_s \cos \theta}{\cos \theta - \mu_s \sin \theta} &= \frac{v^2}{\rho g} \;. \end{align} \end{split}\]

This is our equation to find the banking angle, but unfortunately it has no closed-form solution. So, how do we find \(\theta\)? Using a numerical method!

Method 1: manual iteration

We could first attack this problem by manually guessing and checking different values of \(\theta\), until the left-hand side of the equation equals the right-hand side. For example, trying different values from 20° to 40°:

# need to convert to radians
vals = np.arange(20, 41, 2) * np.pi / 180

print('Theta   LHS    RHS')
for theta in vals:
    lhs = (np.sin(theta) + mu*np.cos(theta)) / (np.cos(theta) - mu*np.sin(theta))
    rhs = velocity**2 / (rho*g)
    print(f'{theta*180/np.pi: 4.1f}° {lhs: 5.3f} {rhs: 5.3f}')
Theta   LHS    RHS
 20.0°  0.608  0.917
 22.0°  0.657  0.917
 24.0°  0.708  0.917
 26.0°  0.762  0.917
 28.0°  0.819  0.917
 30.0°  0.879  0.917
 32.0°  0.943  0.917
 34.0°  1.011  0.917
 36.0°  1.084  0.917
 38.0°  1.163  0.917
 40.0°  1.249  0.917

So, clearly the correct value is between 30° and 32°. A bit more manual iteration shows that the correct angle is just about 31.2°:

theta = 31.2 * np.pi / 180

lhs = (np.sin(theta) + mu*np.cos(theta)) / (np.cos(theta) - mu*np.sin(theta))
rhs = velocity**2 / (rho*g)
print(lhs, rhs)
0.9166501382856723 0.9174311926605505

Method 2: root_scalar

Manually solving like this would be quite tedious; fortunately, there are numerical methods for solving scalar equations like this. We refer to this at root finding, since to solve we formulate the equation like \(F(x) = 0\), and find the value of the unknown variable that makes the function zero (i.e., the root).

In this case, we make the equation into the form

\[ F(\theta) = \frac{\sin \theta + \mu_s \cos \theta}{\cos \theta - \mu_s \sin \theta} - \frac{v^2}{\rho g} = 0 \;, \]

Then, to solve, we can use the root_scalar function provided in the scipy.optimize module, which needs us to provide it with a function that returns \(F(\theta)\) for candidate values of \(\theta\) (with the goal of finding the one that makes \(F(\theta)=0\)), along with a few guess values:

from scipy.optimize import root_scalar

def f(theta):
    '''This function evaluates the equation for finding theta.
    '''
    return (
        (np.sin(theta) + mu*np.cos(theta)) / (np.cos(theta) - mu*np.sin(theta)) -
        velocity**2 / (rho*g)
        )

sol = root_scalar(f, x0=(20*np.pi/180), x1=(40*np.pi/180))
print(f'theta ={sol.root * 180/np.pi: .2f}°')
theta = 31.22°