I have a simple top down bike game that I'm trying to add steering to. I would like to know how I use the heading of the front wheel to determine the heading and velocity of the bike.

void Update ()
{
//Get input from user Vertical: 0 to 1, Horizontal -1 to 1
float forwardInput = Input.GetAxis("Vertical");
float sidewaysInput = Input.GetAxis("Horizontal") * m_steeringAmount;

// Turn front wheel
m_frontWheelTransform.localEulerAngles = new Vector3(0, sidewaysInput, 90);

// get speed and drag
float   speed           = m_velocity.magnitude;
Vector3 forwardDrag     = -m_forwardDragConstant * m_velocity * speed;

// calculate acceleration
float engineForce       = forwardInput * m_enginePower;
Vector3 forwardTraction = transform.forward * engineForce;
Vector3 forwrdForce     = forwardTraction + forwardDrag;
Vector3 acceleration    = forwrdForce / m_mass;

// update velocity and position
m_velocity += acceleration * Time.deltaTime;
transform.localPosition += m_velocity * Time.deltaTime;
}


I have tried to apply the bike velocity to the front and rear wheel and use the difference of there positions to determine the bike heading, but the forward drag make it confusing.

• I'm on my phone at the moment so I'll just give a brief answer: the wheels are tangent to a fictitious circle along which the bike goes, therefore making the bike turn. The center of the circle is at the intersection of the lines orthogonal to each wheel. If the wheels are both straight (the bike isn't turning) then these lines cross path infinitely far (they're parallel) resulting in a circle of infinite radius, i.e. A line. Eventually, this gives you the trajectory the bike should follow (the circle) or its curvature, whichever suits your needs. – jrsala Dec 21 '12 at 17:04
• Thanks for the answer madshogo. Could you have a look at the diagram I've added and tell me if that is correct. Red line is the bike heading. Cheers – user346443 Dec 21 '12 at 23:36
• Oh wait, the front wheel isn't tangent to the circle in your drawing. In my head, both wheels were tangent. That changes a few things. – jrsala Dec 22 '12 at 0:22
• Have you seen the Wikipedia page for bike physics? It has useful formulas for turn radius that take leaning into account. – sam hocevar Dec 22 '12 at 22:32

Ok, I'm back with results!

I tried two approaches:

• Using solids mechanics to derive a differential equation governing the movement of the centers of the wheels: the inputs of the system "bike" are the torque at the rear wheel and the angle of the front wheel, and the outputs are the kinematics of the centers of the wheels. But I gave up, it was hard!

• Trying to guess what happens from a geometric point of view when the rear wheel "pushes" the front wheel forward with the front wheel not straight. This method directly yields an equation of infinitesimal increments (see below) from which you can get an actual differential equation. I haven't tried manipulating this first equation to get the ODE but my guess is that I would have obtained that very same ODE using solids mechanics. It just feels right.

## Notations and hypotheses:

We are in the plane with basis vectors ex and ey.

A is the center of the rear wheel. B is the center of the front wheel. The length of the bike L is the distance between A and B. The angle between ey and the vector AB is φ. The angle between AB and the front wheel is θ.

## Intuitive rationale:

We suppose that, at a certain instant t, A(t) has a velocity V(t) colinear with AB. Therefore, for an infinitesimal timestep dt,

A(t+dt) = A(t) + V(t).dt.

We also suppose that, at time t, the front wheel doesn't drift, i.e. the speed of B is colinear with the direction of the front wheel, i.e. forms an angle θ with AB. We call the unit vector forming an angle θ with AB, i.e. the unit vector with the same direction as the front wheel.

Therefore, at t+dt,

B(t+dt) = B(t) + λ.Uθ

for a certain real, positive λ such that the length of the bike L is conserved:

distance( A(t+dt) , B(t+dt) ) = L

## Calculations:

This last equation translates to

norm²( B(t) + λ.Uθ - A(t) - V(t).dt ) = L²

but B(t), by definition, is A(t) + L.Uφ, so that λ must satisfy the equation

norm²( L.Uφ + λ.Uθ - V(t).dt ) = L².

The solution, of course, is independent from φ since the problem is the same when the bike points towards positive y. Therefore, if we call R the rotation matrix with angle , λ must be the positive solution of

norm²( L.ey; + λ.Uθ - R.V(t).dt ) = L².

After a few calculations, if we call v the norm of V, you get

λ = L.( sqrt( 1 - (sin(θ).(1-v.dt/L))² ) - cos(θ) ) + v.dt.cos(θ).

Here's the pseudocode I used to get the animation above (instead of using , I use u = U(θ+φ) because it was simpler):

// I start at i=1 because i=0 contains the initial values
for (int i=1; i<=N; i++)
{
// the array in which I stored the successive A points
Aarray[i] = Aarray[i-1] + dt*V;
float lambda = L*( sqrt(1 - (sin(theta)*(1-v*dt/L))**2) - cos(theta) )
+ cos(theta)*v*dt;
// the array in which I stored the successive B points
Barray[i] = Barray[i-1] + lambda*u;
// the AB vector normalized
AiBiUnit = (Barray[i] - Aarray[i])/L;
// Refreshing the velocity of A
V = v*AiBiUnit;
// Refreshing u.
// u is indeed a unit vector separated from AiBiUnit by an angle theta,
// so you get it by rotating the newly computed AiBiUnit by an angle
// of +theta:
u = AiBiUnit.rotate(theta);
}


If you repeat a lot and/or increase the steering angle, the trajectory is a circle, which is coherent, I believe.