JuliaGeometry / Rotations.jl

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

Angle2d seems superfluous #275

Closed cafaxo closed 10 months ago

cafaxo commented 10 months ago

It seems that Angle2d represents a 2D rotation by an angle. This seems confusing to me: This representation is basically the same as the Lie algebra representation by a 2x2 skew-symmetric matrix. So if I want to represent a 2D rotation "lazily" by an angle, I would use the proper Lie algebra type RotationGenerator{2,T}. What is the point of having Angle2d?

When I exponentiate the RotationGenerator{2,T} I would expect to receive the actual rotation matrix. Having to apply an additional RotMatrix is not nice when writing generic code that works for multiple dimensions.

Edit: It seems that 3D rotations also behave in the same way with first producing a RotationVec when exponentiating an element from the Lie algebra. It just seems a bit opaque to me that the actual work is delayed to the RotMatrix constructor and does not happen in the exp.

cafaxo commented 10 months ago

After looking at this some more, I understand why it is done this way. (exp does not make the decision how the rotation is represented; and there are various representations of 3D rotations available).

hyrodium commented 10 months ago

there are various representations of 3D rotations available

Yeah, that's right.

Here's a draft comment that I was trying to send.


What is the point of having Angle2d?

For more performance on 2D rotations. (See #14, #89 and docs)

julia> using Rotations, StaticArrays, BenchmarkTools

julia> subtypes(Rotation{2})
2-element Vector{Any}:
 Angle2d
 RotMatrix{2}

julia> r1 = Angle2d(3.0)
2×2 Angle2d{Float64} with indices SOneTo(2)×SOneTo(2)(3.0):
 -0.989992  -0.14112
  0.14112   -0.989992

julia> r2 = RotMatrix{2}(3.0)
2×2 RotMatrix2{Float64} with indices SOneTo(2)×SOneTo(2):
 -0.989992  -0.14112
  0.14112   -0.989992

julia> @btime r1^3
  16.464 ns (1 allocation: 16 bytes)
2×2 Angle2d{Float64} with indices SOneTo(2)×SOneTo(2)(9.0):
 -0.91113   -0.412118
  0.412118  -0.91113

julia> @btime r2^3
  68.839 ns (1 allocation: 48 bytes)
2×2 RotMatrix2{Float64} with indices SOneTo(2)×SOneTo(2):
 -0.91113   -0.412118
  0.412118  -0.91113

I would use the proper Lie algebra type RotationGenerator{2,T}.

You can also use Angle2dGenerator type.

julia> g = Angle2dGenerator(3.0)
2×2 Angle2dGenerator{Float64} with indices SOneTo(2)×SOneTo(2)(3.0):
 0.0  -3.0
 3.0   0.0

julia> exp(g)
2×2 Angle2d{Float64} with indices SOneTo(2)×SOneTo(2)(3.0):
 -0.989992  -0.14112
  0.14112   -0.989992

It just seems a bit opaque to me that the actual work is delayed to the RotMatrix constructor and does not happen in the exp.

There are many ways to represent a rotations: Euler angles, rotation around an axis, quaternions, etc. Rotations.jl has types for each rotation representation.

julia> 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
cafaxo commented 10 months ago

Thanks for elaborating on this!