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 coordinates3×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^23×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 equal3×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}\]

Differentiation

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 = RotationVec(2π/3(√3), 2π/3(√3), 2π/3(√3)) # This matrix swaps the xyz coordinates3×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^23×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 equal3×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 equaltrue
julia> RotY(β) ≈ RotationVec(0,β,0) # These matrices are equaltrue
julia> RotZ(γ) ≈ RotationVec(0,0,γ) # These matrices are equaltrue