eulerAngles
使い方
- 回転行列からオイラー角に変換できる。
- 0, 1, 2 を渡した場合、回転順序は X <-- Y <-- Z になる
using namespace Eigen; const Vector3f originalInEuler= { 0.2f, 0.4f, 0.6f }; const AngleAxisf originalInAa = AngleAxisf( originalInEuler(0), Vector3f::UnitX() ) * AngleAxisf( originalInEuler(1), Vector3f::UnitY() ) * AngleAxisf( originalInEuler(2), Vector3f::UnitZ() ); const Vector3f resultInEuler = Quaternionf(originalInAa).toRotationMatrix().eulerAngles(0, 1, 2);
オイラー角の値域
ドキュメントより
- X : [0, +180] deg
- Y : [-180, +180] deg
- Z : [-180, +180] deg
問題点
- X 回転が 0 <--> 180 deg で不連続になる
- -180 <--> 180 deg なら ±360 deg の補正をかけることで連続扱いできるが、 0 <--> 180 deg だとどうあがいても不連続
- そのため、真の X 回転がほぼ 0 deg ちょうどの場合でも、数値誤差で 0 deg がでたり 180 deg が出たりする
- ±180 deg で不連続なのは想定内として、 0 deg で不連続なのは場合によっては不便
じゃあどうするのか?
※以下は引数に 0, 1, 2 を渡した場合の話
- X 回転を求めるのに atan2 を使っているので、直接得られるのは [-180, +180] の値
- それを [-180, 0] に収まるように、 atan2 で得られた値が 0 deg 以上なら -180 deg の補正を行っている (最後にオイラー角の符号を反転させているので、計算途中の値は符号が反転している)
- この -180 deg 補正のフローに入る分岐を削除したオレオレ eulerAngles を作ればいい (幸い、 Eigen3 はヘッダオンリーだからソースは見れるし、 eulerAngles は実装自体は結構簡素)
感想
- なんで [0, +180] に限定したんだろうか?