• Create Account

## Simple question concering rotation.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

13 replies to this topic

### #1Doublefris  Members

316
Like
0Likes
Like

Posted 02 April 2013 - 03:34 PM

Hello fellows of gamedev.net. I've been struggling with a bit of a problem on my AI.

Me and a friend are working on a space game. Our use-case is a basic kind of AI that will stop and turn to the player when the player comes near.
The problem as follows:

How do I find the (target) angular velocity that will rotate a ship towards a given point?

The knee-jerk solution would be to create a look-at rotation matrix, but this isn't an option. The ship must be rotated indirectly by changing it's target velocity.

I have looked in the book "Artificial Intelligence for Games, Second Edition", from page 180 and on, however this example use quaternions, not matrices like we do.

I guess the basic idea would be to align the ships z-axis with the vector between the two ships, however I don't know how to achieve this( my math skills are lacking )

Edited by Doublefris, 02 April 2013 - 03:39 PM.

### #2Álvaro  Members

20272
Like
0Likes
Like

Posted 02 April 2013 - 04:18 PM

This should probably be moved to "Math & Physiscs".

Why don't you use quaternions for this computation? It's much easier to do that way.

### #3deftware  Prime Members

1676
Like
0Likes
Like

Posted 02 April 2013 - 05:44 PM

I wrote this function for an aimbot project for a popular online game over a decade ago:

void VecToAngles( const float *forward, float *angles )
{
float	tmp, yaw, pitch;

if (forward[1] == 0 && forward[0] == 0)
{
yaw = 0;
if (forward[2] > 0)
pitch = 90;
else
pitch = 270;
}
else
{
yaw = (atan2(forward[1], forward[0]) * 180 / 3.14159);

if (yaw < 0)
yaw += 360;

tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);

pitch = (atan2(forward[2], tmp) * 180 / 3.14159);
}

angles[0] = pitch;
angles[1] = yaw;
angles[2] = 0;
}



The rest is history.

### #4Doublefris  Members

316
Like
0Likes
Like

Posted 03 April 2013 - 07:27 AM

This should probably be moved to "Math & Physiscs".

Why don't you use quaternions for this computation? It's much easier to do that way.

The main reason is our code base doen't have support for quaternions as of now. Furthermore I have never used quaternions before and therefore am not really comfortable with them. Anyway, do you really think the only suitable solution would be quaternions?

### #5Álvaro  Members

20272
Like
0Likes
Like

Posted 03 April 2013 - 07:56 AM

The main reason is our code base doen't have support for quaternions as of now. Furthermore I have never used quaternions before and therefore am not really comfortable with them. Anyway, do you really think the only suitable solution would be quaternions?

No, I don't think it's the only solution, but it's probably the easiest. If you stick to representing attitudes as matrices, figuring out the most natural transition between two attitudes involves some heavy math.

### #6before-it-was-popular  Members

546
Like
0Likes
Like

Posted 03 April 2013 - 12:13 PM

How do I find the (target) angular velocity that will rotate a ship towards a given point?

You can calculate the target angular velocity vector by taking the cross product of the current direction and the desired direction, and scaling according to the desired rotation speed.  That leaves the question of the ship's roll when it reaches the destination, though - if you care about that, this problem becomes more complicated.

### #7Doublefris  Members

316
Like
0Likes
Like

Posted 03 April 2013 - 12:45 PM

How do I find the (target) angular velocity that will rotate a ship towards a given point?

You can calculate the target angular velocity vector by taking the cross product of the current direction and the desired direction, and scaling according to the desired rotation speed.  That leaves the question of the ship's roll when it reaches the destination, though - if you care about that, this problem becomes more complicated.

this is a very nice solution seems to be working well so far. As for the roll, I think it's fine to have spaceship gravitate towards an 'up' vector, or I'll just figure something out

Edited by Doublefris, 03 April 2013 - 12:51 PM.

### #8Doublefris  Members

316
Like
0Likes
Like

Posted 04 April 2013 - 12:02 PM

The main reason is our code base doen't have support for quaternions as of now. Furthermore I have never used quaternions before and therefore am not really comfortable with them. Anyway, do you really think the only suitable solution would be quaternions?

No, I don't think it's the only solution, but it's probably the easiest. If you stick to representing attitudes as matrices, figuring out the most natural transition between two attitudes involves some heavy math.

Say, if we were to implement quatornions, what would be the basic steps used to get an angular velocity? Find the angular displacement vector that is the lowest?

### #9Álvaro  Members

20272
Like
0Likes
Like

Posted 04 April 2013 - 12:29 PM

Say, if we were to implement quatornions, what would be the basic steps used to get an angular velocity? Find the angular displacement vector that is the lowest?

You would take the logarithm of the ratio of the target attitude and the current attitude. This is a quaternion whose real part is 0; the other three components give you the angular velocity that, when applied for 1 second, will convert the current attitude into the target attitude.
#include <iostream>
#include <boost/math/quaternion.hpp>

typedef boost::math::quaternion<double> Q;

int main() {
Q a(0.0, 1.0, 0.0, 0.0);
Q b(0.0, 0.0, 1.0, 0.0);

Q ratio = b / a;
double scale = std::acos(ratio.R_component_1());
Q log_of_ratio(0.0,
scale * ratio.R_component_2(),
scale * ratio.R_component_3(),
scale * ratio.R_component_4());

std::cout << log_of_ratio << '\n';
}



Edited by Álvaro, 04 April 2013 - 12:30 PM.

### #10Doublefris  Members

316
Like
0Likes
Like

Posted 07 April 2013 - 03:46 PM

EDIT: actually nvm it, something else about my code was faulty ^^

Edited by Doublefris, 07 April 2013 - 04:16 PM.

### #11Doublefris  Members

316
Like
0Likes
Like

Posted 12 April 2013 - 09:01 AM

So I got it to work in XNA and it works beatifully, however using my own quaternion class or directx's quaternions the spaceship keeps 'flipping over' when you get behind on the Z axis it seems.  Is there something specific I'm doing wrong?

my basic algorithm is :

Quaternion q1 = (shipforward, 0.0f)

Quaternion q2 = (shipposition - LookAtPosition, 0.0f)

then get the angular velocity using the method you described. weird thing is it works very well in XNA but trying to port it to my c++ engine keeps bringing this annoying bug.

A reason I thought of is that my division operator is wrong? what is the exact implementation of the division operator here?

Edited by Doublefris, 12 April 2013 - 09:07 AM.

### #12Álvaro  Members

20272
Like
0Likes
Like

Posted 12 April 2013 - 02:54 PM

I am not sure what (something, 0.0f) means. What is the 0.0f?

### #13Doublefris  Members

316
Like
0Likes
Like

Posted 13 April 2013 - 10:06 AM

0.0f is simply the scalar( I guess real part) of the quaternion.

the f suffix means its a float.

5832
Like
0Likes
Like

Posted 13 April 2013 - 10:24 AM

What problems with flipping are you having?

If you set up a quaternion with just a vector part and the w part being 0 you get a 180 degree rotation around the axis specified in the imaginary part... probably not what you want.

If flipping means you interpolate "the long way round" you can get rid of that by doing a dot product (in 4d) of the 2 quaternions and negating one if the dot product is negative.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.