3D Rotation around an axis
In Rotations.jl
, there are two concrete types to represent a rotation with given an axis and an angle.
AngleAxis
RotationVec
AngleAxis
A 3D rotation with fields theta
, axis_x
, axis_y
, and axis_z
to store the rotation angle and axis of the rotation. Like all other types in this package, once it is constructed it acts and behaves as a 3×3 AbstractMatrix
. The axis will be automatically renormalized by the constructor to be a unit vector, so that theta
always represents the rotation angle in radians.
\[\begin{aligned} R_{\bm{n}} (\theta) &= \exp(\theta K(\bm{n})) \\ &= I + (\sin\theta) K(\bm{n}) + (1-\cos\theta) K^2(\bm{n}) \\ &= \begin{pmatrix} \cos\theta + n_x^2 (1-\cos\theta) & n_xn_y (1-\cos\theta) - n_z \sin\theta & n_zn_x (1-\cos\theta) + n_y \sin\theta \\ n_xn_y (1-\cos\theta) + n_z \sin\theta & \cos\theta + n_y^2 (1-\cos\theta) & n_yn_z (1-\cos\theta) - n_x \sin\theta \\ n_zn_x (1-\cos\theta) - n_y \sin\theta & n_yn_z (1-\cos\theta) + n_x \sin\theta & \cos\theta + n_z^2 (1-\cos\theta) \end{pmatrix} \\ % K(\bm{n}) &= \begin{pmatrix} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{pmatrix} \\ % {\bm{n}} &= \begin{pmatrix} n_x \\ n_y \\ n_z \end{pmatrix} % \quad \left(\|\bm{n}\|= 1\right) \end{aligned}\]
example
julia> using Rotations, LinearAlgebra # 1/3 (120°) rotation around the (1/√3, 1/√3, 1/√3) vector
julia> R = AngleAxis(2π/3, 1/√3, 1/√3, 1/√3) # This matrix swaps the xyz coordinates
3×3 AngleAxis{Float64} with indices SOneTo(3)×SOneTo(3)(2.0944, 0.57735, 0.57735, 0.57735): 1.11022e-16 -1.11022e-16 1.0 1.0 1.11022e-16 -1.11022e-16 -1.11022e-16 1.0 1.11022e-16
julia> R * [1,2,3]
3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 3.0 0.9999999999999999 2.0000000000000004
julia> R^2
3×3 AngleAxis{Float64} with indices SOneTo(3)×SOneTo(3)(4.18879, 0.57735, 0.57735, 0.57735): -3.33067e-16 1.0 3.33067e-16 3.33067e-16 -3.33067e-16 1.0 1.0 3.33067e-16 -3.33067e-16
julia> R^3 # These matrices are approximately equal
3×3 AngleAxis{Float64} with indices SOneTo(3)×SOneTo(3)(6.28319, 0.57735, 0.57735, 0.57735): 1.0 1.4141e-16 -1.4141e-16 -1.4141e-16 1.0 1.4141e-16 1.4141e-16 -1.4141e-16 1.0
julia> R^3 ≈ I(3)
true
RotationVec
A 3D rotation encoded by an angle-axis representation as angle * axis
. This type is used in packages such as OpenCV.
\[\begin{aligned} R(\bm{v}) &= R_{\bm{n}} (\theta) & \left(\bm{n} = \frac{\bm{v}}{\|\bm{v}\|}, \theta = \|\bm{v}\| \right) \end{aligned}\]
If you're differentiating a Rodrigues Vector check the result is what you expect at theta = 0. The first derivative of the rotation should behave, but higher-order derivatives of it (as well as parameterization conversions) should be tested. The Stereographic Quaternion Projection (MRP
) is the recommended three parameter format for differentiation.
example
julia> using Rotations, LinearAlgebra # 1/3 (120°) rotation around the (1/√3, 1/√3, 1/√3) vector
julia> R = R = RotationVec(2π/3(√3), 2π/3(√3), 2π/3(√3)) # This matrix swaps the xyz coordinates
3×3 RotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(1.2092, 1.2092, 1.2092): 1.11022e-16 -1.11022e-16 1.0 1.0 1.11022e-16 -1.11022e-16 -1.11022e-16 1.0 1.11022e-16
julia> R * [1,2,3]
3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 3.0 0.9999999999999999 2.0000000000000004
julia> R^2
3×3 RotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(2.4184, 2.4184, 2.4184): -3.33067e-16 1.0 3.33067e-16 3.33067e-16 -3.33067e-16 1.0 1.0 3.33067e-16 -3.33067e-16
julia> R^3 # These matrices are approximately equal
3×3 RotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(3.6276, 3.6276, 3.6276): 1.0 1.4141e-16 -1.4141e-16 -1.4141e-16 1.0 1.4141e-16 1.4141e-16 -1.4141e-16 1.0
julia> R^3 ≈ I(3)
true
julia> α, β, γ = 1.2, -0.8, 0.1;
julia> RotX(α) ≈ RotationVec(α,0,0) # These matrices are equal
true
julia> RotY(β) ≈ RotationVec(0,β,0) # These matrices are equal
true
julia> RotZ(γ) ≈ RotationVec(0,0,γ) # These matrices are equal
true