up:: Programming
up:: Summareading
source:: クォータニオン (Quaternion) を総整理! ~ 三次元物体の回転と姿勢を鮮やかに扱う ~ - Qiita
1. クォータニオンでやりたいこと
クォータニオンでやりたいのは、3D空間における回転と、3D物体の姿勢を表すこと。姿勢は「どう回転してその向きになったか」で回転と同じく表せる。(姿勢は回転の結果)
姿勢は方向よりも多くの情報を持つ。方向に大きさは要らないため、自由度(次元と大体同じ)は2。しかし姿勢は航空機でいうロール成分が必要になるので、方向に+1して3になる。
つまり、姿勢は最小3個のパラメータで表せる。 回転は姿勢と本質的に同じなので、同様に3個でいい。実際に3個で姿勢や回転を表しているのがオイラー角。
対して、クォータニオンは4個のパラメータを使っている。このままでは自由度が1つ余るので、それを解決する方法として「ノルムが1」という制約がある。
ちなみに、3x3個のパラメータを使う回転行列という表現法もある。これを縛る制約は「正規直行行列である」こと。
1-1. クォータニオンとは
三次元空間において、
- 方向ベクトル を回転軸として
- 角度だけ回転する
という「回転」クォータニオンは、四次元ベクトル で表す。
UnityではそれぞれQuaternion.x,y,z,wとして実装している。生成したいならQuaternion.AngleAxis(角度, 軸)
で作れる。
1-2. クォータニオンによる回転操作
回転は表せたが、これを実際に回転操作として実装するにはどうすればよいだろう。
仮に回転操作をと置くと、このようなシンプルな式ができる。
回転させるもの | 回転結果 | 備考 |
---|---|---|
ベクトル | は の逆回転 | |
姿勢クォータニオン |
クォータニオン同士の掛け算、クォータニオンとベクトルの掛け算の定義は1-4で。掛け算は不可換、つまり左右の入れ替えは不可能。
なお、はテンソル積という代物。あるベクトル空間における新しいベクトル空間を示す。が、ここではめんどいので専用掛け算記号として見ていればいい。
unityでは*
で表現する。普段の掛け算と同じ。
1-3. クォータニオンを選ぶ理由
パラメータ数 | メモリ消費 | 計算上の扱いやすさ | 備考 | |
---|---|---|---|---|
クォータニオン | 4 | ⚪︎ | ◎ | バランス型で、その他様々なメリットがあります |
オイラー角 | 3 | ◎ | × | 具体的な姿勢をイメージしやすく、メモリ的にも優しいですが、計算上の難点を抱えています |
回転行列 or DCM | 9 | × | ⚪︎ |
クォータニオンはメモリ消費、扱いやすさの両面でバランスが取れている。数値誤差も生じにくい。
オイラー角はメモリ消費が少ないが、三角関数を多用する関係上計算時間が大きい。 また、二番目の角度が+-90度によって起きる問題、ジンバルロックが厄介。(ヨーとロールの回転軸がそろい、区別がつかなくなる)
しかしイメージしやすいので今でもよく見る表現方法。
回転行列は、実はクォータニオンと本質的には同じ。回転行列の持つ性質を維持しつつ、4個のパラメータに圧縮したのがクォータニオンといえる。
2. クォータニオンの使い方
2-1. クォータニオンの生成
指定するもの | Unity 関数 | 備考 | |
---|---|---|---|
1 | 回転軸と回転角度 | Quaternion.AngleAxis | クォータニオン本来の定義 |
2 | オイラー角 | Quaternion.Euler | 角度を 3 つ指定します |
3 | 向けたい方向 | Transform.LookAt | 今の向いてる方向 (デフォルトで上方向) と、向けたい方向を指定します |