四元数

四元数笔记

Posted by 武龙飞 on March 11, 2018

前言

在我刚开始做游戏的时候,在学习到三维物体旋转时第一次遇到四元数,那时候只学习到使用欧拉角旋转会遇到旋转死锁的问题,四元数可以解决。自己那时候学习了下四元数,感觉好难理解。最后照着Unity官方文档,只做到了会用,我在学习新东西时候总是想把原理搞个清楚,这样心里才会舒服。这个四元数的问题一直如鲠在喉,最近在看《游戏引擎架构》,对于里面每一个知识点都不想放过去,所以就有了这篇文章。

四元数

复数

要说明白四元数,首先得搞清楚复数的概念,数学家为了解决对负数开平方的问题,引入了复数。

\[z = a + bi\]

其中$i^2 = -1$

复数

如果将二维复数扩展到三维,就是四元数

\[q = s + xi + yj + zk\]

有序对表达式

\(q = [s, v]\)

v可以单独为组件

\(q = [s, xi + yj + zk]\)

加法

\(\begin{array}{rcl} q_a & = & [s_a,\mathbf{a}] \\ q_b & = & [s_b,\mathbf{b}] \\ q_a+q_b & = & [s_a+s_b,\mathbf{a}+\mathbf{b}] \\ q_a-q_b & = & [s_a-s_b,\mathbf{a}-\mathbf{b}]\end{array}\)

四元数乘法

\(\begin{array}{rcl} q_a & = & [s_a,\mathbf{a}] \\ q_b & = & [s_b,\mathbf{b}] \\ q_aq_b & = & [s_a,\mathbf{a}][s_b,\mathbf{b}] \\ &= &(s_a+ x_ai + y_aj + z_ak)(s_b + x_bi + y_bj + z_bk) \\ &= &(s_as_b - x_ax_b - y_ay_b - z_az_b) \\ & &+(s_ax_b + s_bx_a + y_az_b - y_bz_a)i \\ & &+(s_ay_b + s_by_a + z_ax_b - x_az_b)j\\ & &+(s_az_b + x_ay_b - y_ax_b + s_bz_a)k \end{array}\)

\(i = [0,i] ~~~ j = [0, j] ~~~~ k = [0,k]\) 实数部分用$[1, 0]$

\[\begin{array}{rcl} [s_a,\mathbf{a}][s_b,\mathbf{b}] &= &(s_as_b - x_ax_b - y_ay_b - z_az_b)[1, 0] \\ & &+(s_ax_b + s_bx_a + y_az_b - y_bz_a)[0, i] \\ & &+(s_ay_b + s_by_a + z_ax_b - x_az_b)[0, j]\\ & &+(s_az_b + s_bz_a + x_ay_b - y_ax_b)[0,k] \end{array}\]

展开

\[\begin{array}{rcl} [s_a,\mathbf{a}][s_b,\mathbf{b}] &= &[s_as_b - x_ax_b - y_ay_b - z_az_b, 0] \\ & &+[0,(s_ax_b + s_bx_a + y_az_b - y_bz_a)i] \\ & &+[0,(s_ay_b + s_by_a + z_ax_b - x_az_b)j]\\ & &+[0,(s_az_b + s_bz_a + x_ay_b - y_ax_b)k] \end{array}\]

虚数部分结合

\[\begin{array}{rcl} [s_a,\mathbf{a}][s_b,\mathbf{b}] &= &[s_as_b - x_ax_b - y_ay_b - z_az_b, 0] \\ &+&[0,s_a(x_bi + y_bj + z_bk) + s_b(x_ai + y_aj + z_ak) \\ &+&(y_az_b - y_bz_a)i + (z_ax_b - x_az_b)j + (x_ay_b - y_ax_b)k]\\ \end{array}\]

最终结果

\[\begin{array}{rcl} [s_a,\mathbf{a}][s_b,\mathbf{b}] &= &[s_as_b - x_ax_b - y_ay_b - z_az_b, \\ &&s_a(x_bi + y_bj + z_bk) + s_b(x_ai + y_aj + z_ak) \\ &+&(y_az_b - y_bz_a)i + (z_ax_b - x_az_b)j + (x_ay_b - y_ax_b)k]\\ \end{array}\]

当前设定

\[\begin{array}{rcl} \mathbf{a}~ = & x_ai + y_aj + z_ak \\ \mathbf{b}~ = & x_bi + y_bj + z_bk \\ \mathbf{a.b}~ = & x_ax_b + y_ay_b + z_az_b \\ \mathbf{a}\times\mathbf{b}~ = &(y_az_b - y_bz_a)i + (z_ax_b - x_az_b)j + (x_az_b - z_ax_b)k \end{array}\]

带入得到结果

