Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

[DOCS] Help understanding basic usage of distances pls #268

Closed
dehann opened this issue Nov 22, 2020 · 3 comments
Closed

[DOCS] Help understanding basic usage of distances pls #268

dehann opened this issue Nov 22, 2020 · 3 comments

Comments

@dehann
Copy link
Contributor

dehann commented Nov 22, 2020

Good day,

I'm testing out how to compute the distance between two points on the same manifold, but not quite sure how the API works yet. Been up and down the docs and code but still getting stuck. Thought I might ask here direct and can then help send as PR on documentation -- soft of a "Getting Started" paragraph...

This is closest to what I'm trying to do

M_se2 = SpecialEuclidean(2)
sI = SMatrix{3,3,Float64}(diagm(ones(3)))
T1 = Manifolds.hat(M_se2, sI, SVector(0,0,pi/2))
T2 = Manifolds.hat(M_se2, sI, SVector(1,0,0))

distance(M_se2, T1, T2)

but results in an error. Error is probably expected, I just need a pointer on how to fix please

julia> distance(M_se2, T1, T2)
ERROR: type MArray has no field parts
Stacktrace:
 [1] getproperty(::MArray{Tuple{3,3},Float64,2,9}, ::Symbol) at ./Base.jl:33
 [2] submanifold_components at /home/dehann/.julia/packages/Manifolds/lCAWg/src/product_representations.jl:213 [inlined]
 [3] submanifold_components at /home/dehann/.julia/packages/Manifolds/lCAWg/src/product_representations.jl:212 [inlined]
 [4] distance(::ProductManifold{ℝ,Tuple{GroupManifold{ℝ,Euclidean{Tuple{2},ℝ},AdditionOperation},GroupManifold{ℝ,Rotations{2},MultiplicationOperation}}}, ::MArray{Tuple{3,3},Float64,2,9}, ::MArray{Tuple{3,3},Float64,2,9}) at /home/dehann/.julia/packages/Manifolds/lCAWg/src/manifolds/ProductManifold.jl:227
 [5] distance__transparent(::GroupManifold{ℝ,ProductManifold{ℝ,Tuple{GroupManifold{ℝ,Euclidean{Tuple{2},ℝ},AdditionOperation},GroupManifold{ℝ,Rotations{2},MultiplicationOperation}}},Manifolds.SemidirectProductOperation{RotationAction{GroupManifold{ℝ,Euclidean{Tuple{2},ℝ},AdditionOperation},GroupManifold{ℝ,Rotations{2},MultiplicationOperation},LeftAction}}}, ::MArray{Tuple{3,3},Float64,2,9}, ::MArray{Tuple{3,3},Float64,2,9}) at /home/dehann/.julia/packages/ManifoldsBase/QO0FO/src/DecoratorManifold.jl:375
 [6] distance(::GroupManifold{ℝ,ProductManifold{ℝ,Tuple{GroupManifold{ℝ,Euclidean{Tuple{2},ℝ},AdditionOperation},GroupManifold{ℝ,Rotations{2},MultiplicationOperation}}},Manifolds.SemidirectProductOperation{RotationAction{GroupManifold{ℝ,Euclidean{Tuple{2},ℝ},AdditionOperation},GroupManifold{ℝ,Rotations{2},MultiplicationOperation},LeftAction}}}, ::MArray{Tuple{3,3},Float64,2,9}, ::MArray{Tuple{3,3},Float64,2,9}) at /home/dehann/.julia/packages/ManifoldsBase/QO0FO/src/DecoratorManifold.jl:361
 [7] top-level scope at REPL[77]:1

xref:

@sethaxen
Copy link
Member

Currently the affine matrix point representation of SpecialEuclidean is only supported for group-related functions. This is because the default metric on SpecialEuclidean(2) is the same as its base manifold TranslationGroup(2) × SpecialOrthogonal(2), so the point is transparently passed to the same function for the base manifold, where it expects the point to be like ProductArray or ProductRepr.

