Writing a physics engine (Part 2.1: Rotations and orientations)


Intro

Now that we just learned about generalized coordinates, we know that free rigid objects in 3D have 6 DOFs. The natural next question is “which degrees of freedom should I choose?” For representing positions, this is super easy, just choose \((x,y,z)\) and call it a day. It’s more tricky for rotations.

In my opinion, this is the most frustrating part of 3D simulations: how to represent rotations (and angular velocities). I still get tripped up when dealing with rotations. Which is annoying because it’s so fundamental. As I think this is the most annoying part of writing a simulation, I’m going to write this blog post first before we get to the arguably more interesting parts. I promise things get a lot more fun after this.

This blog post is a little rushed, I may come back to polish this up after finishing other posts.


What do we want out of a rotation representation?

Before we can even talk about the multiple different ways to represent a rotation/orientation, I think it’s important to realize what we want out of “rotation system.”

Start simple, say I have a cube in my simulation. Here’s a list of things that you might want to support in a physics engine:

  1. Simplicity: prefer fewer, interpretable values.
  2. Ability to apply transformations: e.g., where do the corners of a cube get mapped to after a rotation?.
  3. Handling of angular velocities: say my object is rotating. How does my angular velocity update my rotation? How do I compute an angular velocity given the time derivative of my rotation?
  4. Composing rotations: e.g., rotate an object with respect to a parent object.
  5. Limiting the range of rotations: self explanatory, this is necessary for limiting ranges of motions, like joint limits.

Brief recap: 2D

In 2D, rotations are very nice and simple: here’s a vector and a square both rotated by some angle \(\theta\).

Let’s look at how it handles our criteria:

  1. Simplicity: Just one angle (from \(0\) to \(2\pi\)) is needed to represent a rotation. Easy to interpret what this angle means.
  2. Ability to apply transformations. To find where a point \(p\) relative to the center of rotation gets mapped after the rotation, we apply the rotation matrix:

    \[p' = Rp, \quad\quad R = \begin{bmatrix} \cos \theta & -\sin \theta \\ \sin \theta & \cos \theta \end{bmatrix}\]
  3. Mapping to angular velocities: Converting to angular velocity is straightforward: \(\omega = \dot \theta = \frac{d \theta}{d t}\).
  4. Composing rotations: Composing rotations is as simple as adding an angle. Want to rotate by \(\frac{\pi}{6}\) degrees? Add it and you’re done.
  5. Limiting the range of rotations: Want the black side of the square to face up? Easy, just limit/clamp \(\theta\) to \((-\frac{\pi}{4}, \frac{\pi}{4})\).

Moving to 3D

Adding in one more dimension and moving to 3D can’t be much harder, right? Now, instead of one axis of rotation, there’s three axes of rotations. So it feels like the most natural thing to do would be to express rotations as three angles denoting rotations about three axes. The two popular methods of representing rotations this way are fixed angles and euler angles.


Rotation matrices

“Hey wait, I remember that all rotations can be expressed as a rotation matrix \(R\)! And the matrix has special properties such that it’s orthogonal (\(R^TR = I\))! Can’t we just use those?”

Rotation matrices are less intuitive (have to remember 9 numbers) and are hard to limit the ranges of motion (how would we do this)? Rotation, however, are super useful for composing rotations and applying transformations and will be used downstream in simulation, just not as the primary representation of a rotation.


Fixed angles (extrinsic rotations)

Here, we define three angles, call them \(\alpha, \beta, \gamma\). Together, these three angles will represent a rotation of \(\alpha\) about the \(x\)-axis followed by \(\beta\) about the \(y\)-axis, then \(\gamma\) about the \(z\)-axis. Remember that the order does matter, because rotations do not commute, but conventions change all the time so this is just a particular convention (X-Y-Z).

Euler angles (intrinsic rotations)

Rather than the axes staying fixed, imagine the axes are now attached to the body. This can feel more natural in many scenarios; for example, imagine a robot with a series of three hinge (1 DOF) joints. As the base/first joint rotates, the next two joints have now been rotated.

As shown in the figure above, the red axes represent the body-fixed (intrinsic) axes of rotation. The bold blue axes are fixed and do not depend on the body’s rotation (extrinsic).

This is a personal opinion, but I think it’s frustrating when people call fixed angle rotations as “extrinsic Euler angles”. Let’s keep the term “euler angles” to mean rotations about body axes only.

What’s the issue with Fixed and Euler angles?

It seems like Fixed and Euler angles handle everything we need:

  1. Simplicity: Three angles that make intuitive sense.
  2. Ability to apply transformations. Every set of \((\alpha, \beta, \gamma)\) can be converted into a rotation matrix by composing the relevant rotation matrices (compute \(R_x, R_y, R_z\)).
  3. Limiting the range of rotations: This is pretty straightforward, since we can just limit/clamp each of \((\alpha, \beta, \gamma)\).

However, if you’ve played around with cameras or robotics, you probably have heard of gimbal lock. Gimbal lock occurs when there is a loss of a “degree of freedom” (I’ll explain more).

This is unfinished, but I’ll come back later

Some people find it easier to build a visual intuition for gimbal lock. Think of the image above for instrinsic Euler angles. When two of the rotation axes line up (imagine \(\beta\), the second rotation, is 90 degrees; now).


Angle-Axis

A nice property of 3D rotations is that every 3D rotation rotation can be expressed as one rotation about a 3D vector.

Quaternions

Four numbers, but are always normalized.


Side note: People will often refer to the group of all rotations in 3D as the \(SO(3)\) group. If you’re interested in Algebra and Lie groups, this might be meaningful to you. I honestly don’t have anything to add besides that it is a cool name.

Next blog will come out next week, I’ll actually hold myself accountable this time.