Eigen3 AngleAxis()の基本から応用まで:初心者向けプログラミング解説

2025-04-07

Eigen::AngleAxis クラスの役割

Eigen::AngleAxis クラスは、3次元空間における回転を「軸」と「角度」の組み合わせで表現します。これは、回転行列やクォータニオンなどの他の回転表現と比較して、直感的で理解しやすいという利点があります。

Eigen::AngleAxis::AngleAxis() コンストラクタ

Eigen::AngleAxis::AngleAxis() は、デフォルトコンストラクタであり、初期化時に引数を指定しない場合に呼び出されます。このデフォルトコンストラクタは、回転を初期化する際に、特定の回転をすぐに設定する必要がない場合に使用されます。

デフォルトコンストラクタの動作

デフォルトコンストラクタを呼び出すと、Eigen::AngleAxis オブジェクトは初期状態に設定されます。具体的には、通常、角度は0(回転なし)に、軸は (1, 0, 0) など特定のデフォルトの軸に設定されます。しかし、Eigenのバージョンやコンパイラの設定によって、初期状態が異なる可能性があります。

コード例

#include <iostream>
#include <Eigen/Geometry>

int main() {
  Eigen::AngleAxis<float> rotation; // デフォルトコンストラクタを呼び出す

  std::cout << "Angle: " << rotation.angle() << std::endl;
  std::cout << "Axis: " << rotation.axis().transpose() << std::endl;

  return 0;
}

この例では、Eigen::AngleAxis<float> rotation; という行でデフォルトコンストラクタを呼び出し、rotation オブジェクトを初期化しています。その後、rotation.angle()rotation.axis() を使用して、初期化された角度と軸を出力しています。

  • 初期化後、angle() メソッドと axis() メソッドを使用して、角度と軸を取得できます。
  • デフォルトコンストラクタは、角度を0、軸を特定のデフォルト値に設定します。
  • Eigen::AngleAxis::AngleAxis() は、引数を指定せずに Eigen::AngleAxis オブジェクトを初期化するためのデフォルトコンストラクタです。


初期化の誤解

  • トラブルシューティング
    デフォルトコンストラクタは、回転を「無回転」に近い状態に初期化します。特定の回転が必要な場合は、他のコンストラクタを使用するか、fromRotationMatrix()fromQuaternion() などの変換関数を使用する必要があります。
    • 初期化された角度と軸を確認するために、rotation.angle()rotation.axis() を使用して値を出力します。
    • 特定の回転を設定する場合は、Eigen::AngleAxis<float> rotation(angle, axis); のように角度と軸を引数に指定します。
  • エラー
    デフォルトコンストラクタを呼び出した後、回転が特定の値に初期化されていると誤解する。

回転軸の正規化

  • トラブルシューティング
    回転軸は単位ベクトルである必要があります。axis() メソッドで軸を取得した後、normalized() メソッドを使用して正規化します。
    • 例:rotation.axis().normalized()
    • 回転軸の長さを確認するために、rotation.axis().norm() を使用します。
  • エラー
    回転軸が正規化されていない場合、予期しない回転結果が生じる。

型の不一致

  • トラブルシューティング
    Eigen::AngleAxis と、それを使用する Eigen::MatrixEigen::Quaternion などの型を一致させます。
    • 例:Eigen::AngleAxis<float>Eigen::Matrix3fEigen::Quaternionf を組み合わせる。
  • エラー
    Eigen::AngleAxis のテンプレート引数(floatdouble)と、それを使用する他のEigenオブジェクトの型が一致しない。

回転行列やクォータニオンとの変換

  • トラブルシューティング
    toRotationMatrix()toQuaternion() などの変換関数を使用する際、変換先の型が正しいことを確認します。また、回転の方向や角度の範囲に注意します。
    • Eigen::Matrix3f rotationMatrix = rotation.toRotationMatrix();
    • Eigen::Quaternionf quaternion = rotation.toQuaternion();
    • 回転行列からAngleAxisへの変換 Eigen::AngleAxis<float> rotation(rotationMatrix);
    • クォータニオンからAngleAxisへの変換 Eigen::AngleAxis<float> rotation(quaternion);
  • エラー
    Eigen::AngleAxis と回転行列やクォータニオンとの変換で、予期しない結果が生じる。

