Euler Angles
The Euler Angles are defined by the following immutable structure:
struct EulerAngles{T}
a1::T
a2::T
a3::T
rot_seq::Symbol
end
in 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 * a1
EulerAngles{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 * a1
EulerAngles{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 * a1
EulerAngles{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°)