Skip to content

Commit 89b1892

Browse files
authored
Custom DFG errors (#1147)
1 parent 1b6116f commit 89b1892

File tree

15 files changed

+169
-117
lines changed

15 files changed

+169
-117
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Listing news on any major breaking changes in DFG. For regular changes, see int
2222
- Deprecate getBlobentryFirst -> getfirstBlobentry, see #1114
2323
- OrderedDict is no longer exported
2424
- FolderStore path now includes the store label.
25+
- Standardized error types and behaviour.
2526

2627
# v0.26
2728
- Graph structure plotting now uses GraphMakie.jl instead of GraphPlot.jl. Update by replacing `using GraphPlot` with `using GraphMakie`.

docs/src/func_ref.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ Modules = [DistributedFactorGraphs]
4444
Pages = ["entities/DFGFactor.jl"]
4545
```
4646

47+
### Error Types
48+
```@autodocs
49+
Modules = [DistributedFactorGraphs]
50+
Pages = ["errors.jl"]
51+
```
52+
4753
## DFG Plots [GraphMakie.jl]
4854

4955
```@autodocs

src/DataBlobs/services/BlobEntry.jl

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,18 +67,14 @@ Also see: [`addBlobentry!`](@ref), [`getBlob`](@ref), [`listBlobentries`](@ref)
6767
"""
6868
function getBlobentry(var::AbstractDFGVariable, key::Symbol)
6969
if !hasBlobentry(var, key)
70-
throw(
71-
KeyError(
72-
"No dataEntry label $(key) found in variable $(getLabel(var)). Available keys: $(keys(var.dataDict))",
73-
),
74-
)
70+
throw(LabelNotFoundError("Blobentry", key, collect(keys(var.dataDict))))
7571
end
7672
return var.dataDict[key]
7773
end
7874

7975
function getBlobentry(var::VariableDFG, key::Symbol)
8076
if !hasBlobentry(var, key)
81-
throw(KeyError(key))
77+
throw(LabelNotFoundError("Blobentry", key))
8278
end
8379
return var.blobEntries[findfirst(x -> x.label == key, var.blobEntries)]
8480
end
@@ -156,19 +152,18 @@ Should be extended if DFG variable is not returned by reference.
156152
157153
Also see: [`getBlobentry`](@ref), [`addBlob!`](@ref), [`mergeBlobentries!`](@ref)
158154
"""
159-
function addBlobentry!(var::AbstractDFGVariable, entry::Blobentry;)
155+
function addBlobentry!(var::AbstractDFGVariable, entry::Blobentry)
160156
# see https://github.com/JuliaRobotics/DistributedFactorGraphs.jl/issues/985
161157
# blobId::Union{UUID,Nothing} = (isnothing(entry.blobId) ? entry.id : entry.blobId),
162158
# blobSize::Int = (hasfield(Blobentry, :size) ? entry.size : -1)
163-
haskey(var.dataDict, entry.label) &&
164-
error("blobEntry $(entry.label) already exists on variable $(getLabel(var))")
159+
haskey(var.dataDict, entry.label) && throw(LabelExistsError("Blobentry", entry.label))
165160
var.dataDict[entry.label] = entry
166161
return entry
167162
end
168163

169164
function addBlobentry!(var::VariableDFG, entry::Blobentry)
170165
entry.label in getproperty.(var.blobEntries, :label) &&
171-
error("blobEntry $(entry.label) already exists on variable $(getLabel(var))")
166+
throw(LabelExistsError("Blobentry", entry.label))
172167
push!(var.blobEntries, entry)
173168
return entry
174169
end

src/Deprecated.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,16 @@ function fncStringToData(args...; kwargs...)
420420
return error("fncStringToData is obsolete.")
421421
end
422422

423+
#TODO make sure getFactorOperationalMemoryType is obsolete
424+
function getFactorOperationalMemoryType(dummy)
425+
return error(
426+
"Please extend your workspace with function getFactorOperationalMemoryType(<:AbstractParams) for your usecase, e.g. IncrementalInference uses `CommonConvWrapper <: FactorSolverCache`",
427+
)
428+
end
429+
function getFactorOperationalMemoryType(dfg::AbstractDFG)
430+
return getFactorOperationalMemoryType(getSolverParams(dfg))
431+
end
432+
423433
## ================================================================================
424434
## Deprecated in v0.25
425435
##=================================================================================

src/DistributedFactorGraphs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ export plotDFG
354354
##==============================================================================
355355

356356
# Entities
357+
include("errors.jl")
357358

358359
include("entities/AbstractDFG.jl")
359360

src/GraphsDFG/FactorGraphs/FactorGraphs.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,10 @@ function addFactor!(
139139
(@error "Label $(factor.label) already in fg"; return false)
140140

141141
for vlabel in variableLabels
142-
!haskey(g.labels, vlabel) && (throw(KeyError(vlabel))
143-
# @error "Variable '$(vlabel)' not found in graph when creating Factor '$(factor.label)'"; return false
144-
) #TODO debug error or exception?
142+
if !haskey(g.labels, vlabel)
143+
@error "Variable '$(vlabel)' not found in graph when creating Factor '$(factor.label)'"
144+
return false
145+
end
145146
end
146147

147148
add_vertex!(g.graph) || return false

src/GraphsDFG/GraphsDFG.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ using OrderedCollections
88
using StructTypes
99

1010
using ...DistributedFactorGraphs
11-
using ...DistributedFactorGraphs: Agent
11+
using ...DistributedFactorGraphs: Agent, LabelNotFoundError, LabelExistsError
1212

1313
# import DFG functions to extend
1414
import ...DistributedFactorGraphs:

src/GraphsDFG/services/GraphsDFG.jl

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,8 @@ function addVariable!(
4242
dfg::GraphsDFG{<:AbstractParams, V, <:AbstractDFGFactor},
4343
variable::V,
4444
) where {V <: AbstractDFGVariable}
45-
#TODO should this be an error
4645
if haskey(dfg.g.variables, variable.label)
47-
error("Variable '$(variable.label)' already exists in the factor graph")
46+
throw(LabelExistsError("Variable", variable.label))
4847
end
4948

5049
FactorGraphs.addVariable!(dfg.g, variable) || return false
@@ -104,11 +103,15 @@ function addFactor!(
104103
factor::F,
105104
) where {F <: AbstractDFGFactor}
106105
if haskey(dfg.g.factors, factor.label)
107-
error("Factor '$(factor.label)' already exists in the factor graph")
106+
throw(LabelExistsError("Factor", factor.label))
108107
end
109108
# TODO
110109
# @assert FactorGraphs.addFactor!(dfg.g, getVariableOrder(factor), factor)
111-
@assert FactorGraphs.addFactor!(dfg.g, Symbol[factor._variableOrderSymbols...], factor)
110+
variableLabels = Symbol[factor._variableOrderSymbols...]
111+
for vlabel in variableLabels
112+
!exists(dfg, vlabel) && throw(LabelNotFoundError("Variable", vlabel))
113+
end
114+
@assert FactorGraphs.addFactor!(dfg.g, variableLabels, factor)
112115
return factor
113116
end
114117

@@ -121,16 +124,15 @@ end
121124

122125
function getVariable(dfg::GraphsDFG, label::Symbol)
123126
if !haskey(dfg.g.variables, label)
124-
error("Variable label '$(label)' does not exist in the factor graph")
127+
throw(LabelNotFoundError("Variable", label))
125128
end
126129

127130
return dfg.g.variables[label]
128131
end
129132

130133
function getFactor(dfg::GraphsDFG, label::Symbol)
131134
if !haskey(dfg.g.factors, label)
132-
#TODO throw a typed error
133-
error("Factor label '$(label)' does not exist in the factor graph")
135+
throw(LabelNotFoundError("Factor", label))
134136
end
135137
return dfg.g.factors[label]
136138
end
@@ -151,8 +153,8 @@ function mergeFactor!(dfg::GraphsDFG, factor::AbstractDFGFactor;)
151153
#TODO should we allow merging the factor neighbors or error as before?
152154
error("Cannot update the factor, the neighbors are not the same.")
153155
# We need to delete the factor if we are updating the neighbors
154-
deleteFactor!(dfg, factor.label)
155-
addFactor!(dfg, factor)
156+
# deleteFactor!(dfg, factor.label)
157+
# addFactor!(dfg, factor)
156158
else
157159
dfg.g.factors[factor.label] = factor
158160
end
@@ -162,7 +164,7 @@ end
162164

163165
function deleteVariable!(dfg::GraphsDFG, label::Symbol)#::Tuple{AbstractDFGVariable, Vector{<:AbstractDFGFactor}}
164166
if !haskey(dfg.g.variables, label)
165-
error("Variable label '$(label)' does not exist in the factor graph")
167+
throw(LabelNotFoundError("Variable", label))
166168
end
167169

168170
deleteNeighbors = true # reserved, orphaned factors are not supported at this time
@@ -175,7 +177,7 @@ end
175177

176178
function deleteFactor!(dfg::GraphsDFG, label::Symbol; suppressGetFactor::Bool = false)
177179
if !haskey(dfg.g.factors, label)
178-
error("Factor label '$(label)' does not exist in the factor graph")
180+
throw(LabelNotFoundError("Factor", label))
179181
end
180182
rem_vertex!(dfg.g, dfg.g.labels[label])
181183
return 1
@@ -280,10 +282,7 @@ end
280282
function _isSolvable(dfg::GraphsDFG, label::Symbol, ready::Int)
281283
haskey(dfg.g.variables, label) && (return dfg.g.variables[label].solvable >= ready)
282284
haskey(dfg.g.factors, label) && (return dfg.g.factors[label].solvable >= ready)
283-
284-
#TODO should this be a breaking error?
285-
@error "Node not in factor or variable"
286-
return false
285+
throw(LabelNotFoundError(label))
287286
end
288287

289288
function listNeighbors(dfg::GraphsDFG, node::DFGNode; solvable::Int = 0)
@@ -292,7 +291,7 @@ end
292291

293292
function listNeighbors(dfg::GraphsDFG, label::Symbol; solvable::Int = 0)
294293
if !exists(dfg, label)
295-
error("Variable/factor with label '$(label)' does not exist in the factor graph")
294+
throw(LabelNotFoundError(label))
296295
end
297296

298297
neighbors_il = FactorGraphs.outneighbors(dfg.g, dfg.g.labels[label])
@@ -540,9 +539,7 @@ end
540539

541540
function addGraphBlobentry!(fg::GraphsDFG, entry::Blobentry)
542541
if haskey(fg.graphBlobEntries, entry.label)
543-
error(
544-
"Blobentry '$(entry.label)' already exists in the factor graph's blob entries.",
545-
)
542+
throw(LabelExistsError("Blobentry", entry.label))
546543
end
547544
push!(fg.graphBlobEntries, entry.label => entry)
548545
return entry

src/errors.jl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""
2+
LabelNotFoundError(label, available)
3+
4+
Error thrown when a requested label is not found in the factor graph.
5+
"""
6+
struct LabelNotFoundError <: Exception
7+
name::String
8+
label::Symbol
9+
available::Vector{Symbol}
10+
end
11+
12+
LabelNotFoundError(name::String, label::Symbol) = LabelNotFoundError(name, label, Symbol[])
13+
LabelNotFoundError(label::Symbol) = LabelNotFoundError("Node", label, Symbol[])
14+
15+
function Base.showerror(io::IO, ex::LabelNotFoundError)
16+
print(io, "LabelNotFoundError: ", ex.name, " label '", ex.label, "' not found.")
17+
if !isempty(ex.available)
18+
println(io, " Available labels:")
19+
show(io, ex.available)
20+
end
21+
end
22+
23+
"""
24+
LabelExistsError(label)
25+
26+
Error thrown when attempting to add a label that already exists in the collection.
27+
"""
28+
struct LabelExistsError <: Exception
29+
name::String
30+
label::Symbol
31+
end
32+
33+
LabelExistsError(label::Symbol) = LabelExistsError("Node", label)
34+
35+
function Base.showerror(io::IO, ex::LabelExistsError)
36+
return print(
37+
io,
38+
"LabelExistsError: ",
39+
ex.name,
40+
" label '",
41+
ex.label,
42+
"' already exists.",
43+
)
44+
end
45+
46+
"""
47+
SerializationError(msg)
48+
49+
Error thrown when serialization or deserialization fails.
50+
"""
51+
struct SerializationError <: Exception
52+
msg::String
53+
end
54+
55+
function Base.showerror(io::IO, ex::SerializationError)
56+
return print(io, "SerializationError: ", ex.msg)
57+
end

src/services/AbstractDFG.jl

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,6 @@ getAddHistory(dfg::AbstractDFG) = dfg.addHistory
9797
"""
9898
getSolverParams(dfg::AbstractDFG) = dfg.solverParams
9999

100-
"""
101-
$(SIGNATURES)
102-
103-
Method must be overloaded by the user for Serialization to work. E.g. IncrementalInference uses `CommonConvWrapper <: FactorSolverCache`.
104-
"""
105-
function getFactorOperationalMemoryType(dummy)
106-
return error(
107-
"Please extend your workspace with function getFactorOperationalMemoryType(<:AbstractParams) for your usecase, e.g. IncrementalInference uses `CommonConvWrapper <: FactorSolverCache`",
108-
)
109-
end
110-
function getFactorOperationalMemoryType(dfg::AbstractDFG)
111-
return getFactorOperationalMemoryType(getSolverParams(dfg))
112-
end
113-
114100
"""
115101
$(SIGNATURES)
116102
@@ -121,7 +107,10 @@ function rebuildFactorCache!(
121107
factor::AbstractDFGFactor,
122108
neighbors = [],
123109
)
124-
@warn("rebuildFactorCache! is not implemented for $(typeof(dfg))")
110+
@warn(
111+
"FactorCache not build, rebuildFactorCache! is not implemented for $(typeof(dfg)). Make sure to load IncrementalInference.",
112+
maxlog = 1
113+
)
125114
return nothing
126115
end
127116

@@ -533,7 +522,7 @@ function getVariable(dfg::AbstractDFG, label::Symbol, solveKey::Symbol)
533522
var = getVariable(dfg, label)
534523

535524
if isa(var, VariableCompute) && !haskey(var.solverDataDict, solveKey)
536-
error("Solvekey '$solveKey' does not exists in the variable")
525+
throw(LabelNotFoundError("VariableNode", solveKey))
537526
elseif !isa(var, VariableCompute)
538527
@warn "getVariable(dfg, label, solveKey) only supported for type VariableCompute."
539528
end
@@ -1096,7 +1085,7 @@ function copyGraph!(
10961085
elseif overwriteDest
10971086
mergeVariable!(destDFG, variableCopy)
10981087
else
1099-
error("Variable $(variable.label) already exists in destination graph!")
1088+
throw(LabelExistsError("Variable", variable.label))
11001089
end
11011090
end
11021091
# And then all factors to the destDFG.

0 commit comments

Comments
 (0)