四元数によるベクトルの回転に関する注意

出版構造







ベクトルと回転角の値から四元数を取得する



もう一度- クォータニオンとは何ですか? 開発者にとって、これは主にアクションを説明するツールです-与えられた角度による軸の周りの回転



(w、vx、vy、vz)、



ここで、vはベクトルで表される軸です。

wは、回転(角度の半分の余弦)を記述するコンポーネントです。



回転角度の正の値は、ベクトルの終わりから始まりを見た場合、ベクトルに沿った時計回りの回転を意味します。



たとえば、X軸に沿った90度の回転の四元数の成分の値は次のとおりです。w = 0.7071; x = 0.7071; y = 0; z =0。左または右の座標系、違いはありません-主なことは、すべての操作が同じ座標系で実行されるか、すべてが左またはすべてが右で実行されることです。







次のコード(Visual Basicが手元にあった)を使用して、ベクトルとその周りの回転角度からクォータニオンを取得できます。



Public Function create_quat(rotate_vector As TVector, rotate_angle As Double) As TQuat rotate_vector = normal(rotate_vector) create_quat.w = Cos(rotate_angle / 2) create_quat.x = rotate_vector.x * Sin(rotate_angle / 2) create_quat.y = rotate_vector.y * Sin(rotate_angle / 2) create_quat.z = rotate_vector.z * Sin(rotate_angle / 2) End Function
      
      





コードでは、rotate_vectorはピボット軸を記述するベクトルで、rotate_angleはラジアン単位のピボット角度です。 ベクトルは正規化する必要があります。 つまり、その長さは1に等しくなければなりません。



 Public Function normal(v As TVector) As TVector Dim length As Double length = (vx ^ 2 + vy ^ 2 + vz ^ 2) ^ 0.5 normal.x = vx / length normal.y = vy / length normal.z = vz / length End Function
      
      





長さが0になる可能性がある状況を忘れないでください。エラーの代わりに、この状況を個別に処理する必要がある場合があります。



逆四元数



クォータニオンでベクトルを回転するには、逆回転を行い、クォータニオンを乗算する操作を正しく実行できる必要があります。 逆ピボットとは、逆クォータニオン、つまり反対方向に回転するクォータニオンを意味します。



指定された四元数から逆四元数を取得するには、軸ベクトルを他の方向に回転し、必要に応じて四元数を正規化するだけで十分です。 クォータニオンの正規化とベクトルでは、長さ= 1に単純に縮小されます。



 Public Function quat_scale(q As TQuat, val As Double) As TQuat qw = qw * val ' x qx = qx * val ' x qy = qy * val ' y qz = qz * val ' z quat_scale = q End Function Public Function quat_length(q As TQuat) As Double quat_length = (qw * qw + qx * qx + qy * qy + qz * qz) ^ 0.5 End Function Public Function quat_normalize(q As TQuat) As TQuat Dim n As Double n = quat_length(q) quat_normalize = quat_scale(q, 1 / n) End Function Public Function quat_invert(q As TQuat) As TQuat Dim res As TQuat res.w = qw res.x = -qx res.y = -qy res.z = -qz quat_invert = quat_normalize(res) End Function
      
      





たとえば、Y軸の周りの回転が90度=(w = 0.707; x = 0; y = 0.707; z = 0)の場合、反対の=(w = 0.707; x = 0; y = -0.707; z = 0) 。 Wコンポーネントのみを反転できるように見えますが、180度回転すると0になります。「ターンなし」を意味するクォータニオン=(w = 1; x = 0; y = 0; z = 0)、つまり軸ベクトル長= 0。



四元数の乗算



四元数の乗算は非常に便利です。 乗算の結果はクォータニオンであり、ターン後に乗算されたクォータニオンによって連続して実行された場合、ターン後に同じ結果が得られます。 さらに、回転したベクトルのローカルレポートシステムで反転が発生します。つまり、回転したベクトルのレポートシステムも移動します。







四元数の乗算は次のように実行されます。



 Public Function quat_mul_quat(a As TQuat, b As TQuat) As TQuat Dim res As TQuat res.w = aw * bw - ax * bx - ay * by - az * bz res.x = aw * bx + ax * bw + ay * bz - az * by res.y = aw * by - ax * bz + ay * bw + az * bx res.z = aw * bz + ax * by - ay * bx + az * bw quat_mul_quat = res End Function
      
      





クォータニオンに3Dベクトルを乗算するには、コンポーネントW = 0を割り当ててベクトルをクォータニオンに変換し、クォータニオンにクォータニオンを乗算する必要があります。 または、ゼロを置き換えて、関数として表現します。



 Public Function quat_mul_vector(a As TQuat, b As TVector) As TQuat Dim res As TQuat res.w = -ax * bx - ay * by - az * bz res.x = aw * bx + ay * bz - az * by res.y = aw * by - ax * bz + az * bx res.z = aw * bz + ax * by - ay * bx quat_mul_vector = res End Function
      
      





ベクトルを回転



さて、実際には、四元数によるベクトルの回転:



 Public Function quat_transform_vector(q As TQuat, v As TVector) As TVector Dim t As TQuat t = quat_mul_vector(q, v) t = quat_mul_quat(t, quat_invert(q)) quat_transform_vector.x = tx quat_transform_vector.y = ty quat_transform_vector.z = tz End Function
      
      





例:



軸を記述するベクトル(x = 1; y = 0; z = 1)。 回転角度は180度です。

回転ベクトル(x = 0; y = 0; z = 1)。 結果は(x = 1; y = 0; z = 0)です。







ヨー、ピッチ、ロール



軸の1つを中心とした回転を使用してクォータニオンを形成するツールを検討します。

ヨー=ヘディング=ヨー= Z軸の周り。 ピッチ=高度=ピッチ= y軸の周り; roll = bank = roll = X軸の周り。



 Public Function quat_from_angles_rad(angles As TKrylov) As TQuat Dim q_heading As TQuat Dim q_alt As TQuat Dim q_bank As TQuat Dim q_tmp As TQuat q_heading.x = 0 q_heading.y = 0 q_heading.z = Sin(angles.heading / 2) q_heading.w = Cos(angles.heading / 2) q_alt.x = 0 q_alt.y = Sin(angles.altitude / 2) q_alt.z = 0 q_alt.w = Cos(angles.altitude / 2) q_bank.x = Sin(angles.bank / 2) q_bank.y = 0 q_bank.z = 0 q_bank.w = Cos(angles.bank / 2) q_tmp = quat_mul_quat(q_heading, q_alt) quat_from_angles_rad = quat_mul_quat(q_tmp, q_bank) End Function
      
      





そして、反対方向に、クォータニオンから:



 Public Function quat_to_krylov(q As TQuat) As TKrylov Dim qx2 As Double Dim qy2 As Double Dim qz2 As Double q = quat_normalize(q) '    qx2 = qx * qx qy2 = qy * qy qz2 = qz * qz quat_to_krylov_v3.bank = atan2(2 * (qx * qw + qy * qz), 1 - 2 * (qx2 + qy2)) quat_to_krylov_v3.altitude = Application.WorksheetFunction.Asin(2 * (qy * qw - qz * qx)) quat_to_krylov_v3.heading = atan2(2 * (qz * qw + qx * qy), 1 - 2 * (qy2 + qz2)) End Function
      
      





変換式は、採用された座標系に依存します。



ターンシリーズ



例を考えてみましょう:

1.最初の回転-ヨー(Z周り)時計回りに90度。

2. 2番目の回転-時計回りに90度ピッチ(Y周り)。

3. 3番目の回転-時計回りに90度回転(約X)。



回転を描写し、「グローバル」とラベル付けされた図面は、固定XYZ軸に対する回転を示しています。 ターンのクォータニオンを個別に使用すると、このような結果が得られます。 4番目の図は、初期座標がX = 1の場合のベクトルの位置を示しています。 Y = 0; Z = 0。



「ローカル」とラベル付けされた写真は、平面に沿った軸の回転を示しています。 つまり、すべての回転はパイロットに対して相対的であり、固定座標系に対してではありません。 4番目の図は、3つのターンすべての結果として同じベクトル(1; 0; 0)が表示される場所を示しています。 Uターンのクォータニオンを乗算し、取得したクォータニオンを適用することにより、このような結果を取得します。






















All Articles