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

towards val::Vector{T} #783

Merged
merged 7 commits into from
Jun 28, 2021
Merged

towards val::Vector{T} #783

merged 7 commits into from
Jun 28, 2021

Conversation

dehann
Copy link
Member

@dehann dehann commented Jun 19, 2021

fyi @Affie , im changing @defVariable slightly to take the identity point for a variable rather than just a point type. We still get the same point type information using typeof. Let me know if there is a problem.

Issue is we need for serialization something like getCoordinates and getPoint. For the default dispatch, im just pointing through to the basic Manifolds get_coordinates and get_vector functions. Users doing something more fancy should override DFGs getCoordinates and getPoint functions if needed.

@dehann dehann added this to the v0.15.0 milestone Jun 19, 2021
@dehann dehann self-assigned this Jun 19, 2021
@Affie
Copy link
Member

Affie commented Jun 19, 2021

Hi, I also considered it, but as far as i know the identity element is not general on all manifolds, but only for groups.

https://en.m.wikipedia.org/wiki/Identity_element

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

i know the identity element is not general on all manifolds

Sorry I should clarify, i mean user specifies with @defVariable one example data object (not type). And, in addition to make it the zero/reference/identity element if the manifold is also a group, which allows for more automation in serialization and elsewhere.

Either way, we definitely need something for serialization. I think getCoordinates is more general than requiring users to write dedicated serialization converters for each manifold? Hence the need for an easy Identity element.

Besides, I don't think it is that big a difference between writing (might actually even be simpler for more complicated array types):

@defVariable SpecialEuclidean(3) ProductRepr([0;0;0.0], [1 0 0; 0 1 0; 0 0 1.0])

and

@defVariable SpecialEuclidean(3) ProductRepr{Tuple{Vector{Float64}, Matrix{Float64}}}

If you really don't like it, can we at least just use it as a transition mechanism, until we find something better than defaulting to DFG.getCoordinates / Manifolds.get_coordinates in serialization?

@dehann dehann marked this pull request as ready for review June 19, 2021 18:36
@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

as far as i know the identity element is not general on all manifolds

