wacchoz’s note

プログラミングとか数学について

Quaternionと回転の話

どうせ暇だしQuaternionについてまとめてみる。

Quaternion(クォータニオン)は3次元グラフィクス分野でよく出てくるツールである。
もともとはHamiltonによって考案された概念で、複素数の自然な拡張となっている。

単位複素数がGauss平面上での回転を表すことは高校数学で学んだ通り。
原点周りにθだけ回転させるには、複素数

\displaystyle u=e^{i\theta} = \cos\theta + i\sin\theta

を乗算すればよいのであった。


さて3次元上での回転は、複素数を拡張したQuaternionで表すことができる。

以下のように定義される。
\displaystyle \mathbf{u}=q_w+q_x\mathbf{i}+q_y\mathbf{j}+q_z\mathbf{k}
ここで、i, j, kは
\displaystyle \mathbf{i}^2=\mathbf{j}^2=\mathbf{k}^2=\mathbf{ijk}=-1
と定義される。

この定義からすぐに従うが、
\displaystyle \mathbf{ij}=-\mathbf{ji}
となる。つまり乗法は非可換である。
3次元上の回転は回転の順序により結果が変わるというのは広く知られるところだが、Quaternionの非可換性はこれと対応するものだ。

Quaternionは複素数の拡張であると言ったが、類似する性質を見ていこう。
単位Quaternionを
\displaystyle \mathbf{u}=x\mathbf{i}+y\mathbf{j}+z\mathbf{k}, \mbox{ where } x^2+y^2+z^2=1
と書こう。
このとき複素数と同様に \displaystyle \exp(\mathbf{u}\theta)=\cos\theta+\mathbf{u}\sin\theta
が成り立つのである。

なお、一般に単位Quaternionは
\displaystyle \mathbf{q}=\cos\theta+\mathbf{u}\sin\theta
と書ける。

さて、Quaternionを用いてどのように点を回転させるのか見ていこう。
\displaystyle \mathbf{q}=\cos\frac{\theta}{2}+v_x\sin\frac{\theta}{2}\mathbf{i}+v_y\sin\frac{\theta}{2}\mathbf{j}+v_z\sin\frac{\theta}{2}\mathbf{k}
これが回転軸 (v_x, v_y, v_z)の回りに回転角\thetaでの回転をあらわすQuaternionである。

複素数の場合とは違い、単純に頂点座標に乗算するわけではない。
頂点座標 p=(p_x, p_y, p_z)
\displaystyle \mathbf{p}=p_x\mathbf{i}+p_y\mathbf{j}+p_z\mathbf{k}
のようにQuaternionに変換しておく。
このとき、
\displaystyle \mathbf{p}'=\mathbf{q}\mathbf{p}\mathbf{q}^{*}
のように左右から乗算することで、p'の各成分が、頂点pを回転した座標となる。

回転の合成は回転行列の場合と同様で、Quaternionを単純に乗算すればよい。

Quaternionが重宝される理由の1つは回転の補間が容易にできることである。
3次元グラフィクスでは、回転q0と回転q1の間を最短距離で等速になるよう補間したいと思うことがしばしばある。
Quaternionを使うことにより、球面線形補間とよばれる式でこのような補間が可能となる。
以下の\mathbf{q}'\mathbf{q}_0\mathbf{q}_1の球面線形補間である。
\displaystyle \mathbf{q}'=\frac{\sin(\theta(1-t))}{\sin\theta}\mathbf{q_0}+\frac{\sin(\theta t)}{\sin\theta}\mathbf{q_1}

ここで\displaystyle \cos\theta=(\mathbf{q_0},\mathbf{q_1})である。
なお\displaystyle (\mathbf{q_0},\mathbf{q_1})<0のときは\mathbf{q}_0-\mathbf{q}_0で置き換える必要があるとのこと。
\mathbf{q}_0-\mathbf{q}_0も同じ回転を表す)


さて少し違う話題。

複素数に戻ろう。 \displaystyle u=e^{i\theta} = \cos\theta + i\sin\theta
について対数をとると \displaystyle \log{u} = i\theta
となる。(簡便のため、対数の主値のみを記載)
これを見ると、対数をとると回転角を取り出せることがわかる。

実は同様のアナロジーがQuaternionにも成り立つ。
\displaystyle \mathbf{q}=\cos\frac{\theta}{2}+v_x\sin\frac{\theta}{2}\mathbf{i}+v_y\sin\frac{\theta}{2}\mathbf{j}+v_z\sin\frac{\theta}{2}\mathbf{k}
について、
\displaystyle \log{\mathbf{q}} = \frac{\theta}{2}(v_x\mathbf{i}+v_y\mathbf{j}+v_z\mathbf{k})
が成り立つ。
つまり対数をとると、回転角と回転軸が取り出されるのである。

ネイピアが対数を発明したモチベーションは、乗算や除算を加減算で行うことで煩雑な計算を楽にすることであった。
Quaternionについて対数を用いて乗算を加算にすることができるだろうか。
そもそも対数で乗算を加算にできるのは、
\displaystyle e^{x+y}=e^x e^y
が成り立つためであった。
Quaternionの場合には乗算の非可換性のために、この式が成り立たない。
Baker-Campbell-Hausdorffの公式とよばれる \displaystyle \exp(x) \exp(y)=\exp\left(x+y+\frac{1}{2}[x,y]+\frac{1}{12}[x,[x,y]])-\frac{1}{12}[y,[x,y]]-\dots\right)
が成り立つ。
つまりQuaternionの場合には、対数をとり加算してから指数関数をとっても、乗算した場合と結果が一致しないのである。
しかしながら近似的には成り立ちそれなりに便利なため、たまに使われるようだ。