Skip to content

Instantly share code, notes, and snippets.

@tbrosman
Created May 9, 2020 19:46
Show Gist options
  • Save tbrosman/43c451f10cddd0826353ccf8af716898 to your computer and use it in GitHub Desktop.
Save tbrosman/43c451f10cddd0826353ccf8af716898 to your computer and use it in GitHub Desktop.
Vector-Quaternion Frame Example

Vector Quaternion Frame Example

The following is a concrete example of what happens when you concatenate two vector-quaternion "frames" (rigid body transformations). For the purpose of making this comprehensible, I'm leaving out a lot of the gritty details of quaternion multiplication.

Frame notation: <Rotation operator, Translation operator>.

Input frames:

A = <Rot(90, y), Trans(10, 0, 0)>
B = <Rot(90, x), Trans(0, 0, 5)>

And we want to calculate (and verify) the product:

C = A * B

As a starting point, we expand the frames into operators and vectors:

C * v =
<Rot(90, y), Trans(10, 0, 0)> * <Rot(90, x), Trans(0, 0, 5)> v =
<Rot(90, y), Trans(10, 0, 0)> * (Rot(90, x) * v + (0, 0, 5)) =
Rot(90, y) * (Rot(90, x) * v + (0, 0, 5)) + (10, 0, 0)

Quaternions for A and B

(x, y, z in the below are "unit x", "unit y", "unit z")

A, Rot(90, y): p = exp((pi/4)*y) = [cos(pi/4), sin(pi/4)*y] = (sqrt(2)/2)[0, y]
B, Rot(90, x): q = exp((pi/4)*x) = [cos(pi/4), sin(pi/4)*x] = (sqrt(2)/2)[0, x]

Equivalent quaternion-vector expression for C * v

p * (q * v * q' + (0, 0, 5)) * p' + (10, 0, 0)

Simplify the first Quaternion product:

q * v * q' = (vx, -vz, vy)

This is Rot(90, x). The intuition is that a rotation around the x axis leaves x fixed. The rotation itself can be interpreted as a rotation of the basis. If the x axis points out of the screen:

   y     y'--x
   |         |
z--x  =>     z'

New basis:

x' = x
y' = z
z' = -y

[x z -y] * (vx, vy, vz) =

[1 0  0][vx]   [ vx]
[0 0 -1][vy] = [-vz]
[0 1  0][vz]   [ vy]

Which leaves:

p * ((vx, -vz, vy) + (0, 0, 5)) * p' + (10, 0, 0) =
p * (vx, -vz, vy + 5) * p' + (10, 0, 0)

Simplify the second quaternion product for some input vector u (makes the calculations nicer):

p * u * p' = (uz, uy, -ux)

Intuitive picture with y pointing out of the screen:

y--x     x'
|        |
z    =>  y--z'

x' = -z
y' = y
z' = x

[-z y x] * (ux, uy, uz) =
[ 0 0 1][ux]   [ uz]
[ 0 1 0][uy] = [ uy]
[-1 0 0][uz]   [-ux]

Substitute u = (vx, -vz, vy + 5):

p * (vx, -vz, vy + 5) * p' = (vy + 5, -vz, -vx)

Original equation is now:

(vy + 5, -vz, -vx) + (10, 0, 0) =
(vy + 15, -vz, -vx) =
(vy, -vz, -vx) + (15, 0, 0)

Decomposing, this is the net-effect of:

<Rot(90, y) * Rot(90, x), Trans(15, 0, 0)>

If you turn the above rotations into matrices and multiply, it is easy to verify that the (vy, -vz, -vx) coming from the quaternion multiplication matches:

Rot(90, y) * Rot(90, x) * v =

[ 0 0 1][1 0  0][vx]
[ 0 1 0][0 0 -1][vy] =
[-1 0 0][0 1  0][vz]

[0  1  0][vx]   [ vy]
[0  0 -1][vy] = [-vz]
[-1 0  0][vz]   [-vx]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment