如何将欧拉角转换为四元数并从四元数中获得相同的欧拉角?

时间:2018-10-28 16:24:28

标签: python math graphics rotation quaternions

我正在使用XYZ顺序的Euler角旋转n个3D形状,这意味着对象首先沿X轴旋转,然后依次沿YZ旋转。我想将Euler角转换为四元数,然后使用一些[最好] Python代码或仅使用一些伪代码或算法,从四元数中获得相同的Euler角。下面,我有一些代码将Euler角转换为四元数,然后将四元数转换为Euler角。但是,这并不能给我相同的欧拉角。

我认为问题是我不知道如何将偏航,俯仰和横滚与X,Y和Z轴相关联。另外,我不知道如何更改代码中的转换顺序,以正确地将Euler角转换为四元数,然后将四元数转换为Euler角,这样我就可以获得相同的Euler角。有人可以帮我吗?

这是我使用的代码:

此函数将欧拉角转换为四元数:

def euler_to_quaternion(yaw, pitch, roll):

        qx = np.sin(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) - np.cos(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)
        qy = np.cos(roll/2) * np.sin(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.cos(pitch/2) * np.sin(yaw/2)
        qz = np.cos(roll/2) * np.cos(pitch/2) * np.sin(yaw/2) - np.sin(roll/2) * np.sin(pitch/2) * np.cos(yaw/2)
        qw = np.cos(roll/2) * np.cos(pitch/2) * np.cos(yaw/2) + np.sin(roll/2) * np.sin(pitch/2) * np.sin(yaw/2)

        return [qx, qy, qz, qw]

这会将四元数转换为欧拉角:

def quaternion_to_euler(x, y, z, w):

        import math
        t0 = +2.0 * (w * x + y * z)
        t1 = +1.0 - 2.0 * (x * x + y * y)
        X = math.degrees(math.atan2(t0, t1))

        t2 = +2.0 * (w * y - z * x)
        t2 = +1.0 if t2 > +1.0 else t2
        t2 = -1.0 if t2 < -1.0 else t2
        Y = math.degrees(math.asin(t2))

        t3 = +2.0 * (w * z + x * y)
        t4 = +1.0 - 2.0 * (y * y + z * z)
        Z = math.degrees(math.atan2(t3, t4))

        return X, Y, Z

我按如下方式使用它们:

import numpy as np
euler_Original = np.random.random(3) * 360).tolist() # Generate random rotation angles for XYZ within the range [0, 360)
quat = euler_to_quaternion(euler_Original[0], euler_Original[1], euler_Original[2]) # Convert to Quaternion
newEulerRot = quaternion_to_euler(quat[0], quat[1], quat[2], quat[3]) #Convert the Quaternion to Euler angles

print (euler_Original)
print (newEulerRot)

打印语句为euler_OriginalnewEulerRot打印不同的数字,我不想这样。例如,如果euler_original包含以弧度表示的(0.2, 1.12, 2.31)之类的数字,我得到这个四元数-> [0.749, 0.290, -0.449, 0.389]并将四元数转换为欧拉角就得到了-> (132.35, 64.17, 11.45)错了。我不知道该如何解决?

尽管我有兴趣通过更改上面的代码来使上面的代码起作用,但是,我宁愿学习如何正确设置方程式。这样,即使改变了应用欧拉角的旋转顺序(XYZ-> YZX等),我也将知道如何获得正确的四元数。

2 个答案:

答案 0 :(得分:3)

我们可以使用glob()中的Rotation

scipy.spatial.transform

结果将是:

from scipy.spatial.transform import Rotation

# Create a rotation object from Euler angles specifying axes of rotation
rot = Rotation.from_euler('xyz', [90, 45, 30], degrees=True)

# Convert to quaternions and print
rot_quat = rot.as_quat()
print(rot_quat)

然后,您也可以以欧拉角将其取回:

[ 0.56098553  0.43045933 -0.09229596  0.70105738]

这将导致:

print(rot.as_euler('xyz', degrees=True))

作为最终检查,从上面计算的四元数创建一个旋转对象,并将其作为欧拉角:

[90. 45. 30.]

这将导致:

rot = Rotation.from_quat(rot_quat)

# Convert the rotation to Euler angles given the axes of rotation
print(rot.as_euler('xyz', degrees=True))

答案 1 :(得分:2)

主要问题

  

euler_to_quaternion的输入顺序与quaternion_to_euler的输出顺序不同

前者按Z, Y, X(偏航,俯仰,侧倾)的顺序取角,而后者返回X, Y, Z。修复:

def euler_to_quaternion(roll, pitch, yaw):
# or
euler_to_quaternion(euler_Original[2], euler_Original[1], euler_Original[0])

次要问题

  

euler_to_quaternion取弧度,而quaternion_to_euler返回度数。

本质上这并不是一个真正的问题,但是最好将弧度角保持为弧度,因为大多数库函数都使用它们。

X = math.atan2(t0, t1)
Y = math.asin(t2)
Z = math.atan2(t3, t4)