我得到了前左上 (FLU) 坐标系中对象 [w, x, y, z] 的四元数数据,我想将其转换为前右下 (FRD) 坐标系中的四元数数据。在 C++14 中执行此操作最有效的方法是什么?
我尝试翻转 y 和 z 值上的符号,但我读到了关于这是否是正确方法的相互矛盾的信息。
#include <Eigen/Eigen>
#include <iostream>
using namespace Eigen;
Eigen::Quaterniond FLUtoFRD(const Eigen::Quaterniond& flu) {
double angle = M_PI; // pi radians for 180 degrees
Eigen::Vector3d rotationAxis = Eigen::Vector3d::UnitX();
Eigen::AngleAxisd rotX_axis(angle, rotationAxis);
Eigen::Quaterniond rotX(rotX_axis);
return rotX * flu * rotX.inverse();
}
int main() {
Eigen::Quaterniond flu(0.7071, 0.69, 0.77, 0);
Eigen::Quaterniond frd = FLUtoFRD(flu);
std::cout << "FRD quaternion: \n" << frd.coeffs() << std::endl;
return 0;
}
绕 x 旋转 180 度的四元数变换为:
qFLU2FRD = (w,x,y,z) = (cos(pi/2),sin(pi/2),0,0) = (0,1,0,0)
然后是你的原始四元数采用什么约定的问题。如果你的原始qFLU表示汉密尔顿被动坐标系变换,那么连续的坐标系变换在右侧叠加,你会得到:
qFRD = qFLU * qFLU2FRD
否则你会得到:
qFRD = qFLU2FRD * qFLU
我不熟悉 Eigen 包的四元数约定,因此无法建议您其中哪一个对于您的特定问题是正确的。要查看该四元数翻转 y 和 z 元素的符号,请使用 MATLAB 假设被动汉密尔顿约定的示例:
>> a = 1:3 % an arbitrary vector in FLU
a =
1 2 3
>> qa = quaternion([0,a]) % a as quaternion
qa =
quaternion
0 + 1i + 2j + 3k
>> qFLU2FRD = quaternion(cosd(180/2), sind(180/2), 0, 0)
qFLU2FRD =
quaternion
0 + 1i + 0j + 0k
>> conj(qFLU2FRD) * qa * qFLU2FRD % rotate the vector a
ans =
quaternion
0 + 1i - 2j - 3k
如您所见,y 和 z 元素按预期翻转了符号。
由于我们知道 qFLU2FRD 的形式,因此我们可以简单地符号化 qFLU * qFLU2FRD 来查看四元数如何变化,再次使用 MATLAB:
>> syms qw qx qy qz % the elements of qFLU
>> qv = [qx,qy,qz] % the vector part of qFLU
qv =
[ qx, qy, qz]
>> pw = 0 % the scalar part of qFLU2FRD
pw =
0
>> pv = [1 0 0] % the vector part of qFLU2FRD
pv =
1 0 0
>> qpw = qw*pw - sum(qv.*pv) % the scalar part of qFLU * qFLU2FRD
qpw =
-qx
>> qpv = qw*pv + pw*qv + cross(qv,pv) % the vector part of qFLU * qFLU2FRD
qpv =
[ qw, qz, -qy]
因此,如果 qFLU = (qw,qx,qy,qz),则 qFRD = (-qx,qw,qz,-qy)。即,您可以进行一些简单的元素+符号交换来获得新的四元数。