Common Methods for Rotations

rotation_angle, rotation_axis

3D

A rotation matrix can be expressed with one rotation around an axis and angle. these function can calculate these values.

example

julia> R = RotXYZ(2.4, -1.8, 0.5)3×3 RotXYZ{Float64} with indices SOneTo(3)×SOneTo(3)(2.4, -1.8, 0.5):
 -0.199389   0.108926  -0.973848
 -0.930798  -0.331759   0.153467
 -0.306366   0.937055   0.167537
julia> θ = rotation_angle(R)2.3210234148741837
julia> n = rotation_axis(R) # These matrices are approximately equal.3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 0.5355785581183807 -0.4562206495732595 -0.7106464148835127
julia> R ≈ AngleAxis(θ, n...)true

2D

julia> R = Angle2d(2.4)2×2 Angle2d{Float64} with indices SOneTo(2)×SOneTo(2)(2.4):
 -0.737394  -0.675463
  0.675463  -0.737394
julia> θ = rotation_angle(R)2.4

Rotations.params

The parameters of the rotation can be obtained by Rotations.params.

example

julia> R = one(RotMatrix{3})  # Identity matrix3×3 RotMatrix3{Bool} with indices SOneTo(3)×SOneTo(3):
 1  0  0
 0  1  0
 0  0  1
julia> Rotations.params(RotYZY(R)) # Proper Euler angles, (y,z,y)3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 0.0 0.0 0.0
julia> Rotations.params(RotXYZ(R)) # Tait–Bryan angles, (x,y,z)3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 0.0 0.0 0.0
julia> Rotations.params(AngleAxis(R)) # Rotation around an axis (theta, axis_x, axis_y, axis_z)4-element StaticArraysCore.SVector{4, Float64} with indices SOneTo(4): 0.0 1.0 0.0 0.0
julia> Rotations.params(RotationVec(R)) # Rotation vector (v_x, v_y, v_z)3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 0.0 0.0 0.0
julia> Rotations.params(QuatRotation(R)) # Quaternion (w, x, y, z)4-element StaticArraysCore.SVector{4, Float64} with indices SOneTo(4): 1.0 0.0 0.0 0.0
julia> Rotations.params(RodriguesParam(R)) # Rodrigues Parameters (x, y, z)3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 0.0 0.0 0.0
julia> Rotations.params(MRP(R)) # Modified Rodrigues Parameters (x, y, z)3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3): 0.0 0.0 0.0

isrotation

Check the given matrix is rotation matrix.

example

(TBW)

nearest_rotation

Get the nearest special orthonormal matrix from given matrix M. The problem of finding the orthogonal matrix nearest to a given matrix is related to the Wahba's problem.

example

julia> M = randn(3,3)  # Generate random matrix3×3 Matrix{Float64}:
 -0.412686   0.620441  -2.84546
  1.37408   -1.03458    0.788797
 -0.940306  -0.338145  -0.45724
julia> R = nearest_rotation(M) # Find the nearest rotation matrix3×3 RotMatrix3{Float64} with indices SOneTo(3)×SOneTo(3): 0.111725 0.105561 -0.988117 0.688409 -0.725322 0.0003508 -0.716666 -0.680268 -0.153706
julia> U, V = R\M, M/R # Polar decomposition of M([1.5737100287181613 -0.40055764733304694 0.5527945896002082; -0.40055764733304733 1.0459271518489115 -0.5614564733412604; 0.5527945896002089 -0.5614564733412605 2.8822050278688716], [2.8310350792154293 -0.7351152816460444 0.3110556909943626; -0.7351152816460446 1.696612041835573 -0.4022111711227181; 0.3110556909943624 -0.40221117112271776 0.9741950873849418])
julia> U ≈ U' # U is a symmetric matrix (The same for V)true

rand

rand for $SO(2)$

The following types have the same algebraic structure as $SO(2)$

  • RotMatrix{2}
  • Angle2d
  • RotX
  • RotY
  • RotZ

The random distribution is based on Haar measure.

example

julia> R = rand(Angle2d)2×2 Angle2d{Float64} with indices SOneTo(2)×SOneTo(2)(2.26144):
 -0.637033  -0.770836
  0.770836  -0.637033

rand for $SO(3)$

The following types have an algebraic structure that is homomorphic to $SO(3)$.

  • RotMatrix{3}
  • RotXYZ (and other Euler angles)
  • AngleAxis
  • RotationVec
  • QuatRotation
  • RodriguesParam
  • MRP

example

julia> R = rand(RotationVec)3×3 RotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(1.19129, -0.523395, -0.0440173):
  0.880476  -0.23754   -0.410288
 -0.302729   0.384315  -0.872157
  0.364852   0.892119   0.26647

The random distribution is based on Haar measure.

rand for RotXY and etc.

There also are methods for rand(::RotXY) and other 2-axis rotations.

example

julia> R = rand(RotXY)3×3 RotXY{Float64} with indices SOneTo(3)×SOneTo(3)(1.95807, 2.74154):
 -0.92104    0.0       0.389468
  0.360625  -0.377664  0.85283
  0.147088   0.925943  0.347843

The random distribution is NOT based on Haar measure because the set of RotXY doesn't have group structure.

Note that:

  • rand(RotX) is same as RotX(2π*rand()).
  • rand(RotXY) is same as RotXY(2π*rand(), 2π*rand()).
  • rand(RotXYZ) is not same as RotXYZ(2π*rand(), 2π*rand(), 2π*rand()).
  • But rand(RotXYZ) is same as RotXYZ(rand(QuatRotation)).