Determining Yaw, Pitch and Roll
from
Up and Forward Vectors

by

J. L. Doty

Copyright © 2009–2016 by J. L. Doty

Contents

Basics

Notational Conventions

Determining Yaw and Pitch

Determining Roll

Singularities

 

Basics

In 3D programming the conventional wisdom is that one should avoid Yaw, Pitch and Roll (YPR) at all costs and use 3D rotation matrices and/or the Up and Forward (UF) vectors of a first-person camera. But the fact remains that coding the UF vectors of a first-person camera requires frame-to-frame incremental adjustment of YPR, making it nearly impossible to avoid YPR. Hence, the ever present need to convert between UF and YPR, or between a rotation matrix and YPR. And, as will be shown in this article, the conversion algorithms are quite robust. That said, the one real problem with YPR is singularities.

This article is not going to teach anyone the basics of vectors. If you don’t understand the basics of vectors and 3D coordinate space, go away and learn them before reading this article. Furthermore, this article limits itself to the 3D conventions established in the DirectX® programming environment:

  • The x-y-z coordinate system is left-handed,
  • Yaw, Pitch and Roll are rotations about the y, x and z axes respectively, meaning image001, image002, and image003, and
  • given a set of YPR values, the order of rotation is Roll first, followed by Pitch, then Yaw.
  • zero YPR results in a Forward vector coincident with the z-axis, and an Up vector coincident with the y-axis.

However, converting to a right-handed coordinate system, OpenGL or any other geometry is relatively straightforward.

Notational Conventions

The vector notational conventions used in this article are:

  • image004is a scalar quantity with magnitude, but no direction.
  • image005is an arbitrary vector, with arbitrary direction and length.
  • image006is the magnitude, or length, of arbitrary vector image007, a scalar quantity.
  • image008is an arbitrary vector that has been normalized, with arbitrary direction and unit length.

Hence, the relationship:

image009

eq. 1

image010 are orthonormal basis vectors that define a 3D coordinate system. Orthonormal means that all three vectors are of unit length, and all three are perpendicular to each other. We define an arbitrary vector as a sum of scalars and the orthonormal basis vectors:

image011

eq. 2a

image012

eq. 2b

The Forward and Up vectors simply define a local x-y-z coordinate system in the frame of reference of the camera. To complete that local coordinate system we’ll define a Right vector to go along with the Forward and Up vectors such that when image013, then

image014, image015, and image016.

Determining Yaw and Pitch

The first two quantities, Yaw and Pitch, are relatively easy to determine. Referring to figure 1, which illustrates the orientation of the Up and Forward vectors within the x-y-z coordinate system.

image017
Figure 1. Up and Forward Vectors

Pitch is the angle between the forward vector and its projection on the x-z plane, and Yaw is the angle between that projection and the z-axis. If the normalized Forward vector is defined as:

image018

eq. 3

then Pitch and Yaw are computed in the following way:

image019

eq. 4

image020

eq. 5

When coding equation 5 the Atan2(y, x) function should be used, which will handle Yaw in all four quadrants, and it prevents a divide-by-zero exception when image021.

Determining Roll

Roll is more problematic, and I’ve seen a number of articles on the internet that just plain get it wrong. At this stage they usually propose dividing a couple of numbers and using an inverse trigonometric function, a solution that is not always correct. I use a much more robust algorithm.

Many first-person cameras don’t maintain proper orthonormal Up and Forward vectors. This algorithm assumes that the Up and Forward vectors are orthonormal. If they are not, then they must be orthonormalized in the following way:

  1. Normalize the Forward vector using equations 1 and 2.
  2. Compute the Right vector by taking the cross product of the Up and Forward vectors: image022
  3. Normalize the Right vector using equations 1 and 2
  4. Compute the orthonormal Up vector by taking the cross product of the Forward and Right vectors: image023.

This produces a complete set of basis vectors in the local reference frame of the camera.

Now consider figure 2, which illustrates the geometry for rotation of the x and y axes about the z-axis, where image024 and image025 are the basis vectors before rotation, and image026 and image027 are the basis vectors after a rotation of image028.

image029
Figure 2. Z rotation geometry.

Keep in mind that these are local basis vectors that are defined in terms of our world basis vectors in the following way:

image030

eq. 6

image031

eq. 7

image032

eq. 8

image033

eq. 9

and it can be shown that the relationship between the two sets of basis vectors is:

image034

eq. 10

image035

eq. 11

These basis vectors, however, are in the frame of reference of the camera, looking down the camera’s z-axis, which is the Forward vector. image036 and image037 are the Right and Up vectors with Yaw and Pitch, but no Roll, while image038 and image039 are the Right and Up vectors with Yaw, Pitch and Roll. Furthermore, since image040 is the Up vector with no roll, we know that image041. However, while image042 is normalized, it is not orthonormal in the frame of reference of the camera, meaning it is not perpendicular to the Up and Forward vectors. So we must determine orthonormalized Right and Up vectors (image043 and image044) in the following way:

  1. image045
  2. then normalize image046 using equations 1 and 2, and
  3. image047

At this point we have computed image048, the Up vector for zero Roll, and we know image049, the present Up vector. Now we can simply determine image050 from:

image051

eq. 12

image052

eq. 13

However, equation 12 always results in a positiveimage053, even when the actual value is negative. So to remove the +/- ambiguity, invert equation 11 to produce

image054

eq. 14

and into equation 14 substitute equations 6, 7 and 9. The result yields a rather long vector equation with image055 components on both sides. However, for the right and left sides of the vector equation to be equal, each of the scalar values for the individual image056 components must be equal, resulting in the following three equations:

image057

eq. 15

image058

eq. 16

image059

eq. 17

All three of these equations hold true, and, using equation 12 to compute image060, we can use any of the above three equations to compute image061, and therefore image062, without the +/- ambiguity. All three will yield the same result, but for accuracy, and to prevent a divide-by-zero exception, test image063, image064 and image065, and use the equation that has the greatest absolute value in the denominator. Furthermore, there is no need to specifically test to prevent a divide-by-zero exception since, by definition, at least one of the three denominators will be finite and non-zero.

Singularities

One singularity must be accounted for, and that is the case where image066 and image067, resulting in

image068

eq. 18

image069

eq. 19

In most programming languages the Atan2(0, 0) function will return 0 for Yaw, when in fact Yaw is undefined under these circumstances. However, a decision must made as to how this singularity will be handled:

  1. Set Yaw to 0 and attribute the remaining object attitude to Roll, or
  2. Set Roll to 0 and attribute the remaining object attitude to Yaw

More often than not, scenario 1 is adopted, and the Roll computation is carried out using

image070

image071

image072

or

image073

image074

image075

both of which result in

image076

eq. 20

One artifact of this singularity is that YPR values of (90°, 90°, 0) produce the same orientation as (0, 90°, -90°), and an object may occasionally experience a sudden flip from one to the other.