ぬうぱんの備忘録

技術系のメモとかいろいろ

作った曲一覧はこちら

Eigen3 の eulerAngles の値域

eulerAngles

eigen.tuxfamily.org

使い方

  • 回転行列からオイラー角に変換できる。
  • 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] に限定したんだろうか?