ベクトルの回転と座標回転の違い
ある座標においてベクトルを回転させることと、ある座標とそれを回転させた座標において、固定されたベクトルの座標表現がどのように変わるかの2つのケースを考えてみる。
固定座標でのベクトル回転(固定角表現とも呼ぶ)
座標Aにおいてベクトルaがと表されていたとし、回転した後のベクトルをとすると、
となる。
座標回転における固定ベクトルの表現(オイラー角表現とも呼ぶ)
座標系Aでと表されていたベクトルが、座標系Bでと表されるときの関係性を知りたい。この場合
となる。
考察
上の2つの回転の様子を比較してみると、ベクトル座標の方は回転後の座標表現が等号の左側にある一方で、座標回転の方は回転前の表現の方等号の左側にある。ベクトルの回転と座標の回転でこの順序が変わっていることがポイントである。
固定座標での連続ベクトル回転
X、Y、Zの順番で軸周りにベクトルを回転させる場合
となり、回転演算の順序はとなる。
連続座標回転における固定ベクトル表現
X、Y、Zの順番で軸周りに座標を回転させ固定ベクトルを観測する場合、
となり、回転演算の順序はとなる。
オイラー角の表記方法
オイラー角を使って姿勢を表現する方法には方法がたくさんある。 1. 回転角度の順番 2. 固定角表現かオイラー角表現か
- については、連続で同じ回転軸を選択しなければよいので、通りの選択肢がある。2.は2通りなので、合計24通りの表記方法がある。ただ、本章の議論で、固定角でXYZの順で表現された回転とオイラー角でZYXとして表現された回転は一致するので実質表現自由度は12である。
参考
http://www.st.nanzan-u.ac.jp/info/akiran/mces/mech_ctrl_eng_study_20160120.pdf
回転行列が直行行列であることの証明
ある座標からへの回転行列をとする。における基底ベクトルを、における基底ベクトルをとする。それぞれの成分をの座標系で表すことにし(すなわちはそれぞれ第1、第2、第3成分のみが1で他が0のベクトル)、回転行列の定義から
同様な考察から、の番目の成分は
と表されることがわかる。これを利用すると
これがとなるべきことから、が単位行列であること、すなわち回転行列が直行行列であることが示された。
参考
Why is the Rotation Matrix Orthogonal? | Classical Mechanics - YouTube
x, y, z軸周りの3次元回転の可換性
x,y,z軸周りの一般の3次元
軸周りの角度回転を表す、軸周りの角度回転を表す、軸周りの角度回転を表すを考える。
一方
となり両者は一致しない。したがって3次元空間におけるx,y,z軸周りの回転は可換ではない。
回転角が小さい場合
の場合、それぞれの1次の項まで展開すると
となり両者は一致する。これは三角関数をテーラー展開すれば納得できることで、任意の行列が単位行列と可換であることから1次の項までは回転する順番に依存しないことがわかる。
角度が小さい時にオイラーとangle axis表現による姿勢表現が同じベクトルとして表される
角度が小さい時、固定角(1, 2, 3)表現によるオイラー角表現されたベクトルとangle axisによる回転表現は一致する。証明の方針として、まず回転をクォータニオンで表現し、それを通じてオイラー角とangle axisに表現し直してどのように変換されるか調べてみる。また、「x, y, z軸周りの3次元回転の可換性」で述べたように回転角が小さい場合は回転の順番は可換になるため、以降の議論で回転の順番は気にしないこととする。
クォータニオンによる表現
オイラー角による表現
この資料の式(290)によれば、クォータニオンから固定角(1, 2, 3)表現のオイラー角への変換は
元の資料との定義が異なっていることに注意。ここではオイラー角をと定義している。
したがって
となり、オイラー角はと表されることがわかった。
angle axisによる表現
この資料の式(198)と(199)によれば、クォータニオンからangle axisへの変換は
よってこの式から既にangle axisの方向ベクトルはと一致していることがわかる。また、
となるので、angle axis表現でもと表されることがわかった。
ジンバルロック
ジンバルロックとは、オイラー角で3次元の姿勢を表現した時にy軸周りの回転角が+-90度付近の姿勢に特異点が生じることによる不具合のことである。
そもそもオイラー角とは?
オイラー角とはz, y, xの3つの軸周りの回転として任意の姿勢を表現する手法である。「x, y, z軸周りの3次元回転の可換性」の章で説明しているように、これらの回転は可換ではないので順番を定義する必要があり、ここではz軸、y軸、x軸の順番でだけ回転させることにする。このとき、、、、の範囲を使って全ての姿勢を一意に表現できる。オイラー角可視化ツールを使ってその表現方法を説明していく。
初期状態では、、、である。このときの初期姿勢を以下とする。 ここでを増やしていくと、青()軸まわりに飛行機が回転していく。この状態では青軸はglobalとlocalのframeで一致していることに注意。
次にを増やしていくと、local frameの緑()軸まわりに飛行機が回転していく。この状態では緑軸はglobalとlocalのframeで一致していない。
最後にを増やしていくと、local frameの赤()軸まわりに飛行機が回転していく。この状態では赤軸はglobalとlocalのframeで一致していない。
つまり、、軸まわりの回転は全てlocal frameの軸周りの回転であると言うことができる。
注意点は、、の順で角度を0から動かしていく必要があるということである。例えば、が0でない状態でを回転させても、もはやそれはどの軸まわりの回転でもなくなってしまう。
ジンバルロックとは
ここまででオイラー角を使って任意の3次元姿勢を表現できることがわかったが、付近では1つの姿勢に対して複数の表現方法が存在する。例えばとは全く同じ姿勢を表していることになる。そしてのときにはを回転させた時の回転方向とを回転させた時の回転方向が全く同じになる。この現象がジンバルロックと呼ばれている
ジンバルロックの何が問題なのか?
ジンバルロックの問題点は2つ挙げられる。
- 付近の姿勢をとっているときに、最適化などをするためにオイラー角で微分したときに、とが同じ回転方向を表してしまうために微分ベクトルが一次独立でなくなってしまうこと
- 付近では2つの姿勢間の補間が不自然になってしまうこと。 例えばという姿勢とという姿勢の間を補間しようとしたとき、図のように飛行機が一回転してしまうのである!
EigenのeulerAngles関数の動作の確認
EigenのMatrixクラスにはeulerAnglesという関数があり、例えば
const auto a = R.eulerAngles(2, 1, 0);
とすれば、a[0]がz軸周りの回転角、a[1]がy軸周りの回転角、a[2]がx軸周りの回転角を表す。すなわち、
using namespace Eigen; Matrix3d R = AngleAxisd(psi, Vector3d::UnitZ()) * AngleAxisd(theta, Vector3d::UnitY()) * AngleAxisd(phi, Vector3d::UnitX()); const auto a = R.eulerAngles(2, 1, 0);
とすれば
a[0] = psi; a[1] = theta; a[2] = phi;
となる。ただし注意しないといけない点があり、Eigenのドキュメントに
The returned angles are in the ranges [0:pi]x[-pi:pi]x[-pi:pi].
と記載がある。すなわち、一番左の回転演算の回転角の定義域は]でないといけない。もしこの定義域から外れる角度を入力した場合、
a[0] = psi; a[1] = theta; a[2] = phi;
は成立しなくなる(が一致しなくなるだけでなく、他の回転角も一致しなくなる)。特に一般的なロールピッチヨーの回転を考える場合、ピッチ(2番目の回転)の定義域が]となっていることが多いので、eulerAngles
の関数で取得しても所望の角度が取得できないことに注意。