Sign in to follow this  
sipickles

Getting a vehicle to drive towards a point.

Recommended Posts

Hi, I have some simple vehicles driving about in the background of my app. They follow a sequence of waypoints. My problem is in the way I am getting the vehicles to decide if they need to turn left or right. Sometimes, due to the heading, they will turn all the way round left when they only needed to turn right, plus sometimes they think drive backwards! :) Heres my crude code:
// find the vector from present position to next waypoint
		D3DXVECTOR3 vec = m_lorryPath->GetWaypoint( m_lorryWaypoint ) - m_lorry->GetTranslation();
		float presentHeading = m_lorry->GetHeading();
		float goalHeading = atan( vec.z/vec.x );
		D3DXVec3Normalize( &vec, &vec );
		m_lorry->SetTranslation( m_lorry->GetTranslation() + vec * g_timeDelta * LORRY_SPEED );
// turn
                m_lorry->Yaw( ( presentHeading - goalHeading ) * g_timeDelta * LORRY_TURN_RATE);
		// Has it reached its waypoint?
		if ( m_lorryPath->CheckWaypoint( m_lorry->GetTranslation(), m_lorryWaypoint ) )
			m_lorryWaypoint = m_lorryPath->NextWaypoint( m_lorryWaypoint, true );

Obviously, its to do with atan returning a value from -PI to PI, or -180deg to 180deg. If the truck is on 175deg heading and needs to turn to 185deg, it will turn left 350deg. Can anyone suggest a more reliable way of doing this? Thanks Simon

Share this post


Link to post
Share on other sites
my guess is you need to calibrate the atan() result a bit, I was working on a similar (but 2D) game and I remember, I used a slightly modificated atan() calcs:



if (vec.x > 0)
goalHeading = atan(vec.z/vec.x) - 2*PI
else if ( vec.x < 0 )
goalHeading = atan(vec.z / vec.x) + 2*PI
else
goalHeading = 2 * atan( vec.x > 0 ? -1.0f : 1.0f );




possibly not accurate enough, as I write from memory, but I was having exactly the same vehicle turning problems.
maybe you should ask in the math board

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you use atan2() instead of atan() then it should give you a value in the correct quadrant, i.e. an angle between o and 360 degrees. Then you just need to work out which way to turn.


float goalHeading = atan2f( vec.z/vec.x );
float headingDifference = presentHeading - goalHeading;

if(headingDifference > PI)
headingDifference -= (PI * 2.f);
else if(headingDifference Yaw(headingDifference * g_timeDelta * LORRY_TURN_RATE);


...this is untested by the way...

Share this post


Link to post
Share on other sites
Whoops sorry - I forgot the code thingy


float goalHeading = atan2f( vec.z/vec.x );
float headingDifference = presentHeading - goalHeading;

if(headingDifference > PI)
headingDifference -= (PI * 2.f);
else if(headingDifference < -PI)
headingDifference += (PI * 2.f);

m_lorry->Yaw(headingDifference * g_timeDelta * LORRY_TURN_RATE);


Share this post


Link to post
Share on other sites
Guest Anonymous Poster
If you measure directions in the Cars Local Coordinate System
as opposed to a world compass heading angle
then you would not have this issue
plus it makes the car logic simpler and more encapsulated

Id reccomend tossing out angles entirely
just use the vector from the car to the waypoint, and internally to the car object evalute that...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this