Skip to content

Commit 2945c8e

Browse files
authored
Merge pull request #1359 from JuliaRobotics/21Q3/enh/sampleTangent_Point
`sampleTangent` and `samplePoint`
2 parents 6077d84 + 15d2909 commit 2945c8e

File tree

5 files changed

+88
-76
lines changed

5 files changed

+88
-76
lines changed

src/Factors/GenericFunctions.jl

Lines changed: 11 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,6 @@ function distancePrior(M::AbstractManifold, meas, p)
3838
# return distance(M, p, meas)
3939
end
4040

41-
## ======================================================================================
42-
## Default Identities #TODO only development, replace with better idea
43-
## ======================================================================================
44-
45-
default_identity(M) = error("No default identity element defined for $(typeof(M))")
46-
default_identity(M::GroupManifold{ℝ, <:ProductManifold}) = error("No default identity element defined for $(typeof(M))")
47-
function default_identity(::SpecialEuclidean{N}) where N
48-
T = Float64
49-
t = zeros(SVector{N, T})
50-
R = SMatrix{N,N,T}(one(T)I)
51-
return ProductRepr(t, R)
52-
end
53-
function default_identity(M::GroupManifold{ℝ, <:AbstractManifold})
54-
T = Float64
55-
s = representation_size(M)
56-
return identity_element(M, zeros(SArray{Tuple{s...},T}))
57-
end
58-
59-
# function default_identity(::SpecialOrthogonal{N}) where N
60-
# T = Float64
61-
# return SMatrix{N,N,T}(one(T)I)
62-
# end
63-
6441
## ======================================================================================
6542
## ManifoldFactor
6643
## ======================================================================================
@@ -78,17 +55,15 @@ end
7855

7956
DFG.getManifold(f::ManifoldFactor) = f.M
8057

81-
# function getSample(cf::ManifoldFactor, N::Int=1)
8258
function getSample(cf::CalcFactor{<:ManifoldFactor}, N::Int=1)
8359
#TODO @assert dim == cf.factor.Z's dimension
8460
#TODO investigate use of SVector if small dims
8561
ret = [rand(cf.factor.Z) for _ in 1:N]
86-
87-
#TODO tangent or not?
88-
# tangent for now to fit with rest
62+
#return coordinates as we do not know the point here #TODO separate Lie group
8963
(ret, )
9064
end
9165

66+
# function (cf::CalcFactor{<:ManifoldFactor{<:AbstractGroupManifold}})(Xc, p, q)
9267
function (cf::CalcFactor{<:ManifoldFactor})(Xc, p, q)
9368
# function (cf::ManifoldFactor)(X, p, q)
9469
M = cf.factor.M
@@ -103,12 +78,16 @@ end
10378
export ManifoldPrior
10479
# `p` is a point on manifold `M`
10580
# `Z` is a measurement at the tangent space of `p` on manifold `M`
106-
struct ManifoldPrior{M <: AbstractManifold, T <: SamplableBelief, P} <: AbstractPrior
81+
struct ManifoldPrior{M <: AbstractManifold, T <: SamplableBelief, P, B <: AbstractBasis} <: AbstractPrior
10782
M::M
10883
p::P #NOTE This is a fixed point from where the measurement `Z` is made in coordinates on tangent TpM
10984
Z::T
85+
basis::B
86+
retract_method::AbstractRetractionMethod
11087
end
11188

89+
ManifoldPrior(M::AbstractGroupManifold, p, Z) = ManifoldPrior(M, p, Z, ManifoldsBase.VeeOrthogonalBasis(), ExponentialRetraction())
90+
11291
DFG.getManifold(f::ManifoldPrior) = f.M
11392

11493
#TODO
@@ -120,32 +99,24 @@ DFG.getManifold(f::ManifoldPrior) = f.M
12099

121100
# ManifoldPrior{M}(Z::SamplableBelief, p) where M = ManifoldPrior{M, typeof(Z), typeof(p)}(Z, p)
122101

123-
# function getSample(cf::ManifoldPrior, N::Int=1)
124102
function getSample(cf::CalcFactor{<:ManifoldPrior}, N::Int=1)
125103
Z = cf.factor.Z
126104
p = cf.factor.p
127105
M = cf.factor.M
128-
# Z = cf.Z
129-
# p = cf.p
130-
# M = cf.M
131-
132-
Xc = [rand(Z) for _ in 1:N]
133-
134-
# X = get_vector.(Ref(M), Ref(p), Xc, Ref(DefaultOrthogonalBasis()))
135-
X = hat.(Ref(M), Ref(p), Xc)
136-
points = exp.(Ref(M), Ref(p), X)
106+
basis = cf.factor.basis
107+
retract_method = cf.factor.retract_method
137108

109+
points = [samplePoint(M, Z, p, basis, retract_method) for _=1:N]
110+
138111
return (points, )
139112
end
140113

141114
#TODO investigate SVector if small dims, this is slower
142115
# dim = manifold_dimension(M)
143116
# Xc = [SVector{dim}(rand(Z)) for _ in 1:N]
144117

145-
# function (cf::ManifoldPrior)(m, p)
146118
function (cf::CalcFactor{<:ManifoldPrior})(m, p)
147119
M = cf.factor.M
148-
# M = cf.M
149120
# return log(M, p, m)
150121
return vee(M,p,log(M, p, m))
151122
# return distancePrior(M, m, p)
@@ -163,35 +134,3 @@ function mahalanobus_distance2(M, X, inv_Σ)
163134
Xc = vee(M, p, X)
164135
return Xc' * inv_Σ * Xc
165136
end
166-
167-
if false
168-
using IncrementalInference
169-
using Manifolds
170-
using LinearAlgebra
171-
using StaticArrays
172-
173-
f = ManifoldFactor(SpecialOrthogonal(3), MvNormal([0.1, 0.02, 0.01]))
174-
s = getSample(f,10)[1]
175-
s[1]
176-
177-
f = ManifoldFactor(SpecialEuclidean(2), MvNormal([0.1, 0.2, 0.01]))
178-
s = getSample(f,10)[1]
179-
s[1]
180-
181-
182-
f = ManifoldPrior(SpecialOrthogonal(2), SA[1.0 0; 0 1], MvNormal([0.1]))
183-
meas = getSample(f,10)[1]
184-
meas[1]
185-
f.(meas, Ref(SA[1.0 0; 0 1]))
186-
187-
f = ManifoldPrior(SpecialOrthogonal(3), SA[1.0 0 0; 0 1 0; 0 0 1], MvNormal([0.1, 0.02, 0.01]))
188-
s = getSample(f,10)[1]
189-
s[1]
190-
191-
f = ManifoldPrior(SpecialEuclidean(2), ProductRepr(SA[0,0], SA[1.0 0; 0 1]), MvNormal([0.1, 0.2, 0.01]))
192-
s = getSample(f,10)[1]
193-
s[1]
194-
195-
196-
197-
end

src/IncrementalInference.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,8 @@ include("SolverAPI.jl")
501501
# Symbolic tree analysis files.
502502
include("AnalysisTools.jl")
503503

504+
include("ManifoldSampling.jl")
505+
504506
# deprecation legacy support
505507
include("Deprecated.jl")
506508

src/ManifoldSampling.jl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export sampleTangent
2+
export samplePoint
3+
"""
4+
$SIGNATURES
5+
6+
Return a random sample as a tangent vector from a belief represented by coordinates on a manifold at point p.
7+
8+
Notes
9+
10+
"""
11+
function sampleTangent end
12+
13+
# Sampling MKD
14+
function sampleTangent(M::AbstractGroupManifold, x::ManifoldKernelDensity, p=mean(x))
15+
# get legacy matrix of coordinates and selected labels
16+
coords, lbls = sample(x.belief,1)
17+
X = hat(x.manifold, p, coords)
18+
return X
19+
end
20+
21+
function sampleTangent(x::ManifoldKernelDensity, p=mean(x))
22+
return sampleTangent(x.manifold, coords, p)
23+
end
24+
25+
# Sampling Distributions
26+
function sampleTangent(M::AbstractManifold, z::Distribution, p, basis::AbstractBasis)
27+
return get_vector(M, p, rand(z), basis)
28+
end
29+
30+
function sampleTangent(M::AbstractGroupManifold, z::Distribution, p=identity_element(M))
31+
return hat(M, p, rand(z))
32+
end
33+
34+
35+
"""
36+
$SIGNATURES
37+
38+
Return a random sample point on a manifold from a belief represented by coordinates at point p.
39+
40+
Notes
41+
42+
"""
43+
function samplePoint(M::AbstractManifold, sbelief, p, basis, retraction_method::AbstractRetractionMethod=ExponentialRetraction())
44+
X = sampleTangent(M, sbelief, p, basis)
45+
return retract(M, p, X, retraction_method)
46+
end
47+
function samplePoint(M::AbstractGroupManifold, sbelief, p=identity_element(M), retraction_method::AbstractRetractionMethod=ExponentialRetraction())
48+
X = sampleTangent(M, sbelief, p)
49+
return retract(M, p, X, retraction_method)
50+
end
51+
52+
53+
## default getSample
54+
# getSample(cf::CalcFactor{<:AbstractPrior}, N::Int=1) = ([samplePoint(getManifold(cf.factor), cf.factor.Z, ) for _=1:N], )
55+
# getSample(cf::CalcFactor{<:AbstractRelative}, N::Int=1) = ([sampleTangent(getManifold(cf.factor), cf.factor.Z) for _=1:N], )

