# Need help about simple car steering in 2D

This topic is 3748 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am trying to make the car turn in 2D. There is really no physics involved. It should be as simple as possible. I know I have to calculate the angular velocity. But all the tutorials I've found are complex for my case. All I need is the position and the heading vector after time dt. Let's say that I have the following information: - Position vector - Direction vector - Current speed (For now think that the car moves in constant speed. No acceleration) - Turning angle How can I find the next position and direction with the given info? Thanks, Yenal

##### Share on other sites
if you have the wheelbase, you're sorted.

you can find the point of rotation (O) given the turning angle and the wheelbase.

the rate of turn is also given by the equation.

w = V / r

r is calculated from the wheel turning angle. And so is the centre of rotation O.

##### Share on other sites

Position vector += Directrion vector * Current speed
Direction vector.x = Direction vector.x * cos (Turning angle) - Direction vector.y * sin (Turning angle)
Direction vector.y = Direction vector.x * sin (Turning angle) + Direction vector.y * cos (Turning angle)

Where Direction vector is the absolute orientation (and unit vector, of course), and Turning angle is relative to the Direction vector.

##### Share on other sites
Now I have to got to work. I'll check this out when I get back. Thanks for the help.

##### Share on other sites
You need to define what you mean by "turning angle" and even speed...

Bear in mind that the two front wheels will turn different amounts:

