Skip to content

Commit ccbf97b

Browse files
authored
Merge pull request #894 from JuliaRobotics/22Q3/perf/var_point_param
Point type parameter in DFGVariable and vnd.covar
2 parents 77253a9 + 447ddb4 commit ccbf97b

File tree

10 files changed

+94
-100
lines changed

10 files changed

+94
-100
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
2121
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
2222
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
2323
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
24+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2425
StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
2526
TensorCast = "02d47bb6-7ce6-556a-be16-bb1710789e2b"
2627
TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53"

src/DistributedFactorGraphs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export AbstractManifold, manifold_dimension
4141

4242
import RecursiveArrayTools: ArrayPartition
4343
export ArrayPartition
44+
using StaticArrays
4445

4546
import Base: getindex
4647

src/entities/DFGVariable.jl

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ $(TYPEDEF)
1313
Data container for solver-specific data.
1414
1515
---
16+
T: Variable type, such as Position1, or RoME.Pose2, etc.
17+
P: Variable point type, the type of the manifold point.
18+
N: Manifold dimension.
1619
Fields:
1720
$(TYPEDFIELDS)
1821
"""
19-
Base.@kwdef mutable struct VariableNodeData{T<:InferenceVariable, P}
22+
Base.@kwdef mutable struct VariableNodeData{T<:InferenceVariable, P, N}
23+
"DEPRECATED remove in DFG v0.22"
24+
variableType::T=T() #tricky deprecation, also change covar to using N and not variableType
2025
"""
2126
Globally unique identifier.
2227
"""
@@ -26,37 +31,35 @@ Base.@kwdef mutable struct VariableNodeData{T<:InferenceVariable, P}
2631
"""
2732
val::Vector{P} = Vector{P}()
2833
"""
29-
Common kernel bandwith parameter used with ManifoldKernelDensity, and as legacy also stores covariance until a dedicated field is created for parametric case.
34+
Common kernel bandwith parameter used with ManifoldKernelDensity, see field `covar` for the parametric covariance.
3035
"""
3136
bw::Matrix{Float64} = zeros(0,0)
37+
"Parametric (Gaussian) covariance."
38+
covar::Vector{SMatrix{N, N, Float64}} = SMatrix{getDimension(variableType), getDimension(variableType), Float64}[]
3239
BayesNetOutVertIDs::Vector{Symbol} = Symbol[]
3340
dimIDs::Vector{Int} = Int[] # TODO Likely deprecate
3441

35-
dims::Int = 0
42+
dims::Int = getDimension(variableType) #TODO should we deprecate in favor of N
3643
"""
37-
Flag used by junction (Bayes) tree construction algorith to know whether this variable has yet been included in the tree construction.
44+
Flag used by junction (Bayes) tree construction algorithm to know whether this variable has yet been included in the tree construction.
3845
"""
3946
eliminated::Bool = false
4047
BayesNetVertID::Symbol = :NOTHING # Union{Nothing, }
4148
separator::Vector{Symbol} = Symbol[]
4249
"""
43-
Variables each have a type, such as Position1, or RoME.Pose2, etc.
44-
"""
45-
variableType::T = T()
46-
"""
4750
False if initial numerical values are not yet available or stored values are not ready for further processing yet.
4851
"""
4952
initialized::Bool = false
5053
"""
5154
Stores the amount information (per measurement dimension) captured in each coordinate dimension.
5255
"""
53-
infoPerCoord::Vector{Float64} = Float64[0.0;]
56+
infoPerCoord::Vector{Float64} = zeros(getDimension(variableType))
5457
"""
5558
Should this variable solveKey be treated as marginalized in inference computations.
5659
"""
5760
ismargin::Bool = false
5861
"""
59-
Shoudl this variable solveKey always be kept fluid and not be automatically marginalized.
62+
Should this variable solveKey always be kept fluid and not be automatically marginalized.
6063
"""
6164
dontmargin::Bool = false
6265
"""
@@ -68,7 +71,7 @@ Base.@kwdef mutable struct VariableNodeData{T<:InferenceVariable, P}
6871
"""
6972
solvedCount::Int = 0
7073
"""
71-
solveKey identifier associated with thsi VariableNodeData object.
74+
solveKey identifier associated with this VariableNodeData object.
7275
"""
7376
solveKey::Symbol = :default
7477
"""
@@ -81,8 +84,8 @@ end
8184

8285
##------------------------------------------------------------------------------
8386
## Constructors
84-
VariableNodeData{T}(; kwargs...) where T <: InferenceVariable = VariableNodeData{T,getPointType(T)}(; kwargs...)
85-
VariableNodeData(variableType::InferenceVariable; kwargs...) = VariableNodeData{typeof(variableType)}(; kwargs...)
87+
VariableNodeData{T}(; kwargs...) where T <: InferenceVariable = VariableNodeData{T,getPointType(T),getDimension(T)}(; kwargs...)
88+
VariableNodeData(variableType::InferenceVariable; kwargs...) = VariableNodeData{typeof(variableType)}(;kwargs...)
8689

8790

8891
##==============================================================================
@@ -117,6 +120,7 @@ Base.@kwdef mutable struct PackedVariableNodeData
117120
solveInProgress::Int
118121
solvedCount::Int
119122
solveKey::Symbol
123+
covar::Vector{Float64}
120124
_version::String = string(_getDFGVersion())
121125
end
122126

@@ -243,35 +247,35 @@ Complete variable structure for a DistributedFactorGraph variable.
243247
Fields:
244248
$(TYPEDFIELDS)
245249
"""
246-
Base.@kwdef struct DFGVariable{T<:InferenceVariable} <: AbstractDFGVariable
250+
Base.@kwdef struct DFGVariable{T<:InferenceVariable, P, N} <: AbstractDFGVariable
247251
"""The ID for the variable"""
248-
id::Union{UUID, Nothing}
252+
id::Union{UUID, Nothing} = nothing
249253
"""Variable label, e.g. :x1.
250254
Accessor: [`getLabel`](@ref)"""
251255
label::Symbol
252256
"""Variable timestamp.
253257
Accessors: [`getTimestamp`](@ref), [`setTimestamp`](@ref)"""
254-
timestamp::ZonedDateTime
258+
timestamp::ZonedDateTime = now(localzone())
255259
"""Nano second time, for more resolution on timestamp (only subsecond information)"""
256-
nstime::Nanosecond
260+
nstime::Nanosecond = Nanosecond(0)
257261
"""Variable tags, e.g [:POSE, :VARIABLE, and :LANDMARK].
258262
Accessors: [`getTags`](@ref), [`mergeTags!`](@ref), and [`removeTags!`](@ref)"""
259-
tags::Set{Symbol}
263+
tags::Set{Symbol} = Set{Symbol}()
260264
"""Dictionary of parametric point estimates keyed by solverDataDict keys
261265
Accessors: [`addPPE!`](@ref), [`updatePPE!`](@ref), and [`deletePPE!`](@ref)"""
262-
ppeDict::Dict{Symbol, <: AbstractPointParametricEst}
266+
ppeDict::Dict{Symbol, AbstractPointParametricEst} = Dict{Symbol, AbstractPointParametricEst}()
263267
"""Dictionary of solver data. May be a subset of all solutions if a solver key was specified in the get call.
264268
Accessors: [`addVariableSolverData!`](@ref), [`updateVariableSolverData!`](@ref), and [`deleteVariableSolverData!`](@ref)"""
265-
solverDataDict::Dict{Symbol, <: VariableNodeData{T}}
269+
solverDataDict::Dict{Symbol, VariableNodeData{T,P,N}} = Dict{Symbol, VariableNodeData{T,P,N}}()
266270
"""Dictionary of small data associated with this variable.
267271
Accessors: [`getSmallData`](@ref), [`setSmallData!`](@ref)"""
268-
smallData::Dict{Symbol, SmallDataTypes}
272+
smallData::Dict{Symbol, SmallDataTypes} = Dict{Symbol, SmallDataTypes}()
269273
"""Dictionary of large data associated with this variable.
270274
Accessors: [`addBlobEntry!`](@ref), [`getBlobEntry`](@ref), [`updateBlobEntry!`](@ref), and [`deleteBlobEntry!`](@ref)"""
271-
dataDict::Dict{Symbol, BlobEntry}
275+
dataDict::Dict{Symbol, BlobEntry} = Dict{Symbol, BlobEntry}()
272276
"""Solvable flag for the variable.
273277
Accessors: [`getSolvable`](@ref), [`setSolvable!`](@ref)"""
274-
solvable::Base.RefValue{Int}
278+
solvable::Base.RefValue{Int} = Ref(1)
275279
end
276280