test/testSpecialEuclidean2Mani.jl

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fg = initfg()
4040
v0 = addVariable!(fg, :x0, SpecialEuclidean2)
4141

4242
# mp = ManifoldPrior(SpecialEuclidean(2), ProductRepr(@MVector([0.0,0.0]), @MMatrix([1.0 0.0; 0.0 1.0])), MvNormal([0.01, 0.01, 0.01]))
43-
mp = ManifoldPrior(SpecialEuclidean(2), ProductRepr(@MVector([0.0,0.0]), @MMatrix([1.0 0.0; 0.0 1.0])), MvNormal([0.01, 0.01, 0.01]))
43+
mp = ManifoldPrior(SpecialEuclidean(2), ProductRepr(@MVector([0.0,0.0]), @MMatrix([1.0 0.0; 0.0 1.0])), MvNormal(Diagonal(abs2.([0.01, 0.01, 0.01]))))
4444
p = addFactor!(fg, [:x0], mp)
4545

4646

@@ -109,6 +109,16 @@ pbel_ = approxConvBelief(fg, :x0f1, :x0)
109109
##
110110
end
111111

112+
struct ManifoldFactorSE2{T <: SamplableBelief} <: IIF.AbstractManifoldMinimize
113+
Z::T
114+
end
115+
116+
ManifoldFactorSE2() = ManifoldFactorSE2(MvNormal(Diagonal([1,1,1])))
117+
DFG.getManifold(::ManifoldFactorSE2) = SpecialEuclidean(2)
118+
119+
IIF.selectFactorType(::Type{<:SpecialEuclidean2}, ::Type{<:SpecialEuclidean2}) = ManifoldFactorSE2
120+
121+
112122
@testset "Test Pose2 like hex as SpecialEuclidean2" begin
113123
##
114124

@@ -151,7 +161,13 @@ vnd = getVariableSolverData(fg, :x6)
151161
smtasks = Task[]
152162
solveTree!(fg; smtasks);
153163

154-
##
164+
## Special test for manifold based messages
165+
166+
#FIXME this may show some bug in propagateBelief caused by empty factors
167+
fg.solverParams.useMsgLikelihoods = true
168+
@test_broken solveTree!(fg; smtasks) isa Tuple
169+
170+
155171
end
156172

157173
## ======================================================================================

test/testSphereMani.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ using Test
66

77
##
88

9-
@testset "Test Sphere(2) prior" begin
9+
@testset "Test Sphere(2) prior and relative (broken)" begin
1010
##
1111

1212
Base.convert(::Type{<:Tuple}, M::Sphere{2, ℝ}) = (:Euclid, :Euclid)
@@ -26,7 +26,7 @@ fg = initfg()
2626

2727
v0 = addVariable!(fg, :x0, Sphere2)
2828

29-
mp = ManifoldPrior(Sphere(2), SA[1., 0, 0], MvNormal([0.01, 0.01]))
29+
mp = ManifoldPrior(Sphere(2), SA[1., 0, 0], MvNormal([0.01, 0.01]), DefaultOrthonormalBasis(), ExponentialRetraction())
3030
p = addFactor!(fg, [:x0], mp)
3131

3232
doautoinit!(fg, :x0)

0 commit comments

Comments
 (0)