Skip to content

Commit d683fb4

Browse files
authored
Merge pull request #509 from JuliaRobotics/feat/4Q19/savetree
add save load Tree,
2 parents 799c40c + 23ee348 commit d683fb4

File tree

5 files changed

+168
-33
lines changed

5 files changed

+168
-33
lines changed

src/CanonicalGraphExamples.jl

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,25 @@ Canonical example from literature, Kaess, et al.: ISAM2, IJRR, 2011.
1010
Notes
1111
- Paper variable ordering: p = [:l1;:l2;:x1;:x2;:x3]
1212
"""
13-
function loadCanonicalFG_Kaess()
13+
function loadCanonicalFG_Kaess(;graphinit::Bool=false)
1414
fg = initfg()
1515

1616
addVariable!(fg,:x1, ContinuousScalar)
17-
addFactor!(fg, [:x1;], Prior(Normal()))
17+
addFactor!(fg, [:x1;], Prior(Normal()), autoinit=graphinit)
1818

1919

2020
addVariable!(fg,:x2, ContinuousScalar)
21-
addFactor!(fg,[:x1, :x2], LinearConditional(Normal()))
21+
addFactor!(fg,[:x1, :x2], LinearConditional(Normal()), autoinit=graphinit)
2222

2323
addVariable!(fg, :x3, ContinuousScalar)
24-
addFactor!(fg,[:x2,:x3],LinearConditional(Normal()))
24+
addFactor!(fg,[:x2,:x3],LinearConditional(Normal()), autoinit=graphinit)
2525

2626
addVariable!(fg, :l1, ContinuousScalar)
27-
addFactor!(fg, [:x1,:l1], LinearConditional(Normal()) )
28-
addFactor!(fg, [:x2,:l1], LinearConditional(Normal()) )
27+
addFactor!(fg, [:x1,:l1], LinearConditional(Normal()) , autoinit=graphinit)
28+
addFactor!(fg, [:x2,:l1], LinearConditional(Normal()) , autoinit=graphinit)
2929

3030
addVariable!(fg, :l2, ContinuousScalar)
31-
addFactor!(fg, [:x3,:l2], LinearConditional(Normal()))
31+
addFactor!(fg, [:x3,:l2], LinearConditional(Normal()), autoinit=graphinit)
3232

3333
return fg
3434
end
@@ -42,7 +42,7 @@ Canonical example introduced by Borglab.
4242
Notes
4343
- Known variable ordering: p = [:x1; :l3; :l1; :x5; :x2; :l2; :x4; :x3]
4444
"""
45-
function loadCanonicalFG_TestSymbolic()
45+
function loadCanonicalFG_TestSymbolic(;graphinit::Bool=false)
4646
fg = initfg()
4747

4848
addVariable!(fg, :x1, ContinuousScalar)
@@ -54,16 +54,16 @@ function loadCanonicalFG_TestSymbolic()
5454
addVariable!(fg, :l2, ContinuousScalar)
5555
addVariable!(fg, :l3, ContinuousScalar)
5656

57-
addFactor!(fg, [:x1;:l1], LinearConditional(Normal()))
58-
addFactor!(fg, [:x1;:x2], LinearConditional(Normal()))
59-
addFactor!(fg, [:x2;:l1], LinearConditional(Normal()))
60-
addFactor!(fg, [:x2;:x3], LinearConditional(Normal()))
61-
addFactor!(fg, [:x3;:x4], LinearConditional(Normal()))
62-
addFactor!(fg, [:x4;:l2], LinearConditional(Normal()))
63-
addFactor!(fg, [:x4;:x5], LinearConditional(Normal()))
64-
addFactor!(fg, [:l2;:x5], LinearConditional(Normal()))
65-
addFactor!(fg, [:x4;:l3], LinearConditional(Normal()))
66-
addFactor!(fg, [:x5;:l3], LinearConditional(Normal()))
57+
addFactor!(fg, [:x1;:l1], LinearConditional(Normal()), autoinit=graphinit)
58+
addFactor!(fg, [:x1;:x2], LinearConditional(Normal()), autoinit=graphinit)
59+
addFactor!(fg, [:x2;:l1], LinearConditional(Normal()), autoinit=graphinit)
60+
addFactor!(fg, [:x2;:x3], LinearConditional(Normal()), autoinit=graphinit)
61+
addFactor!(fg, [:x3;:x4], LinearConditional(Normal()), autoinit=graphinit)
62+
addFactor!(fg, [:x4;:l2], LinearConditional(Normal()), autoinit=graphinit)
63+
addFactor!(fg, [:x4;:x5], LinearConditional(Normal()), autoinit=graphinit)
64+
addFactor!(fg, [:l2;:x5], LinearConditional(Normal()), autoinit=graphinit)
65+
addFactor!(fg, [:x4;:l3], LinearConditional(Normal()), autoinit=graphinit)
66+
addFactor!(fg, [:x5;:l3], LinearConditional(Normal()), autoinit=graphinit)
6767

