我有一个来自传感器设备的 3D 单位四元数 = {w,x,y,z}。我想获得关于 X、Y 和 Z 轴的角度(ax、ay、az)的数量(但角度应该是独立的,当另一个变化时一个不应该改变)。我遇到过,四元数到欧拉角的转换,他们有万向节锁定问题并且他们是依赖项。所以我想采取不同的方法。
取 3D 向量 x = [1,0,0]、y = [0,1,0] 和 z = [0,0,1]。如果我将这些向量 x、y 和 z 旋转四元数,我们会得到 3 个向量 xx、yy 和 zz。然后计算 x, xx 向量之间的角度。类似地,y, yy 和 z, zz 之间的夹角。这似乎也不起作用。以下是我编写的 C# 代码。角度范围应为 -180 到 180 或 0 到 360 度。acos不是首选,因为它存在精度问题。
如何完成这项工作?有标准方法吗?如何将 3D 四元数分解为 3 个四元数,分别用于 X、Y 和 Z 轴?
Vector3D rotVecX = QuatVecRotation(Quaternion, new Vector3D(1,0,0));
Vector3D rotVecY = QuatVecRotation(Quaternion, new Vector3D(0,1,0));
Vector3D rotVecZ = QuatVecRotation(Quaternion, new Vector3D(0,0,1));
float aX = (float)GetXangle(new Vector3D(1, 0, 0), rotVec1);
float aY = (float)GetYangle(new Vector3D(0, 1, 0), rotVec2);
float aZ = (float)GetZangle(new Vector3D(0, 0, 1), rotVec3);
Vector3D QuatVecRotation(Quaternion quat, Vector3D vec)
{
Quaternion Qvec = new Quaternion(0,vec.X,vec.Y,vec.Z);
Quaternion QvecR = Quaternion.Multiply(quat, Qvec);
Quaternion Qinv = new Quaternion( quat.W, -quat.X, -quat.Y, -quat.Z); // conjugate or Inverse
Quaternion Qr = Quaternion.Multiply(QvecR, Qinv);
Vector3D resultVec = new Vector3D(Qr.X, Qr.Y, Qr.Z);
resultVec.Normalize();
return resultVec;
}
public double GetXangle(Vector3D vec1, Vector3D vec2)
{
Vector3D axis = Vector3D.CrossProduct(vec1, vec2);
double angle = Rad2Deg((float)Math.Atan2(axis.Length, Vector3D.DotProduct(vec1, vec2)));
double dir = Vector3D.DotProduct(Vector3D.CrossProduct(axis, vec1), new Vector3D(0, 1, 1));
if(dir<0)
angle = angle * Math.Sign(dir);
return angle;
}