由四元数旋转的3D中的两个3D矢量之间的角度

时间:2013-10-07 09:10:20

标签: vector 3d angle quaternions euler-angles

我有来自传感器设备的3D单位四元数= {w,x,y,z}。我想获得关于X,Y和Z轴的角度(ax,ay,az)(但是角度应该独立,当另一个变化时,不应该改变)。我遇到过, Quaternion Euler 角度转换,他们有万向节锁问题&他们是家属。 所以我想采取不同的方法。

取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至360deg。 acos 不是首选,因为它有精确问题。

如何完成这项工作?有标准方法吗?如何将3D四元数分解为单个X,Y和Z轴的3个四元数?

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;
    }

3 个答案:

答案 0 :(得分:0)

使用点积:

x·xx = | x || xx | cos(角度)

这样:

angle = acos(x·xx /(| x || xx |))

答案 1 :(得分:0)

如果从四元数得到的欧拉角变大,那么我们将遇到万向节锁定问题,如果它们较小(在两个连续的四元数之间),则应该没有问题。我们可能只是将当前角度添加到之前的角度&amp;可以使它们达到理想的范围。

答案 2 :(得分:0)

我建议先计算Rodriguez旋转。这很简单

考虑到你有两个向量 a b

旋转轴将由其叉积 N = a x b 定义。

旋转角度将由其标准化点积定义 cos(theta)= a * b /(|| a |||| b ||)< / p>

在Rodriguez旋转和它的四元数之间转换的公式是here