Add more abstract subtypes of `Rotation`?
The problems
type conversion
On the current master branch:
julia> UnitQuaternion(RotX(2π))
3×3 UnitQuaternion{Float64} with indices SOneTo(3)×SOneTo(3)(1.0, -1.22465e-16, 0.0, 0.0):
1.0 -0.0 0.0
0.0 1.0 2.44929e-16
-0.0 -2.44929e-16 1.0
The result should approximately equal to UnitQuaternion(-1,0,0,0), not UnitQuaternion(1,0,0,0). (See https://github.com/JuliaGeometry/Rotations.jl/issues/171#issuecomment-950324745)
power operator ^
On the current master branch:
julia> AngleAxis(2π, 0,0,1)^(1/4)
3×3 AngleAxis{Float64} with indices SOneTo(3)×SOneTo(3)(1.5708, 0.0, 0.0, 1.0):
2.22045e-16 -1.0 0.0
1.0 2.22045e-16 0.0
0.0 0.0 1.0
julia> AngleAxis(0, 0,0,1)^(1/4)
3×3 AngleAxis{Float64} with indices SOneTo(3)×SOneTo(3)(0.0, 0.0, 0.0, 1.0):
1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
julia> AngleAxis(0, 0,0,1) ≈ AngleAxis(2π, 0,0,1)
true
I think this is okay, but it would be nice if it will be easier to understand.
product operator *
On the current master branch:
julia> UnitQuaternion(1.,0.,0.,0.) * MRP(1.,2.,3.)
3×3 RotMatrix3{Float64} with indices SOneTo(3)×SOneTo(3):
0.537778 0.764444 -0.355556
-0.622222 0.644444 0.444444
0.568889 -0.0177778 0.822222
Both UnitQuaternion and MRP are points on SU(2), but the output result is RotMatrix (on SO(3)).
This means the operation drops the information on SU(2).
summary
The subtypes of Rotation are treated as a real matrix, but it is not just a matrix.
How to fix this
Classify the types
There are 27 subtypes of Rotation{3}, and this can be classified as the following.
- Rotation on SO(3)
- Its parameters are bijective to SO(3), almost everywhere.
- Should be named
RotationSO3 <: Rotation{3}?? - its subtypes
RotMatrix{3}RodriguteParam
- Rotation on SU(2)
- Its parameters are bijective to SU(2), almost everywhere.
- Should be named
RotationSU2 <: Rotation{3}?? - its subtypes
UnitQuaternion(QuatRotationin the future)MRP
- Path on the rotational space
- Its can be considered as a path on rotational space (SO(3) or SU(2)).
- The mapping parameters doesn't have to be injective or surjective.
- All of its subtypes are not injective. (e.g.
RotX(0)=Rot(2π)on SO(3),RotX(0)=Rot(4π)on SU(2)) - Some of them are surjective (e.g.
RotXYZ,AngleAxis)
- All of its subtypes are not injective. (e.g.
- Should be named
RotationPath{3} <: Rotation{3}?? - its subtypes
RotXand etc.RotXYand etc.RotXYZand etc.AngleAxisRotationVec
Methods
With those abstract types (RotationSO3, RotationSU2 and RotationPath), we can update methods like the following:
UnitQuaternion(::RotXYZ) # This conversion is surjective on SU(2)
MRP(::RotXYZ) # This conversion is surjective on SU(2)
RodriguesParam(::MRP) # This conversion is surjective on SO(3)
MRP(::RodriguesParam) # This conversion is injective on SU(2), and chosen principal value (PR#97)
*(::RotationSO3,::RotationSO3) isa RotationSO3
*(::RotationSU2,::RotationSU2) isa RotationSU2
*(::RotationSO3,::RotationSU2) isa RotationSO3 # This is for associativity, (pq)r = p(qr)
*(::RotationPath,::RotationPath) isa Union{RotationPath, RotationSU2} # If possible, should be RotationPath. (e.g. RotX(1)*RotY(2)) In other cases, should be RotationSU2 because SU(2) is a simply-connected.
*(::RotationPath,::RotationSO3) isa RotationSO3
*(::RotationPath,::RotationSU2) isa RotationSO2
0 ≤ rotation_angle(::RotationSO3) < π
0 ≤ rotation_angle(::RotationSU2) < 2π
-∞ < rotation_angle(::RotationPath) < +∞
exp(::InfinitesimalRotation{3}) isa RotationVec # Note that RotationVec <: RotationPath
Questions
- Does this sounds good?
- If so, are there any suggestions for naming types?
- I think there would be better namings than
RotationSO3andRotationSU2.
- I think there would be better namings than
Ah, it is unable to create types like RotMatrix{3} <: RotationSO3 <: Rotation{3}....
Maybe RotationSO{3}?