Skip to main content
PLOS One logoLink to PLOS One
. 2022 Nov 10;17(11):e0276302. doi: 10.1371/journal.pone.0276302

Quaternion to Euler angles conversion: A direct, general and computationally efficient method

Evandro Bernardes 1, Stéphane Viollet 1,*
Editor: Yaodong Gu2
PMCID: PMC9648712  PMID: 36355707

Abstract

Current methods of the conversion between a rotation quaternion and Euler angles are either a complicated set of multiple sequence-specific implementations, or a complicated method relying on multiple matrix multiplications. In this paper a general formula is presented for extracting the Euler angles in any desired sequence from a unit quaternion. This is a direct method, in that no intermediate conversion step is required (no quaternion-to-rotation matrix conversion, for example) and it is general because it works with all 12 possible sequences of rotations. A closed formula was first developed for extracting angles in any of the 12 possible sequences, both “Proper Euler angles” and “Tait-Bryan angles”. The resulting algorithm was compared with a popular implementation of the matrix-to-Euler angle algorithm, which involves a quaternion-to-matrix conversion in the first computational step. Lastly, a single-page pseudo-code implementation of this algorithm is presented, illustrating its conciseness and straightforward implementation. With an execution speed 30 times faster than the classical method, our algorithm can be of great interest in every aspect.

1 Introduction

When dealing with 3D orientation problems, many different formalisms can be used to describe a given rotation [1], each of which has its own set of advantages and shortcomings. Arguably the most direct representation of a 3D rotation is a matrix RSO(3), where SO(3) is the group of invertible 3 × 3 matrices such that det(R) = 1 and RRT=RTR=I, where I is the identity matrix. These rotation matrices represent direct linear transformations such that, with vR3:

vrotated=Rv (1)

Apart from being simple to use, a rotation matrix also has the advantage of being continuous, and a simple matrix multiplication can be used to compose rotations: R = R2R1 is the rotation matrix corresponding to a rotation by R1 followed by a rotation by R2. 3D rotation matrices have some numerical shortcomings, however. For example, as many as 9 numbers (and 6 constraints) are required to represent a 3 degree of freedom rotation, and it can be difficult and computationally costly to orthogonalize a rotation matrix numerically [2] (i.e., to check that the matrix has its determinant equal to 1 and its inverse equal to its transpose, which is necessary to compensate for the accumulated floating point errors).

However, it is possible to parametrize this rotation matrix with a smaller set of numbers [3]. One of the most usual set of parameters are the Euler angles. The approach consists in decomposing the 3D rotation matrix into the product of three rotations:

R=Rθ3e3Rθ2e2Rθ1e1 (2)

Where Rθ e is a rotation by the angle θ around the axis e, and the consecutive axes are orthogonal (e1e2 = e2e3 = 0). The advantages of using Euler angles include the fact that only three numbers have to be stored, and due to their familiarity, they can be more easily understood, which explains why they are still being so widely used, even in cases where other forms of representation may be more appropriate. The use of Euler angles also has several disadvantages. For example, they are discontinuous and it is difficult to directly compose two 3D rotations expressed in Euler angles. Euler angles are also affected by the phenomenon commonly called “gymbal lock”: when two axes become aligned, making the system underdetermined, special care has to be taken. In addition, since there are 12 possible axis sequences (24, when considering the difference between “intrinsic” and “extrinsic” rotations), the correct sequence has to be checked in the case of each application. An arguably preferable parametrization are quaternions. A quaternion is a hypercomplex number defined by one real part and three distinct imaginary parts (which can also be regarded as the vector part). When the norm of a quaternion is equal to 1, quaternions are a useful and efficient representation of 3D orientation: they can be composed as easily as rotation matrices, they are continuous, and they are easily constructed from the axis-angle representation. In addition, quaternions can be normalized trivially, which is much more efficient than having to cope with the corresponding matrix orthogonalization problem. For these reasons, most 3D graphical applications and rotation engines carry quaternions under the hood. Besides these advantages, Euler angles are still being preferred by many authors: Euler angles are the most familiar concept to most engineers and researchers. In addition, in the case of many problems in which there exists only one degree of freedom, angles can suffice.

To be able to perform fast calculations with quaternions and at the same time analyze rotations using angles, it might be necessary to have an efficient method of converting the one set of parameters to the other. Calculating the corresponding quaternion (or rotation matrix) for a given set of Euler angles is trivial. Extracting the Euler angles is much harder, however. One of the following two methods has generally been used up to now. The first method consists in adopting a different set of formulas for each possible angle sequence [4], which is difficult to implement and debug. The second method is that described in [5]. SciPy [6], for example, a widely used scientific library for the Python programming language, implements this method. It converts rotation matrices into Euler angles and involves many different matrix multiplications, including the inverse trigonometric functions required, which are naturally computationally costly. In addition, if rotations are stored in the form of quaternions (as is usually the case in many of the 3D rendering software tools dealing with rotations), an additional conversion step from quaternions to rotation matrices is necessary.

Since many robotic, graphic and other high-level applications involve the use of quaternions (even if they are hidden from the user), it can be necessary to have a concise, efficient method for the conversion between quaternions and Euler angles. The direct conversion formula from quaternions to Euler angles presented here requires fewer computational steps and less expensive computational resources. Moreover, this conversion formula is much simpler to implement and debug, making it a great option for any new applications needing to implement this kind of conversions.

2 Quaternion algebra summary

In this section, the key properties of quaternions are summarized. It is assumed in this work that we are dealing with the classical Hamilton quaternions. Since the definitions concerning quaternion algebra are not perfectly consistent in the literature [7], some of the main notations and definitions used in this study are then presented. Quaternions form a non-commutative division algebra denoted by H, which extends the complex numbers. A quaternion qH consists of four components:

q=qr+qxi+qyj+qzk (3)

Where qr,qx,qy,qzR. All the properties of quaternions can be obtained using its fundamental property, as given by Hamilton:

i2=j2=k2=ijk=-1 (4)

Using the above properties, the product of two quaternions q and p can be expressed by the Hamilton product:

qp=(prqr-pxqx-pyqy-pzqz)+(prqx+pxqr-pyqz+pzqy)i+(prqy+pxqz+pyqr-pzqx)j+(prqz-pxqy+pyqx+pzqr)k (5)

For the sake of simplicity, quaternions will be written here as 4 × 1 vectors (with the scalar qr as the first element):

q=[qrqxqyqz]=[qrq] (6)

Where q=[qxqyqz]T is the the imaginary/vector part of q. The Hamilton product between two quaternions in 4-vector form will be denoted by:

qp=[qrq][prp]=[qrpr-q·pqrp+prq+q×p] (7)

Defining the conjugate q*=[qr-q] and the absolute value as |q|=qr2+qx2+qy2+qz2, the inverse q−1 of q is given by:

q-1=q*|q|2 (8)

And for any quaternion q:

qq-1=q-1q=[10] (9)

If q is a unit quaternion, which means that |q| = 1 and q−1 = q*, it can be used to represent the rotation between two reference frames. Denoting vA and vB a vector v in frames A and B, respectively, and q=qAB the unit quaternion corresponding to the rotation from A to B:

[0vB]=qAB[0vA](qAB)* (10)

The equivalent rotation matrix is given by:

RAB=[qr2+qx2-qy2-qz2-2qrqz+2qxqy2qrqy+2qxqz2qrqz+2qxqyqr2-qx2+qy2-qz2-2qrqx+2qyqz-2qrqy+2qxqz2qrqx+2qyqzqr2-qx2-qy2+qz2] (11)

And the equivalent quaternion for a rotation of an angle θ around an axis e is given by:

qθe=[cos(θ/2)sin(θ/2)e] (12)

3 Formula development

In the section, the formula for the conversion between a quaternion and any of the 6 proper Euler angle sequences is derived, and then an adaptation for the 6 remaining Tait-Bryan sequences is demonstrated.

3.1 Case 1: Proper Euler angles

Assuming q = [qr, qT]T is unit an known, it can be decomposed as follows:

q=[c3s3e][c2s2e][c1s1e] (13)

In which (for 0 ≤ θ2π):

s1sin(θ1/2),c1cos(θ1/2)s2sin(θ2/2),c2cos(θ2/2)s3sin(θ3/2),c3cos(θ3/2) (14)

Where s2 ≥ 0, c2 ≥ 0. Taking e and e′ to be orthogonal unit vectors (ee′ = 0), there is a third unit vector which is orthogonal to the other two such that:

eεe×e (15)

Where ε = (e × e′) ⋅ e′′ = ±1. Together, e, e′ and e′′ form an orthonormal basis. We also define:

θ+=θ1+θ32θ-=θ1-θ32 (16)

And:

s+sin(θ+)=s1c3+c1s3s-sin(θ-)=s1c3-c1s3c+cos(θ+)=s1s3-c1c3c-cos(θ-)=s1s3+c1c3 (17)

Analyzing Eq 13:

q=[c3s3e][c2s2e][c1s1e]=c2[c3s3e][c1s1e]+s2[c3s3e][0e][c1s1e]=c2[c+s+e]+s2[0c-e+s-e×e] (18)

And noting that e × e′ = ε e′′:

q=[c2c+c2s+e+s2c-e+s2s-εe] (19)

Defining the following four components:

[abcd][qrq·eq·eεq·e] (20)

We obtain:

[abcd]=[c2c+c2s+s2c-s2s-] (21)

Alternatively, we can see that [bcd]T is simply a permutation of the components of q:

[bcd]=[eee×e]Tq (22)

3.1.1 Extraction of angles

Using complex numbers, we can define:

z+a+ib=c2(c++is+)z-c+id=s2(c-+is-) (23)

Since c2, s2 ≥ 0, we know that |z+| = c2, arg(z+) = θ+, |z| = s2 and arg(z) = θ. We can then rewrite:

z+=a+ib=c2exp(iθ+)z-=c+id=s2exp(iθ-) (24)

And we know that:

θ+=θ3+θ12=arg{a+ib}=atan2(b,a)θ-=θ3-θ12=arg{c+id}=atan2(d,c) (25)

3.1.2 Singularities

There are two different singularities in these expressions. When θ2 = 0, we have s2 = 0 and θ is undefined. When θ2 = π, we have c2 = 0 and θ+ is undefined. In both cases, one degree of freedom is lost and we can argue that θ1 (or alternatively, θ3) loses its geometrical meaning. We can then either set θ1 to zero, or keep it fixed in its latest value (for example, when updating an estimator, for the sake of continuity). Defining:

θ1θ^1,ifθ2=0orθ2=π (26)

Taking θ^1 to be some constant (zero or otherwise), we can calculate:

