{ "cells": [ { "cell_type": "markdown", "id": "bc6ab28e", "metadata": {}, "source": [ "## Quaternion\n", "Quaternion is a adding operator Group. It isn't a Field and the missing part is commutative of multiplication.\n", "\n", "#### Format\n", "$$\n", "q = a + bi + cj + dk\n", "$$\n", "\n", "#### Algebra\n", "$$\n", "i^2 = j^2 = k^2 = −1\\\\\n", "ij = k, ji = −k\\\\\n", "jk = i, kj = − i\\\\\n", "ki = j, ik = − j\n", "$$\n", "\n", "#### Conjugate\n", "$$q^* = a - bi - cj - dk$$\n", "\n", "\n", "#### Norm\n", "$$\\|q\\|=\\sqrt{a^2 + b^2 + c^2 + d^2}$$\n", "\n", "#### Inverse\n", "$$q^{-1} = \\frac {q^*} {\\|q\\|^2} = \\frac {a - bi - cj - dk} {a^2 + b^2 + c^2 + d^2}$$\n", "$$ qq^{−1} = q^{−1}q = 1$$\n", "\n", "#### Identity\n", "For adding group, the identity element is real number $0$.\n", "For multiplication, the identity element is real number $1$.\n", "\n", "\n", "#### Associativity \n", " The associativity holds for every $x, y, z \\in G$ in both adding and multiplication:\n", " $$x \\ast (y \\ast z) = (x \\ast y) \\ast z$$\n", "\n", "#### Distributive\n", "$$ p(q + r) = pq + pr$$ \n", "\n", "#### Commutative\n", "Only true for adding\n", "$$ p + q = q + p $$\n", "\n", "Not true for multiplication.\n", "$$pq \\neq qp$$\n", "\n", "DO NOT USE $p/q$ since it isn't clear whether it is $pq^{-1}$ or $q^{-1}q$. \n", " \n", " ## Quaternions for rotations\n", "\n", "#### Vector\n", " A vector in three-dimensional space can be expressed as a **pure quaternion**, a quaternion with no real part: $q = 0 + bi + cj + dk$. \n", "\n", "#### Rotation Matrix\n", "A rotation can be expressed by a quaternion $q$ if \n", "$$\\|q\\| = 1$$\n", "\n", "#### From quaternion to a rotation matrix\n", "A rotation from one coordinate frame $A$ to another frame $B$ is given by the conjugation operation of transform quaternion $q_R$ :\n", "$$q_B = q_Rq_Aq^*_R$$\n", "\n", "Assuming $q_A$ represent a vector or a point in $R^3$, we have\n", "$$\n", "q_A = xi + yj + zk \\\\\n", "q_R = a + bi + cj + dk\n", "$$\n", "The transform result is\n", "$$\n", "\\begin{split} q_B = q_Rq_Aq^*_R\n", "&= (a + bi + cj + dk)( xi + yj + zk )(a − bi − cj − dk)\\\\\n", "&= [x(a^2 + b^2 − c^2 − d^2) + 2y(bc − ad) + 2z(ac + bd)]i\\\\\n", "&+ [2x(ad + bc) + y(a^2 − b^2 + c^2 − d^2) + 2z(cd − ab)]j\\\\\n", "&+ [2x(bd − ac) + 2y(ab + cd) + z(a^2 − b^2 − c^2 + d^2)]k\n", "\\end{split}$$\n", "\n", "If we express this in a matrix formulation\n", "$$ q_B = Mq_A$$\n", "in which \n", "$$\n", "M = \n", "\\begin{bmatrix}\n", "a^2 + b^2 − c^2 − d^2 & 2(bc − ad) & 2(ac + bd) \\\\\n", "2(ad + bc) & a^2 − b^2 + c^2 − d^2 & 2(cd − ab) \\\\\n", "2(bd - ac) & 2(ab + cd) & a^2 − b^2 − c^2 + d^2\n", "\\end{bmatrix}\n", "$$\n", "\n", "#### From a rotation matrix of angles to a quaternion\n", "\n", "$$\n", "\\begin{split} Trace(M)\n", "& = M_{11} + M_{22} + M_{33} \\\\\n", "& = 2(3a^2 + b^2 + c^2 + d^2 - 1.5) \\\\\n", "& = 2(3a^2 + (1 - a^2) - 1.5 \\\\\n", "& = 2(2a^2 - 0.5) \\\\\n", "& = 4a^2 - 1\n", "\\end{split} $$\n", "\n", "We can solve this equation for $a$:\n", "$$|a| = \\sqrt\\frac{Trace(M) + 1} 4$$\n", "\n", "Once we have $a$, we can obtain $b$ from $M_{11}$\n", "\n", "$$M_{11} = 2(a^2 + b^2 - 0.5) = 2(\\frac{Trace(M) + 1}4 + b^2 - 0.5)$$\n", "\n", "$$|b| = \\sqrt{\\frac{M_{11}} 2 + \\frac {1 - Trace(M)} 4}$$\n", "\n", "Similarly, $c$ and $d$ can be computed from $M_{22}$ and $M_{33}$.\n", "$$|c| = \\sqrt{\\frac{M_{22}} 2 + \\frac {1 - Trace(M)} 4}$$\n", "$$|d| = \\sqrt{\\frac{M_{33}} 2 + \\frac {1 - Trace(M)} 4}$$\n", "\n", "#### From Euler angles to a quaternion\n", "The general logic is simple \n", "1. From Euler angels, construct its rotation matrix.\n", "2. Convert rotation matrix to quaternion." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 }