Closed Affie closed 2 years ago
To me it looks like we might have missed to make the translation group transparent w.r.t. exp, i.e. that it passes exp – which is here just + – down to Euclidean. Will take a look.
First addition, no my first assumption was wrong, since
M = TranslationGroup(2)
p = [2,0]
X = [1,0]
exp(M,p,X)
retract(M, p, X, ExponentialRetraction())
both last lines work fine. The very last one – on a MetricManifold might fall back to calling the ODE solver, which is what errors for you, since to approximate the Exponential map using a retraction, one can not use exp as a retraction.
edit: Uh! Narrowed it down, its not exp, it's exp!
in the above code calling
exp!(M,q,p,X)
fails. So now we at least have a minimal erroring example.
Found the culprit, as you can see in the PR. Up to one general point (which is just a short general discussion and maybe moving that one new function definition further up in the manifold Hierarchy), this should be available soon.
Maybe a little longer explanation. The old system of AbstractGroupManifold and AbstractMetricManifold and all these was changed to a more flexible (completely TTHT based) system of a list of traits one can attach to a manifold.
The TranslationGroup
itself got a BiInvariant Metric trait and EuclideanMetric as its default metric (if no other is given using MetricManifold
). But it also inherited all traits from Euclidean
before finally IsExplicitDecorator
is kind of a “catch-all” trait that passes all functions that were not handled further down to Euclidean
itself.
This works really nicely in general with exp!
as the really only exception, since for exp!
with a IsMetricManifold
decorator we have a fallback to solving the corresponding ODE (for the geodesic/exp) as long as you can specify a retraction that is not ExponentialRetration
itself on a MetricManifold
. This solver itself is called the ODEExponentialRetraction(r)
retraction, where r
is the nice/new default_retraction(M)
. This is - without surprise – ExponentialRetraction()
for M=Euclidean
.
And this is how we got to that error. The fix is, that exp!
for TranslationGroup
now just gets the IsExplicitDecorator
trait and hence directly passes down to Euclidean
.
And the one thing to discuss is, whether we should do this for all group manifolds maybe.
Besides that: I grew quite fond of the new system we came up with, since it is more flexible, reasonable to read (In your StackTrance [3]. you can see that the exp for an IsMetricManifold
is what is considered and that tries to start the ODE solver).
Thank you very much for the quick fix.
The original issue is fixed, however, It looks like exp!
is still not working on the SE group:
julia> using Manifolds
julia> p = ProductRepr([0.0,0.0], [1.0 0.0; 0.0 1.0])
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
1.0 0.0
0.0 1.0
julia> X = ProductRepr([0.0,0.0], [0.0 0.1; -0.1 0.0])
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
0.0 0.1
-0.1 0.0
julia> M = SpecialEuclidean(2)
SpecialEuclidean(2)
julia> exp(M, p, X)
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
0.995004 0.0998334
-0.0998334 0.995004
julia> exp!(M, p, p, X)
ERROR: DomainError with ExponentialRetraction():
You can not use the exponential map as an inner method to solve the ode for the exponential map.
Stacktrace:
[1] ODEExponentialRetraction(r::ExponentialRetraction, #unused#::DefaultOrthonormalBasis{ℝ, ManifoldsBase.TangentSpaceType})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:93
[2] ODEExponentialRetraction(r::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:82
[3] exp!(#unused#::ManifoldsBase.TraitList{IsMetricManifold, ManifoldsBase.TraitList{ManifoldsBase.IsExplicitDecorator, ManifoldsBase.EmptyTrait}}, M::GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, q::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, p::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, X::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}})
@ Manifolds ~/.julia/packages/Manifolds/G5bzq/src/manifolds/MetricManifold.jl:257
[4] exp! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[5] exp!(M::GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, q::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, p::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, X::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275
[6] top-level scope
@ REPL[19]:1
I didn't know if I should open a new issue as it looks related.
So we might have missed another case, ah for the specific GroupManifold. I have to check (maybe tonight after my travels), but adapting the same traits as we just did for the previous error should to the trick here as well.
SE(n) is more complicated. I think we haven't decided yet whether we want the product metric or the left-invariant metric by default. Which one is more important for you?
We also use RealCircleGroup
and it has the same issue.
SE(n) is more complicated. I think we haven't decided yet whether we want the product metric or the left-invariant metric by default. Which one is more important for you?
If I understand it correctly, I think the left-invariant metric. Perhaps @dehann can confirm.
We also use
RealCircleGroup
and it has the same issue.
That's simple, I'll fix it today.
I have a somewhat related question:
With the updated trait system, should we use retract!
with ExponentialRetraction()
as opposed to exp!
I guess it's more general in any case? We currently only (or mostly) use exp and log
Note that retract! works where exp! gives an error:
julia> using Manifolds
julia> p = [1.0]
1-element Vector{Float64}:
1.0
julia> X = [0.1]
1-element Vector{Float64}:
0.1
julia> M = RealCircleGroup()
RealCircleGroup()
julia> retract!(M, p, p, X, ExponentialRetraction())
1-element Vector{Float64}:
1.1
julia> exp!(M, p, p, X)
ERROR: DomainError with ExponentialRetraction():
You can not use the exponential map as an inner method to solve the ode for the exponential map.
Stacktrace:
[1] ODEExponentialRetraction(r::ExponentialRetraction, #unused#::DefaultOrthonormalBasis{ℝ, ManifoldsBase.TangentSpaceType})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:93
[2] ODEExponentialRetraction(r::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:82
[3] exp!(#unused#::ManifoldsBase.TraitList{IsMetricManifold, ManifoldsBase.TraitList{HasBiinvariantMetric, ManifoldsBase.TraitList{HasLeftInvariantMetric, ManifoldsBase.TraitList{HasRightInvariantMetric, ManifoldsBase.TraitList{ManifoldsBase.IsExplicitDecorator, ManifoldsBase.EmptyTrait}}}}}, M::RealCircleGroup, q::Vector{Float64}, p::Vector{Float64}, X::Vector{Float64})
@ Manifolds ~/.julia/packages/Manifolds/G5bzq/src/manifolds/MetricManifold.jl:257
[4] exp! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[5] exp!(M::RealCircleGroup, q::Vector{Float64}, p::Vector{Float64}, X::Vector{Float64})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275
[6] top-level scope
@ REPL[13]:1
exp!(M, p, p, X)
not working is a bug (it will be fixed by #486). retract!
is more general but you should use exp!(M, p, p, X)
instead of retract!(M, p, p, X, ExponentialRetraction())
.
SE(n) is more complicated. I think we haven't decided yet whether we want the product metric or the left-invariant metric by default. Which one is more important for you?
I think the left-invariant metric. Perhaps dehann can confirm.
As I understand, left-invariant is more important for us, however, I'm not yet able to complete foresee how the difference would effect us. My sense is to stay with the usual Lie Group / Algebra definitions (which is the way we are using it). Don't believe I have ever used Lie Groups under product invariant mechanization before. I probably need to learn more about the distinction in this context to give a better answer.
I'm not yet able to complete foresee how the difference would effect us
Don't worry, it would not affect you much, either metric can always be used with the MetricManifold(Manifold,Metric)
scheme, just that Manifold
itself will default to using the one we specify. My favourite would maybe be the left invariant since we are tiling about Lie groups here?
OK, left-invariant definitely makes sense.
It's possible to write a relatively generic code for left-invariant metrics on Lie groups but for SE(2) and SE(3) it would be nice to have optimized implementations. @dehann are you aware of some existing implementations we could copy here?
I've encounter a tricky issue. By giving SpecialEuclidean
the left-invariant metric we need to adjust get_vector
and get_coordinates
so that they also respect orthogonality and orthonormality in the new metric. The easiest way to solve it is by transporting vectors to and from identity. Which is a significant departure from what we currently do so I'm not entirely sure if that's something we want.
My favourite would maybe be the left invariant since we are [talking] about Lie groups here?
OK, left-invariant definitely makes sense.
By giving SpecialEuclidean the left-invariant metric we need to adjust get_vector and get_coordinates so that they also respect orthogonality and orthonormality in the new metric. The easiest way to solve it is by transporting vectors to and from identity.
hmm, so I'm barely keeping up... This sounds like going for left-nvariant may have a performance implication, and we'd rather avoid bottlenecks for the sake of speed.
Don't worry, it would not affect you much, either metric can always be used with the MetricManifold(Manifold,Metric) scheme, just that Manifold itself will default to using the one we specify.
I'd say ignore my input on Product metric vs left-invariant metric decision (my knowledge likely too limited to help). Perhaps reduce scope of my input to "i'd vote for speed on SE(2) since we will be using that excessively in hot-loops".
It's possible to write a relatively generic code for left-invariant metrics on Lie groups but for SE(2) and SE(3) it would be nice to have optimized implementations.
If there is a performance implication on the decision between metrics, is this maybe one of those trade-off cases where either, general == slower, vs focused solution == better performance?
relatively generic code for left-invariant metrics
@dehann
are you aware of some existing implementations we could copy here?
Unfortunately no, not immediately.
[generic left invariant changes to get_vector, get_coordinates].. is a significant departure from what we currently do so I'm not entirely sure if that's something we want.
I'm a little nervous about pushing for one or the other option that results in bigger changes being made ... and then later as I learn more discover it was the wrong decision. The best hedge I can come up with (before learning more) is go for a simple focused implementation for speed that uses dispatch properly. And let the more "general flexibility" grow via Julia's multiple dispatch as the use-cases arrive.
My homework is to go get sharp on left-invariant vs. product metric to be useful on this topic in the future. So I'm starting by reading this:
also respect orthogonality and orthonormality in the new metric.
think I'm still following with that part, but I don't feel crisp about original question and fundamental choice between product vs left-invariant metric choice.
hmm, so I'm barely keeping up... This sounds like going for left-nvariant may have a performance implication, and we'd rather avoid bottlenecks for the sake of speed.
For SE(n) probably what we currently do is correct and there would be no performance implication but I'll have to check. It doesn't look correct for arbitrary semisimple products of Lie groups though.
Don't worry, it would not affect you much, either metric can always be used with the MetricManifold(Manifold,Metric) scheme, just that Manifold itself will default to using the one we specify.
I'd say ignore my input on Product metric vs left-invariant metric decision (my knowledge likely too limited to help). Perhaps reduce scope of my input to "i'd vote for speed on SE(2) since we will be using that excessively in hot-loops".
I definitely want to support both metrics and have both as fast as possible :slightly_smiling_face: .
If there is a performance implication on the decision between metrics, is this maybe one of those trade-off cases where either, general == slower, vs focused solution == better performance?
Yes, exactly. We should have focused implementations for SE(2) and SE(3) though so you shouldn't worry too much -- it's just a matter of writing some specialized methods.
Unfortunately no, not immediately.
That's OK, I will work on that then.
I'm a little nervous about pushing for one or the other option that results in bigger changes being made ... and then later as I learn more discover it was the wrong decision. The best hedge I can come up with (before learning more) is go for a simple focused implementation for speed that uses dispatch properly. And let the more "general flexibility" grow via Julia's multiple dispatch as the use-cases arrive.
Yes, sure, we can start with focused implementations.
My homework is to go get sharp on left-invariant vs. product metric to be useful on this topic in the future. So I'm starting by reading this:
That's way too general for our case here. We are talking about invariance as defined here: https://idv.sinica.edu.tw/ftliang/diff_geom/*diff_geometry(II)/4.08/lie_group_curvature.pdf .
EDIT: Ignore this one as the next two comments shows the issue better
I got another similar error, I'm still trying to figure out if it's a new error or related, I'll post an MWE as soon as I trace down the issue, but here is the stack trace in the meantime.
ERROR: DomainError with ManifoldsBase.ExponentialRetraction():
You can not use the exponential map as an inner method to solve the ode for the exponential map.
Stacktrace:
[1] ManifoldsBase.ODEExponentialRetraction(r::ManifoldsBase.ExponentialRetraction, #unused#::ManifoldsBase.DefaultOrthonormalBasis{ℝ, ManifoldsBase.TangentSpaceType})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:93
[2] ManifoldsBase.ODEExponentialRetraction(r::ManifoldsBase.ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:82
[3] exp!(#unused#::ManifoldsBase.TraitList{Manifolds.IsMetricManifold, ManifoldsBase.TraitList{ManifoldsBase.IsExplicitDecorator, ManifoldsBase.EmptyTrait}}, M::Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, q::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, p::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, X::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/manifolds/MetricManifold.jl:257
[4] exp! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[5] exp!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275 [inlined]
[6] map
@ ./tuple.jl:266 [inlined]
[7] exp!(M::ProductManifold{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/manifolds/ProductManifold.jl:394
[8] _retract!(M::ProductManifold{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, #unused#::ManifoldsBase.ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:636
[9] retract!(M::ProductManifold{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, m::ManifoldsBase.ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:619
[10] retract!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:308 [inlined]
[11] retract! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[12] retract!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275 [inlined]
[13] retract!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:291 [inlined]
[14] retract! (repeats 3 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[15] retract!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275 [inlined]
[16] retract!(M::Manifolds.ProductGroup{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, t::Float64, method::ManifoldsBase.ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:629
[17] mean!(M::Manifolds.ProductGroup{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, y::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, x::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}}, w::StatsBase.UnitWeights{Float64}, ::Manifolds.GradientDescentEstimation; p0::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, stop_iter::Int64, retraction::ManifoldsBase.ExponentialRetraction, inverse_retraction::ManifoldsBase.LogarithmicInverseRetraction, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:389
[18] mean!
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:367 [inlined]
[19] mean(M::Manifolds.ProductGroup{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, x::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}}, w::StatsBase.UnitWeights{Float64}, method::Manifolds.GradientDescentEstimation; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:320
[20] mean
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:319 [inlined]
[21] #mean_and_var#173
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:987 [inlined]
[22] #mean_and_var#174
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:1000 [inlined]
[23] mean_and_var(M::Manifolds.ProductGroup{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, x::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}}, method::Manifolds.GradientDescentEstimation) (repeats 2 times)
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:998
[24] #var#171
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:940 [inlined]
[25] var
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:940 [inlined]
[26] std(M::Manifolds.ProductGroup{ℝ, Tuple{Manifolds.GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{Manifolds.RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, Manifolds.LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, args::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:958
[27] std
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:958 [inlined]
[28] #std#9
@ ~/.julia/dev/IncrementalInference/src/VariableStatistics.jl:5 [inlined]
[29] std
@ ~/.julia/dev/IncrementalInference/src/VariableStatistics.jl:5 [inlined]
[30] calcStdBasicSpread(vartype::DynPose2, ptsArr::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}})
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/VariableStatistics.jl:14
[31] evalPotentialSpecific(Xi::Vector{DFGVariable{DynPose2}}, ccwl::CommonConvWrapper{DynPose2VelocityPrior{FullNormal, FullNormal}, Nothing, Vector{Int64}, NamedTuple{(:x0,), Tuple{Vector{Any}}}, Nothing, ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, Nothing}, solvefor::Symbol, T_::Type{DynPose2VelocityPrior{FullNormal, FullNormal}}, measurement::Vector{Tuple}; needFreshMeasurements::Bool, solveKey::Symbol, N::Int64, dbg::Bool, spreadNH::Float64, inflateCycles::Int64, nullSurplus::Float64, skipSolve::Bool, _slack::Nothing)
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/services/EvalFactor.jl:433
[32] #evalPotentialSpecific#342
@ ~/.julia/dev/IncrementalInference/src/services/EvalFactor.jl:511 [inlined]
[33] evalFactor(dfg::GraphsDFG{SolverParams, DFGVariable, DFGFactor}, fct::DFGFactor{CommonConvWrapper{DynPose2VelocityPrior{FullNormal, FullNormal}, Nothing, Vector{Int64}, NamedTuple{(:x0,), Tuple{Vector{Any}}}, Nothing, ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, Nothing}, 1}, solvefor::Symbol, measurement::Vector{Tuple}; needFreshMeasurements::Bool, solveKey::Symbol, N::Int64, inflateCycles::Int64, nullSurplus::Float64, dbg::Bool, skipSolve::Bool, _slack::Nothing)
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/services/EvalFactor.jl:550
[34] approxConvBelief(dfg::GraphsDFG{SolverParams, DFGVariable, DFGFactor}, fc::DFGFactor{CommonConvWrapper{DynPose2VelocityPrior{FullNormal, FullNormal}, Nothing, Vector{Int64}, NamedTuple{(:x0,), Tuple{Vector{Any}}}, Nothing, ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, Nothing}, 1}, target::Symbol, measurement::Vector{Tuple}; solveKey::Symbol, N::Int64, nullSurplus::Float64, skipSolve::Bool)
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/services/ApproxConv.jl:18
[35] #calcProposalBelief#352
@ ~/.julia/dev/IncrementalInference/src/services/ApproxConv.jl:164 [inlined]
[36] proposalbeliefs!(dfg::GraphsDFG{SolverParams, DFGVariable, DFGFactor}, destlbl::Symbol, factors::Vector{DFGFactor{CommonConvWrapper{DynPose2VelocityPrior{FullNormal, FullNormal}, Nothing, Vector{Int64}, NamedTuple{(:x0,), Tuple{Vector{Any}}}, Nothing, ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, Nothing}, 1}}, dens::Vector{ManifoldKernelDensity}, measurement::Vector{Tuple}; solveKey::Symbol, N::Int64, nullSurplusAdd::Float64, dbg::Bool)
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/services/ApproxConv.jl:247
[37] propagateBelief(dfg::GraphsDFG{SolverParams, DFGVariable, DFGFactor}, destvar::DFGVariable{DynPose2}, factors::Vector{DFGFactor{CommonConvWrapper{DynPose2VelocityPrior{FullNormal, FullNormal}, Nothing, Vector{Int64}, NamedTuple{(:x0,), Tuple{Vector{Any}}}, Nothing, ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, Nothing}, 1}}; solveKey::Symbol, dens::Vector{ManifoldKernelDensity}, N::Int64, needFreshMeasurements::Bool, dbg::Bool, logger::Logging.ConsoleLogger)
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/GraphProductOperations.jl:30
[38] doautoinit!(dfg::GraphsDFG{SolverParams, DFGVariable, DFGFactor}, xi::DFGVariable{DynPose2}; solveKey::Symbol, singles::Bool, N::Int64, logger::Logging.ConsoleLogger)
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/services/GraphInit.jl:126
[39] #doautoinit!#25
@ ~/.julia/dev/IncrementalInference/src/services/GraphInit.jl:160 [inlined]
[40] doautoinit!(dfg::GraphsDFG{SolverParams, DFGVariable, DFGFactor}, Xi::Vector{DFGVariable{DynPose2}})
@ IncrementalInference ~/.julia/dev/IncrementalInference/src/services/GraphInit.jl:156
[41] top-level scope
@ REPL[10]:1
It looks related here is a simpler test:
julia> M = ProductGroup(ProductManifold(SpecialEuclidean(2), TranslationGroup(2)))
ProductGroup with 2 subgroups:
SpecialEuclidean(2)
TranslationGroup(2; field = ℝ)
julia> p1 = ProductRepr(ProductRepr([0;0.0],[1 0; 0 1.0]),[0;0.0])
ProductRepr with 2 submanifold components:
Component 1 =
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
1.0 0.0
0.0 1.0
Component 2 =
2-element Vector{Float64}:
0.0
0.0
julia> p2 = ProductRepr(ProductRepr([0;0.0],[0.0 -1.0; 1.0 0.0]),[0;0.0])
ProductRepr with 2 submanifold components:
Component 1 =
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
0.0 -1.0
1.0 0.0
Component 2 =
2-element Vector{Float64}:
0.0
0.0
julia> mean(M, [p1,p2])
ERROR: DomainError with ExponentialRetraction():
You can not use the exponential map as an inner method to solve the ode for the exponential map.
Stacktrace:
[1] ODEExponentialRetraction(r::ExponentialRetraction, #unused#::DefaultOrthonormalBasis{ℝ, ManifoldsBase.TangentSpaceType})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:93
[2] ODEExponentialRetraction(r::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:82
[3] exp!(#unused#::ManifoldsBase.TraitList{IsMetricManifold, ManifoldsBase.TraitList{ManifoldsBase.IsExplicitDecorator, ManifoldsBase.EmptyTrait}}, M::GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, q::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, p::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, X::ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/manifolds/MetricManifold.jl:257
[4] exp! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[5] exp!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275 [inlined]
[6] map
@ ./tuple.jl:266 [inlined]
[7] exp!(M::ProductManifold{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/manifolds/ProductManifold.jl:394
[8] _retract!(M::ProductManifold{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, #unused#::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:636
[9] retract!(M::ProductManifold{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, m::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:619
[10] retract!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:308 [inlined]
[11] retract! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[12] retract!
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275 [inlined]
[13] retract!(M::ProductManifold{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, t::Float64, method::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:629
[14] mean!(M::ProductManifold{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, y::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, x::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}}, w::StatsBase.UnitWeights{Float64}, ::GradientDescentEstimation; p0::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, stop_iter::Int64, retraction::ExponentialRetraction, inverse_retraction::LogarithmicInverseRetraction, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:389
[15] mean!
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:367 [inlined]
[16] #mean!#146
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:351 [inlined]
[17] mean!
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:350 [inlined]
[18] mean(M::ProductManifold{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, x::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}}, method::GradientDescentEstimation; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:310
[19] mean (repeats 2 times)
@ ~/.julia/packages/Manifolds/oiCZl/src/statistics.jl:309 [inlined]
[20] mean
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:308 [inlined]
[21] mean (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[22] mean
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275 [inlined]
[23] mean
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:291 [inlined]
[24] mean (repeats 3 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[25] mean(M::ProductGroup{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, x::Vector{ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}})
@ Manifolds ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275
[26] top-level scope
@ REPL[23]:1
Or just the exp:
julia> p = ProductRepr(ProductRepr([0;0.0],[1 0; 0 1.0]),[0;0.0]);
julia> X = ProductRepr(ProductRepr([0;0.0],[0.0 -0.0; 0.0 0.0]),[0;0.0]);
julia> retract(M, p, X)
ProductRepr with 2 submanifold components:
Component 1 =
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
1.0 0.0
0.0 1.0
Component 2 =
2-element Vector{Float64}:
0.0
0.0
julia> exp(M, p, X)
ProductRepr with 2 submanifold components:
Component 1 =
ProductRepr with 2 submanifold components:
Component 1 =
2-element Vector{Float64}:
0.0
0.0
Component 2 =
2×2 Matrix{Float64}:
1.0 0.0
0.0 1.0
Component 2 =
2-element Vector{Float64}:
0.0
0.0
julia> exp!(M, p, p, X)
ERROR: DomainError with ExponentialRetraction():
You can not use the exponential map as an inner method to solve the ode for the exponential map.
Stacktrace:
[1] ODEExponentialRetraction(r::ExponentialRetraction, #unused#::DefaultOrthonormalBasis{ℝ, ManifoldsBase.TangentSpaceType})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:93
[2] ODEExponentialRetraction(r::ExponentialRetraction)
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/retractions.jl:82
[3] exp!(#unused#::ManifoldsBase.TraitList{IsMetricManifold, ManifoldsBase.TraitList{ManifoldsBase.IsExplicitDecorator, ManifoldsBase.EmptyTrait}}, M::ProductGroup{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}})
@ Manifolds ~/.julia/packages/Manifolds/oiCZl/src/manifolds/MetricManifold.jl:257
[4] exp! (repeats 2 times)
@ ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:282 [inlined]
[5] exp!(M::ProductGroup{ℝ, Tuple{GroupManifold{ℝ, ProductManifold{ℝ, Tuple{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}}}, Manifolds.SemidirectProductOperation{RotationAction{TranslationGroup{Tuple{2}, ℝ}, SpecialOrthogonal{2}, LeftAction}}}, TranslationGroup{Tuple{2}, ℝ}}}, q::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, p::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}}, X::ProductRepr{Tuple{ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}, Vector{Float64}}})
@ ManifoldsBase ~/.julia/packages/ManifoldsBase/wwhwL/src/nested_trait.jl:275
[6] top-level scope
@ REPL[28]:1
These issues will be fixed soon, somehow we didn't properly test manifold operations on special euclidean groups. I put fixes in #491 , it should fix everything except some issues with in-place mutation I haven't found yet.
Manifolds.jl 0.8.9 should fix all of these issues except some rare cases of in-place mutation.
Thanks @mateuszbaran, the exp!
issues look fixed.
This one still gives an error though: https://github.com/JuliaManifolds/Manifolds.jl/issues/483#issuecomment-1147520585
EDIT: no it works, was my error testing it
Thanks!
Hi, I'm upgrading code to v0.8 and get a DomainError, here is a minimum example: