irfpy.util.eulerangle

Implementation on Euler angle.

Euler angle is a set of three angles to represent any rotation in 3D.

See https://en.wikipedia.org/wiki/Euler_angles for better description.

class irfpy.util.eulerangle.EulerAngleZXZ(alpha, beta, gamma)[source]

Bases: object

Z-X-Z Euler angle

Z-X-Z Euler angle

Z-X-Z Euler angle, represented by the angles \(\alpha, \beta, \gamma\).

Also, see figure https://commons.wikimedia.org/wiki/File:Eulerangles.svg for reference.

Parameters:
  • alpha\(\alpha\) in radians. No restriction of the range.

  • beta\(\beta\) in radians. No restriction of the range.

  • gamma\(\gamma\) in radians. No restriction of the range.

  1. Rotate \(\alpha\) with respective to z. Range -\(\pi\) to \(\pi\), theoretically

  2. Rotate \(\beta\) with respective to new x. Range 0 to \(\pi\), theoretically

  3. Rotate \(\gamma\) with respective to new z. Range -\(\pi\) to \(\pi\), theoretically

get_matrix3d_rot_frm()[source]

Return the conversion matrix of the vector components.

Let us think a fixed vector. The vector is expressed by components of the original frame (x, y, z). Then, the frame (x, y, z) is rotated to (X, Y, Z) according to the Euler angles. The fixed vector is expressed by components of (X, Y, Z). The obtained matrix, R, shows the relation of

\[\begin{split}\left(\begin{array}{c} X \\ Y \\ Z \end{array}\right) = R\cdot \left(\begin{array}{c} x \\ y \\ z \end{array}\right)\end{split}\]
Returns:

(3, 3) shaped np.array, R

get_matrix3d_rot_vec()[source]

Return the rotation matrix for the vector.

