クォータニオン

クォータニオンは主に物理計算における剛体の向きや回転を表現するために使います. クォータニオンは4次元ベクトルの基本機能を備えています.

要素アクセスは[]演算子に加えて以下の方法が使えます.

Quaterniond q;
q.w;                   // same as q[0]
q.x;                   // same as q[1]
q.y;                   // same as q[2]
q.z;                   // same as q[3]
q.V();                 // vector composed of x,y,z elements

演算は以下のように行います. まず,クォータニオン同士の積は回転の合成を表します.

Quaterniond q, q0, q1;
q0 = Quaterniond::Rot(Rad(30.0), 'x');   // 30deg rotation along x-axis
q1 = Quaterniond::Rot(Rad(-90.0), 'y');  // -90deg rotationt along y-axis

q = q1 * q0;

つぎに,クォータニオンと3次元ベクトルとの積は,ベクトルの回転を表します.

Vec3d a(1, 0, 0);
Vec3d b = q0 * a;

このように,クォータニオンは基本的に回転行列を同じような感覚で使えます. Quaterniond[f\d]には以下のメンバ関数があります. まず回転軸と回転角度を取得するには

Vec3d axis = q.Axis();        // rotation axis
double angle = q.Theta();     // rotation angle

とします. また,逆回転を表す共役クォータニオンを得るには

q.Conjugate();         // conjugate (reverse rotation)

Quaterniond y;
y = q.Conjugated();    // return conjugated quaternion
y = q.Inv();           // return inverse (normalized conjugate)

とします. Conjugateはそのクォータニオン自体を共役クォータニオンに変換するのに対し, Conjugatedは単位共役クォータニオンを返します. InvConjugatedとほぼ等価ですが,戻り値のノルムが$1$となるように正規化を行います. 回転を表すクォータニオンは理論上は必ずノルムが$1$なので正規化は不要ですが, 実際は数値計算における誤差で次第にノルムがずれてくることがあります. このような誤差を補正するために適宜正規化を行う必要があります.

回転行列と相互変換するには以下のようにします.

Matrix3d R = Matrix3d::Rot(Rad(60.0), 'z');
q.FromMatrix(R);       // conversion from rotation matrix
q.ToMatrix(R);         // conversion to rotation matrix

FromMatrixは渡された回転行列Rと等価なクォータニオンとしてqを設定します. 一方ToMatrixは,参照渡しされたRqと等価な回転行列として設定します.

同様に,以下はオイラー角との相互変換を行います.

Vec3d angle;
q.ToEuler(angle);      // to Euler angle
q.FromEuler(angle);    // from Euler angle

最後に,以下の関数は2つのベクトルに対し,片方をもう片方に一致されるような回転を表すクォータニオンを求めます. 一般に2つのベクトルを一致させる回転は一意ではありませんが,RotationArcは両方のベクトルに直交する軸に関する回転, いわば最短距離の回転を求めます.

Vec3d r0(1, 0, 0), r1(0, 1, 0);
q.RotationArc(r0, r1);    // rotation that maps r0 to r1