-
Notifications
You must be signed in to change notification settings - Fork 44
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
Treating antipodal quaternions as equal breaks some operations #171
Comments
I think the As a related example, the following code satisfies julia> a, b = 0.0, -0.0
(0.0, -0.0)
julia> typeof(a), typeof(b)
(Float64, Float64)
julia> 1/a ≠ 1/b
true If we'd like to deal with the problem correctly, I think it's better to add types for |
I agree, I think subtyping is not appropriate here. It seems sensible to me for |
Indeed, but I think the relation between However, I don't think it is necessary to go through function UnitQuaternion(r::RotX)
θ = r.theta
UnitQuaternion(cos(θ/2),sin(θ/2),0,0)
end |
I'm totally on board with implementing efficient conversions where possible, such as So, I think the decision to have So, making some or all of the concrete |
Also, while I agree that the reasoning you give here is self-consistent:
it is a pretty big red flag to me that the rest of the world already has a notion of what it means for unit quaternions to be equal, and the above described notion of equality differs substantially from that one, not just because of rounding errors but conceptually. One way to improve this i.m.o. would be to rename I don't think the above is a fire or anything, but I do think it would be beneficial to make a clarifying change such as the above, on some appropriate timeframe. And we can definitely give a generous deprecation timeline if we do decide to make breaking changes. |
This is the main problem you're having with this package — a matter of terminology. The API for this package has long taken the stance that "rotations are matrices which happen to be efficiently parameterized". So the previous implementation (called A while back we were lucky to have many improvements merged in from @bjack205's package DifferentialRotations.jl. At that point Overall I think the idea that "Rotations are just specially-parameterized matrices" could be questioned, but it's worth keeping the history of the package in mind — it's always had a practical focus on simple 3D geometry and optimization. If wholesale API changes made it more practical for those uses while improving the conceptual clarity, they could be worthwhile. But if the perceived problems with |
Thanks for this input @c42f, all of this sounds great.
I think we should do two things:
Infinitesimal rotations are not rotations (skew-symmetric matrices are not orthogonal matrices), and rotations don't have a zero. And the thing returned by One use case I have in mind by the way, is machine learning on orientation-valued data where the loss function includes geometric operations on the orientation. There, unit quaternions have some advantages over other representations, particularly regarding singularities such as gimbal lock. I don't see any problems with the current API for that -- the user can just keep track of the quaternion components themself and feed them into Rotations.jl when they need to do geometric operations -- but just wanted to bring that use case into the mix. |
Yeah, that rotations are just matrices is kinda fundamental here. It sounds like the current I always hoped to add |
I totally agree with that. Or maybe I just found out the word "versor" today. (same as unit quaternion) |
I had never heard of versor before - thanks. It’s an apt name (I love the word!), but probably less well-known to other users so might hurt in discoverability… |
Personally I'd go with
I think this makes sense — in this case, it's the derivative of the constructor with respect to the parameters which we care about? So calling rotation constructors as part of the model evaluation seems important.
I've long thought that this package should have integration with ChainRulesCore.jl. I assume this would tie in naturally there? |
Currently, antipodal quaternions are treated as equal, i.e.,
q == -q
. I can see the motivation for this -- they induce the same rotation -- but this leads to several issues:AFAIK, accessing the quaternion components is part of the public API. So it's confusing that two
UnitQuaternion
s can be==
but have different values of the field:q == -q
butq.w != (-q).w
.The exponential map is broken: exp(Rotations.UnitQuaternion(0, π, 0, 0)) gives incorrect result #128
zero(UnitQuaternion)
is not a valid unit quaternion. As described in Skew-symmetric matrices as generators for rotations #30 (comment)), there is an undocumented semantics of "unnormalized unit quaternion" which is used for some operations such as exp and log, but is not ultimately coherent. Better would be to have a separate type for infinitesimal unit quaternions, similar to what's being done in Skew-symmetric matrices as generators for rotations #30. That type has a zero;UnitQuaternion
should not have a zero.The text was updated successfully, but these errors were encountered: