taitbryan

Euler angle rotations and their conversions for Tait-Bryan zyx convention

See euler for general discussion of Euler angles and conventions.

This module has specialized implementations of the extrinsic Z axis, Y axis, X axis rotation convention.

The conventions in this module are therefore:

  • axes \(i, j, k\) are the \(z, y, x\) axes respectively. Thus an Euler angle vector \([ \alpha, \beta, \gamma ]\) in our convention implies a \(\alpha\) radian rotation around the \(z\) axis, followed by a \(\beta\) rotation around the \(y\) axis, followed by a \(\gamma\) rotation around the \(x\) axis.
  • the rotation matrix applies on the left, to column vectors on the right, so if R is the rotation matrix, and v is a 3 x N matrix with N column vectors, the transformed vector set vdash is given by vdash = np.dot(R, v).
  • extrinsic rotations - the axes are fixed, and do not move with the rotations.
  • a right-handed coordinate system

The convention of rotation around z, followed by rotation around y, followed by rotation around x, is known (confusingly) as “xyz”, pitch-roll-yaw, Cardan angles, or Tait-Bryan angles.

Terms used in function names:

  • mat : array shape (3, 3) (3D non-homogenous coordinates)
  • euler : (sequence of) rotation angles about the z, y, x axes (in that order)
  • axangle : rotations encoded by axis vector and angle scalar
  • quat : quaternion shape (4,)
axangle2euler(vector, theta) Convert axis, angle pair to Euler angles
euler2axangle(z, y, x) Return angle, axis corresponding to these Euler angles
euler2mat(z, y, x) Return matrix for rotations around z, y and x axes
euler2quat(z, y, x) Return quaternion corresponding to these Euler angles
mat2euler(M[, cy_thresh]) Discover Euler angle vector from 3x3 matrix
quat2euler(q) Return Euler angles corresponding to quaternion q

axangle2euler

transforms3d.taitbryan.axangle2euler(vector, theta)

Convert axis, angle pair to Euler angles

Parameters:

vector : 3 element sequence

vector specifying axis for rotation.

theta : scalar

angle of rotation

Returns:

z : scalar

y : scalar

x : scalar

Rotations in radians around z, y, x axes, respectively

Notes

It’s possible to reduce the amount of calculation a little, by combining parts of the angle_axis2mat and mat2euler functions, but the reduction in computation is small, and the code repetition is large.

Examples

>>> z, y, x = axangle2euler([1, 0, 0], 0)
>>> np.allclose((z, y, x), 0)
True

euler2axangle

transforms3d.taitbryan.euler2axangle(z, y, x)

Return angle, axis corresponding to these Euler angles

Uses the z, then y, then x convention above

Parameters:

z : scalar

Rotation angle in radians around z-axis (performed first)

y : scalar

Rotation angle in radians around y-axis

x : scalar

Rotation angle in radians around x-axis (performed last)

Returns:

vector : array shape (3,)

axis around which rotation occurs

theta : scalar

angle of rotation

Examples

>>> vec, theta = euler2axangle(0, 1.5, 0)
>>> np.allclose(vec, [0, 1, 0])
True
>>> theta
1.5

euler2mat

transforms3d.taitbryan.euler2mat(z, y, x)

Return matrix for rotations around z, y and x axes

Uses the convention of static-frame rotation around the z, then y, then x axis.

Parameters:

z : scalar

Rotation angle in radians around z-axis (performed first)

y : scalar

Rotation angle in radians around y-axis

x : scalar

Rotation angle in radians around x-axis (performed last)

Returns:

M : array shape (3,3)

Rotation matrix giving same rotation as for given angles

Notes

The direction of rotation is given by the right-hand rule. Orient the thumb of the right hand along the axis around which the rotation occurs, with the end of the thumb at the positive end of the axis; curl your fingers; the direction your fingers curl is the direction of rotation. Therefore, the rotations are counterclockwise if looking along the axis of rotation from positive to negative.

Examples

>>> zrot = 1.3 # radians
>>> yrot = -0.1
>>> xrot = 0.2
>>> M = euler2mat(zrot, yrot, xrot)
>>> M.shape == (3, 3)
True

The output rotation matrix is equal to the composition of the individual rotations

>>> M1 = euler2mat(zrot, 0, 0)
>>> M2 = euler2mat(0, yrot, 0)
>>> M3 = euler2mat(0, 0, xrot)
>>> composed_M = np.dot(M3, np.dot(M2, M1))
>>> np.allclose(M, composed_M)
True

When applying M to a vector, the vector should column vector to the right of M. If the right hand side is a 2D array rather than a vector, then each column of the 2D array represents a vector.

>>> vec = np.array([1, 0, 0]).reshape((3,1))
>>> v2 = np.dot(M, vec)
>>> vecs = np.array([[1, 0, 0],[0, 1, 0]]).T # giving 3x2 array
>>> vecs2 = np.dot(M, vecs)

Rotations are counter-clockwise.

>>> zred = np.dot(euler2mat(np.pi/2, 0, 0), np.eye(3))
>>> np.allclose(zred, [[0, -1, 0],[1, 0, 0], [0, 0, 1]])
True
>>> yred = np.dot(euler2mat(0, np.pi/2, 0), np.eye(3))
>>> np.allclose(yred, [[0, 0, 1],[0, 1, 0], [-1, 0, 0]])
True
>>> xred = np.dot(euler2mat(0, 0, np.pi/2), np.eye(3))
>>> np.allclose(xred, [[1, 0, 0],[0, 0, -1], [0, 1, 0]])
True

euler2quat

transforms3d.taitbryan.euler2quat(z, y, x)

Return quaternion corresponding to these Euler angles

Uses the z, then y, then x convention above

Parameters:

z : scalar

Rotation angle in radians around z-axis (performed first)

y : scalar

Rotation angle in radians around y-axis

x : scalar

Rotation angle in radians around x-axis (performed last)

Returns:

quat : array shape (4,)

Quaternion in w, x, y z (real, then vector) format

Notes

Formula from Sympy - see eulerangles.py in derivations subdirectory

mat2euler

transforms3d.taitbryan.mat2euler(M, cy_thresh=None)

Discover Euler angle vector from 3x3 matrix

Uses the conventions above.

Parameters:

M : array-like, shape (3,3)

cy_thresh : None or scalar, optional

threshold below which to give up on straightforward arctan for estimating x rotation. If None (default), estimate from precision of input.

Returns:

z : scalar

y : scalar

x : scalar

Rotations in radians around z, y, x axes, respectively

Notes

If there was no numerical error, the routine could be derived using Sympy expression for z then y then x rotation matrix, (see eulerangles.py in derivations subdirectory):

[                       cos(y)*cos(z),                       -cos(y)*sin(z),         sin(y)],
[cos(x)*sin(z) + cos(z)*sin(x)*sin(y), cos(x)*cos(z) - sin(x)*sin(y)*sin(z), -cos(y)*sin(x)],
[sin(x)*sin(z) - cos(x)*cos(z)*sin(y), cos(z)*sin(x) + cos(x)*sin(y)*sin(z),  cos(x)*cos(y)]

This gives the following solutions for [z, y, x]:

z = atan2(-r12, r11)
y = asin(r13)
x = atan2(-r23, r33)

Problems arise when cos(y) is close to zero, because both of:

z = atan2(cos(y)*sin(z), cos(y)*cos(z))
x = atan2(cos(y)*sin(x), cos(x)*cos(y))

will be close to atan2(0, 0), and highly unstable.

The cy fix for numerical instability in this code is from: Euler Angle Conversion by Ken Shoemake, p222-9 ; in: Graphics Gems IV, Paul Heckbert (editor), Academic Press, 1994, ISBN: 0123361559. Specifically it comes from EulerAngles.c and deals with the case where cos(y) is close to zero:

The code appears to be licensed (from the website) as “can be used without restrictions”.

quat2euler

transforms3d.taitbryan.quat2euler(q)

Return Euler angles corresponding to quaternion q

Parameters:

q : 4 element sequence

w, x, y, z of quaternion

Returns:

z : scalar

Rotation angle in radians around z-axis (performed first)

y : scalar

Rotation angle in radians around y-axis

x : scalar

Rotation angle in radians around x-axis (performed last)

Notes

It’s possible to reduce the amount of calculation a little, by combining parts of the quat2mat and mat2euler functions, but the reduction in computation is small, and the code repetition is large.