コンパイルエラー

  • トラブルシューティング
    Eigen3ライブラリが正しくインストールされ、コンパイラにパスが設定されていることを確認します。
    • #include <Eigen/Geometry> をインクルードしているか確認します。
    • コンパイラにEigen3のインクルードディレクトリとライブラリディレクトリが設定されているか確認します。
    • CMakeなどのビルドシステムを使用している場合は、find_package(Eigen3 REQUIRED) が正しく設定されているか確認します。
  • エラー
    Eigen3ライブラリのヘッダーファイルが正しくインクルードされていない、またはコンパイラの設定が正しくない。
  • 最小限のコード
    問題を再現する最小限のコードを作成し、問題を特定しやすくします。
  • デバッガ
    デバッガを使用して、変数の値やプログラムの実行フローを確認します。
  • ドキュメント参照
    Eigen3の公式ドキュメントを参照し、Eigen::AngleAxis クラスの仕様を確認します。


例1: デフォルトコンストラクタと初期値の確認

#include <iostream>
#include <Eigen/Geometry>

int main() {
  // デフォルトコンストラクタを使用して AngleAxis オブジェクトを作成
  Eigen::AngleAxis<float> rotation;

  // 初期化された角度と軸を出力
  std::cout << "デフォルト初期化後の角度: " << rotation.angle() << std::endl;
  std::cout << "デフォルト初期化後の軸: " << rotation.axis().transpose() << std::endl;

  return 0;
}

この例では、引数なしで Eigen::AngleAxis オブジェクトを初期化し、初期状態の角度と軸を出力しています。これにより、デフォルトコンストラクタがどのように初期化するかを確認できます。

例2: 特定の角度と軸での初期化

#include <iostream>
#include <Eigen/Geometry>

int main() {
  // 回転角度と軸を定義
  float angle = M_PI / 4.0f; // 45度
  Eigen::Vector3f axis(0.0f, 0.0f, 1.0f); // Z軸回転

  // 指定された角度と軸で AngleAxis オブジェクトを作成
  Eigen::AngleAxis<float> rotation(angle, axis);

  // 回転行列に変換して出力
  Eigen::Matrix3f rotationMatrix = rotation.toRotationMatrix();
  std::cout << "回転行列:\n" << rotationMatrix << std::endl;

  return 0;
}

この例では、特定の角度(45度)と軸(Z軸)で Eigen::AngleAxis オブジェクトを初期化し、その回転を回転行列に変換して出力しています。

例3: 回転軸の正規化

#include <iostream>
#include <Eigen/Geometry>

int main() {
  // 正規化されていない回転軸
  Eigen::Vector3f axis(1.0f, 2.0f, 3.0f);

  // 正規化された回転軸を使用して AngleAxis オブジェクトを作成
  Eigen::AngleAxis<float> rotation(M_PI / 2.0f, axis.normalized());

  // 正規化された軸を出力
  std::cout << "正規化された軸: " << rotation.axis().transpose() << std::endl;

  return 0;
}

この例では、正規化されていない回転軸を使用して Eigen::AngleAxis オブジェクトを作成し、normalized() メソッドを使用して回転軸を正規化しています。

例4: クォータニオンからの変換

#include <iostream>
#include <Eigen/Geometry>

int main() {
  // クォータニオンを作成
  Eigen::Quaternionf quaternion(Eigen::AngleAxisf(M_PI / 3.0f, Eigen::Vector3f(1.0f, 0.0f, 0.0f))); // X軸60度回転

  // クォータニオンから AngleAxis オブジェクトを作成
  Eigen::AngleAxis<float> rotation(quaternion);

  // 角度と軸を出力
  std::cout << "角度: " << rotation.angle() << std::endl;
  std::cout << "軸: " << rotation.axis().transpose() << std::endl;

  return 0;
}

この例では、クォータニオンから Eigen::AngleAxis オブジェクトを作成し、角度と軸を出力しています。

#include <iostream>
#include <Eigen/Geometry>

int main() {
    //回転行列を作成
    Eigen::Matrix3f rotationMatrix;
    rotationMatrix = Eigen::AngleAxisf(M_PI / 2, Eigen::Vector3f::UnitZ()); // Z軸90度回転
    //回転行列からAngleAxisへ変換
    Eigen::AngleAxis<float> angleAxis(rotationMatrix);

    std::cout << "Angle: " << angleAxis.angle() << std::endl;
    std::cout << "Axis: " << angleAxis.axis().transpose() << std::endl;

    return 0;
}


引数付きコンストラクタ

  • Eigen::AngleAxis<Scalar>(Scalar angle, const Eigen::Vector3<Scalar>& axis);

    • このコンストラクタは、回転角度と回転軸を引数として受け取り、Eigen::AngleAxis オブジェクトを初期化します。
    • 特定の回転を直接指定する場合に便利です。
    #include <iostream>
    #include <Eigen/Geometry>
    
    int main() {
      float angle = M_PI / 4.0f; // 45度
      Eigen::Vector3f axis(0.0f, 0.0f, 1.0f); // Z軸
    
      Eigen::AngleAxis<float> rotation(angle, axis);
    
      std::cout << "角度: " << rotation.angle() << std::endl;
      std::cout << "軸: " << rotation.axis().transpose() << std::endl;
    
      return 0;
    }
    

回転行列からの変換

  • Eigen::AngleAxis<Scalar>(const Eigen::Matrix3<Scalar>& matrix);

    • 回転行列を引数として受け取り、Eigen::AngleAxis オブジェクトを初期化します。
    • 既存の回転行列から Eigen::AngleAxis 表現に変換する場合に便利です。
    #include <iostream>
    #include <Eigen/Geometry>
    
    int main() {
      Eigen::Matrix3f rotationMatrix;
      rotationMatrix = Eigen::AngleAxisf(M_PI / 2.0f, Eigen::Vector3f::UnitZ()).toRotationMatrix(); // Z軸90度回転
    
      Eigen::AngleAxis<float> rotation(rotationMatrix);
    
      std::cout << "角度: " << rotation.angle() << std::endl;
      std::cout << "軸: " << rotation.axis().transpose() << std::endl;
    
      return 0;
    }
    

クォータニオンからの変換

  • Eigen::AngleAxis<Scalar>(const Eigen::Quaternion<Scalar>& quaternion);

    • クォータニオンを引数として受け取り、Eigen::AngleAxis オブジェクトを初期化します。
    • 既存のクォータニオンから Eigen::AngleAxis 表現に変換する場合に便利です。
    #include <iostream>
    #include <Eigen/Geometry>
    
    int main() {
      Eigen::Quaternionf quaternion(Eigen::AngleAxisf(M_PI / 3.0f, Eigen::Vector3f::UnitX())); // X軸60度回転
    
      Eigen::AngleAxis<float> rotation(quaternion);
    
      std::cout << "角度: " << rotation.angle() << std::endl;
      std::cout << "軸: " << rotation.axis().transpose() << std::endl;
    
      return 0;
    }
    

fromRotationMatrix() メソッド

  • Eigen::AngleAxis<Scalar>& fromRotationMatrix(const Eigen::Matrix3<Scalar>& matrix);

    • 既存の Eigen::AngleAxis オブジェクトに対して、回転行列から値を設定します。
    • オブジェクトを再利用する場合に便利です。
    #include <iostream>
    #include <Eigen/Geometry>
    
    int main() {
      Eigen::AngleAxis<float> rotation;
      Eigen::Matrix3f rotationMatrix;
      rotationMatrix = Eigen::AngleAxisf(M_PI / 6.0f, Eigen::Vector3f::UnitY()).toRotationMatrix(); // Y軸30度回転
    
      rotation.fromRotationMatrix(rotationMatrix);
    
      std::cout << "角度: " << rotation.angle() << std::endl;
      std::cout << "軸: " << rotation.axis().transpose() << std::endl;
    
      return 0;
    }
    
  • Eigen::AngleAxis<Scalar>& fromQuaternion(const Eigen::Quaternion<Scalar>& quaternion);

    • 既存の Eigen::AngleAxis オブジェクトに対して、クォータニオンから値を設定します。
    • オブジェクトを再利用する場合に便利です。
    #include <iostream>
    #include <Eigen/Geometry>
    
    int main() {
      Eigen::AngleAxis<float> rotation;
      Eigen::Quaternionf quaternion(Eigen::AngleAxisf(M_PI / 4.0f, Eigen::Vector3f::UnitZ())); // Z軸45度回転
    
      rotation.fromQuaternion(quaternion);
    
      std::cout << "角度: " << rotation.angle() << std::endl;
      std::cout << "軸: " << rotation.axis().transpose() << std::endl;
    
      return 0;
    }