Skip to content

Commit cdb86ca

Browse files
authored
Merge pull request #416 from JuliaRobotics/maint/21Q1/consol_range
Consolidate Range Factors
2 parents 2defb91 + 792c389 commit cdb86ca

File tree

8 files changed

+277
-73
lines changed

8 files changed

+277
-73
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ DistributedFactorGraphs = "0.12"
3535
Distributions = "0.21, 0.22, 0.23, 0.24"
3636
DocStringExtensions = "0.7, 0.8"
3737
FileIO = "1.0.2, 1.1, 1.2"
38-
IncrementalInference = "0.21.1"
38+
IncrementalInference = "0.21.2"
3939
JLD2 = "0.2, 0.3, 0.4"
4040
KernelDensityEstimate = "0.5.1, 0.6"
4141
Optim = "0.22, 1.0"

src/factors/Range2D.jl

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,21 @@ $(TYPEDEF)
66
"""
77
mutable struct Point2Point2Range{D <: IIF.SamplableBelief} <: IncrementalInference.AbstractRelativeMinimize
88
Z::D
9-
Point2Point2Range{D}() where {D} = new{D}()
10-
Point2Point2Range{D}(d::D) where {D <: IIF.SamplableBelief} = new{D}(d)
9+
# Point2Point2Range{D}() where {D} = new{D}()
10+
# Point2Point2Range{D}(d::D) where {D <: IIF.SamplableBelief} = new{D}(d)
1111
end
12-
Point2Point2Range(d::D) where {D <: IIF.SamplableBelief} = Point2Point2Range{D}(d)
12+
# Point2Point2Range(d::D) where {D <: IIF.SamplableBelief} = Point2Point2Range{D}(d)
13+
1314
function getSample(cfo::CalcFactor{<:Point2Point2Range}, N::Int=1)
14-
return (reshape(rand(cfo.factor.Z,N),1,N), 2*pi*rand(N))
15-
end
16-
function (cfo::CalcFactor{<:Point2Point2Range})(rho, theta, xi, lm)
17-
#
18-
XX = lm[1] - (rho[1]*cos(theta[1]) + xi[1])
19-
YY = lm[2] - (rho[1]*sin(theta[1]) + xi[2])
20-
#TODO JT - Should this have a sqrt for parametric?
21-
# return XX^2 + YY^2
22-
return sqrt(XX^2 + YY^2)
15+
return (reshape(rand(cfo.factor.Z,N),1,N),)
2316
end
2417

18+
function (cfo::CalcFactor{<:Point2Point2Range})(rho, xi, lm)
19+
# Basically `EuclidDistance`
20+
# must return all dimensions
21+
return rho .- norm(lm[1:2] .- xi[1:2])
22+
# return [rho[1] - norm(lm[1:2] .- xi[1:2])]
23+
end
2524

2625
passTypeThrough(d::FunctionNodeData{Point2Point2Range}) = d
2726

@@ -30,8 +29,8 @@ $(TYPEDEF)
3029
"""
3130
mutable struct PackedPoint2Point2Range <: IncrementalInference.PackedInferenceType
3231
str::String
33-
PackedPoint2Point2Range() = new()
34-
PackedPoint2Point2Range(s::AS) where {AS <: AbstractString} = new(s)
32+
# PackedPoint2Point2Range() = new()
33+
# PackedPoint2Point2Range(s::AS) where {AS <: AbstractString} = new(s)
3534
end
3635
function convert(::Type{PackedPoint2Point2Range}, d::Point2Point2Range)
3736
return PackedPoint2Point2Range(convert(PackedSamplableBelief, d.Z))
@@ -47,35 +46,29 @@ end
4746
4847
Range only measurement from Pose2 to Point2 variable.
4948
"""
50-
mutable struct Pose2Point2Range{T} <: IIF.AbstractRelativeMinimize
49+
mutable struct Pose2Point2Range{T <: IIF.SamplableBelief} <: IIF.AbstractRelativeMinimize
5150
Z::T
5251
partial::Tuple{Int,Int}
53-
Pose2Point2Range{T}() where T = new()
54-
Pose2Point2Range{T}(Z::T) where {T <: IIF.SamplableBelief} = new{T}(Z, (1,2))
52+
# Pose2Point2Range{T}() where T = new()
5553
end
56-
Pose2Point2Range(Z::T) where {T <: IIF.SamplableBelief} = Pose2Point2Range{T}(Z)
54+
Pose2Point2Range(Z::T) where {T <: IIF.SamplableBelief} = Pose2Point2Range{T}(Z, (1,2))
55+
# Pose2Point2Range(Z::T) where {T <: IIF.SamplableBelief} = Pose2Point2Range{T}(Z)
5756

5857
function getSample(cfo::CalcFactor{<:Pose2Point2Range}, N::Int=1)
59-
return (reshape(rand(cfo.factor.Z,N),1,N) , 2*pi*rand(N))
60-
end
61-
function (pp2r::CalcFactor{<:Pose2Point2Range})(rho,
62-
theta,
63-
xi,
64-
lm )
65-
#
66-
# DONE in IIF -- still need to add multi-hypotheses support here
67-
# this is the noisy range
68-
XX = lm[1] - (rho[1]*cos(theta[1]) + xi[1])
69-
YY = lm[2] - (rho[1]*sin(theta[1]) + xi[2])
70-
return sqrt(XX^2 + YY^2)
58+
return (reshape(rand(cfo.factor.Z,N),1,N), )
7159
end
7260

61+
function (cfo::CalcFactor{<:Pose2Point2Range})(rho, xi, lm)
62+
# Basically `EuclidDistance`
63+
return rho .- norm(lm[1:2] .- xi[1:2])
64+
# return [rho[1] - norm(lm[1:2] .- xi[1:2])]
65+
end
7366

7467

7568
mutable struct PackedPose2Point2Range <: IncrementalInference.PackedInferenceType
7669
str::String
77-
PackedPose2Point2Range() = new()
78-
PackedPose2Point2Range(s::AS) where {AS <: AbstractString} = new(s)
70+
# PackedPose2Point2Range() = new()
71+
# PackedPose2Point2Range(s::AS) where {AS <: AbstractString} = new(s)
7972
end
8073
function convert(::Type{PackedPose2Point2Range}, d::Pose2Point2Range)
8174
return PackedPose2Point2Range(convert(PackedSamplableBelief, d.Z))

test/TestPoseAndPoint2Constraints.jl

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ using Test
55
using RoME
66
# , IncrementalInference, Distributions
77

8+
##
89

910
@testset "test pose and point combinations..." begin
1011

12+
##
1113

1214
N = 100
1315
fg = initfg()
@@ -21,9 +23,9 @@ v1 = addVariable!(fg, :x0, Pose2, N=N)
2123
initPosePrior = PriorPose2(MvNormal(zeros(3), initCov))
2224
f1 = addFactor!(fg,[v1], initPosePrior)
2325

24-
@test Pose2Pose2(MvNormal(randn(2), Matrix{Float64}(LinearAlgebra.I, 2,2))) != nothing
25-
@test Pose2Pose2(MvNormal(randn(2), Matrix{Float64}(LinearAlgebra.I, 2,2))) != nothing
26-
@test Pose2Pose2(MvNormal(randn(2), Matrix{Float64}(LinearAlgebra.I, 2,2))) != nothing
26+
@test Pose2Pose2(MvNormal(randn(2), Matrix{Float64}(LinearAlgebra.I, 2,2))) !== nothing
27+
@test Pose2Pose2(MvNormal(randn(2), Matrix{Float64}(LinearAlgebra.I, 2,2))) !== nothing
28+
@test Pose2Pose2(MvNormal(randn(2), Matrix{Float64}(LinearAlgebra.I, 2,2))) !== nothing
2729

2830
# and a second pose
2931
v2 = addVariable!(fg, :x1, Pose2, N=N)
@@ -32,9 +34,13 @@ f2 = addFactor!(fg, [:x0;:x1], ppc)
3234

3335
# test evaluation of pose pose constraint
3436
pts = approxConv(fg, :x0x1f1, :x1)
35-
# pts = evalFactor(fg, f2, v2.index)
36-
@test norm(Statistics.mean(pts,dims=2)[1:2] - [50.0;0.0]) < 10.0
37-
@test abs(Statistics.mean(pts,dims=2)[3] - pi/2) < 0.5
37+
38+
pts[3,:] .= TU.wrapRad.(pts[3,:])
39+
@show mv = Statistics.mean(pts,dims=2)
40+
@test norm(mv[1:2] - [50.0;0.0]) < 10.0
41+
@test abs(mv[3] - pi/2) < 0.5
42+
43+
##
3844

3945
# @show ls(fg)
4046
tree, smt, hist = solveTree!(fg)
@@ -45,10 +51,14 @@ tree, smt, hist = solveTree!(fg)
4551

4652
# test post evaluation values are correct
4753
pts = getVal(fg, :x0)
54+
pts[3,:] .= TU.wrapRad.(pts[3,:])
55+
4856
@test norm(Statistics.mean(pts, dims=2)[1:2] - [0.0;0.0]) < 10.0
4957
@test abs(Statistics.mean(pts, dims=2)[3]) < 0.5
5058

5159
pts = getVal(fg, :x1)
60+
pts[3,:] .= TU.wrapRad.(pts[3,:])
61+
5262
@test norm(Statistics.mean(pts, dims=2)[1:2]-[50.0;0.0]) < 10.0
5363
@test abs(Statistics.mean(pts, dims=2)[3]-pi/2) < 0.5
5464

@@ -64,14 +74,17 @@ solveTree!(fg)
6474
# test post evaluation values are correct
6575
pts = getVal(fg, :x0)
6676
@test norm(Statistics.mean(pts, dims=2)[1:2]-[0.0;0.0]) < 20.0
77+
pts[3,:] .= TU.wrapRad.(pts[3,:])
6778
@test abs(Statistics.mean(pts, dims=2)[3]) < 0.5
6879

6980
pts = getVal(fg, :x1)
7081
@test norm(Statistics.mean(pts, dims=2)[1:2]-[50.0;0.0]) < 20.0
82+
pts[3,:] .= TU.wrapRad.(pts[3,:])
7183
@test abs(Statistics.mean(pts, dims=2)[3] - pi/2) < 0.5
7284

7385
pts = getVal(fg, :x2)
7486
@test norm(Statistics.mean(pts, dims=2)[1:2]-[50.0;50.0]) < 20.0
87+
pts[3,:] .= TU.wrapRad.(pts[3,:])
7588
@test abs(Statistics.mean(pts, dims=2)[3]-pi/2) < 0.5
7689

7790
println("test bearing range evaluations")

test/testBearingRange2D.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,11 @@ addFactor!(fg, [:x0; :l1], p2br, graphinit=false)
225225
# check the forward convolution is working properly
226226
pts, = predictbelief(fg, :x0, ls(fg, :x0), N=75)
227227

228+
pts[3,:] .= TU.wrapRad.(pts[3,:])
228229
@show abs.(Statistics.mean(pts,dims=2))
229230
@test sum(abs.(Statistics.mean(pts,dims=2)) .< [2.0; 2.0; 2.0]) == 3
230231
@show Statistics.std(pts,dims=2)
231-
@test sum([0.1; 0.1; 0.01] .< Statistics.std(pts,dims=2) .< [5.0; 5.0; 2.0]) == 3
232+
@test sum([0.1; 2.0; 0.01] .< Statistics.std(pts,dims=2) .< [5.0; 10.0; 2.0]) == 3
232233

233234
##
234235

test/testInflation380.jl

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,134 @@ using Statistics
99

1010
##
1111

12+
13+
@testset "test inflation is working via distance" begin
14+
15+
##
16+
17+
fg = initfg()
18+
# getSolverParams(fg).inflation = 50.0
19+
20+
N = 100
21+
22+
addVariable!(fg, :x0, ContinuousEuclid{2})
23+
addVariable!(fg, :x1, ContinuousEuclid{2})
24+
25+
X0_ = zeros(2,N)
26+
X0_[1,:] .+= 1000.0
27+
initManual!(fg, :x0, X0_)
28+
29+
addFactor!(fg, [:x0;:x1], EuclidDistance(Normal(100.0, 1.0)))
30+
31+
pts = approxConv(fg, :x0, :x1)
32+
33+
34+
##
35+
# does this give a "donut ring" at 1000?
36+
37+
res = 99999*ones(100)
38+
39+
for i in 1:N
40+
res[i] = calcFactorResidual(fg, :x0x1f1, [100.0], [1000.0;0.0], pts[:,i])[1]
41+
end
42+
43+
@test 0.9*N < sum(abs.(res) .< 5)
44+
45+
## new test trying to force inflation error
46+
47+
X1_ = randn(2,N)
48+
X1_[1,:] .+= 1100.0
49+
initManual!(fg, :x1, X1_)
50+
51+
52+
##
53+
54+
IIF._getCCW(fg, :x0x1f1).inflation = 50.0
55+
pts = approxConv(fg, :x0x1f1, :x1)
56+
57+
initManual!(fg, :x1, pts)
58+
59+
pts = approxConv(fg, :x0x1f1, :x1)
60+
61+
62+
##
63+
# does this give a "donut ring" at 1000?
64+
65+
res = 99999*ones(100)
66+
67+
for i in 1:N
68+
res[i] = calcFactorResidual(fg, :x0x1f1, [100.0], [1000.0;0.0], pts[:,i])[1]
69+
end
70+
71+
@test 0.9*N < sum(abs.(res) .< 5)
72+
73+
74+
##
75+
76+
# using RoMEPlotting
77+
# Gadfly.set_default_plot_size(25cm,20cm)
78+
79+
# ##
80+
81+
# # pts = getBelief(fg, :x1) |> getPoints
82+
# plotKDE(manikde!(pts, ContinuousEuclid{2}))
83+
84+
85+
##
86+
87+
end
88+
89+
90+
@testset "test inflation on range solve" begin
91+
92+
##
93+
94+
N = 100
95+
fg = initfg()
96+
fg.solverParams.inflation = 10.0 # super size the inflation to force wide coverage
97+
98+
addVariable!(fg, :x1, ContinuousEuclid{2})
99+
addVariable!(fg, :l1, ContinuousEuclid{2})
100+
101+
addFactor!(fg, [:l1], Prior(MvNormal([-1000.0,0], [0.1, 0.1])))
102+
addFactor!(fg, [:x1; :l1], EuclidDistance(Normal(100.0, 1.0)))
103+
104+
pts = zeros(2,100)
105+
pts[1,:] .-= 900
106+
initManual!(fg, :x1, pts)
107+
108+
##
109+
110+
tree, _, = solveGraph!(fg);
111+
112+
##
113+
114+
pts = getBelief(fg, :x1) |> getPoints
115+
116+
@test 0.9*N < sum( -1150 .< pts[1,:] .< -850)
117+
@test 0.9*N < sum( -150 .< pts[2,:] .< 150)
118+
119+
pts_ = [norm(pts[:,i] - [-1000;0]) for i in 1:N]
120+
121+
@test 0.9*N < sum(80 .< pts_ .< 120)
122+
123+
# must still test spread
124+
125+
@test 0.2*N < sum(-1150 .< pts[1,:] .< -1000)
126+
@test 0.2*N < sum(-1000 .< pts[1,:] .< -850)
127+
@test 0.2*N < sum(-150 .< pts[2,:] .< 0)
128+
@test 0.2*N < sum(0 .< pts[2,:] .< 150)
129+
130+
131+
##
132+
133+
# pl = plotKDE(fg, ls(fg))
134+
135+
##
136+
137+
end
138+
139+
12140
@testset "test bearing range with inflation, #380, IIF #1051" begin
13141

14142
##

test/testParametric.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,32 @@ vardict, result, varIds, Σ = IIF.solveFactorGraphParametric!(fg)
190190
@test isapprox(vardict[:x1].val, [10, 0, 0, 10, 0], atol = 1e-3)
191191

192192
end
193+
194+
195+
@testset "Test Parametric PriorPoint2 and Point2Point2Range" begin
196+
197+
fg = LightDFG( solverParams=SolverParams(algorithms=[:default, :parametric]))
198+
199+
addVariable!(fg, :x1, Point2)
200+
addVariable!(fg, :l1, Point2)
201+
addVariable!(fg, :l2, Point2)
202+
addVariable!(fg, :l3, Point2)
203+
204+
addFactor!(fg, [:l1], PriorPoint2(MvNormal([0., 0], [0.01, 0.01])))
205+
addFactor!(fg, [:l2], PriorPoint2(MvNormal([1., 0], [0.01, 0.01])))
206+
addFactor!(fg, [:l3], PriorPoint2(MvNormal([0., 1], [0.01, 0.01])))
207+
208+
addFactor!(fg, [:x1; :l1], Point2Point2Range(Normal(sqrt(2), 0.1)))
209+
addFactor!(fg, [:x1; :l2], Point2Point2Range(Normal(1.0, 0.1)))
210+
addFactor!(fg, [:x1; :l3], Point2Point2Range(Normal(1.0, 0.1)))
211+
212+
# ensureAllInitialized!(fg)
213+
#FIXME needs initializaiton from non-parametric to converge
214+
solveTree!(fg)
215+
IIF.initParametricFrom!(fg)
216+
217+
vardict, result, varIds, Σ = IIF.solveFactorGraphParametric(fg)
218+
219+
@test isapprox(vardict[:x1].val, [1, 1], atol = 1e-3)
220+
221+
end

0 commit comments

Comments
 (0)