Euler Angles
The Euler Angles are defined by the following immutable structure:
struct EulerAngles{T}
a1::T
a2::T
a3::T
rot_seq::Symbol
endin which a1, a2, and a3 define the angles and the rot_seq is a symbol that defines the axes. The valid values for rot_seq are:
:XYX,:XYZ,:XZX,:XZY,:YXY,:YXZ,:YZX,:YZY,:ZXY,:ZXZ,:ZYX, andZYZ.
The constructor for this structure is:
function EulerAngles(a1::T1, a2::T2, a3::T3, rot_seq::Symbol = :ZYX) where {T1,T2,T3}in which a EulerAngles with angles a1, a2, and a3 [rad] and rotation sequence rot_seq will be created. Notice that the type of the returned structure will be selected according to the input types T1, T2, and T3. If rot_seq is omitted, then it defaults to :ZYX.
julia> EulerAngles(1, 1, 1)EulerAngles{Int64}: R(Z) : 1 rad ( 57.2958°) R(Y) : 1 rad ( 57.2958°) R(X) : 1 rad ( 57.2958°)julia> EulerAngles(1, 1, 1.0f0, :XYZ)EulerAngles{Float32}: R(X) : 1.0 rad ( 57.2958°) R(Y) : 1.0 rad ( 57.2958°) R(Z) : 1.0 rad ( 57.2958°)julia> EulerAngles(1., 1, 1, :XYX)EulerAngles{Float64}: R(X) : 1.0 rad ( 57.2958°) R(Y) : 1.0 rad ( 57.2958°) R(X) : 1.0 rad ( 57.2958°)
Operations
Multiplication
The multiplication of two Euler angles is defined here as the composition of the rotations. Let $\Theta_1$ and $\Theta_2$ be two sequences of Euler angles (instances of the structure EulerAngles). Thus, the operation:
\[\Theta_{2,1} = \Theta_2 \cdot \Theta_1\]
will return a new set of Euler angles $\Theta_{2,1}$ that represents the composed rotation of $\Theta_1$ followed by $\Theta_2$. Notice that $\Theta_{2,1}$ will be represented using the same rotation sequence as $\Theta_2$.
julia> a1 = EulerAngles(1, 0, 0, :ZYX)EulerAngles{Int64}: R(Z) : 1 rad ( 57.2958°) R(Y) : 0 rad ( 0.0°) R(X) : 0 rad ( 0.0°)julia> a2 = EulerAngles(0, -1, 0, :YZY)EulerAngles{Int64}: R(Y) : 0 rad ( 0.0°) R(Z) : -1 rad (-57.2958°) R(Y) : 0 rad ( 0.0°)julia> a2 * a1EulerAngles{Float64}: R(Y) : 0.0 rad ( 0.0°) R(Z) : 0.0 rad ( 0.0°) R(Y) : 0.0 rad ( 0.0°)julia> a1 = EulerAngles(1, 1, 1, :YZY)EulerAngles{Int64}: R(Y) : 1 rad ( 57.2958°) R(Z) : 1 rad ( 57.2958°) R(Y) : 1 rad ( 57.2958°)julia> a2 = EulerAngles(0, 0, -1, :YZY)EulerAngles{Int64}: R(Y) : 0 rad ( 0.0°) R(Z) : 0 rad ( 0.0°) R(Y) : -1 rad (-57.2958°)julia> a2 * a1EulerAngles{Float64}: R(Y) : 1.0 rad ( 57.2958°) R(Z) : 1.0 rad ( 57.2958°) R(Y) : 1.31938e-16 rad ( 7.55951e-15°)julia> a1 = EulerAngles(1.3, 2.2, 1.4, :XYZ)EulerAngles{Float64}: R(X) : 1.3 rad ( 74.4845°) R(Y) : 2.2 rad ( 126.051°) R(Z) : 1.4 rad ( 80.2141°)julia> a2 = EulerAngles(-1.4, -2.2, -1.3, :ZYX)EulerAngles{Float64}: R(Z) : -1.4 rad (-80.2141°) R(Y) : -2.2 rad (-126.051°) R(X) : -1.3 rad (-74.4845°)julia> a2 * a1EulerAngles{Float64}: R(Z) : -8.32667e-17 rad (-4.77083e-15°) R(Y) : 3.33067e-16 rad ( 1.90833e-14°) R(X) : -1.11022e-16 rad (-6.36111e-15°)
Inversion
The inv function applied to Euler angles will return the inverse rotation. If the Euler angles $\Theta$ represent a rotation through the axes $a_1$, $a_2$, and $a_3$ by angles $\alpha_1$, $\alpha_2$, and $\alpha_3$, then $\Theta^{-1}$ is a rotation through the axes $a_3$, $a_2$, and $a_1$ by angles $-\alpha_3$, $-\alpha_2$, and $-\alpha_1$.
julia> a = EulerAngles(1, 2, 3, :ZYX)EulerAngles{Int64}: R(Z) : 1 rad ( 57.2958°) R(Y) : 2 rad ( 114.592°) R(X) : 3 rad ( 171.887°)julia> inv(a)EulerAngles{Int64}: R(X) : -3 rad (-171.887°) R(Y) : -2 rad (-114.592°) R(Z) : -1 rad (-57.2958°)julia> a = EulerAngles(1.2, 3.3, 4.6, :XYX)EulerAngles{Float64}: R(X) : 1.2 rad ( 68.7549°) R(Y) : 3.3 rad ( 189.076°) R(X) : 4.6 rad ( 263.561°)julia> a * inv(a)EulerAngles{Float64}: R(X) : -1.92593e-34 rad (-1.10348e-32°) R(Y) : 0.0 rad ( 0.0°) R(X) : 0.0 rad ( 0.0°)