Getting a vehicle to drive towards a point.

Started by
3 comments, last by GameDev.net 17 years, 6 months ago
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
Advertisement
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

.

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...
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);

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...

This topic is closed to new replies.

Advertisement