Skip to content

Instantly share code, notes, and snippets.

@danzimmerman
Last active January 25, 2024 18:30
Show Gist options
  • Save danzimmerman/222621cb5cc80ccbac5d3db6525082e6 to your computer and use it in GitHub Desktop.
Save danzimmerman/222621cb5cc80ccbac5d3db6525082e6 to your computer and use it in GitHub Desktop.
Quaternion Notes

Quaternion Notes and Cheatsheet

Basics

Following [1], which has further useful information.

A quaternion is defined in terms of its scalar part $w$ and vector part $\mathbf{v}$:

$\huge\mathbf{q} = (w,\hspace{0.5em}\mathbf{v}) = (w, x, y, z)$

Addition is just component-wise, or can be interpreted as adding the scalar parts and adding the vectors with usual vector math:

$\huge \mathbf{q}_a + \mathbf{q}_b = (w_a+w_b,\hspace{0.5em}\mathbf{v}_a + \mathbf{v}_b)$

In terms of three-dimensional vector operations, a quaternion product can be expressed as:

$\huge\mathbf{q}_a\mathbf{q}_b = (w_a w_b-\mathbf{v}_a\cdot\mathbf{v}_b,\hspace{0.5em}\mathbf{v}_a\times\mathbf{v}_b + w_a\mathbf{v}_b + w_b\mathbf{v}_a)$

Conjugation negates the vector part:

$\huge \mathbf{q}^* = (w, -\mathbf{v})$

The inverse of any quaternion is given by

$\huge \mathbf{q}^{-1} = \mathbf{q}^*/(\mathbf{q}\mathbf{q}^*)$

so for unit quaternions, the inverse is the conjugate.

Difference/Error Quaternion

Given two quaternions $q_A$ and $q_B$ we know that there is some composition rotation $q_d$ such that

$\huge q_B = q_d q_A$

This is true when the difference quaternion $q_d$ is [1]:

$\huge q_d = q_B q_A^{-1}$

SLERP

SLERP Formula

$$\huge \mathrm{Slerp}(\mathbf{q}_a, \mathbf{q_b}; t) = \mathbf{q_a}\frac{\sin{\Omega(1-t)}}{\sin{\Omega}} + \mathbf{q_b}\frac{\sin{\Omega(t)}}{\sin{\Omega}}; \cos{\Omega} = \mathbf{q}_b\mathbf{q}_a^{*} $$

SLERP Angular Velocity

By Theorem 1 in [1], part 3:

If $N(\mathbf{q}) = 1$ then $\mathbf{q} = (\cos\Omega, \hat{\mathbf{v}}\sin\Omega)$ acts to rotate around unit axis $\hat{\mathbf{v}}$ by $2\Omega$.

To find $\Omega$ we look at the quaternion log

$\huge ln(\mathbf{q}_b\mathbf{q}_a^{-1}) = \hat{\mathbf{v}}\Omega$

and, as noted,

$\huge \frac{1}{2}\mathbf{\omega} = \hat{\mathbf{v}}\Omega$

a fact that we back out from the definition of $e^{\hat{\mathbf{v}}\Omega}$

An explicit version of the quat log for any (non-unit) quaternion can be found in [2]:

$$\huge \ln(\mathbf{q}) = \begin{pmatrix} \ln(|\mathbf{q}|) \\ \frac{\mathbf{v}}{|\mathbf{v}|} \cos^{-1}\left(\frac{w}{|\mathbf{q}|}\right) \end{pmatrix} $$

Which is indeed a pure vector for unit quaternions.

📚References

[1] Quaternions - Ken Shoemake: https://campar.in.tum.de/twiki/pub/Chair/DwarfTutorial/quatut.pdf

[2] Notes on Quaternions - Simo Särkkä: https://users.aalto.fi/~ssarkka/pub/quat.pdf

🔗Misc Links

Some handling of edge cases https://gepettoweb.laas.fr/doc/stack-of-tasks/pinocchio/master/doxygen-html/explog-quaternion_8hpp_source.html#l00084

Other Rotation Notes

Rodrigues's Rotation Formula

A rotation matrix that takes normalized vector $\mathbf{a}$ onto normalized vector $\mathbf{b}$ [1], [2]:

$$\huge R = 2\frac {(\mathbf{a} + \mathbf{b})(\mathbf{a} + \mathbf{b})^T} {(\mathbf{a} + \mathbf{b})^T(\mathbf{a} + \mathbf{b})}-\mathbf{I}$$

TO-DO

Implement the other rotation formula in [1], which for dimension three, gives you the rotation perpendicular to the plane spanned by the two vectors.

📚References

[1] https://math.stackexchange.com/a/2672702

[1] https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula

def rodrot(a, b):
"""
Returns a rotation matrix that rotates vector a onto vector b
"""
ahat = 1.0*np.asarray(a)[:, np.newaxis] #float column vectors
bhat = 1.0*np.asarray(b)[:, np.newaxis]
for v in ahat, bhat:
v/=np.linalg.norm(v)
num = (ahat+bhat)@(ahat+bhat).T
denom = (ahat+bhat).T@(ahat+bhat)
if np.isclose(denom, 0):
return np.eye(3)
else:
return 2*num/denom-np.eye(3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment