2
$\begingroup$

This is going to be difficult to describe, as I have no real concept of this sort of physics, so please bear with me. If this is too much or beyond the scope of this website, I apologize.

I am making a simple-ish driving simulator and I need a formula that I can use to determine the rotation of the vehicle for every frame. If the car's rotation is 90.0 degrees and the wheels are pointing 20.0 degrees to the right, that should mean I can use a simple polar offset to send it a distance of a toward 70.0 (90.0 - 20.0). This does not work when the car is not moving, or when the air resistance is large, like when the car is turning at high speeds, and I am not sure how I should be dealing with such factors. What I have works for now, but I need a more accurate solution.

What I have

What I have barely turns the car at low speeds, and allows it to turn on a dime at high speeds. This is the algorithm that I am currently using in pseudo-code.

    if (vehicle.engineCurrentRPM > vehicle.engineMaxRPM) vehicle.engineCurrentRPM = vehicle.engineMaxRPM;
    if (vehicle.engineCurrentRPM < -vehicle.engineMaxRPM) vehicle.engineCurrentRPM = -vehicle.engineMaxRPM; // This allows it to go full speed in reverse, which I can fix myself.

// The engineMaxRPM is from a Bugatti Veyron and is equal to 6000.0.
// That is 600.0 lower than the redline, and I did that on purpose.

vehicle.engineCurrentTorque = (vehicle.engineCurrentRPM * (922.0 / 2200.0));
// A simple formula that approximates the torque-rpm relationship. I only include this because torque _might_ be relevant.

differentialRatio = 4.0;
drag = 0.39;
gearRatio = 3.64;
grip = 1.0;
wheelRadius = (2.0 * 0.0254);
// 20 inch wheels converted to meters and set to 10%. I don't know why this is necessary, but it seems to be in all of the formulas I have seen
weight = 1995.806; // 4400 pounds * 0.453592 to get kilograms.
power = (vehicle.engineCurrentTorque * vehicle.engineCurrentRPM) / 5252.0; // HP = Torque x RPM ÷ 5252

// The variable "power" is unused, but there if you need it.

airResistance = 0.05 * (1.0 - drag);

tWheels = vehicle.engineCurrentTorque * gearRatio * differentialRatio;
f = (tWheels / wheelRadius);
vehicle.acceleration = (f / weight) * grip;

vehicle.object.rotation.z -= vehicle.wheelAngle * vehicle.acceleration * time;
float angle = vehicle.rotation.z;
angle *= M_PI; // The pi constant.
angle /= 180.0;

vehicle.velocity.x -= vehicle->acceleration * sin(angle) * time;
// The world is upside-down for some reason, so subtracting is necessary. This will be fixed!
vehicle.velocity.y += vehicle->acceleration * cos(angle) * time;
vehicle.velocity.z += 0.0;

vehicle.position.x += vehicle.velocity.x;
vehicle.position.y += vehicle.velocity.y;
vehicle.position.z += vehicle.velocity.z;

vehicle.velocity.x *= (1.0 - airResistance);
vehicle.velocity.y *= (1.0 - airResistance);
vehicle.velocity.z *= (1.0 - airResistance);
$\endgroup$
  • 2
    $\begingroup$ airResistance should affect the tangential acceleration, not the velocity, and your way of linking velocity, acceleration, and turning angle do not look right to me. $\endgroup$ – Mike Dunlavey May 12 '14 at 0:41
  • $\begingroup$ You have set airResistance twice and I don't see where you set airDensity: airResistance = 0.05; and airResistance = 0.05 * airDensity * (1.0 - drag); $\endgroup$ – LDC3 May 12 '14 at 0:42
  • $\begingroup$ @MikeDunlavey Thanks for letting me know. Do you happen to know of a good place to read about the correct technique? $\endgroup$ – Xcode_t May 12 '14 at 0:43
  • $\begingroup$ Also in real life, air resistance depends on the velocity squared. $\endgroup$ – LDC3 May 12 '14 at 0:44
  • $\begingroup$ @LDC3 Yeah, I completely forgot about that. airDensity is simply 1.0 right now. I was thinking I could use that for different elevations to simulate the decreased density. $\endgroup$ – Xcode_t May 12 '14 at 0:44
3
$\begingroup$

A few items I would do differently.

First - make sure everything is in SI units (you are mostly doing that by converting inches to meters etc). And don't try to get 6 digits of precision. 4400 pounds is 2000 kg, not 1995.806. Really.

Next, don't assume that a "unit of time" (in terms of your calculations of where the car is next) needs to be a second. Create a "time step" - call it deltaT or whatever you want. Then, when you compute the new velocity, position etc, you do things like

position.x = position.x + velocity.x * deltaT;
velocity.x = velocity.x + acceleration.x * deltaT;

You seem to be mixing this up - sometimes you multiply by time, at other times you don't.

Next, for the rotation of the car, you need the velocity, not the acceleration - and you need to take into account the length of the wheel base (because it is the combination of wheel base length, angle of wheels, and velocity, that determines the rate of turning). So instead of

vehicle.object.rotation.z -= vehicle.wheelAngle * vehicle.acceleration * time;

You need something like

omega = vehicle.wheelAngle * vehicle.speed / vehicle.wheelbase;

(note - this is a little bit approximate, since in reality the rate of rotation of the car would go to infinity if you have rear wheel drive and set the front wheels at 90 degrees, but you would get a finite answer if you did the same thing with the front wheels being driven. The above formula works OK for small angles - you can draw yourself a diagram to see what I am talking about).

And then you compute the new direction of the velocity with:

theta = omega * deltaT; // step change in direction
tempx = velocity.x * cos(theta) - velocity.y * sin(theta);
velocity.y = velocity.x * sin(theta) + velocity.y * cos(theta);
velocity.x = tempx;

Note that I created a temporary variable so we are using the "old" value of the X velocity during the computation of the rotation.

I hope this gives you a nudge in the right direction...

$\endgroup$
2
$\begingroup$

The angular velocity of the car equals the tangential velocity of the rear wheels divided by the radius of turn. $$\omega = \frac{v}{\rho}$$

The radius of turn is found from the steering geometry, but in general you can simplify it by $$ \rho = \frac{ \ell }{ \tan \theta} $$ where $\ell$ is the wheelbase of the car and $\theta$ is the steering angle.

Together they make $$\omega = \frac{v \tan\theta}{\ell} $$

This means that the angular acceleration is

$$ \dot{\omega} = \frac{\dot{v} \tan \theta}{\ell} + \frac{v \dot\theta}{\ell \cos^2 \theta} $$

where $\dot{v}$ is linear acceleration and $\dot{\theta}$ the rate of steering change.

If you have any questions on how to calculate $\dot{v}$ please ask another question.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.