{θ3=2atan2(b,a)-θ^1,whenθ2=0θ3=2atan2(d,c)+θ^1,whenθ2=π (27)

3.1.3 General formula for θ1 and θ3 in the absence of singularities

If θ2 ≠ 0 and θ2π/2, multiplying z+ and z yields:

z+z-=(a+ib)(c+id)=c2s2exp(iθ3+θ1+θ3-θ12)=c2s2exp(iθ3) (28)

On similar lines, multiplying z+ and the conjugate of z yields:

z+z-*=(a+ib)(c-id)=c2s2exp(iθ1) (29)

The angles can then be obtained using:

θ1=arg(z+z-*)=arg((a+ib)(c-id))θ3=arg(z+z-)=arg((a+ib)(c+id)) (30)

Or, more simply, from Eq 25:

θ1=arg(a+ib)-arg(c+id)θ3=arg(a+ib)+arg(c+id) (31)

Or:

θ1=θ+-θ-θ3=θ++θ- (32)

It is worth noting that Eq 32 requires fewer operations than Eq 30: only 2 calls to atan2, one addition and one subtraction, but a final wrapping step may be required in order to either keep the angles either in (−π, π] or [0, 2π).

3.1.4 General formulas for calculating θ2

From Eq 24, we know that:

c2=cos(θ2/2)=|z+|=a2+b2s2=sin(θ2/2)=|z-|=c2+d2 (33)

And we can use any of the following equivalent formulas obtained directly from the definition:

θ2=2asin(c2+d2n2)=2acos(a2+b2n2)=2atan(c2+d2a2+b2) (34)

Where the factor n2 = a2 + b2 + c2 + d2 = |q|2 can be ignored if the quaternion is already normalized. Using the properties of inverse trigonometric functions, we can also find the following formula, which avoids the need for a square root:

θ2=acos(2a2+b2n2-1) (35)

3.2 Case 2: Tait-Bryan angles

We now define:

q=[c3s3e][c2s2e][c1s1e] (36)

Where −π/2 < ϕ2 < π/2. Again assuming that e, e′ and e′′ are orthogonal unit vectors and e′′ = ε e × e′, where ε = (e × e′) ⋅ e′′ = ±1, we define:

λ[cos(π/4)sin(π/4)e]=12[1e] (37)

We note that:

λ*[c3s3εe]λ=[c3s3εe×e]=[c3s3e] (38)

Which gives:

q=[c3s3e][c2s2e][c1s1e]q=λ*[c3s3εe]λ[c2s2e][c1s1e]q=[c3s3e][c2s2e][c1s1e] (39)

Where:

s2sinθ2/2(0)c2cosθ2/2(0)s3sinθ3/2c3cosθ3/2 (40)

Where θ2=θ2+π/2 and θ3=εθ3, and:

qλq=12[1e][abe+ce+de]=12[a-c(b+d)e+(c+a)e+(d-b)e] (41)

3.2.1 General formula

Using Eq 41, we can define:

[abcd]=12[a-cb+dc+ad-b] (42)

And then calculate θ1, θ2 and θ3 using the formulas obtained in the proper case. Using the acos formula for θ2, we have:

θ2=θ2-π/2=acos(2a2+b2n2-1)-π/2 (43)

Which results in singularities when θ2=0 or θ2=π, which is equivalent to θ2 = −π/2 or θ2 = π/2, as was to be expected. In addition, we know that when no singularities are present:

θ1=atan2(b,a)-atan2(d,c)θ3=ε(atan2(b,a)+atan2(d,c)) (44)

3.3 Example of a proper sequence: The sequence ZYZ

If we decide to use the sequence ZYZ, then e = ez, e′ = ey and e′′ = ez × ey = −ex. This leads to:

[abcd]=[qrqzqy-qx] (45)

And the general formulas for θ1, θ2 and θ3 (when no singularities are present, and assuming q to have been normalized) are:

θ1=atan2(qz,qr)-atan2(-qx,qy)θ2=acos(2(qr2+qz2)-1)θ3=atan2(qz,qr)+atan2(-qx,qy) (46)

3.4 Second example: The sequence XYZ

Using the sequence XYZ, equivalent to the common aeronautical angles, then e = ex, e′ = ey and e′′ = ez. This leads to:

[abcd]=12[qr-qyqx+qzqy+qrqz-qx] (47)

And the general formulas for θ1, θ2 and θ3 are:

θ1=atan2(qx+qz,qr-qy)-atan2(qz-qx,qy+qr)θ2=acos((qr-qy)2+(qx+qz)2-1)-π/2θ3=atan2(qx+qz,qr-qy)+atan2(qz-qx,qy+qr) (48)

4 Complete algorithm

Algorithm 1, presented in this section, implements the conversion method from this work. Assuming that our inputs are qR4, the rotation quaternion and i, j and kN, an array of integers defining the sequence of angles (for example, [i, j, k] = [323] is equivalent to the sequence ZYZ). A Python implementation can be found on [8].

Algorithm 1: Complete implementation of conversion between a rotation quaternion and Euler angles in any sequence, setting θ1 = 0 in case of singularity.

Input: qR4, and i, j, k ∈ {1, 2, 3}, where ij, jk

Output: θ1, θ2, θ3

if i == k then

not_proper ← False

k ← 6 − ij // because i + j + k = 1 + 2 + 3 = 6

else

not_proper ← True

end

ε ← (ij) × (jk) × (ki)/2 // equivalent to the Levi-Civita symbol

if not_proper then

aq[0] − q[j]

bq[i] + q[k] × ε

cq[j] + q[0]

dq[k] × εq[i]

else

aq[0]

bq[i]

cq[j]

dq[k] × ε

end

θ2acos[2(a2+b2a2+b2+c2+d2)-1]

θ+ ← atan2(b, a)

θ ← atan2(d, c)

switch value of θ2 do

case 0 do

  θ1 ← 0 // For simplicity, we are setting θ^1=0

  θ3 ← 2 × θ+θ1

case π/2 do

  θ1 ← 0

  θ3 ← 2 × θ + θ1

otherwise do

  θ1θ+θ

  θ3θ+ + θ

end

end

if not_proper then

θ3ε × θ3

θ2θ2π/2

end

θ1, θ3 ← (θ1, θ3) // “wrap” assures θ1, θ3 ∈ (−π, π] or θ1, θ3 ∈ [0, 2π)

Many operations are required to convert a quaternion into a rotation matrix. Using the homogeneous formula from Eq 11, for example, if special care is taken in order not to repeat any operations, we have to perform at least 42 = 16 floating point multiplications (all the possible products between two different components of the quaternion, plus all the squares of each component), 4 × 3 = 12 multiplications by 2 and 3 × 3 + 6 = 15 additions/subtractions. This conversion step alone is more than enough to make an algorithm based on [5] much slower than the proposed method. In addition, multiple matrix multiplications also have to be computed. By comparison, our algorithm replaces all the conversions and matrix multiplications by a simple permutation of the quaternion elements and in the case of Tait-Bryan angles, only 5 additional additions/subtractions and possibly a sign change are required.

5 Results

In this section, a performance comparison between our method and the Shuster method is presented. We adapted the SciPy library in order to compile the algorithm as described in Section 4. A real data set comprising the orientation of a spinning object with 3284 data points was used to compare the efficiency of the two algorithms. The full implementation and data set can be downloaded from [8]. First we noted that both methods give the same results: adding the absolute value of the differences between the two methods in a whole data set gives an error of the order of 10−12. The execution times required in our tests for each sequence (and their ratios) are presented in the Table 1. From this test, it can be clearly seen that the method presented here is about 30 times faster.

Table 1. Comparison of execution times between the two methods.

The Python module timeit was used to check the execution time required to convert the whole data set 500 times on an Intel® Core i3-4030U CPU with a 1.90GHz clock speed.

seq new method [5] implemented in [6] ratio
ZYZ 0.487 s 13.770 s 28.261
ZXZ 0.384 s 13.361 s 34.805
XYX 0.382 s 13.381 s 34.998
XZX 0.414 s 13.187 s 31.832
YXY 0.359 s 13.029 s 36.262
YZY 0.375 s 13.078 s 34.884
ZYX 0.371 s 13.152 s 35.408
ZXY 0.364 s 13.124 s 36.048
XYZ 0.373 s 13.170 s 35.291
XZY 0.385 s 13.157 s 34.213
YXZ 0.365 s 13.087 s 35.838
YZX 0.425 s 13.122 s 30.844

6 Conclusion

The Euler angles are still a useful intuitive 3D orientation parametrization. A fast method of conversion to/from any other set of parameters can therefore be of great interest for displaying or analyzing data, for instance. In this study, we therefore developed a general formula for this conversion which is concise, easy to implement and easy to debug. In addition, the fact that our method is about 30 times faster than the method proposed by [5], which required an intermediate conversion into rotation matrices, we believe that our proposed method can be of great interest. This faster execution time also makes this method suitable for use in embedded real time applications such as inertial measurement units (IMUs). We propose that this method could be adopted as the new standard method for converting quaternions into Euler angles, and we are now planning to contributing to several scientific libraries accordingly. Moreover, a possible further development is to generalize this formula for the Davenport angles [9], a generalization of the Euler angles in which any set of distinct non-orthogonal axes are used.

Acknowledgments

We thank J. Blanc for the English improvement.

Data Availability

Data are within the Open Science Foundation repository: https://osf.io/prcmq/.

Funding Statement

The authors received funding from Aix-Marseille university, CNRS and national agency for research (ANR OrigaBot project ANR-18-CE33-0008-0). The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript.

References

  • 1. Shuster M. Survey of attitude representations. Journal of the Astronautical Sciences. 1993;41(4):439–517. [Google Scholar]
  • 2. Sarabandi S, Shabani A, Porta JM, Thomas F. On Closed-Form Formulas for the 3-D Nearest Rotation Matrix Problem. IEEE Transactions on Robotics. 2020;36(4):1333–1339. doi: 10.1109/TRO.2020.2973072 [DOI] [Google Scholar]
  • 3. Stuelpnagel J. On the Parametrization of the Three-Dimensional Rotation Group. Siam Review. 1964;6(4):422–430. doi: 10.1137/1006093 [DOI] [Google Scholar]
  • 4. Henderson D. Euler Angles, Quaternions, and Transformation Matrices. NASA JSC Report. 1977; p. 42. [Google Scholar]
  • 5. Shuster M, Markley L. General Formula for Extracting the Euler Angles. Journal of Guidance Control and Dynamics. 2006;29(1):215–221. doi: 10.2514/1.16622 [DOI] [Google Scholar]
  • 6. Virtanen P, Gommers R, Oliphant TE, Haberland M, Reddy T, Cournapeau D, et al. SciPy 1.0: Fundamental Algorithms for Scientific Computing in Python. Nature Methods. 2020;17:261–272. doi: 10.1038/s41592-019-0686-2 [DOI] [PMC free article] [PubMed] [Google Scholar]
  • 7. Sommer H, Gilitschenski I, Bloesch M, Weiss S, Siegwart R, Nieto J. Why and how to avoid the flipped quaternion multiplication. Aerospace. 2018;5(3):1–15. doi: 10.3390/aerospace5030072 [DOI] [Google Scholar]
  • 8.Quaternion to Euler Scipy implementation; 2022. https://github.com/evbernardes/quaternion_to_euler.
  • 9. Shuster M, Markley L. Generalization of the Euler Angles. Journal of the Astronautical Sciences. 2003;51(2):132–123. doi: 10.1007/BF03546304 [DOI] [Google Scholar]

Associated Data

This section collects any data citations, data availability statements, or supplementary materials included in this article.

Data Availability Statement

Data are within the Open Science Foundation repository: https://osf.io/prcmq/.


Articles from PLOS ONE are provided here courtesy of PLOS

RESOURCES