Let us think a vector in the original system, (x, y, z). The vector is rotated according to the Euler angles. The rotated vector is expressed in the original frame \((x', y', z')\).

The obtained matrix, M, exhibids the relation of

\[\begin{split}\left(\begin{array}{c} x' \\ y' \\ z' \end{array}\right) = M\cdot \left(\begin{array}{c} x \\ y \\ z \end{array}\right)\end{split}\]
Returns:

(3,3) shaped np.array, M

>>> import numpy as np
>>> from irfpy.util.nptools import trim_epsilon as trim
>>> alpha = np.pi / 2    # 90 deg
>>> euler_zxz = EulerAngleZXZ(alpha, 0, 0)    # This will give the rotation of axes of x -> y and y -> -x.
>>> euler_m_vec = euler_zxz.get_matrix3d_rot_vec()
>>> v2 = euler_m_vec.dot((1, 0, 0))     # x-axis is converted to y
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
0.00 1.00 0.00
>>> v2 = euler_m_vec.dot((0, 1, 0))     # y-axis is conveted to -x
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
-1.00 0.00 0.00
>>> beta = np.pi / 2    # 90 deg
>>> euler_zxz = EulerAngleZXZ(alpha, beta, 0)   # This will give x->y->y, y->-x->z, z->z->x.
>>> euler_m_vec = euler_zxz.get_matrix3d_rot_vec()
>>> v2 = euler_m_vec.dot((1, 0, 0))     # x-axis is converted to y
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
0.00 1.00 0.00
>>> v2 = euler_m_vec.dot((0, 1, 0))     # y-axis is conveted to z
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
0.00 0.00 1.00
>>> v2 = euler_m_vec.dot((0, 0, 1))     # z-axis is conveted to x
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
1.00 0.00 0.00
>>> gamma = np.pi / 2   # 90 deg
>>> euler_zxz = EulerAngleZXZ(alpha, beta, gamma)   # This will give x->y->y->z, y->-x->z->-y, z->z->x->x.
>>> euler_m_vec = euler_zxz.get_matrix3d_rot_vec()
>>> v2 = euler_m_vec.dot((1, 0, 0))     # x-axis is converted to z
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
0.00 0.00 1.00
>>> v2 = euler_m_vec.dot((0, 1, 0))     # y-axis is conveted to -y
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
0.00 -1.00 0.00
>>> v2 = euler_m_vec.dot((0, 0, 1))     # z-axis is conveted to x
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trim(v2)))
1.00 0.00 0.00
rotate_vectors(vec)[source]

Rotate the vectors.

Parameters:

vec – Vector, shaped with (…, 3)

Returns:

The rotated vector. Same shape as input.

The vector is rotated according to the Euler angle. See get_matrix3d_rot_vec().

>>> import numpy as np
>>> from irfpy.util.nptools import trim_epsilon as trimep    # To trim the very small floating points from matrix
>>> alpha = beta = gamma = np.pi / 2.
>>> euler_zxz = EulerAngleZXZ(alpha, beta, gamma)   # This will give x->y->y->z, y->-x->z->-y, z->z->x->x.
>>> v1 = [1, 0, 0]
>>> v2 = [0, 1, 0]
>>> v3 = [0, 0, 1]
>>> v4 = [-1, 0, 0]
>>> v5 = [0, -1, 0]
>>> v6 = [0, 0, -1]
>>> v = np.array([v1, v2, v3, v4, v5, v6])
>>> print(v.shape)
(6, 3)
>>> vr = euler_zxz.rotate_vectors(v)   # Rotate six vectors at once.
>>> print(vr.shape)
(6, 3)
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trimep(vr[0])))   # +x to +z
0.00 0.00 1.00
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trimep(vr[1])))   # +y to -y
0.00 -1.00 0.00
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trimep(vr[2])))   # +z to +x
1.00 0.00 0.00
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trimep(vr[3])))   # -x to -z
0.00 0.00 -1.00
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trimep(vr[4])))   # -y to +y
0.00 1.00 0.00
>>> print('{v[0]:.2f} {v[1]:.2f} {v[2]:.2f}'.format(v=trimep(vr[5])))   # -z to -x
-1.00 0.00 0.00
irfpy.util.eulerangle.matrix3d_rot_vec_z(angle_radian)[source]

Return the 3D matrix that rotate a vector by a given angle with respective to z.

Parameters:

angle_radian – The angle \(\theta\), in radians.

Returns:

Matrix, M.

Theory

\[\begin{split}\mathbf{M} = \left(\begin{array}{ccc} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{array}\right)\end{split}\]

Any vector \(\vec{v}\) will be rotated by \(\theta\) with

\[\vec{v'} = \mathbf{M}\vec{v}\]
         y
    v'   ^     v
    \    |    /
     \   |   /
theta \<-|--/
       \ | /
        \|/
         +-----------------> x

Example

Obtain the 30 degree’s rotation matrix.

>>> import numpy as np
>>> rot30z = matrix3d_rot_vec_z(np.deg2rad(30))
>>> print(rot30z)
[[ 0.8660254 -0.5        0.       ]
 [ 0.5        0.8660254  0.       ]
 [ 0.         0.         1.       ]]

The vector (1, 0, 0) will be rotated to (sqrt(3)/2, 1/2, 0)

>>> x0 = (1, 0, 0)
>>> x1 = rot30z.dot(x0)
>>> print(x1)
[0.8660254 0.5       0.       ]

The vector (0, 1, 0) will be rotated to (-1/2, sqrt(3)/2, 0)

>>> y0 = (0, 1, 0)
>>> y1 = rot30z.dot(y0)
>>> print(y1)
[-0.5        0.8660254  0.       ]
irfpy.util.eulerangle.matrix3d_rot_frm_z(angle_radian)[source]

Return the 3D matrix that convert a vector to the frame rotated by a given angle with respective to z.

Parameters:

angle_radian – The angle \(\alpha\), in radians.

Returns:

The conversion matrix, R.

Theory

\[\begin{split}\mathbf{R} = \left(\begin{array}{ccc} \cos\theta & \sin\theta & 0 \\ -\sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end{array}\right)\end{split}\]

It is the inverse matrix of the matrix M obtained in matrix3d_rot_vec_z(). As M is an orthogonal matrix, the inverse is the same as transpose.

\[R = M^{-1} (=M^{T})\]

Let the original frame, (x, y, z), and rotate the frame by 45 degrees with respective to z axis. Let us denote the new frame as (X, Y, Z).

Then the components of the vector \(\vec{v}\) expressed in (x, y, z) frame is different from those in (X, Y, Z). The relation is

\[\vec{v}_{XYZ} = R \vec{v}_{xyz}\]
           y      X
Y          ^     /    v
  \        |    /    /
    \      |   /\  /
      \    |  /  /
        \  | / /  \  theta
          \|//     \
           +-----------------> x
>>> import numpy as np
>>> vec_xyz = (1, 0, 0)

Then, consider a vector, \(\vec{v}=(1, 0, 0)\) in the original frame, (x, y, z). If we see the vector in the new frame (X, Y, Z). It can be done with

>>> r_mat = matrix3d_rot_frm_z(np.deg2rad(30))
>>> vec_XYZ = r_mat.dot(vec_xyz)
>>> print(vec_XYZ)
[ 0.8660254 -0.5        0.       ]
irfpy.util.eulerangle.matrix3d_rot_vec_x(angle_radian)[source]

Return the 3D matrix that rotate a vector by a given angle with respective to x.

Parameters:

angle_radian – The angle \(\theta\), in radians.

Returns:

Matrix, M.

Theory

\[\begin{split}\mathbf{M} = \left(\begin{array}{ccc} 1 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta\\ 0 & \sin\theta & \cos\theta \end{array}\right)\end{split}\]
         z
    v'   ^     v
    \    |    /
     \   |   /
theta \<-|--/
       \ | /
        \|/
         +-----------------> y

Example

Obtain the 30 degree’s rotation matrix.

>>> import numpy as np
>>> rot30x = matrix3d_rot_vec_x(np.deg2rad(30))
>>> print(rot30x)
[[ 1.         0.         0.       ]
 [ 0.         0.8660254 -0.5      ]
 [ 0.         0.5        0.8660254]]

The vector (0, 1, 0) will be rotated to (0, sqrt(3)/2, 1/2)

>>> y0 = (0, 1, 0)
>>> y1 = rot30x.dot(y0)
>>> print(y1)
[0.        0.8660254 0.5      ]

The vector (0, 0, 1) will be rotated to (0, -1/2, sqrt(3)/2)

>>> z0 = (0, 0, 1)
>>> z1 = rot30x.dot(z0)
>>> print(z1)
[ 0.        -0.5        0.8660254]
irfpy.util.eulerangle.matrix3d_rot_frm_x(angle_radian)[source]

Return the 3D matrix that convert a vector to the frame rotated by a given angle with respective to x.

Parameters:

angle_radian – The angle \(\alpha\), in radians.

Returns:

The conversion matrix, R.

Theory

\[\begin{split}\mathbf{R} = \left(\begin{array}{ccc} 1 & 0 & 0 \\ 0 & \cos\theta & \sin\theta \\ 0 & -\sin\theta & \cos\theta \end{array}\right)\end{split}\]

It is the inverse matrix of the matrix M obtained in matrix3d_rot_vec_x(). As M is an orthogonal matrix, the inverse is the same as transpose.

\[R = M^{-1} (=M^{T})\]

Let the original frame, (x, y, z), and rotate the frame by 45 degrees with respective to x axis. Let us denote the new frame as (X, Y, Z).

Then the components of the vector \(\vec{v}\) expressed in (x, y, z) frame is different from those in (X, Y, Z). The relation is

\[\vec{v}_{XYZ} = R \vec{v}_{xyz}\]
           z      Y
Z          ^     /    v
  \        |    /    /
    \      |   /\  /
      \    |  /  /
        \  | / /  \  theta
          \|//     \
           +-----------------> y
>>> import numpy as np
>>> vec_xyz = (0, 1, 0)

Then, consider a vector, \(\vec{v}=(0, 1, 0)\) in the original frame, (x, y, z). If we see the vector in the new frame (X, Y, Z). It can be done with

>>> r_mat = matrix3d_rot_frm_x(np.deg2rad(30))
>>> vec_XYZ = r_mat.dot(vec_xyz)
>>> print(vec_XYZ)
[ 0.         0.8660254 -0.5      ]
irfpy.util.eulerangle.matrix3d_rot_vec_y(angle_radian)[source]

Return the 3D matrix that rotate a vector by a given angle with respective to y.

Parameters:

angle_radian – The angle \(\theta\), in radians.

Returns:

Matrix, M.

Theory

\[\begin{split}\mathbf{M} = \left(\begin{array}{ccc} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{array}\right)\end{split}\]

Any vector \(\vec{v}\) will be rotated by \(\theta\) with

\[\vec{v'} = \mathbf{M}\vec{v}\]
         x
    v'   ^     v
    \    |    /
     \   |   /
theta \<-|--/
       \ | /
        \|/
         +-----------------> z

Example

Obtain the 30 degree’s rotation matrix.

>>> import numpy as np
>>> rot30y = matrix3d_rot_vec_y(np.deg2rad(30))
>>> print(rot30y)
[[ 0.8660254  0.         0.5      ]
 [ 0.         1.         0.       ]
 [-0.5        0.         0.8660254]]

The vector (1, 0, 0) will be rotated to (sqrt(3)/2, 0, -1/2)

>>> x0 = (1, 0, 0)
>>> x1 = rot30y.dot(x0)
>>> print(x1)
[ 0.8660254  0.        -0.5      ]

The vector (0, 0, 1) will be rotated to (1/2, 0, sqrt(3)/2)

>>> z0 = (0, 0, 1)
>>> z1 = rot30y.dot(z0)
>>> print(z1)
[0.5       0.        0.8660254]
irfpy.util.eulerangle.matrix3d_rot_frm_y(angle_radian)[source]

Return the 3D matrix that convert a vector to the frame rotated by a given angle with respective to y.

Parameters:

angle_radian – The angle \(\alpha\), in radians.

Returns:

The conversion matrix, R.

Theory

\[\begin{split}\mathbf{R} = \left(\begin{array}{ccc} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{array}\right)\end{split}\]

It is the inverse matrix of the matrix M obtained in matrix3d_rot_vec_y(). As M is an orthogonal matrix, the inverse is the same as transpose.

\[R = M^{-1} (=M^{T})\]

Let the original frame, (x, y, z), and rotate the frame by 45 degrees with respective to z axis. Let us denote the new frame as (X, Y, Z).

Then the components of the vector \(\vec{v}\) expressed in (x, y, z) frame is different from those in (X, Y, Z). The relation is

\[\vec{v}_{XYZ} = R \vec{v}_{xyz}\]
           x      Z
X          ^     /    v
  \        |    /    /
    \      |   /\  /
      \    |  /  /
        \  | / /  \  theta
          \|//     \
           +-----------------> z
>>> import numpy as np
>>> vec_xyz = (1, 0, 0)

Then, consider a vector, \(\vec{v}=(1, 0, 0)\) in the original frame, (x, y, z). If we see the vector in the new frame (X, Y, Z). It can be done with

>>> r_mat = matrix3d_rot_frm_y(np.deg2rad(30))
>>> vec_XYZ = r_mat.dot(vec_xyz)
>>> print(vec_XYZ)
[0.8660254 0.        0.5      ]