\[\begin{array}{rcl} [s_a,\mathbf{a}][s_b,\mathbf{b}] = [s_as_b - \mathbf{a.b}, s_a\mathbf{b} + s_b\mathbf{a} + \mathbf{a}\times\mathbf{b}] \end{array}\]

实数四元数

\(\begin{array}{rcl} q & = &[s, 0] \\ q_a & = &[s_a, 0] \\ q_b & = &[s_b, 0] \\ q_aq_b & = &[s_as_b, 0] \end{array}\)

虚数四元数

\(\begin{array}{rcl} q & = &[0, v] \\ q_a & = &[0, v_a] \\ q_b & = &[0, v_b] \\ q_aq_b & = &[-v_av_b, v_a\times\mathbf{v_b}] \end{array}\)

共轭

\(\begin{array}{rcl} q & = &[s, v] \\ q^* & = &[s, -v] \\ qq^* &= &[s^2+v^2, 0] \end{array}\)

归一化

\(q^{\prime} = \frac{q}{\sqrt{s^2 + v^2}}\)

逆四元数

\(qq^{-1} = [1, 0]\) \(q^{-1} = \frac{q^{*}}{|q|^2}\)

点积

\(\begin{array}{rcl} q_1 & = & [s_1, x_1i + y_1j + z_1k] \\ q_2 & = & [s_2, x_2i + y_2j + z_2k] \\ q_1{\cdot}q_2 & = & s_1s_2 + x_1x_2 + y_1y_z + z_1z_2\\ \end{array}\)

余弦

\(cos{\theta} = \frac{q_1.q_2}{|q_1||q_2|}\)

旋转

2d 旋转

\(q = cos{\theta} + sin{\theta}i\)

3d 旋转

\(q = [cos{\theta}, sin{\theta}\mathbf{v}]\)

旋转

矢量p用四元数表示为纯虚数为:

\[p = [0, \mathbf{p}]\]

旋转四元数为:

\[q = [s, \lambda\hat{v}]\]

乘法

\[\begin{array}{rcl} p^{\prime} &=& qp \\ &=& [s, \lambda\hat{v}][0, \mathbf{p}] \\ &=& [-\lambda\hat{v}\cdot\mathbf{p}, s\cdot\mathbf{p} + \lambda\hat{v}\times\mathbf{p}] \end{array}\]

旋转例子一

绕$k$旋转45°

\[\begin{array}{rcl} p &=& [0, 2i] \\ q &=& [\cos{\theta}, \sin{\theta}\hat{v}] \\ \hat{v} &=& [0, k] \\ p^{\prime} &=&\left[\frac{\sqrt{2}}{2}, \frac{\sqrt{2}}{2}k][0,2i\right] \\ &=& \left[0, \sqrt{2}i + \sqrt{2}j\right] \end{array}\]

旋转例子二

绕$jk$的中间轴旋转45˚

\[\begin{array}{rcl} p &=& [0, 2i] \\ q &=& [\cos{\theta}, \sin{\theta}\hat{v}] \\ \hat{v} &=& \left[0, \frac{\sqrt{2}}{2}i + \frac{\sqrt{2}}{2}k\right] \\ \end{array}\]

计算结果为:

\[\begin{array}{rcl} p^{\prime} &=& \left[-\frac{\sqrt{2}}{2}\left(\frac{\sqrt{2}}{2}\mathbf{i}+\frac{\sqrt{2}}{2}\mathbf{k}\right)\cdot2\mathbf{i},\frac{\sqrt{2}}{2}2\mathbf{i}+\frac{\sqrt{2}}{2}\left(\frac{\sqrt{2}}{2}\mathbf{i}+\frac{\sqrt{2}}{2}\mathbf{k}\right)\times2\mathbf{i}\right] \\ &=& [-1, \sqrt{2}\mathbf{i} + j] \end{array}\]

矢量表示为纯虚数,旋转结果不是纯虚数,模变为 $\sqrt{3}$

现在来求q的逆矩阵

\[\begin{array}{rcl} q^{-1} &=& [\cos{\theta}, -\sin{\theta}\hat{v}] \\ q^{-1} &=& \left[\frac{\sqrt{2}}{2}, -\frac{1}{2}i -\frac{1}{2}k\right] \end{array}\]

乘逆矩阵:

\[\begin{array}{rcl} p^{\prime}q^{-1} &=& \left[-1, \sqrt{2}i + j\right]\left[\frac{\sqrt{2}}{2}, -\frac{1}{2}i -\frac{1}{2}k\right] \\ &=&\frac{1}{2}\left[-\sqrt{2} + \sqrt{2},i+k+2i +\sqrt{2}j -i +\sqrt{2}j+k\right] \\ &=&\frac{1}{2}\left[0, 2k + 2i + 2\sqrt{2}j\right] \\ &=&[0,i +\sqrt{2}j + k] \end{array}\]