We could overload submanifold_component for this base manifold as well, to ensure that the blocks of the affine matrix are then interpreted as points of the submanifold (this is what we do for SpecialEuclidean's group functions), but this only gets us partway there, because the affine structure needs to be enforced every time a point is allocated, and that will require a lot of overloads I think.

So there are a few ways forward. One is to use ProductArray or ProductRepr. Another is to implement a custom AffineArray type, similar to Rotations.jl's custom array types (and this maybe would belong in this package). Third, you could use a custom type like CoordinateTransformations.AffineMap (though I don't see the benefit of this, as it's basically the same idea as ProductArray or ProductRepr). For the latter two options, you probably only need a few overloads in Manifolds to make it work.

@dehann
Copy link
Contributor Author

dehann commented Nov 22, 2020

Hi Seth, thanks for the reply. I'm trying to build a picture between your comment where I'm trying to get to... Unfortunately I'm not familiar enough with ProductArray or ProductRepr yet to comment properly. Perhaps you could give a quick pseudo code example of what you mean by the first option please, specifically for something like distance. Can I not just assume non-commutative logmap as a "distance" for all Manifolds (or at least for <: RiemannianManifold)?

distance(::SE2, T2, T1) = norm(vee(logmap(inverse(T2) * T1))) 
 # or whatever is most efficient

Apologies, I'm still going through the learning curve on the Manifolds.jl implementation. FYI i mostly need Reimannian at this stage.

I'm after a setup to allow a vector of on-manifold points for use with NearestNeighbors.BallTree for all <: Manifold cases (as well as later run-time custom user manifolds). For this I think I need a standard distance for dispatch based on what the user is using -- i.e. user asks for MetricTreeDensity{SE3}. I'm following the initial basic distance(Euclidean(1), 2, 3) example as inspiration, I was thinking about bridging between all these Julia packages with something like a AMP.ManiFakeArrayBridge{T <: Manifold} <: AbstractArray as a way to get all the packages together as type-stable and in-place only operation (JuliaRobotics/ApproxManifoldProducts.jl#41 including CoordTrans / Rotations.jl). Is this related to the second option you suggested?

Another is to implement a custom AffineArray type, similar to Rotations.jl's custom array types (and this maybe would belong in this package).

Also, is there a plan or decision regarding use/compat/dependency etc. with other packages like CoordinateTransformations.jl? I looked through issues but did not see anything. Manifolds is obviously working to get a fundamental Abstraction down. The previous packages seem to be more dedicated libraries focusing only on one or two manifolds. Closest so far seems to be Mateusz's comment (JuliaRobotics/ApproxManifoldProducts.jl#41 (comment)).

Basically I'm checking if my conclusion is correct that there seems to be a need for first undoing the foundational AbstractArray as always Euclidean assumption in many packages, and rather drive the development towards Vector{ManifoldPoint{T}} where T is perhaps <: AbstractArray or whatever is best suited to store the underlying on-manifold point data (for GPU kernels etc)?


const AMP = ApproxManifoldProducts

@mateuszbaran
Copy link
Member

Also, is there a plan or decision regarding use/compat/dependency etc. with other packages like CoordinateTransformations.jl? I looked through issues but did not see anything.

We don't really have much set in stone here regarding this. ManifoldsBase.jl is going to remain as lean as possible, I'm essentially against any new dependencies there. Manifolds.jl may or may not get new ones but we're also going to split away parts related to distributions, so there may be even fewer in the future.

Compatibility layers with other packages are either written in separate packages (currently ManifoldML.jl) or loaded on-demand using Requires.jl.

Basically I'm checking if my conclusion is correct that there seems to be a need for first undoing the foundational AbstractArray as always Euclidean assumption in many packages, and rather drive the development towards Vector{ManifoldPoint{T}} where T is perhaps <: AbstractArray or whatever is best suited to store the underlying on-manifold point data (for GPU kernels etc)?

This is a great question with no simple answer. Manifolds.jl can handle many different representations of points. Of course when you want to use it with another package, that package may need to know that arrays don't store values in Euclidean. For example NearestNeighbors works quite well here. Of course it's harder to make a mistake when you have a special type for points on manifolds (and MLJ will have one for integration with Manifolds.jl: https://github.com/alan-turing-institute/MLJScientificTypes.jl/issues/46 ). On the other hand having just arrays makes it easier to maximize performance. I've for example written HybridArrays when I noticed that the standard Array-of-SArrays pattern is difficult to handle.

GPU kernels is another great topic, tracked here: #228 .

The answer necessarily depends on the package you want to use with Manifolds.jl and performance requirements.

Additionally, I've commented about NearestNeighbors.jl compatibility here: JuliaRobotics/ApproxManifoldProducts.jl#41 (comment) .

@JuliaManifolds JuliaManifolds locked and limited conversation to collaborators Jul 7, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants