目次

概要

3次元空間中での回転は、回転軸と回転角で表すことができます。 実用上、回転軸 p = ( px , py , pz ) と回転角 θ は、以下のような形式に変換して置くことが多いです。

( cos
θ
2
, sin
θ
2
px , sin
θ
2
py , sin
θ
2
pz )

これを、以下のように表したりもします。

( cos
θ
2
; sin
θ
2
p )

この形式を四元数といいます。

四元数

四元数なんていうたいそうな名前が付いているは、 元をただせば数学的な意味があるからなんですが、 四元数の数学的意味は、画像処理・3D CG の分野では大して役に立ちません。

応用上は、元々の数学的な意味を知る必要はあまりなく、 回転軸 p = ( px , py , pz ) と回転角 θ の情報を、 4次元の単位ベクトルとして、

( cos
θ
2
; sin
θ
2
p ) = ( cos
θ
2
, sin
θ
2
px , sin
θ
2
py , sin
θ
2
pz )

という形式で持っているものとだけ覚えておけば十分。

3次元空間上の回転

まず、3次元空間上の回転を定式化します。

3次元空間上の回転を表すためには、回転軸ベクトル p と回転角度 θが必要になります。 回転軸ベクトルの絶対値は意味を持たないので、 | p | = 1 であるものとしてます。

座標ベクトル u で表される点 A を、回転軸 p を中心に角度 θ 回転した点 A' の座標ベクトル u' は、以下のような計算で求めることができます。

u' = sinθ u × p + cosθ ( u ( u p ) p ) + ( u p )p
= sinθ u × p + cosθ u + ( 1 cosθ ) ( u p ) p

ちなみに、この式の導出の仕方ですが、下図のようになります。

3次元ベクトルの回転
3次元ベクトルの回転

原点を O、点 A から回転軸におろした垂線の足を H とすると、

OH = ( u p ) p
HA = u ( u p ) p

となります。 また u × p は、 p および HA に垂直で、 絶対値が | HA | と等しいベクトルになります。 HA' は、

HA' = cosθ HA + sinθ u×p
= sinθ u × p + cosθ u + ( 1 cosθ ) ( u p ) p

と表すことができるので、先ほど示した式を導き出すことができます。

行列を使った3次元空間上の回転

前節で示した式で3次元空間中の回転が表現できるんですが、 実際には、この式をそのまま使うのではなく、行列演算に変形してから使います。 (行列にすることで、拡大縮小や平行移動などと一緒に、まとめて扱えるため。)

3次元ベクトルの外積計算は以下のように、

p × u = u [
0 pz py
pz 0 px
py px 0
]

行列とベクトルの積としても書き表わせます。 (ただし、ベクトルは横ベクトルを仮定しています。)

また、 ( u p ) p という部分も、

( u p ) p = u [
px2 px py pz px
px py py2 py pz
pz px py pz pz2
]

と表せます。

これらを使うと、 先ほどの回転の式は、以下のような行列で表すことができます。

u' = sinθ u × p + cosθ u + ( 1 cosθ ) ( u p ) p
= cosθ u + ( 1 cosθ ) u [
px2 px py pz px
px py py2 py pz
pz px py pz pz2
] + sinθ u [
0 pz py
pz 0 px
py px 0
]
= u [
( 1 cosθ ) px2 + cosθ ( 1 cosθ ) px py pz sinθ ( 1 cosθ ) pz px + py sinθ
( 1 cosθ ) px py + pz sinθ ( 1 cosθ ) py2 + cosθ ( 1 cosθ ) py pz px sinθ
( 1 cosθ ) pz px py sinθ ( 1 cosθ ) py pz + px sinθ ( 1 cosθ ) pz2 + cosθ
]

四元数から回転行列を計算

ここで話を四元数に戻します。

四元数は、 回転軸 p = ( px , py , pz ) と回転角 θ の情報を、以下の形式で保持するものです。

( cos
θ
2
; sin
θ
2
p ) = ( cos
θ
2
, sin
θ
2
px , sin
θ
2
py , sin
θ
2
pz )

ここで、sin や cos を何度も書きたくないので、 以下のように書き表わすことにします。

q = ( qw , qx , qy , qz , ) = ( cos
θ
2
, sin
θ
2
px , sin
θ
2
py , sin
θ
2
pz )

ここで、三角関数の倍角の公式を使うと、以下の等式が導かれます。 (* と † の位置には、x, y, z のいずれかが入ります。)

2 q* q = 2 sin2
θ
2
p* p = ( 1 cosθ ) p* p
2 qw q* = 2 sin
θ
2
cos
θ
2
p* = sinθ p*
2 qw2 = 2 cos2
θ
2
= 1 + cosθ

これらを、前節で求めた行列に代入すると、 以下の結果が得られます。

u' = u [
2 ( qx2 + qw2 ) 1 2 ( qx qy qz qw ) 2 ( qx qz + qy qw )
2 ( qx qy + qz qw ) 2 ( qy2 + qw2 ) 1 2 ( qy qz qx qw )
2 ( qx qy qy qw ) 2 ( qy qz + qx qw ) 2 ( qz2 + qw2 ) 1
]

あるいは、 | q | = 1 なことを利用して、以下のようにも書けます。

u' = u [
1 2 ( qy2 + qz2 ) 2 ( qx qy qz qw ) 2 ( qx qz + qy qw )
2 ( qx qy + qz qw ) 1 2 ( qz2 + qx2 ) 2 ( qy qz qx qw )
2 ( qx qy qy qw ) 2 ( qy qz + qx qw ) 1 2 ( qx2 + qy2 )
]

ちなみに、こうやって作られた行列は、必ず直交行列になります。 (実際、計算してみてもらうと、各列が正規直行していることがわかります。) 回転しかしていないんだから、長さも角度も変わらない変換(= 直交行列による1次変換)になっていないとおかしいはずです。

更新履歴

ブログ