方向ベクトル(X、Y、Z)をオイラー角(ヘディング、ピッチ、バンク)に変換する方法を探しています。方向ベクトルだけではバンク角を得るのに十分ではないことを知っているため、別のいわゆるアップベクトルもあります。
方向ベクトル(X、Y、Z)とアップベクトル(X、Y、Z)がある場合、それをオイラー角に変換するにはどうすればよいですか?
正しく理解できるかどうか見てみましょう。これは、飛行中の飛行機のような3次元空間での剛体の方向についてです。その飛行機の機首は方向ベクトル
D=(XD,YD,ZD) .
屋根に向かってアップベクトル
U=(XU,YU,ZU) .
次に、見出しH
は、地表面に投影される方向ベクトルD
になります。
H=(XD,YD,0) ,
関連する角度で
angle_H=atan2(YD,XD) .
ピッチ Pは、水平線に対する機首の上下角度です。方向ベクトルD
が正規化されている場合、
ZD=sin(angle_P)
その結果
angle_P=asin(ZD) .
最後に、バンク角については、翼が体に垂直であると仮定して、翼の方向を考慮します。平面がD
に向かってまっすぐに飛ぶ場合、翼はD
に垂直で、地表面に平行になります。
W0 = ( -YD, XD, 0 )
これは0のバンク角になります。予想されるアップベクトルはW0
に垂直で、D
に垂直です。
U0 = W0 × D
×
は、外積を示します。 U
は、バンク角がゼロの場合はU0
に等しく、そうでない場合はU
とU0
の間の角度はバンク角angle_B
です。
cos(angle_B) = Dot(U0,U) / abs(U0) / abs(U)
sin(angle_B) = Dot(W0,U) / abs(W0) / abs(U) .
ここで、「abs」はベクトルの長さを計算します。それから、次のようにバンク角を取得します
angle_B = atan2( Dot(W0,U) / abs(W0), Dot(U0,U) / abs(U0) ) .
U
とD
が正規化されると、正規化係数は互いに相殺されます。
世界座標系(WCS)で表されるローカル座標系(LCS)のX1、Y1、Z1の3つのベクトルが必要です。以下のコードは、これらの3つのベクトルに基づいて3つのオイラー角を計算する方法を示しています。
#include <math.h>
#include <float.h>
#define PI 3.141592653589793
/**
* @param X1x
* @param X1y
* @param X1z X1 vector coordinates
* @param Y1x
* @param Y1y
* @param Y1z Y1 vector coordinates
* @param Z1x
* @param Z1y
* @param Z1z Z1 vector coordinates
* @param pre precession rotation
* @param nut nutation rotation
* @param rot intrinsic rotation
*/
void lcs2Euler(
double X1x, double X1y, double X1z,
double Y1x, double Y1y, double Y1z,
double Z1x, double Z1y, double Z1z,
double *pre, double *nut, double *rot) {
double Z1xy = sqrt(Z1x * Z1x + Z1y * Z1y);
if (Z1xy > DBL_EPSILON) {
*pre = atan2(Y1x * Z1y - Y1y*Z1x, X1x * Z1y - X1y * Z1x);
*nut = atan2(Z1xy, Z1z);
*rot = -atan2(-Z1x, Z1y);
}
else {
*pre = 0.;
*nut = (Z1z > 0.) ? 0. : PI;
*rot = -atan2(X1y, X1x);
}
}