四元数による回転の要件
が回転を表すためには、長さと角度と掌性を保存しなければなりません。
長さが保存されるのは、 について以下の等式が成り立つときです。
原点から2点 と へ結んだ線分の角が保存されるのは、以下の等式が成り立つときです。
掌性が保存されるのは、以下の等式が成り立つときです。
ここで、 と拡張して、 が成り立つとします。
です。
を変形します。
を変形します。
より、角度と掌性の保存の要件は、以下の1つの式で表せます。
この式 を満たす関数を準同型写像と言います。四元数による回転
四元数による回転は、以下の式で表されます。
とし、 でないとします。式 で表される写像 が要件 を満たすことを示します。
まずは、 が長さを保存すること、すなわち、 を示します。
の変形には、 を用いています。と より、 が示せました。
次に、 が角度、掌性を保存すること、すなわち、 を示します。
より、 が示せました。以上より、 が回転であることが示せました。
を 倍した による写像 を変形してみます。
より、 なので、単純にするために単位四元数のみを考えることにします。 とします。 より、 です。
を計算していきます。
単位ベクトル を用いて とおくと、 は以下のようになります。
任意軸まわりの回転 - ロドリゲスの回転公式の記事でで求めた式 は以下でした。
を係数比較します。
の第三式よりが得られます。また、 の第一式と第三式より、 であることが分かります。
したがって、 でなければならないことが分かります。
以上より、単位ベクトル まわりの角度 回転に対応する単位四元数 が求まりました。
任意軸まわりの回転行列
四元数による回転を表す式 の虚部 を行列で表したいと思います。
と を を用いて、同等の行列で置き換えます。
また、 は単位ベクトルであるので、 です。
これらを用いて、 を書き直します。
また、 は単位四元数であるから、 を満たします。
したがって、
より、四元数 に対応する回転行列 が得られます。
なお、 を変形すると、任意軸まわりの回転 - ロドリゲスの回転公式 の記事の に一致します。
ベクトル3重積の公式
p の q 上への射影を表す行列
外積を表す行列
四元数の積のノルムとノルムの積
であることをSympyを使って示します。
import sympy sympy.init_printing() sympy.var('s_1,x_1,y_1,z_1,s_2,x_2,y_2,z_2') # || (s_1,x_1, y_1, z_1)(s_2, x_2, y_2, z_2) || ** 2 s = s_1 * s_2 - x_1 * x_2 - y_1 * y_2 - z_1 * z_2 x = s_1 * x_2 + s_2 * x_1 + y_1 * z_2 - y_2 * z_1 y = s_1 * y_2 + s_2 * y_1 - x_1 * z_2 + x_2 * z_1 z = s_1 * z_2 + s_2 * z_1 + x_1 * y_2 - x_2 * y_1 nrm_pow2 = s ** 2 + x ** 2 + y ** 2 + z ** 2 # (|| (s_1,x_1, y_1, z_1)|| || (s_2, x_2, y_2, z_2) ||) ** 2 nrm1_pow2 = s_1 ** 2 + x_1 ** 2 + y_1 ** 2 + z_1 ** 2 nrm2_pow2 = s_2 ** 2 + x_2 ** 2 + y_2 ** 2 + z_2 ** 2 multi_nrm_pow2 = nrm1_pow2 * nrm2_pow2 nrm_pow2 = sympy.expand(nrm_pow2) multi_nrm_pow2 = sympy.expand(multi_nrm_pow2) display(nrm_pow2) display(multi_nrm_pow2) display(nrm_pow2.equals(multi_nrm_pow2))
参考文献
ゲームプログラミングのための3Dグラフィックス数学 p69-p72