6868
return fg
6969
end
@@ -78,7 +78,7 @@ Canonical example introduced originally as Caesar Hex Example.
7878
Notes
7979
- Paper variable ordering: p = [:x0;:x2;:x4;:x6;:x1;:l1;:x5;:x3;]
8080
"""
81-
function loadCanonicalFG_CaesarRing1D()
81+
function loadCanonicalFG_CaesarRing1D(;graphinit::Bool=false)
8282

8383
fg = initfg()
8484

@@ -90,17 +90,17 @@ function loadCanonicalFG_CaesarRing1D()
9090
addVariable!(fg, :x5, ContinuousScalar)
9191
addVariable!(fg, :x6, ContinuousScalar)
9292

93-
addFactor!(fg, [:x0], Prior(Normal()))
94-
addFactor!(fg, [:x0;:x1], LinearConditional(Normal()))
95-
addFactor!(fg, [:x1;:x2], LinearConditional(Normal()))
96-
addFactor!(fg, [:x2;:x3], LinearConditional(Normal()))
97-
addFactor!(fg, [:x3;:x4], LinearConditional(Normal()))
98-
addFactor!(fg, [:x4;:x5], LinearConditional(Normal()))
99-
addFactor!(fg, [:x5;:x6], LinearConditional(Normal()))
93+
addFactor!(fg, [:x0], Prior(Normal()), autoinit=graphinit)
94+
addFactor!(fg, [:x0;:x1], LinearConditional(Normal()), autoinit=graphinit)
95+
addFactor!(fg, [:x1;:x2], LinearConditional(Normal()), autoinit=graphinit)
96+
addFactor!(fg, [:x2;:x3], LinearConditional(Normal()), autoinit=graphinit)
97+
addFactor!(fg, [:x3;:x4], LinearConditional(Normal()), autoinit=graphinit)
98+
addFactor!(fg, [:x4;:x5], LinearConditional(Normal()), autoinit=graphinit)
99+
addFactor!(fg, [:x5;:x6], LinearConditional(Normal()), autoinit=graphinit)
100100

101101
addVariable!(fg, :l1, ContinuousScalar)
102-
addFactor!(fg, [:x0;:l1], LinearConditional(Normal()))
103-
addFactor!(fg, [:x6;:l1], LinearConditional(Normal()))
102+
addFactor!(fg, [:x0;:l1], LinearConditional(Normal()), autoinit=graphinit)
103+
addFactor!(fg, [:x6;:l1], LinearConditional(Normal()), autoinit=graphinit)
104104

105105
return fg
106106
end

src/IncrementalInference.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -434,11 +434,13 @@ export
434434
extractdistribution,
435435

436436
# factor graph operating system utils (fgos)
437-
convert2packedfunctionnode,
438-
encodefg,
439-
decodefg,
440-
savejld,
441-
loadjld,
437+
saveTree,
438+
loadTree,
439+
# convert2packedfunctionnode,
440+
# encodefg,
441+
# decodefg,
442+
# savejld,
443+
# loadjld,
442444
landmarks,
443445
setCliqDrawColor,
444446

src/JunctionTree.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,3 +1490,80 @@ Return the variable order stored in a tree object.
14901490
getVariableOrder(treel::BayesTree)::Vector{Symbol} = treel.variableOrder
14911491

14921492
getEliminationOrder(treel::BayesTree) = treel.variableOrder
1493+
1494+
1495+
"""
1496+
$SIGNATURES
1497+
1498+
EXPERIMENTAL, Save a Bayes (Junction) tree object to file.
1499+
1500+
Notes
1501+
- Converts and saves to JLD2 format a set of `PackedBayesTreeNodeData` objects.
1502+
- IIF issue #481
1503+
1504+
Related
1505+
1506+
IIF.loadTree, DFG.saveDFG, DFG.loadDFG, JLD2.@save, JLD2.@load
1507+
"""
1508+
function saveTree(treel::BayesTree,
1509+
filepath=joinpath("/tmp","caesar","savetree.jld2") )
1510+
#
1511+
savetree = deepcopy(treel)
1512+
for i in 1:length(savetree.cliques)
1513+
if savetree.cliques[i].attributes["data"] isa BayesTreeNodeData
1514+
savetree.cliques[i].attributes["data"] = convert(PackedBayesTreeNodeData, savetree.cliques[i].attributes["data"])
1515+
end
1516+
end
1517+
1518+
JLD2.@save filepath savetree
1519+
return filepath
1520+
end
1521+
1522+
function saveTree(treeArr::Vector{BayesTree},
1523+
filepath=joinpath("/tmp","caesar","savetrees.jld2") )
1524+
#
1525+
savetree = deepcopy(treeArr)
1526+
for savtre in savetree, i in 1:length(savtre.cliques)
1527+
if savtre.cliques[i].attributes["data"] isa BayesTreeNodeData
1528+
savtre.cliques[i].attributes["data"] = convert(PackedBayesTreeNodeData, savtre.cliques[i].attributes["data"])
1529+
end
1530+
end
1531+
1532+
JLD2.@save filepath savetree
1533+
return filepath
1534+
end
1535+
1536+
"""
1537+
$SIGNATURES
1538+
1539+
EXPERIMENTAL, Save a Bayes (Junction) tree object to file.
1540+
1541+
Notes
1542+
- Converts and saves to JLD2 format a set of `PackedBayesTreeNodeData` objects.
1543+
- IIF issue #481
1544+
1545+
Related
1546+
1547+
IIF.saveTree, DFG.saveDFG, DFG.loadDFG, JLD2.@save, JLD2.@load
1548+
"""
1549+
function loadTree(filepath=joinpath("/tmp","caesar","savetree.jld2"))
1550+
data = @load filepath savetree
1551+
1552+
# convert back to a type that which could not be serialized by JLD2
1553+
if savetree isa Vector
1554+
for savtre in savetree, i in 1:length(savtre.cliques)
1555+
if savtre.cliques[i].attributes["data"] isa PackedBayesTreeNodeData
1556+
savtre.cliques[i].attributes["data"] = convert(BayesTreeNodeData, savtre.cliques[i].attributes["data"])
1557+
end
1558+
end
1559+
else
1560+
for i in 1:length(savetree.cliques)
1561+
if savetree.cliques[i].attributes["data"] isa PackedBayesTreeNodeData
1562+
savetree.cliques[i].attributes["data"] = convert(BayesTreeNodeData, savetree.cliques[i].attributes["data"])
1563+
end
1564+
end
1565+
end
1566+
1567+
# return loaded and converted tree
1568+
return savetree
1569+
end

test/runtests.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ include("testPartialFactors.jl")
2323
@testset "basic Bayes tree construction" begin
2424
include("testBayesTreeiSAM2Example.jl")
2525
end
26+
27+
include("testTreeSaveLoad.jl")
28+
2629
@testset "Ensure converter types can be run from extending namespaces..." begin
2730
include("saveconvertertypes.jl")
2831
end

test/testTreeSaveLoad.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# test saving and loading of trees
2+
3+
using Test
4+
using IncrementalInference
5+
6+
@testset "Test loading and saving of Bayes (Junction) tree" begin
7+
8+
fg = loadCanonicalFG_Kaess(graphinit=false)
9+
tree = wipeBuildNewTree!(fg)
10+
11+
# save and load tree
12+
saveTree(tree)
13+
tree2 = loadTree()
14+
15+
# perform a few spot checks to see that the trees are similar
16+
@test length(tree.cliques) == length(tree2.cliques)
17+
@test getVariableOrder(tree) == getVariableOrder(tree2)
18+
19+
for (clid,cl) in tree.cliques
20+
fsyms = getFrontals(cl)
21+
cl2 = getCliq(tree2, fsyms[1])
22+
fsyms2 = getFrontals(cl2)
23+
@test fsyms == fsyms2
24+
@test getCliqSeparatorVarIds(cl) == getCliqSeparatorVarIds(cl2)
25+
@test typeof(cl) == typeof(cl2)
26+
end
27+
28+
end
29+
30+
31+
@testset "Test loading and saving of Bayes (Junction) tree" begin
32+
33+
fg = loadCanonicalFG_Kaess(graphinit=false)
34+
tree = wipeBuildNewTree!(fg)
35+
36+
# save and load tree as array
37+
filepath = saveTree([tree;deepcopy(tree)])
38+
trees = loadTree(filepath)
39+
40+
# perform a few spot checks to see that the trees are similar
41+
@test length(tree.cliques) == length(trees[1].cliques)
42+
@test getVariableOrder(tree) == getVariableOrder(trees[1])
43+
44+
for (clid,cl) in tree.cliques
45+
fsyms = getFrontals(cl)
46+
cl2 = getCliq(trees[1], fsyms[1])
47+
fsyms2 = getFrontals(cl2)
48+
@test fsyms == fsyms2
49+
@test getCliqSeparatorVarIds(cl) == getCliqSeparatorVarIds(cl2)
50+
@test typeof(cl) == typeof(cl2)
51+
end
52+
53+
end

0 commit comments

Comments
 (0)