Go Back   AC3D Forums > Technical > AC3D Developers
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

Reply
 
Thread Tools Display Modes
Old 17th May 2005, 12:34 AM   #1
briandavis
Junior Member
Member
 
Join Date: Jul 2004
Posts: 10
Default Determining roll, pitch, and yaw from a normalized vector

Hi,

As an exercise, I am taking the yaw and pitch angles of my simple
simulator and determining the 3D vector that those angles would create.

I am then wanting to take that vector and reverse the process to verify
the yaw and pitch angles. I've supplied my test code below, and as is
indicated by the output, you can see that neither attempt at retrieving
the original pitch and yaw were successful. In my world, X goes into the screen and Z is up.

Any help would be greatly appreciated!

Incidentally, I am planning to use this concept to 'walk' through a scene while looking at a particular point in 3d space.

Code:
#include "math.h"
#include "stdio.h"

float              PI = 3.141592654f;
float              Rad2Deg = 180 / PI;
float              Deg2Rad = PI / 180;

int main(int argc, char* argv[])
{
  float pitch = 10.0;
  float yaw = 98.0;

  pitch *= Deg2Rad;
  yaw *= Deg2Rad;

  float x, y, z;

  x = (float)(cos(pitch) * cos(yaw));
  y = (float)sin(yaw);
  z = (float)(sin(pitch) * cos(yaw));

  float len = (float)sqrt(x * x + y * y + z * z);

  float verify_pitch = (float)atan2(z, len);
  float verify_yaw = (float)atan2(y, x);

  printf("  verify_pitch = %0.5f  ,  pitch = %0.5f\n", verify_pitch,
         pitch);

  printf("  verify_yaw   = %0.5f  ,  yaw   = %0.5f\n", verify_yaw, yaw);

  scanf("done...\n");

  // yields the following output
  //   verify_pitch = -0.02416  ,  pitch = 0.17453
  //   verify_yaw   = 1.70833  ,  yaw   = 1.71042

  return 0;
}
Thanks for any insights into this problem.
briandavis is offline   Reply With Quote
Old 17th May 2005, 08:43 PM   #2
briandavis
Junior Member
Member
 
Join Date: Jul 2004
Posts: 10
Default Find yaw/pitch of one vector relative to another vector.

I've reworded my initial post to hopefully shed more light on what I'm attempting to accomplish.

This is a 3D problem that I am trying to solve. I have a scenario where I need to be able to travel in a direction (v) while maintaining a line of sight with a point in 3D space (u). However, one restriction is that the line of sight must be confined to a fixed viewing area. For instance, the camera traveling in the v direction is restricted so that it can only tilt up/down 45 degrees and turn left/right 50 degrees. If the point in 3D space is too far behind the camera, then the camera will no longer be able to point in the precise direction of the point, but it would point in the general direction of the point.

I've been tackling this problem for some time now, and conceptually, it is very easy to understand. The most confusing aspect to me is how to accurately calculate the angles for the yaw and pitch.

What I've done so far....

To determine the values for the camera's direction vector, I am taking the known yaw and pitch angles (my current heading) and calculating the x, y, z coordinates onto a unit sphere.

v.x = cos(alpha) * cos(beta);
v.y = sin(beta);
v.z = sin(alpha) * cos(beta);

This produces my direction vector in an already normalized form. I then take the point in space that I'm looking at and subtract my current position to create the vector, u, to the point in 3D space. I am not normalizing this vector.

Once I've created these two vectors, I attempt to get the yaw and pitch angles between them. To do this, I create a new vector, w, by subtracting u from v (so w = v - u). I then normalize that vector. I know that the yaw angle will be the asin of the y component of the w vector.

yaw = asin(w.y)

That yaw value can then be plugged in to my sphere equation to give pitch. Of course, I'll have to account for situations where cos(yaw) equals 0.

pitch = acos(w.x / cos(yaw))

However, the results that I'm seeing don't match what I am expecting to see. As an example... in some cases, a yaw angle of 82 might be calculated when I'm actually expecting 98. I know that this is due to the fact that my C compiler returns asin values in the range -PI/2 to PI/2, however I don't know how to deal with it.

Incidentally, I'm not as concerned with verifying whether or not the camera can actually position itself to view the point. That will be relatively easy. I included that in the description to help indicate *why* I need to know the exact values of the pitch and yaw.

Also, the roll angle at this point is 0, but I can't guarantee that it will always be so.

Does anyone have any experience with this type of problem? If so, any help would be greatly appreciated.

Thanks
briandavis is offline   Reply With Quote
Old 18th May 2005, 02:57 AM   #3
Andy
Administrator
Professional user
 
Andy's Avatar
 
Join Date: Jun 2003
Posts: 4,563
Default

I had this problem a long time ago. As you've discovered, using the trig will give you non 0-360 deg values. You'd need to work out the quadrants you are in. You'll also need to assume a default 'up' direction too. It's all a bit nasty.

How about a different method like maintaining your angles and generating a matrix when you need it? Or perhaps using gluLookAt? (you can always read stuff back out of the opengl matrix)