277281
##------------------------------------------------------------------------------
@@ -281,43 +285,34 @@ end
281285
$SIGNATURES
282286
The default DFGVariable constructor.
283287
"""
284-
function DFGVariable(label::Symbol, variableType::Type{T};
285-
id::Union{UUID,Nothing}=nothing,
286-
timestamp::ZonedDateTime=now(localzone()),
287-
nstime::Nanosecond = Nanosecond(0),
288-
tags::Set{Symbol}=Set{Symbol}(),
289-
estimateDict::Dict{Symbol, <: AbstractPointParametricEst}=Dict{Symbol, MeanMaxPPE}(),
290-
solverDataDict::Dict{Symbol, VariableNodeData{T,P}}=Dict{Symbol, VariableNodeData{T,getPointType(T)}}(),
291-
smallData::Dict{Symbol, SmallDataTypes}=Dict{Symbol, SmallDataTypes}(),
292-
dataDict::Dict{Symbol, BlobEntry}=Dict{Symbol,BlobEntry}(),
293-
solvable::Int=1) where {T <: InferenceVariable, P}
294-
#
295-
DFGVariable{T}(id, label, timestamp, nstime, tags, estimateDict, solverDataDict, smallData, dataDict, Ref(solvable))
296-
end
288+
function DFGVariable(
289+
label::Symbol,
290+
T::Type{<:InferenceVariable};
291+
estimateDict=nothing,
292+
timestamp=now(localzone()),
293+
solvable::Union{Int, Base.RefValue{Int}}=Ref(1),
294+
kwargs...
295+
)
296+
#TODO deprecated, remove in v0.21 should have already been deprecated
297+
if !isnothing(estimateDict)
298+
error("Keyword argument `estimateDict` is deprecated use `ppeDict`")
299+
end
300+
if !isa(timestamp, ZonedDateTime)
301+
@warn "timestamp<:DateTime is deprecated, timestamp must be a ZonedDateTime, using local zone."
302+
timestamp = ZonedDateTime(timestamp,localzone())
303+
end
297304

298-
DFGVariable(label::Symbol,
299-
variableType::T;
300-
solverDataDict::Dict{Symbol, VariableNodeData{T,P}}=Dict{Symbol, VariableNodeData{T,getPointType(T)}}(),
301-
kw...) where {T <: InferenceVariable, P} = DFGVariable(label, T; solverDataDict=solverDataDict, kw...)
302-
#
303-
# @deprecate DFGVariable(label::Symbol, T_::Type{<:InferenceVariable},w...; timestamp::DateTime=now(),kw...) DFGVariable(label, T_, w...; timestamp=ZonedDateTime(timestamp), kw...)
304-
#
305-
306-
307-
function DFGVariable(label::Symbol,
308-
solverData::VariableNodeData{T};
309-
id::Union{UUID, Nothing} = nothing,
310-
timestamp::ZonedDateTime = now(localzone()),
311-
nstime::Nanosecond = Nanosecond(0),
312-
tags::Set{Symbol}=Set{Symbol}(),
313-
estimateDict::Dict{Symbol, <: AbstractPointParametricEst}=Dict{Symbol, MeanMaxPPE}(),
314-
smallData::Dict{Symbol, SmallDataTypes}=Dict{Symbol, SmallDataTypes}(),
315-
dataDict::Dict{Symbol, <: BlobEntry}=Dict{Symbol,BlobEntry}(),
316-
solvable::Int=1) where {T <: InferenceVariable}
317-
#
318-
DFGVariable{T}(id, label, timestamp, nstime, tags, estimateDict, Dict{Symbol, VariableNodeData{T, getPointType(T)}}(:default=>solverData), smallData, dataDict, Ref(solvable))
305+
solvable isa Int && (solvable = Ref(solvable))
306+
307+
N = getDimension(T)
308+
P = getPointType(T)
309+
DFGVariable{T,P,N}(;label, timestamp, solvable, kwargs...)
319310
end
320311

312+
DFGVariable(label::Symbol, variableType::InferenceVariable; kwargs...) = DFGVariable(label, typeof(variableType); kwargs...)
313+
314+
DFGVariable(label::Symbol, solverData::VariableNodeData; kwargs...) = DFGVariable(;label, solverDataDict=Dict(:default=>solverData), kwargs...)
315+
321316
Base.getproperty(x::DFGVariable,f::Symbol) = begin
322317
if f == :solvable
323318
getfield(x,f)[]
@@ -335,14 +330,6 @@ Base.setproperty!(x::DFGVariable,f::Symbol, val) = begin
335330
end
336331

337332

338-
##------------------------------------------------------------------------------
339-
# TODO: can't see the reason to overwrite copy, leaving it here for now
340-
# function Base.copy(o::DFGVariable)::DFGVariable
341-
# return DFGVariable(o.label, getVariableType(o)(), tags=copy(o.tags), estimateDict=copy(o.estimateDict),
342-
# solverDataDict=copy(o.solverDataDict), smallData=copy(o.smallData),
343-
# dataDict=copy(o.dataDict), solvable=getSolvable(o))
344-
# end
345-
346333
##------------------------------------------------------------------------------
347334
## DFGVariableSummary lv1
348335
##------------------------------------------------------------------------------

src/services/CompareUtils.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ function compare(a::VariableNodeData, b::VariableNodeData)
175175
a.ismargin != b.ismargin && @debug("ismargin is not equal")==nothing && return false
176176
a.dontmargin != b.dontmargin && @debug("dontmargin is not equal")==nothing && return false
177177
a.solveInProgress != b.solveInProgress && @debug("solveInProgress is not equal")==nothing && return false
178-
typeof(a.variableType) != typeof(b.variableType) && @debug("variableType is not equal")==nothing && return false
178+
getVariableType(a) != getVariableType(b) && @debug("variableType is not equal")==nothing && return false
179179
return true
180180
end
181181

@@ -204,8 +204,8 @@ function compareVariable(A::DFGVariable,
204204
varskiplist = union(varskiplist, [:variableType])
205205
union!(varskiplist, skip)
206206
TP = TP && compareAll(Ad, Bd, skip=varskiplist, show=show)
207-
TP = TP && typeof(Ad.variableType) == typeof(Bd.variableType)
208-
TP = TP && compareAll(Ad.variableType, Bd.variableType, show=show, skip=skip)
207+
TP = TP && typeof(getVariableType(Ad)) == typeof(getVariableType(Bd))
208+
TP = TP && compareAll(getVariableType(Ad), getVariableType(Bd), show=show, skip=skip)
209209
return TP
210210
end
211211

src/services/DFGVariable.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,10 @@ Related
4848
4949
getVariableType
5050
"""
51-
getVariableType(v::DFGVariable{T}) where T <: InferenceVariable = T()
51+
getVariableType(::DFGVariable{T}) where T = T()
52+
53+
getVariableType(::VariableNodeData{T}) where T = T()
5254

