いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

四元数(しげんすう、クオータニオン)を使ってみる(5)

 せっかく四元数が使えるようになったので、いくつか実験しておきます。高校では今は複素数が表す図形などについて少し勉強するようになっていますが、前は行列をやっていました。ぼくも行列を習いました。数学BとかCとかいろんな科目の間をいろんな単元が行ったり来たりして、何がどこにあるのかもう分かりません。そういうこと自体には興味はありませんが、もちろん何か理由をつけて動かしているんでしょうね……。何を考えているんでしょう。構いませんが。
 さて、xy平面上の点をz軸を中心にして回転させてみましょう。ぼくたちの世代はこれを回転の行列(2×2の行列)で計算しました。これだって空間内の点の回転ですから四元数が使えます。
 xy平面の(1,0)を反時計回りに60°回します。行列を知らなくても複素数でも計算できますよね。結果は(1/2,√3/2)になるはずです。

import math
import numpy as np
import quaternion
x = math.pi / 3 #回転角
v = np.array([0, 0, 1]) #回転軸
d = np.linalg.norm(v)
w = v / d #長さを1にする
s = math.sin(x / 2) #回転角はx
c = math.cos(x / 2)
w1 = s * w
qt1 = np.quaternion(c , w1[0], w1[1], w1[2])
qt2 = np.quaternion(0, 1, 0, 0) #もとの点
qt = qt1 * qt2 * np.conj(qt1) #四元数を左右からかける
print('qt = ', qt)
sys.exit()

実行結果は
qt = quaternion(0, 0.5, 0.866025403784439, 0)
でした。最初の0は四元数の実数部分で、点の位置とは関係ありません。第2,3,4成分が空間内の点の座標です。正しいですね。なお、

qt2 = np.quaternion(0, 1, 0, 0) #もとの点

とやっていますが、以下を試すと無事に動きました。

qt2 = np.quaternion(1, 0, 0) #もとの点

また、

qt1 = np.quaternion(c , w1[0], w1[1], w1[2])

qt1 = np.quaternion(c , w1)

とやってみたらこちらはエラー。w1はベクトルだからこれでいいかなと思ったんですがダメでした。まあ、彼(四元数のライブラリ)にも事情はあるんでしょう……。
あとひとつ、直線y=xを回転の軸にしてみましょう。これをベクトルで(1,1,0)と表し、xy平面上の点(0,2)を90°回します。

import math
import numpy as np
import quaternion
x = math.pi / 2 #回転角
v = np.array([1, 1, 0]) #回転軸
d = np.linalg.norm(v)
w = v / d #長さを1にする
s = math.sin(x / 2) #回転角はx
c = math.cos(x / 2)
w1 = s * w
qt1 = np.quaternion(c , w1[0], w1[1], w1[2])
qt2 = np.quaternion(0, 0, 2, 0) #もとの点
qt = qt1 * qt2 * np.conj(qt1) #四元数を左右からかける
print('qt = ', qt)
sys.exit()

実行結果は以下の通りです。
qt = quaternion(0, 1, 1, 1.41421356237309)
さっきの問題よりちょっとイメージしづらいですが、やはり正しく計算されています!
 このシリーズの(1)で「大学では現在四元数をほとんど教えていない」という話を紹介しました。でも実際に試してみると使いやすいですし、面白い気はします。ベクトルの、ロドリゲスの回転公式というのもあって、やはり回転軸とその周りの回転の角度から回転後のベクトルを求めることができます。今回書いたように四元数でもできるわけですが確かにあえて四元数でなくてもいいのかも……。でもやはりいろいろあった方が面白くてよいでしょう!!
 四元数についてはここまで。このくらい書いておけば備忘録としても十分です。