Quaternions Vs Rotation Matrices: Math Options For Robust Rotation

Defining Rotation in 3D Space

Rotation is a key concept in computer graphics and visualization. At its core, rotation refers to changing the orientation of an object in three-dimensional space. There are two major approaches for mathematically representing rotations: Euler angles and quaternions.

Euler angles vs quaternion rotations

Euler angles represent a rotation as a sequence of rotations about the axes of a coordinate system. For instance, a rotation may consist of angles α, β, γ indicating rotations about the X, Y, and Z axes respectively. While conceptually simple, Euler angles can suffer from a problem called gimbal lock, leading to singularities in certain configurations.

Quaternions, on the other hand, use four dimensional vectors to encode rotations. This avoids the gimbal lock problem altogether, enables smooth interpolation between orientations, and is more numerically robust. However, quaternions are less intuitive to understand and implement than Euler angles.

Visualizing quaternion rotations

While Euler angles directly convey the axis and degree of rotation, visualizing rotations from quaternions is less straightforward. We can understand quaternion rotations by tracking how an initial vector transforms under the quaternion’s rotation. For example, applying a quaternion rotation to the vector (1, 0, 0) results in a new vector indicating the rotated X-axis direction.

Animating this vector transformation helps reveal the orientation encoded in the quaternion. Advanced visualizations like hyperspheres also directly convey a quaternion’s 4D coordinate. Both approaches aid in building intuition around this abstract representation.

Quaternions for Smooth and Robust Rotation

Avoiding gimbal lock with quaternions

Gimbal lock occurs when Euler angles become linearly dependent, leading to the loss of one degree of freedom. This causes erratic behavior in animation interpolations. Physically, gimbal lock corresponds to the alignments in certainCardan/gimbal mechanisms.

Quaternions avoid this problem by representing rotations independently of coordinate systems and rotation orders. The 4D quaternion components always remain linearly independent, ensuring smooth transitions regardless of orientation. This robustness makes quaternions the preferred choice for animating 3D objects.

Interpolating quaternion rotations

Interpolating between quaternion orientations is also straightforward. We simply linearly interpolate between the (x,y,z,w) components of two quaternions. This gives the smoothest transition by gradually morphing from one 4D rotation coordinate to the other.

In contrast, interpolating Euler angles requires special algorithms to avoid gimbal lock and discontinuities. Quaternions have no such difficulties, enabling easy implementation of fluid rotational animations.

Example quaternion rotation code

Here is some sample code for applying a quaternion rotation in JavaScript:

// q - quaternion rotation 
// v - 3d vector to be rotated

function rotateVector(q, v) {

  // Quaternion multiplication
  var t = 2 * Math.acos(q[3])
  var s = Math.sin(t/2)
  
  if (s != 0) {
    var x = q[0] / s
    var y = q[1] / s 
    var z = q[2] / s
  } 
  else {
    var x = 0
    var y = 0
    var z = 0
  }

  // Components of rotated vector     
  var vx = (x*x*v[0]) + (x*y*v[1] - z*v[2]) + (x*z*v[2] + y*v[1])
  var vy = (x*y*v[0] + y*y*v[1]) + (y*z*v[2] - x*v[0]) 
  var vz = (x*z*v[0] + y*z*v[1]) + (z*z*v[2] - x*y*v[1] - y*x*v[0])
     
  return [vx, vy, vz] 
}

This performs the quaternion-vector multiplication, giving the rotated vector output. The linear interpolation for orientation morphing is similarly straightfoward to implement.

Rotation Matrices as an Alternative

Building rotation matrices

Rotation matrices provide an alternative representation for orientations, using 3×3 orthogonal matrices rather than quaternions. We can construct these matrices directly from each axis of rotation:

function rotationMatrix(ax, ay, az, theta) {

  var ux = ax/Math.sqrt(ax*ax + ay*ay + az*az)
  var uy = ay/Math.sqrt(ax*ax + ay*ay + az*az) 
  var uz = az/Math.sqrt(ax*ax + ay*ay + az*az)

  var cT = Math.cos(theta) 
  var sT = Math.sin(theta)   

  // Components of the rotation matrix
  var r11 = cT + ux*ux*(1-cT)
  var r12 = ux*uy*(1-cT) - uz*sT
  var r13 = ux*uz*(1-cT) + uy*sT 

  var r21 = uy*ux*(1-cT) + uz*sT
  var r22 = cT + uy*uy*(1-cT)
  var r23 = uy*uz*(1-cT) - ux*sT

  var r31 = uz*ux*(1-cT) - uy*sT 
  var r32 = uz*uy*(1-cT) + ux*sT
  var r33 = cT + uz*uz*(1-cT)

  return [
    [r11, r12, r13],
    [r21, r22, r23],
    [r31, r32, r33]
  ]  
}

This directly sets up the rotation transform’s sin/cos components relative to the provided local axis and angle. The matrix can then be applied to transform vector directions.

Interpolating between rotation matrices

Interpolating between rotation matrices is less straightforward than quaternions, but can be done using Spherical Linear Interpolation (SLERP). SLERP performs interpolation along the hypersphere geodesic between two matrix orientations.

While more complex, this avoids the gimbal lock issues of interpolating Euler angles. The animations remain smooth regardless of initial and final orientations. However, quaternions still provide faster and simpler orientation interpolation.

Example rotation matrix code

Applying a rotation matrix transform to a vector can be done as:

// Rotate vector v by matrix R  

function rotateVector(R, v) {

  var vx = R[0][0]*v[0] + R[0][1]*v[1] + R[0][2]*v[2] 
  var vy = R[1][0]*v[0] + R[1][1]*v[1] + R[1][2]*v[2]
  var vz = R[2][0]*v[0] + R[2][1]*v[1] + R[2][2]*v[2]

  return [vx, vy, vz]  
}  

Where R is the 3×3 rotation matrix and v is the input 3D vector. The matrix multiplication gives the appropriately rotated output vector.

Choosing Between Quaternions and Matrices

Weighing performance vs simplicity

Both quaternions and rotation matrices have tradeoffs to consider. Quaternions are generally faster to normalize and interpolate. They also avoid gimbal lock issues altogether. However, rotation matrices are conceptually simpler, with transformations expressed as standard 3D linear algebra.

For applications emphasizing speed and smooth animation, quaternions tend to be preferable. If conceptual simplicity is more important, rotation matrices may be easier to reason about.

When to use each approach

In general, quaternions work well for interactive graphics requiring smooth animation transitions and interpolation. Flight simulators, FIRST-PERSON video games, and mechanical physics engines benefit from quaternion rotations.

For standalone orientation specification, rotation matrices can be easier to set up directly. Applications like robot kinematics may favor the straightforward matrix transforms. It also helps that most 3D tools have inbuilt support for matrix operations.

In the end, both approaches have merits depending on context. With their complementary strengths and weaknesses, quaternions and rotation matrices together provide flexible mathematical options for rotating objects in three dimensions.

Leave a Reply

Your email address will not be published. Required fields are marked *