はじめに
『秋葉原ロボット部 理論グループ Advent Calendar 2025』の投稿です
線形代数のなかでは特に射影が大好きですが、量子力学を学び始めてから興味の中心はとにかく回転です!
この記事では、四元数と3次元回転 の続編としてSympy Quaternionを実際に使った四元数を利用した回転を紹介します、四元数の回転の振る舞いからSU(2)の特徴を垣間見ることができるのでは・・・
概要
- 動作環境はJupyter notebookを前提としています、(Google Colabは手軽に使えて便利です)
- Python言語で SympyライブラリのQuatarnion (四元数) クラス を利用して
- 実際に、回転を体験します
- $SU(2)$を体感します (多分)
sympyの初期設定
ライブラリのインポートなどお約束ごとです
from sympy import *
from IPython.display import display
init_printing()
四元数クラスQuaternionの使い方
まずは、四元数クラスQuaternionに引数w,x,y,zをセットするだけですの例です
w, x, y, z = symbols("w x y z")
q = Quaternion(w,x,y,z)
display(Eq(Symbol(r'q'), q))
display(Eq(Symbol(r'q^{\dagger}'), q.conjugate())) # 共役
Out:
$$
\begin{aligned}
q &= w+xi+yj+zk \\
q^\dagger &= w-xi-yj-zk \ \ (共役)\
\end{aligned}
$$
ちゃんと、虚数単位$i,j,k$がついた形で表示されていますね
※Eq(Symbol((r'q'))は、表示をq = ...と値が、どの変数のものかを明示する工夫です
四元数の足し算と掛け算
とりあえず、簡単な演算です
# 四元数の定義 (q1, q2)
w1, x1, y1, z1 = symbols("w_1 x_1 y_1 z_1")
w2, x2, y2, z2 = symbols("w_2 x_2 y_2 z_2")
q1 = Quaternion(w1,x1,y1,z1)
q2 = Quaternion(w2,x2,y2,z2)
Out:
\begin{aligned}
q_1=w_1+x_1i+y_1j+z_1k \\
q_2=w_2+x_2i+y_2j+z_2k
\end{aligned}
# 足し算
display(Eq(Symbol(r'q_{1} + q_{2}'), q1+q2))
Out:
q_{1} + q_{2} = \left(w_{1} + w_{2}\right) + \left(x_{1} + x_{2}\right) i + \left(y_{1} + y_{2}\right) j + \left(z_{1} + z_{2}\right)
# 掛け算
display(Eq(Symbol(r'q_{1} * q_{2}'), q1+q2))
Out:
\begin{aligned}
q_{1} \times q_{2} &=
\left(w_{1} w_{2} - x_{1} x_{2} - y_{1} y_{2} - z_{1} z_{2}\right) \\
&+ \left( w_{1} x_{2} + w_{2} x_{1} + y_{1} z_{2} - y_{2} z_{1}\right) i \\
&+ \left(w_{1} y_{2} + w_{2} y_{1} - x_{1} z_{2} + x_{2} z_{1}\right) j \\
&+ \left(w_{1} z_{2} + w_{2} z_{1} + x_{1} y_{2} - x_{2} y_{1}\right) k
\end{aligned}
四元数を使った回転の実装例
いよいよ、実際の点の回転を四元数で実装します
四元数での回転の実装は、回転対象の座標も四元数、回転演算子も四元数で定義します
- 回転対象の座標を四元数の虚部で表現
- 回転演算子も四元数で表現 => こちらは単に四元数ではなく大きさが$1$の単位四元数:($SU(2)$)です
回転演算子を四元数で表現する
回転演算子である単位四元数は以下のように決まります
- 回転軸
- 回転軸は虚部の係数$(q_1, q_2. q_3)$を$(x,y,z)$の方向ベクトルとして指定します
- ただし、$q_1^2 + q_2^2 + q_3^2 = 1$、つまり、大きさは$1$とします
- 回転角
- 回転角は$\theta$で指定します、引数としては$\frac{\theta}{2}$となるので注意してください
- 回転面は、単位方向ベクトル(上記)の原点を通る垂直面となります
- 回転面からみると、方向ベクトルは、単位法線ベクトルともいえます
\begin{aligned}
q = \underbrace{\cos \frac{\theta}{2}}_{実部} + \underbrace{ (q_1 i + q_2 j + q_3 k)\sin \frac{\theta}{2}}_{虚部} \\\\
\end{aligned}
これらの条件に合うように計算して四元数を計算してもよいのですが、Quaternionクラスには便利なfrom_axis_angleメソッドがあります、このメソッドには以下のように引数をセットするだけですべて完了です
- 第1引数:方向ベクトル$[x,y,z]$:あらかじめ大きさを$1$にしなくても、内部的に$1$に変換してくれます
- 第2引数:回転角度$\theta$:直接、回転角度$\theta$を指定します、内部で$\frac{\theta}{2}$に変換されます
ここでは、方向ベクトルはとして$[0,0,99]$,回転角度は$\pi/2$ (90度)としました
q = Quaternion.from_axis_angle((0,0,99),pi/2)
display(Eq(Symbol(r'q'), q))
Out:
$$
q= \frac{\sqrt{2}}{2} + 0 i + 0 j + \frac{\sqrt{2}}{2} k
$$
回転対象(座標)を四元数で表現する
$x$軸上にある点$P:[5,0,0]$を回転対象として四元数で表現します
P = Quaternion(0,5,0,0)
display(Eq(Symbol("P"),P))
Out
$$
P = 0 + 5 i + 0 j + 0 k
$$
回転の計算
最後に、始点$P$に回転演算子を作用させて終点$P'$を求めます
PP = q * P * q.conjugate()
display(Eq(Symbol(r'P^{\prime}=qPq^{\dagger}'),PP))
Out:
$$
P' = qPq^{\dagger}=0 + 0 i + 5 j + 0 k
$$
SU(2)の振る舞い
四元数はSU(2):特殊ユニタリー群だと思い込んでましたが、厳密には、単位四元数がSU(2)ですね
- ユニタリー性
\begin{aligned}
qq^{\dagger} &= q^{\dagger}q = 1 \\
q^{-1} &= q^{\dagger} \\
|q|^2 &=1
\end{aligned}
- スピノール性
\begin{aligned}
q(2\pi) &= \underbrace{\cos \frac{\color{red}{(2\pi)}}{2}}_{実部} + \underbrace{ (q_1 i + q_2 j + q_3 k)\sin \frac{\color{red}{(2\pi)}}{2}}_{虚部} \Rightarrow \color{red}{-1} \ \ (SU(2)は4\pi周期) \\\\
\end{aligned}
- 2重被覆
\begin{aligned}
qPq^{\dagger} &= (-q)P(-q^{\dagger}) \Rightarrow \ \ SO(3) 回転は 2 価
\end{aligned}
まとめ
単位四元数による回転をSympyのQuaternionで実装する中でスピノール性や二重被覆の話が腑に落ちてきました
この投稿をアップデートしながら伝えていけたらと思います
コメントなどいただけると、ありがたいです(お手柔らかに)
参考文献
-『ストラング線形代数イントロダクション』
-『3次元回転: パラメータ計算とリー代数による最適化』