Wednesday, 26 August 2015

About aeronautic coordinates

Often confused with Euler angles, aeronautic coordinates are useful in games (even if you're not writing a flight simulator)

Used in 3D applications, Euler angles 'in general' often become an endless source of surprise, confusion and pain. In contrast, aeronautic coordinates use well defined conventions

Please assume a vehicle's nose (think of a plane) is pointing towards Z positive, and its right wing is lying along the X axis. Many game developers find this orientation intuitive.

Aeronautic coordinates, consist in pitch, yaw and roll, also known as atttidue, heading and bank.
In some litterature you will find the term 'attitude' used to refer aeronautic coordinates altogether.

Unity3D implementation => [source]

Useful definitions.

  • Pitch/Attitude - an angle indicating whether a vehicle is flying upwards or downwards. 
  • Yaw/Heading - an angle indicating a vehicle's general direction/course. In the real world, cardinal points (north, south, east, west) are often used to refer a vehicle's heading but this is unpractical when dealing with computers.
  • Roll/bank - an angle indicating whether a vehicle is tilted or not. For example, a plane is 'tilted' when their wings do not lie in the horizontal plane. 

Calculations

While there are many ways to extract aeronautic coordinates from a transform, and quite possibly several correct ways to do so, I will suggest an approach which I hope you will find safe and intuitive. 

I assume that you have access to the forward, right and up vectors associated with your transform.

Then you can use the following recipes:

Pitch:
   Return -asin( forward.y )

Yaw:
   Let F be the ground projection of the forward vector.
   Let R be the ground  projection of the right vector
   If u is small/degenerate:
      Let α be the angle between R and the right vector (1,0,0)
      Return R.z<0 ? α : -α
   Otherwise... 
      Let α be the angle between u and the forward vector (0,0,1)
      Return F.x>0 ? α :-α

Roll
   Return -asin(right.y)

Important: Your forward, right and up vectors must be normalized.
Occasionally APIs return components (slightly) without the [ -1, 1 ] inclusive range. clamp right.y, forward.y to make sure that this doesn't happen, otherwise asin would return incorrect values.

Additional note

With some implementations, the heading is undefined when a vehicle is pointing straight up. This satisfies the (flawed) intuition that a vehicle pointing upwards isn't going north, east, west or south. It is a flawed intuition because, even when a plane is flying straight up, you can infer its heading from the position of its wings. The suggested recipe and linked implementation leverage this idea to avoid errors.

No comments:

Post a Comment