Confused! Need to compare headings

sipickles
Posts: 44
Joined: Thu Aug 07, 2008 6:57 am

Confused! Need to compare headings

Post by sipickles »

Hello,

I'd like to do some simple maths but have scrambled my head!

I have an object I want to steer to a waypoint.

I know the position of waypoint and object, hence a vector between the two.

I also know the quaternion representing the rotation of the object.

I need to know the vector this quaternion represents, so I can do a dot product between current heading and desired heading.

How do I get the heading from the quaternion?

Many thanks

Si
Dominik
Posts: 32
Joined: Fri Dec 19, 2008 2:51 pm

Re: Confused! Need to compare headings

Post by Dominik »

Well, in general, a rotation does not have one primary direction (except, maybe, the rotation axis, but that is no what you are looking for ;) )

However, if you define a primary direction d for your object ( most likely d = (0,0,1) ), you can simply rotate this direction by the quaternion to get a "heading".
sipickles
Posts: 44
Joined: Thu Aug 07, 2008 6:57 am

Re: Confused! Need to compare headings

Post by sipickles »

Thanks for the reply Dominik. That seems obvious now!

I tried it and am having some strange steering behaviour - the object is not heading towards the waypoint but wandering round randomly!

Here's my approach:

Code: Select all

void CModel::UpdateSteering( const float& timedelta )
{
	// Get waypoint position
	btVector3 targetPos = m_waypoints[m_currentWaypoint];
	
	// Get Model Position
	btTransform t;
	btMotionState* ms = m_body->getMotionState();
	ms->getWorldTransform(t);
	btVector3 modelPos = t.getOrigin();

	// Get current model heading
	// Model points down positive X axis, multiply this by quaternion
	m_heading = btVector3(1.0, 0.0, 0.0) * t.getRotation();
	
	// Calc vector from model to waypoint - desired model heading
	m_headingToTarget = targetPos - modelPos;
	m_headingToTarget.normalize();

	m_steer = m_heading.angle( m_headingToTarget );
	// Affect sensitivity of steering if desired
	//m_steer *=  DEBUG_STEER;
  
	// Still not sure if this acos is needed - bad performance with and without!
	m_steer = acos(m_steer);
	
	//Clamp
	//m_steer = _cpp_min(DEBUG_MAX_STEER, _cpp_max(-DEBUG_MAX_STEER, m_steer));

	// Perform the turn
	Yaw( m_steer * timedelta );

	if ( m_body->getLinearVelocity().length() < DEBUG_MAX_VELOCITY )
		Drive( -m_mass * DEBUG_DRIVE * timedelta );
}
I've been over and over the code and can't see why this doesnt work. Any kind help much appreciated....

Thanks

Si
Dominik
Posts: 32
Joined: Fri Dec 19, 2008 2:51 pm

Re: Confused! Need to compare headings

Post by Dominik »

sipickles wrote:

Code: Select all

m_heading = btVector3(1.0, 0.0, 0.0) * t.getRotation();
This line doesn't look right. First of all, transformations are applied the other way around. So if you want to rotate a point p by Rotation R, use p' = R * p instead of your p' = p * R
The second problem that may arise is the quaternion rotation. Usually, a point p is transformed by a quaternion q through p' = q * p * q^-1, or by Transforming q into a matrix. However, maybe bullet does that automatically in its vector-quaternion rotation, not sure about this... Still, the order is wrong. However, I am not sure if that is the cause of your problem.

Besides, the way you extract the heading is a little inefficient, since you do not have to start with a quaternion.
You first have a matrix, then extract the quaternion, and then use this to rotate a point. It would be easier to use the matrix in the first place;

Code: Select all

m_heading = t.getBasis() * btVector3(1.0, 0.0, 0.0);
Now, we can even simplify it even more since (0,0,1) is a unit vector, and R*e_i is the ith column of R

Code: Select all

m_heading = t.getBasis().getRow(2)