Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RotationGenerator and its subtypes #203

Merged
merged 29 commits into from
Jan 13, 2022

Conversation

hyrodium
Copy link
Collaborator

@hyrodium hyrodium commented Nov 20, 2021

This PR solves #30, #31, #126 and #128. (2021/11/20 EDIT: quaternion conversions will be supported in the other PR.)

julia> using Rotations

julia> m = rand(3,3)
3×3 Matrix{Float64}:
 0.992789  0.0478161  0.639771
 0.826576  0.89928    0.368333
 0.100041  0.986343   0.174436

julia> s = InfinitesimalRotMatrix{3}(m - m')
3×3 InfinitesimalRotMatrix{3, Float64, 9} with indices SOneTo(3)×SOneTo(3):
  0.0      -0.77876   0.53973
  0.77876   0.0      -0.61801
 -0.53973   0.61801   0.0

julia> exp(s)
3×3 RotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(0.61801, 0.53973, 0.77876):
  0.596987  -0.473236   0.647807
  0.772707   0.556304  -0.305697
 -0.215711   0.683062   0.697779

julia> log(exp(s))
3×3 InfinitesimalRotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(0.61801, 0.53973, 0.77876):
  0.0      -0.77876   0.53973
  0.77876   0.0      -0.61801
 -0.53973   0.61801   0.0

julia> log(exp(s)) + s
3×3 InfinitesimalRotMatrix{3, Float64, 9} with indices SOneTo(3)×SOneTo(3):
  0.0      -1.55752   1.07946
  1.55752   0.0      -1.23602
 -1.07946   1.23602   0.0

julia> rotation_angle(exp(log(exp(s)) + s))
2.2624870696189996

julia> rotation_angle(exp(s))
1.1312435348094998

julia> InfinitesimalRotationVec(s)
3×3 InfinitesimalRotationVec{Float64} with indices SOneTo(3)×SOneTo(3)(0.61801, 0.53973, 0.77876):
  0.0      -0.77876   0.53973
  0.77876   0.0      -0.61801
 -0.53973   0.61801   0.0

@codecov
Copy link

codecov bot commented Nov 20, 2021

Codecov Report

Merging #203 (b55c9ee) into master (89e4dd4) will increase coverage by 0.83%.
The diff coverage is 93.61%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #203      +/-   ##
==========================================
+ Coverage   86.74%   87.57%   +0.83%     
==========================================
  Files          14       15       +1     
  Lines        1403     1529     +126     
==========================================
+ Hits         1217     1339     +122     
- Misses        186      190       +4     
Impacted Files Coverage Δ
src/core_types.jl 93.89% <ø> (+3.45%) ⬆️
src/logexp.jl 81.81% <81.81%> (ø)
src/rotation_generator.jl 95.79% <95.79%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 89e4dd4...b55c9ee. Read the comment docs.

@hyrodium hyrodium marked this pull request as ready for review November 20, 2021 18:05
@hyrodium hyrodium requested a review from andyferris November 20, 2021 18:05
Copy link
Contributor

@andyferris andyferris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool. :)

I would still avoid the term "infinitesimal rotation". Julia can represent infinitesimal rotations already, but it's not these. Here's one, with dual numbers:

using DualNumbers

infinitesimal_rotation = [
    1.0 Dual(0.0, 0.5);
    Dual(0.0, -0.5) 1.0
]

What you have in this PR is a rotation generator, so if we aren't going to refer to the matrix structure then we may as well call it by its real name. Note the generator for the above an infinitesimal generator:

infinitesimal_generator = [
    0.0 Dual(0.0, 0.5);
    Dual(0.0, -0.5) 0.0
]

It's easy to figure this out using just exp(ϵ) ≈ I + ϵ.

What doesn't quite work out-of-the-box in Julia is exp and log with Dual matrices, but mathematically the following should hold:

exp(infinitesimal_generator) == infinitesimal_rotation

Hopefully with your work here we'll be able to get all these relationships working even with autodifferentiation on the parameters of the generator! :)

@hyrodium
Copy link
Collaborator Author

I would still avoid the term "infinitesimal rotation". Julia can represent infinitesimal rotations already, but it's not these. Here's one, with dual numbers:

Ah, I didn't quite understand the meaning of inifinitesimal rotation.
Should we just rename the skew-symmetric matrix types like this?

  • InfinitesimalRotation -> RotationGenerator
  • InfinitesimalRotMatrix -> RotMatrixGenerator
  • InfinitesimalRotationVec -> RotationVecGenerator
  • InfinitesimalAngle2c -> Angle2dGenerator

Hopefully with your work here we'll be able to get all these relationships working even with autodifferentiation on the parameters of the generator! :)

Yeah, I'll try to do that! 😄

@andyferris
Copy link
Contributor

Should we just rename the skew-symmetric matrix types like this?

Yes - I think that is perfect :)

@hyrodium hyrodium changed the title Add InfinitesimalRotation and its subtypes Add RotationGenerator and its subtypes Nov 22, 2021
@hyrodium hyrodium requested a review from andyferris November 22, 2021 04:55
Copy link
Contributor

@andyferris andyferris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome.

I had questions about the method defined for promote_op (and perhaps whatever you are trying to acheive there could be tested, too?) but otherwise this looks good to me.

This PR fills a massive gap, and I'm sure the community will appreciate it. Thanks @hyrodium!

# Useful for converting arrays of rotations to another rotation eltype, for instance.
# Only works because parameters of all the rotations are of a similar form
# Would need to be more sophisticated if we have arbitrary dimensions, etc
@inline function Base.promote_op(::Type{R1}, ::Type{R2}) where {R1 <: RotationGenerator, R2 <: RotationGenerator}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this right? The operator is not defined. Did you mean promote_rule?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried renaming promote_op -> promote_rule and isleaftype -> isconcretetype, but it doesn't work well here.
These seems unnecessary, so I've dropped both promote_op definitions from src/core_types.jl and src/rotation_generator.jl.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

More exponentiation operations Skew-symmetric matrices as generators for rotations
2 participants