When the car is turning the normals to each wheel will all point towards one single point (as in oliii's diagram, but with an extra pair of wheels)

and

The inner rear wheel will rotate slower than the outer rear wheel (and the front wheels will go at different rotation speeds too) - so the inner side of the car travels slower than the outer side.

Anyway - to get your answer then you know that each wheel follows a circle, radius R. If you know the speed S of that wheel, you know how far along the circle it goes in a given period of time, t. Divide this distance by the circle circumference (2*pi*R), and multiply by 360 will give the car orientation change in degrees:

orientation angle change = (S * t / (2 * pi * R)) * 360

##### Share on other sites
What I mean by turning angle is the angle between the heading vector and the wheel. I am trying to solve Homicidal Chauffeur Problem. http://www.google.com/search?hl=en&q=homicidal+chauffeur . Before solving the problem I have to get the car moving so it can pursuit the pedestrian. This is not a 3D game. I don't simulate any wheels or anything. All I have is a sprite. Maybe I am underestimating the complexity of the car's movement.

##### Share on other sites
Quote:
 Original post by CybernatorHow about this? (haven't tested it, might be erroneous)Position vector += Directrion vector * Current speedDirection vector.x = Direction vector.x * cos (Turning angle) - Direction vector.y * sin (Turning angle)Direction vector.y = Direction vector.x * sin (Turning angle) + Direction vector.y * cos (Turning angle)Where Direction vector is the absolute orientation (and unit vector, of course), and Turning angle is relative to the Direction vector.

I don't think that would work because that's the regular rotation by the angle. I need a way to calculate the new direction vector. Thanks

##### Share on other sites
Ok I took it this far:

// ( mHeight * 0.75f ) -> this is my wheelbase, mHeight is the sprite's height.
float turningRadius = ( mHeight * 0.75f ) / ( 2.0f * cosf( TORAD( 90 - mMaxTurningAngle / 2 ) ) );

// This is the change in angle for the time elapsed.
float angularVelocity = ( ( mMaxSpeed * elapsedTime ) / ( 2.0f * PI * turningRadius ) ) * 360.0f;

// This is just for drawing the sprite
mRotationAngle += angularVelocity;

// I rotate the Direction vector by the amount of angularVelocity
mDirection = mDirection.rotateAboutGlobalZ( TORAD( angularVelocity ) );

// Here comes the problematic line
mPosition += ( mDirection * mMaxSpeed * elapsedTime );

As long as the simulation runs constantly this line works expected. But if the app stops for a while the elapsedTime becomes too high and car moves too much. How can I fix this behavior?

Maybe I can fix the issue by figuring out if the game is not running. In SDL when you drag the window it somehows stops rendering. But still this solution seems like frame rate dependent. Some help would be appreciated. Thanks.

Yenal

##### Share on other sites
I think I know what is wrong but I do not know how to formulate it. In each update, the car is moved in a straight line. This is fine as long as you have a solid framerate. But to be accurate the car's movement should follow the circle. Correct me if I am wrong. Thanks.

##### Share on other sites
I solved the problem like this:

void Game::Car::Move( float turningAngle, double elapsedTime )
{
if ( turningAngle == 0.0f )
{
mPosition += ( mDirection * float( elapsedTime ) * mCurrentSpeed );
}
else
{
// If the turning angle has changed then calculate the rotation center again
if ( mLastTurningAngle != turningAngle )
{
float angleToFindRotationCenter = 90.0f;
// Set the rotation center
//if ( turningAngle < 0.0f ) // Turning right
// angleToFindRotationCenter = -90.0f;

Vec3 tmpPosition = mPosition + ( mDirection * GetTurningRadius( turningAngle ) );
mRotationCenter.x = cosf( DEG2RAD( angleToFindRotationCenter ) ) * (tmpPosition.x - mPosition.x ) - sinf( DEG2RAD( angleToFindRotationCenter ) ) * (tmpPosition.y - mPosition.y);
mRotationCenter.y = sinf( DEG2RAD( angleToFindRotationCenter ) ) * (tmpPosition.x - mPosition.x ) + cos( DEG2RAD( angleToFindRotationCenter ) ) * (tmpPosition.y - mPosition.y);
mRotationCenter += mPosition;
}

// Calculate the angular velocity
float angularVelocity = ( ( mCurrentSpeed * float( elapsedTime ) ) / ( 2.0f * PI * GetTurningRadius( turningAngle ) ) ) * 360.0f;

// Update the car's direction
mDirection = mDirection.rotateAboutGlobalZ( DEG2RAD( angularVelocity ) );

// Update the current angle of the car, used in sprite drawing
mRotationAngle += angularVelocity;
if ( mRotationAngle > 360.0f)
mRotationAngle -= 360 * ( int( mRotationAngle ) / 360 );

// Calculate the new position
Vec3 tmpPosition = mPosition;
mPosition.x = cosf( DEG2RAD( angularVelocity ) ) * (tmpPosition.x - mRotationCenter.x ) - sinf( DEG2RAD( angularVelocity ) ) * (tmpPosition.y - mRotationCenter.y);
mPosition.y = sinf( DEG2RAD( angularVelocity ) ) * (tmpPosition.x - mRotationCenter.x ) + cos( DEG2RAD( angularVelocity ) ) * (tmpPosition.y - mRotationCenter.y);
mPosition += mRotationCenter;
}

// Assign the last turning angle
mLastTurningAngle = turningAngle;
}

I am sure this is not the most efficient way to do it. Comments are appreciated.

##### Share on other sites
you sure it's cos? for me it's a tangent.

tan(90 - a) = rad / wheelbase
-> rad = wheelbase * tan(90 - a)

and w = v / r

also remember that car have physical limits. They can't turn as fast as they want at high speed. so you can cap the angular velocity given the speed of turn, by for example, using the centrifugal force formulae.

the grip limit is usually a ratio betwee the upward force on the tyre and the longitudinal and side force on the tyre. exceed that, and the car will not turn steadily.

to make it even simpler, you can work with accelerations, and the grip limit would be the coefficient of the centrifugal force and longitudinal force (acceleration), against the gravity. The grip limit of a tyre in the region of 1.0.

-> (car_break_or_accel + centrifugal_accel) / grav < grip

float r  = car.wheelbase() * tan(pi/2 - car.steerAngle());float lf = car.forwardAcceleration(); // brake or accel pedalfloat sf = car.forwardVelocity() * car.forwardVelocity() * / r; // centrifugal accel : v^2 / rfloat slip = car.tyreGrip() * world.gravity() / (lf + sf); // slippageif (slip > 1.0f) slip = 1.0f;car.anglularVelocity() = car.steerAngle() * slip;

something like that. So if you turn the wheels violently at high speed, you'd understeer, just to keep car physics in check. You can also use that for the AI to throttle their inputs and predict how much they can steer, accelerate or brake around a corner.

EDIT : the real slip equation would be something like...

if((lf + sf) > grip * grav)....
turnRad = car.vel() * car.vel()) / (grip * grav - carAccel);
turnAngle = atan(turnRad / wheelbase) - pi/2;

if the grip is exceeded. Something similar. Putting on paper and solving it should be easy.