おべんきょうwiki

クォータニオン

最終更新:

yahirohumpty

- view
管理者のみ編集可

クォータニオン

「四元数」とも呼ばれる. 三次元回転をコンパクトに表現できる,補間がやりやすいなどの利点があるが, 結局同次座標変換行列に落とさないと使えなかったりする. 直感的でないという最大の欠点がある.

回転を表すクォータニオン

普通のクォータニオンは

q = (w \ V) = (w \ x \ y \ z)

とかあらわされる.V = (x \ y \ z)は虚部.

回転を表すクォータニオンの場合,大きさが1のクォータニオンとなる. 回転量を \theta ,回転軸を(n_x \ n_y \ n_z)としたときこれをあらわすクォータニオンは

(\cos \theta /2 \ \ n_x \sin \theta /2 \ \ n_y \sin \theta /2 \ \ n_z \sin \theta /2)

当然,全要素の符号を反転させても同じ回転を表現できる. なお,

-q = (-w \ -V) = (-w \ -x \ -y \ -z)これは同じ回転を意味し

q^{-1} = (w \ -V) = (w \ -x \ -y \ -z)これは逆回転を意味する

基本的な演算

クォータニオンの乗算の定義は

 q_0 q_1 = ( w_0 \ V_0 ) ( w_1 \ V_1) = (w_0 \ x_0 \ y_0 \ z_0) (w_1 \ x_1 \ y_1 \ z_1)

 = (w_0 w_1 - V_0 \cdot V_1  \ \ w_0 V_1 + w_1 V_0 + V_0 \times V_1 )

 = \left( \begin{array}{c} w_0 w_1 - x_0 x_1 - y_0 y_1 - z_0 z_1 \\ w_0 x_1 + x_0 w_1 + y_0 z_1 - z_0 y_1 \\ w_0 y_1 + y_0 w_1 + z_0 x_1 - x_0 z_1 \\ w_0 z_1 + z_0 w_1 + x_0 y_1 - y_0 x_1 \\ \end{array} \right)

ちなみに

 V_0 \cdot V_1 = x_0 x_1 + y_0 y_1 + z_0 z_1

 V_0 \times V_1 = (y_0 z_1 - z_0 y_1 \ \ z_0 x_1 - x_0 z_1 \ \ x_0 y_1 - y_0 x_1)


回転を表すクォータニオンを合成するときは単純に乗算すればよい.


クォータニオンaをbで回転させてクォータニオンcをつくる場合.

 c = b^{-1} a b

コーディングの際にはたぶん展開しても簡単にならないと思うので素直に乗算で組んでしまうのがいいと思う.


他の表現との変換

回転行列の作り方

右手座標列ベクトル形式として,


\begin{bmatrix}
1-2y^2-2z^2 & 2xy-2wz & 2xz+2wy \\
2xy+2wz & 1-2x^2-2z^2 & 2yz-2wx \\
2xz-2wy & 2yz+2wx & 1-2x^2-2y^2 \\
\end{bmatrix}


回転行列からの作り方


axis-angle

回転量を \theta ,回転軸をr = (n_x \ n_y \ n_z)としたとき

 q_a = (\theta, r) = (\theta, (n_x \ \ n_y \ \ n_z))

回転の合成は直接計算では得ることができない. クォータニオンとの変換は簡単なのでそこを経由するとよい.


変換

回転行列への変換はRodoriguesの公式を使う.


R = \cos \theta I_3 + (1- \cos \theta) r r^T + \sin \theta
\begin{bmatrix}
0 & -n_z & n_y \\
n_z & 0 & -n_x \\
-n_y & n_x & 0
\end{bmatrix}

逆変換


\sin \theta
\begin{bmatrix}
0 & -n_z & n_y \\
n_z & 0 & -n_x \\
-n_y & n_x & 0
\end{bmatrix}
= \frac{R-R^T}{2}



対数クォータニオン:exponential map

OpenCVでは「回転ベクトル」と呼ばれている. 回転軸*回転角度で表される.三次元.

 q_e = (\theta n_x \ \ \theta n_y \ \ \theta n_z)

こうすることで,

 q_0 \times q_1 \approx \exp ( \ln (q_0) + \ln (q_1))

ということらしい.

表現形式は文献,実装によって異なるようだが最終的に座標変換がうまくいっていれば問題はない? DirectXでは

 \ln (w V) = (0 \ \ (\phi / \sin \phi ) V) , \phi = \cos ^{-1} w




参考文献