probably not, and in these cases we can just require users to define their own DFG.getCoordinates(::Type{<:InferenceVariable, p) and DFG.getPoint(::Type{<:InferenceVariable}, coords). As default, all manifolds that are also a group can just go on defaults -- i.e. groups always have an identity element:
https://en.wikipedia.org/wiki/Group_(mathematics)

@dehann dehann requested a review from Affie June 19, 2021 18:46
@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

I'm going to continue down this path for now, to get IIF and RoME to also work for vnd.val::Vector{P}. I'm thinking that the least disruption will be to update the internals of getPoints. There are a lot of places in the downstream code where I use:

matrixofcoords = getBelief(fg, :x1) |> getPoints

So I was thinking to use the same DFG.getCoordinates default as transition method for this getPoints function. Note the difference between getPointabove and getPoints here.

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

Oh and forgot to mention the tests here DFG should be passing on this PR at current commit 6e253d0

@Affie
Copy link
Member

Affie commented Jun 19, 2021

Just to take a step back, why is the "identity element" better for serialization?
Also, why would you need coordinates?

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

How do we store something like ProductRepr([1;2], [0 1; 0 1]) in FileDFG or CloudDFG?

Currently all our plumbing is setup for a long vector of Float64 for serialized.

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

PS, the majority of work for this is upgrade is in IIF, so i'm happy to do it in two iterations, but would just like to keep moving rather than grinding away in DFG too long

src/entities/DFGVariable.jl Outdated Show resolved Hide resolved
Comment on lines 152 to 173
function getPoint(::Type{T}, v::AbstractVector) where {T <: InferenceVariable}
M = getManifold(T)
p0 = getPointIdentity(T)
X = get_vector(M, p0, v, DefaultOrthonormalBasis())
exp(M, p0, X)
end

"""
$SIGNATURES

Default reduction of a variable point value (a group element) into coordinates as `Vector`. Override if defaults are not correct.

Related

[`getPoint`](@ref)
"""
function getCoordinates(::Type{T}, p) where {T <: InferenceVariable}
M = getManifold(T)
p0 = getPointIdentity(T)
X = log(M, p0, p)
get_coordinates(M, p0, X, DefaultOrthonormalBasis())
end
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure about this. It's not general and makes a lot of assumptions.

Perhaps it can be more accurate with a new abstract LieGroupInferenceVariable <: InferenceVariable (but also don't like it that much)

Copy link
Member Author

Choose a reason for hiding this comment

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

Lets not pre-optimize. I'm trying to take a reasonable step towards Manifolds based on where we are today. Manifolds.get_coordinates already exists, so my feeling is we can leverage that as default and user must override for general cases.

For this step, I'm totally against building new abstracts. Maybe later once vnd.val::Vector{P} is already working fully downstream.

@Affie
Copy link
Member

Affie commented Jun 19, 2021

How do we store something like ProductRepr([1;2], [0 1; 0 1]) in FileDFG or CloudDFG?
Currently all our plumbing is setup for a long vector of Float64 for serialized.

Maybe I'm missing something, is it not as simple as:

julia> A = SA[1 2; 3 4]
2×2 SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
 1  2
 3  4

julia> v = vec(A)
4-element SVector{4, Int64} with indices SOneTo(4):
 1
 3
 2
 4

julia> B = typeof(A)(v)
2×2 SMatrix{2, 2, Int64, 4} with indices SOneTo(2)×SOneTo(2):
 1  2
 3  4

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

Not everything is ProductRepr, so each variable type will have its own unique way of going between "coordinates" that we can stack in a vector, and the "group" that we use for computations in VND.

We can change all this after the first iteration vnd.val::Vector{P} is working end to end. I'm sure there are better ways. I'm just taking the most direct route to getting the upgrade with least breakages in IIF, RoME, and Plotting

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

busy changing bw back to matrix.. will commit in a few minutes

@Affie
Copy link
Member

Affie commented Jun 19, 2021

We can change all this after the first iteration vnd.val::Vector{P} is working end to end. I'm sure there are better ways. I'm just taking the most direct route to getting the upgrade with least breakages in IIF, RoME, and Plotting

I'm all for getting the ball rolling. As long as it doesn't get baked in because of serialization. I would rather design how it would work best for numerics and then have serialization fit in with that.

So I say go ahead, as you mentioned the hard part will be downstream and we need to get to it.

@Affie
Copy link
Member

Affie commented Jun 19, 2021

If we can serialize:

  • ProductRepr (which is just a tuple)
  • Vector
  • S/MVector
  • S/MMatrix

Is that not enough? If a user wants some other type they can implement a new serialize function

Edit: I took matrix out, I think StaticArrays should be enough, but Vector is easy to do.

@dehann
Copy link
Member Author

dehann commented Jun 19, 2021

rather design how it would work best for numerics and then have serialization fit in with that.

I agree with that, we will revisit #590 so we can be a bit more loose with serialization now. I want to include in this design criteria how easy it is for a newcomer to build new variables and factors.

So I say go ahead, as you mentioned the hard part will be downstream and we need to get to it.

Cool, lets tag downstream working, and then come back to DFG and do a deprecation cycle for cleanup on the Manifolds.jl upgrade.

I took matrix out

Think we (our early users) are very likely to want matrices, so should include that.

If we can serialize:
Is that not enough? If a user wants some other type they can implement a new serialize function

Yup, 100% agree. One thing I've wanted to do for a long time is make variables and factors use a @AutoSerializeDFG macro and avoid the need for users to have to constantly specify types and converters for:

  • PackedDistribution
  • PackedVariable
  • PackedVariableNodeData
  • PackedFunctionNodeData
  • PackedManifoldPoint
  • etc.

I'd say we do that as a cleanup, keeping bits of JSON3, #590, etc in mind; but that is after this work to transition to Manifolds.jl proper, and also get JuliaRobotics/IncrementalInference.jl#1010 resolved first.

@Affie
Copy link
Member

Affie commented Jun 21, 2021

xref #763

@Affie
Copy link
Member

Affie commented Jun 21, 2021

@dehann
Copy link
Member Author

dehann commented Jun 28, 2021

xref JuliaManifolds/Manopt.jl#90

@dehann dehann merged commit 6b7bfef into master Jun 28, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants