DEV Community

Shoichi Okaniwa
Shoichi Okaniwa

Posted on • Originally published at qiita.com

Pythonでクォータニオンをz-y-x系オイラー角に変換するコード書いてみた

Writing Code to Convert Quaternions to Z-Y-X Euler Angles in Python

I needed to calculate Z-Y-X Euler angles from quaternions.

Moreover, the task required me to write the code in Python 2.7, so I couldn't use handy tools like scipy.spatial.transform.Rotation.

When I did some research, I found a sample code in C++ on Wikipedia.

Wikipedia / Quaternion to Euler Angles Conversion

Writing in Python

Based on the Wikipedia sample code, I created a code in Python 2.7.

import math
import numpy as np
from pyquaternion import Quaternion

def quaternion_to_euler_zyx(q):
    """
    Convert quaternion to Z-Y-X Euler angles.

    Parameters
    ----------
    q : Quaternion
        Quaternion (in pyquaternion format)

    Returns
    -------
    np.array
        Z-Y-X Euler angles
    """

    # roll : rotation around x-axis
    sinr_cosp = 2 * (q[0] * q[1] + q[2] * q[3])
    cosr_cosp = 1 - 2 * (q[1] * q[1] + q[2] * q[2])
    roll = math.atan2(sinr_cosp, cosr_cosp)

    # pitch : rotation around y-axis
    sinp = 2 * (q[0] * q[2] - q[3] * q[1])
    if math.fabs(sinp) >= 1:
        pitch = math.copysign(math.pi / 2, sinp)
    else:
        pitch = math.asin(sinp)

    # yaw : rotation around z-axis
    siny_cosp = 2 * (q[0] * q[3] + q[1] * q[2])
    cosy_cosp = 1 - 2 * (q[2] * q[2] + q[3] * q[3])
    yaw = math.atan2(siny_cosp, cosy_cosp)

    # Euler angles
    return np.array([
        math.degrees(roll), 
        math.degrees(pitch), 
        math.degrees(yaw)
    ])
Enter fullscreen mode Exit fullscreen mode

Dependencies

NumPy 1.16.6

Used for vector calculations. Version 1.16.6 seems to be the latest one supporting Python 2.7.

PyQuaternion 0.9.5

PyQuaternion is used for quaternion calculations.

While numpy-quaternion might work better with NumPy, it could not be installed in the Python 2.7 environment.

Easier with SciPy in Python 3

Using scipy.spatial.transform.Rotation makes it simpler if you're using Python 3 or later.

import numpy as np
from pyquaternion import Quaternion
from scipy.spatial.transform import Rotation as R

def quaternion_to_euler_zyx(q):
    r = R.from_quat([q[0], q[1], q[2], q[3]])
    return r.as_euler('zyx', degrees=True)
Enter fullscreen mode Exit fullscreen mode

Unfortunately, scipy.spatial.transform.Rotation does not support Python 2.7.

Conclusion

I'm mostly accustomed to dealing with Unity's Z-X-Y Euler angles, so working with Z-Y-X was quite confusing. I referred to the following articles while creating this post. Thank you for the detailed insights!

Top comments (0)