53-
function getVariableType(vnd::VariableNodeData)
54-
# @warn "getVariableType(::VariableNodeData) is being deprecated, use getVariableType(::DFGVariable) instead."
55-
return vnd.variableType
56-
end
5755

5856

5957
# TODO: Confirm that we can switch this out, instead of retrieving the complete variable.

src/services/Serialization.jl

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ end
8383

8484
# returns a PackedVariableNodeData
8585
function packVariableNodeData(d::VariableNodeData{T}) where {T <: InferenceVariable}
86-
@debug "Dispatching conversion variable -> packed variable for type $(string(d.variableType))"
86+
@debug "Dispatching conversion variable -> packed variable for type $(string(getVariableType(d)))"
8787
castval = if 0 < length(d.val)
8888
precast = getCoordinates.(T, d.val)
8989
@cast castval[i,j] := precast[j][i]
@@ -92,19 +92,23 @@ function packVariableNodeData(d::VariableNodeData{T}) where {T <: InferenceVaria
9292
zeros(1,0)
9393
end
9494
_val = castval[:]
95+
96+
length(d.covar) > 1 && @warn("Packing of more than one parametric covariance is NOT supported yet, only packing first.")
97+
9598
return PackedVariableNodeData(d.id, _val, size(castval,1),
9699
d.bw[:], size(d.bw,1),
97100
d.BayesNetOutVertIDs,
98101
d.dimIDs, d.dims, d.eliminated,
99102
d.BayesNetVertID, d.separator,
100-
typeModuleName(d.variableType),
103+
typeModuleName(getVariableType(d)),
101104
d.initialized,
102105
d.infoPerCoord,
103106
d.ismargin,
104107
d.dontmargin,
105108
d.solveInProgress,
106109
d.solvedCount,
107110
d.solveKey,
111+
isempty(d.covar) ? Float64[] : vec(d.covar[1]),
108112
string(_getDFGVersion()))
109113
end
110114

@@ -131,25 +135,27 @@ function unpackVariableNodeData(d::PackedVariableNodeData)
131135
BW = reshape(d.vecbw,r4,c4)
132136

133137
#
134-
return VariableNodeData{T, getPointType(T)}(
135-
d.id,
136-
vals,
137-
BW,
138-
Symbol.(d.BayesNetOutVertIDs),
139-
d.dimIDs,
140-
d.dims,
141-
d.eliminated,
142-
Symbol(d.BayesNetVertID),
143-
Symbol.(d.separator),
144-
T(),
145-
d.initialized,
146-
d.infoPerCoord,
147-
d.ismargin,
148-
d.dontmargin,
149-
d.solveInProgress,
150-
d.solvedCount,
151-
Symbol(d.solveKey),
152-
Dict{Symbol,Threads.Condition}() )
138+
N = getDimension(T)
139+
return VariableNodeData{T, getPointType(T), N}(;
140+
id = d.id,
141+
val = vals,
142+
bw = BW,
143+
#TODO only one covar is currently supported in packed VND
144+
covar = isempty(d.covar) ? SMatrix{N, N, Float64}[] : [d.covar],
145+
BayesNetOutVertIDs = Symbol.(d.BayesNetOutVertIDs),
146+
dimIDs = d.dimIDs,
147+
dims = d.dims,
148+
eliminated = d.eliminated,
149+
BayesNetVertID = Symbol(d.BayesNetVertID),
150+
separator = Symbol.(d.separator),
151+
initialized = d.initialized,
152+
infoPerCoord = d.infoPerCoord,
153+
ismargin = d.ismargin,
154+
dontmargin = d.dontmargin,
155+
solveInProgress = d.solveInProgress,
156+
solvedCount = d.solvedCount,
157+
solveKey = Symbol(d.solveKey),
158+
events = Dict{Symbol,Threads.Condition}() )
153159
end
154160

155161
##==============================================================================
@@ -188,13 +194,13 @@ function unpackVariable(variable::PackedVariable; skipVersionCheck::Bool=false)
188194
metadata = JSON3.read(base64decode(variable.metadata), Dict{Symbol, DFG.SmallDataTypes})
189195

190196
return DFGVariable(
191-
id = variable.id,
192197
variable.label,
193-
variableType,
198+
variableType;
199+
id = variable.id,
194200
timestamp=variable.timestamp,
195201
nstime=Nanosecond(variable.nstime),
196202
tags=Set(variable.tags),
197-
estimateDict=ppeDict,
203+
ppeDict=ppeDict,
198204
solverDataDict=solverDict,
199205
smallData=metadata,
200206
dataDict=dataDict,

test/data/0_21_0.tar.gz

8.38 KB
Binary file not shown.

test/data/archive/0_20_0.tar.gz

-8 Bytes
Binary file not shown.

test/interfaceTests.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ end
5252

5353

5454
@testset "Custom Printing" begin
55+
global var1, var2, var3, v1_tags, vorphan
5556

5657
iobuf = IOBuffer()
5758
# for now just test the interface and a bit of output
@@ -64,7 +65,7 @@ end
6465
if DistributedFactorGraphs._getDFGVersion() < v"0.19"
6566
@test String(take!(iobuf)) == "DFGVariable{TestVariableType1}\nid:\nnothing\nlabel:\n:a\ntags:\nSet([:VARIABLE, :POSE])\nsmallData:\nDict{Symbol, Union{Bool, Float64, Int64, Vector{Bool}, Vector{Float64}, Vector{Int64}, Vector{String}, String}}(:small=>\"data\")\ndataDict:\nDict{Symbol, DistributedFactorGraphs.BlobEntry}()\nsolvable:\n0\n"
6667
else
67-
@test String(take!(iobuf)) == "DFGVariable{TestVariableType1}\nid:\nnothing\nlabel:\n:a\ntags:\nSet([:VARIABLE, :POSE])\nsmallData:\nDict{Symbol, Union{Bool, Float64, Int64, Vector{Bool}, Vector{Float64}, Vector{Int64}, Vector{String}, String}}(:small=>\"data\")\ndataDict:\nDict{Symbol, BlobEntry}()\nsolvable:\n0\n"
68+
@test String(take!(iobuf)) == "DFGVariable{TestVariableType1, Vector{Float64}, 1}\nid:\nnothing\nlabel:\n:a\ntags:\nSet([:VARIABLE, :POSE])\nsmallData:\nDict{Symbol, Union{Bool, Float64, Int64, Vector{Bool}, Vector{Float64}, Vector{Int64}, Vector{String}, String}}(:small=>\"data\")\ndataDict:\nDict{Symbol, BlobEntry}()\nsolvable:\n0\n"
6869
end
6970

7071
@test printVariable(iobuf, var1, short=true) === nothing

0 commit comments

Comments
 (0)