6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-03-26

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

クォータニオンからz-y-x系オイラー角の計算をしなければならなくなりました。

しかも、Python2.7で書かなければいけない案件なので、scipy.spatial.transform.Rotation みたいな便利なやつ使えません。

公式を調べてみたら、WikipediaにC++のサンプルコードが載っていました。

Wikipedia / Quaternion to Euler Angles Conversion

Pythonで書いてみた

Wikipediaのサンプルコードを参考にして、Python2.7のコードを書いてみました。

import math
import numpy as np
from pyquaternion import Quaternion

def quaternion_to_euler_zyx(q):
    """
    クォータニオンをz-y-x系オイラー角に変換する。

    Parameters
    ----------
    q : Quaternion
        クォータニオン(pyquaternion形式)

    Returns
    -------
    np.array
        z-y-x系オイラー角
    """

    # roll : x軸回転
    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 : y軸回転
    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 : z軸回転
    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)
    
    # オイラー角
    retrun np.array([
        math.degrees(roll), 
        math.degrees(pitch), 
        math.degrees(yaw)
    ])

依存ライブラリ

numpy 1.16.6

ベクトル計算とかに使うやつです。1.16.6がPython2.7対応の中では最新っぽいです。

pyquaternion 0.9.5

Quaternionの計算に pyquaternion 使ってます。

numpy-quaternion の方がnumpyと相性はよさそうなのですが、Python2.7環境だとインストールできませんでした。

Python3以降ならscipy.spatial.transform.Rotationが楽

scipy.spatial.transform.Rotation を使えば、もっとシンプルに書けそうです。

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)

ただ、 scipy.spatial.transform.Rotation はPython2.7には対応してないみたいです。残念。

さいごに

普段はUnityのz-x-y系オイラー角ばかり触ってるので、z-y-x系はかなり混乱しました。
本記事作成にあたり、以下の記事を参考にさせていただきました。ありがとうございました!

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?