JuliaGeometry / Rotations.jl

Julia implementations for different rotation parameterizations
https://juliageometry.github.io/Rotations.jl
MIT License
176 stars 44 forks source link

The output type of some operations should be mainly `QuatRotation` #253

Open hyrodium opened 1 year ago

hyrodium commented 1 year ago

With the current implementation, the output types of some operations such as * are inconsistent.

julia> RotX(1) * RotYZX(1,2,3)
3×3 RotMatrix3{Float64} with indices SOneTo(3)×SOneTo(3):
 -0.224845   0.605127   -0.763718
  0.196633   0.795841    0.572689
  0.954348  -0.0214059  -0.297929

julia> MRP(1,2,3) * QuatRotation(1,2,3,4)
3×3 RotMatrix3{Float64} with indices SOneTo(3)×SOneTo(3):
  0.0325926  -0.514963  0.856593
  0.992593    0.117037  0.0325926
 -0.117037    0.849185  0.514963

julia> MRP(1,2,3) * MRP(2,3,4)
3×3 MRP{Float64} with indices SOneTo(3)×SOneTo(3)(-0.152589, -0.247956, -0.376022):
 -0.0795062  0.975486  -0.205195
 -0.57284    0.123753   0.810272
  0.815802   0.181965   0.548958

julia> RotX(1) * AngleAxis(1,2,3,4.0)
3×3 RotMatrix3{Float64} with indices SOneTo(3)×SOneTo(3):
 0.603709  -0.529919    0.595585
 0.676841  -0.0540276  -0.734144
 0.421215   0.846325    0.326054

julia> AngleAxis(1,2,3,4.0) * AngleAxis(1,2,3,4.0)
3×3 QuatRotation{Float64} with indices SOneTo(3)×SOneTo(3)(QuaternionF64(0.540302, 0.312514, 0.468772, 0.625029)):
 -0.220816  -0.382413  0.897218
  0.968405   0.023347  0.248287
 -0.115896   0.923696  0.365176

The following is a full list of return types of *.

julia> RotTypes = subtypes(Rotation{3})
27-element Vector{Any}:
 AngleAxis
 MRP
 QuatRotation
 RodriguesParam
 RotMatrix{3}
 RotX
 RotXY
 RotXYX
 RotXYZ
 RotXZ
 RotXZX
 RotXZY
 RotY
 RotYX
 RotYXY
 RotYXZ
 RotYZ
 RotYZX
 RotYZY
 RotZ
 RotZX
 RotZXY
 RotZXZ
 RotZY
 RotZYX
 RotZYZ
 RotationVec

julia> [typeof(one(R1)*one(R2)) for R1 in RotTypes, R2 in RotTypes]
27×27 Matrix{DataType}:
 QuatRotation{Float64}  RotMatrix3{Float64}  QuatRotation{Float64}  RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  …  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  QuatRotation{Float64}
 RotMatrix3{Float64}    MRP{Float64}         RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 QuatRotation{Float64}  RotMatrix3{Float64}  QuatRotation{Float64}  RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  QuatRotation{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RodriguesParam{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Int64}    RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotX{Float64}        …  RotXZX{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  RotXZY{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotXYX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotXYX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotXZX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotXZX{Float64}      …  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotYX{Float64}          RotYZX{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  RotYZY{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotYX{Float64}          RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  …  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotYZX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotYZX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotZX{Float64}          RotZX{Float64}       RotZXY{Float64}      RotZXZ{Float64}      RotZY{Float64}       RotZYX{Float64}      RotZYZ{Float64}      RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotZX{Float64}       …  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotZYX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotZYX{Float64}         RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 RotMatrix3{Float64}    RotMatrix3{Float64}  RotMatrix3{Float64}    RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}  …  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}
 QuatRotation{Float64}  RotMatrix3{Float64}  QuatRotation{Float64}  RotMatrix3{Float64}      RotMatrix3{Float64}  RotMatrix3{Float64}     RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  RotMatrix3{Float64}  QuatRotation{Float64}

RotMatrix3 is the most used return type, but I think this should be QuatRotation because it is more efficient. However, I am not sure we would like to have *(::RotMatrix, ::RodriguesVec) is RotMatrix or QuatRotation. (x-ref: https://github.com/JuliaGeometry/Rotations.jl/issues/190)

This issue is not just about the multiplication *, but also includes other operations such as /, ^, sqrt(#234) etc.