Andy
Andy is offline   Reply With Quote
Old 18th May 2005, 10:50 AM   #4
briandavis
Junior Member
Member
 
Join Date: Jul 2004
Posts: 10
Default

Quote:
Originally Posted by Andy Colebourne
I had this problem a long time ago. As you've discovered, using the trig will give you non 0-360 deg values. You'd need to work out the quadrants you are in. You'll also need to assume a default 'up' direction too. It's all a bit nasty.

How about a different method like maintaining your angles and generating a matrix when you need it? Or perhaps using gluLookAt? (you can always read stuff back out of the opengl matrix)

Andy
Can you elaborate on any of these? I'd sure appreciate it.

Thanks,
Brian
briandavis is offline   Reply With Quote
Old 18th May 2005, 11:18 AM   #5
Andy
Administrator
Professional user
 
Andy's Avatar
 
Join Date: Jun 2003
Posts: 4,563
Default

You can use something like this:

Code:
Prototype void person_turn_left(Person *person, float angle) //angle in degrees 
{
float m[16], m2[16];

	matrix4_set_rotation(-angle, 0, 1, 0, m);
	matrix4_multiply(m2, person->matrix, m);
	matrix4_copy(person->matrix, m2);
	person_set_direction_from_matrix(person);
}

Prototype void person_set_direction_from_matrix(Person *person)
{
	person->direction.x= person->matrix[2]; 
	person->direction.y= person->matrix[6];
	person->direction.z= person->matrix[10];
}

gluLookat is used to setup the 'camera' viewpoint in OpenGL, You pass it a location and a direction (which can be location + direction) and OpenGL does all the stuff to set the viewing matrix.

Andy
Andy is offline   Reply With Quote
Old 18th May 2005, 04:22 PM   #6
briandavis
Junior Member
Member
 
Join Date: Jul 2004
Posts: 10
Default

Thanks for the help. I'm still confused as to how I would retrieve the actual angles needed to perform this function. I need to know them so that I can test whether or not the object is actually viewable from my present position and orientation.

For example, suppose that you're watching an airplane as it flies overhead (well, hopefully overhead). However, you cannot turn your body or change the direction you are facing. All you can do is change the orientation of your head. Unless you're an owl, there's only so far that you can turn your head so that you can continue to watch the plane. After that, it simply disappears out of your view as it flies past your position.

The plane is the point in 3D space that I'm wanting to watch, so I know that direction vector. I also know the direction vector that I'm facing. What I need to determine are the angles (yaw and pitch) that are needed in order to actually look at the plane. If these angles exceed my head's maximum turning angles, then I cannot look at the plane.

Thanks again for the help.
briandavis is offline   Reply With Quote
Old 20th May 2005, 05:40 AM   #7
Andy
Administrator
Professional user
 
Andy's Avatar
 
Join Date: Jun 2003
Posts: 4,563
Default

How about using dot products on coordinate pairs of the 3d vectors i.e. 2d dot products. This might give you angles in those planes?

Andy
Andy is offline   Reply With Quote
Old 26th December 2016, 08:00 PM   #8
jentron
Senior Member
Professional user
 
Join Date: Nov 2007
Posts: 139
Default Re: Determining roll, pitch, and yaw from a normalized vector

Code:
#include "math.h"
#include "stdio.h"
#include "stdlib.h"

float              Rad2Deg = 180 / M_PI;
float              Deg2Rad = M_PI / 180;

int main(int argc, char* argv[])
{
  float pitch;
  float yaw;

  if (argc != 3){
        fprintf(stderr, "USAGE:\n%s pitch yaw\n", argv[0]);
        return(-1);
  }

  pitch = atof(argv[1]);
  yaw   = atof(argv[2]);

  pitch *= Deg2Rad;
  yaw *= Deg2Rad;

  float x, y, z;

  x = (float)(cos(pitch) * cos(yaw));
  y = (float) sin(pitch);
  z = (float)(cos(pitch) * sin(yaw));

  float len = (float)sqrt(x * x + z * z);

  float verify_pitch = (float)atan2(y, len);
  float verify_yaw = (float)atan2(z, x);

  printf("  verify_pitch = %0.5f  ,  pitch = %0.5f\n", verify_pitch, pitch);
  printf("  verify_yaw   = %0.5f  ,  yaw   = %0.5f\n", verify_yaw, yaw);
  return 0;
}
For posterity. In the function above, Y is up, X is yaw 0, Z is yaw 90.

In Brian's original code he did:
Code:
float len = (float)sqrt(x * x + y * y + z * z);
He said himself the vector is normalized, so that formula always returns 1. We need to exclude the value that is not multiplied by the cosine.

atan2() selects the correct sector, but in most implantations it returns +/- 180 degrees, not 0-360 degrees.


P.s.
Sorry for the necropost, but I'm just reviewing my trig and vector math over the Christmas break.
jentron is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



All times are GMT -4. The time now is 01:24 AM.


AC3D Forum
(C) Inivis Limited 2020