Skip to content

Commit 4204c3e

Browse files
authored
Merge pull request #611 from JuliaRobotics/22Q3/feat/g2o_parsers
Parse more G2O formats and Improve PriorPose2 performance
2 parents 15049e1 + 6979b9e commit 4204c3e

File tree

3 files changed

+85
-28
lines changed

3 files changed

+85
-28
lines changed

src/factors/Pose2D.jl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,6 @@ function preambleCache(dfg::AbstractDFG, vars::AbstractVector{<:DFGVariable}, pp
4040
(;manifold=M, ϵ0=getPointIdentity(M), Xc=zeros(3), q̂=getPointIdentity(M))
4141
end
4242

43-
@inline function _vee(::SpecialEuclidean{2}, X::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}) where T<:Real
44-
return SVector{3,T}(X.x[1][1],X.x[1][2],X.x[2][2])
45-
end
46-
47-
@inline function _compose(::SpecialEuclidean{2}, p::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}, q::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}) where T<:Real
48-
return ArrayPartition(p.x[1] + p.x[2]*q.x[1], p.x[2]*q.x[2])
49-
end
50-
5143
# Assumes X is a tangent vector
5244
function (cf::CalcFactor{<:Pose2Pose2})(_X::AbstractArray{MT}, _p::AbstractArray{PT}, _q::AbstractArray{LT}) where {MT,PT,LT}
5345
T = promote_type(MT, PT, LT)

src/factors/PriorPose2.jl

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,32 @@ end
1616

1717
DFG.getManifold(::InstanceType{PriorPose2}) = getManifold(Pose2) # SpecialEuclidean(2)
1818

19-
function (cf::CalcFactor{<:PriorPose2})(m, p)
20-
M = getManifold(Pose2)
21-
Xc = vee(M, p, log(M, p, m))
22-
return Xc
19+
@inline function _vee(::SpecialEuclidean{2}, X::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}) where T<:Real
20+
return SVector{3,T}(X.x[1][1],X.x[1][2],X.x[2][2])
21+
end
2322

24-
# M = getManifold(Pose2)
25-
# # X = allocate(p)
26-
# # X = ProductRepr(zeros(MVector{2}), zeros(MMatrix{2,2}))
27-
# # log!(M, X, p, m)
28-
# X = log(M, p, m)
29-
# return SA[X.x[1][1],X.x[1][2],X.x[2][2]]
23+
@inline function _compose(::SpecialEuclidean{2}, p::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}, q::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}) where T<:Real
24+
return ArrayPartition(p.x[1] + p.x[2]*q.x[1], p.x[2]*q.x[2])
25+
end
3026

27+
function (cf::CalcFactor{<:PriorPose2})(_m::AbstractArray{MT}, _p::AbstractArray{PT}) where {MT<:Real,PT<:Real}
28+
T = promote_type(MT, PT)
29+
m = convert(ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}, _m)
30+
p = convert(ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}, _p)
31+
return cf(m,p)
3132
end
32-
# BenchmarkTools.Trial: 10000 samples with 1 evaluation.
33-
# Range (min … max): 22.299 μs … 11.920 ms ┊ GC (min … max): 0.00% … 98.28%
34-
# Time (median): 29.930 μs ┊ GC (median): 0.00%
35-
# Time (mean ± σ): 40.097 μs ± 171.479 μs ┊ GC (mean ± σ): 5.60% ± 1.39%
3633

37-
# ▂▆█▇▆▅▄▃▃▄▃▂ ▂▂▂▂▁ ▂
38-
# ▆██████████████▆▆▆▄▅▇██████▇▇█▆▇▆▄▅▄▆▆▅▅▅▆▅▅▅▄▅▄▄▄▅▅▅▄▄▄▃▅▄▄ █
39-
# 22.3 μs Histogram: log(frequency) by time 127 μs <
34+
# TODO the log here looks wrong (for gradients), consider:
35+
# X = log(p⁻¹ ∘ m)
36+
# X = log(M, ϵ, Manifolds.compose(M, inv(M, p), m))
37+
function (cf::CalcFactor{<:PriorPose2})(
38+
m::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}},
39+
p::ArrayPartition{T, Tuple{SVector{2, T}, SMatrix{2, 2, T, 4}}}) where T<:Real
4040

41-
# Memory estimate: 26.88 KiB, allocs estimate: 481.
41+
M = getManifold(Pose2)
42+
Xc = _vee(M, log(M, p, m))
43+
return Xc
44+
end
4245

4346
#TODO Serialization of reference point p
4447
## Serialization support

src/g2oParser.jl

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,24 @@ end
5353
Parses a single g2o instruction to add information to factor graph.
5454
"""
5555
function parseG2oInstruction!(fg::AbstractDFG,
56-
instruction::Array{SubString{String},1})
57-
if instruction[1] == "EDGE_SE2"
56+
instruction::Array{SubString{String},1};
57+
initialize::Bool=true)
58+
#
59+
infoM6 = zeros(6,6)
60+
61+
if instruction[1] == "VERTEX_SE2"
62+
poseId = Symbol("x", instruction[2])
63+
x = parse(Float64,instruction[3])
64+
y = parse(Float64,instruction[4])
65+
θ = parse(Float64,instruction[5])
66+
#NOTE just useing some covariance as its not included
67+
cov = diagm([1,1,0.1])
68+
addVariable!(fg, poseId, Pose2)
69+
if initialize
70+
# initVariable!(fg, poseId, MvNormal([x,y,θ],cov))
71+
initVariable!(fg, poseId, MvNormal([x,y,θ],cov), :parametric)
72+
end
73+
elseif instruction[1] == "EDGE_SE2"
5874
# Need to add a relative pose measurement between two variables.
5975
# Parse all of the variables starting with the symbols.
6076
from_pose = Symbol("x", instruction[2])
@@ -86,6 +102,52 @@ function parseG2oInstruction!(fg::AbstractDFG,
86102
measurement = MvNormal([x_state; y_state; theta_state], cov_mat)
87103
rel_pose_factor = Pose2Pose2(measurement)
88104
addFactor!(fg, [from_pose, to_pose], rel_pose_factor)
105+
elseif instruction[1] == "EDGE_SE3:QUAT"
106+
107+
# MU1 = Unitary(1,ℍ)
108+
# ϵU1 = identity_element(MU1)
109+
MSO3 = SpecialOrthogonal(3)
110+
ϵSO3 = identity_element(MSO3)
111+
112+
# Need to add a relative pose measurement between two variables.
113+
# Parse all of the variables starting with the symbols.
114+
from_pose = Symbol("x", instruction[2])
115+
to_pose = Symbol("x", instruction[3])
116+
117+
dt = parse.(Float64, instruction[4:6])
118+
qvec = parse.(Float64, instruction[[10;7:9]])
119+
120+
dR = TU.convert(SO3, TU.Quaternion(qvec[1],qvec[2:4])).R
121+
X = log(MSO3, ϵSO3, dR)
122+
Xc = vee(MSO3, ϵSO3, X)
123+
124+
a = parse.(Float64, instruction[11:31])
125+
for i=1:6
126+
vw = view(a, (1+(i-1)*(14-i)÷2):(i*(13-i)÷2))
127+
infoM6[i,i:6] = vw
128+
infoM6[i:6,i] = vw
129+
end
130+
cov_mat = inv(infoM6)
131+
# NOTE workaround to ensure cov_mat is Hermitian -- TODO use inf_mat directly for MvNormal
132+
cov_mat += cov_mat'
133+
cov_mat ./= 2
134+
135+
# Make sure both variables are in the FG. Otherwise add them.
136+
if (from_pose in ls(fg)) == false
137+
addVariable!(fg, from_pose, Pose3)
138+
end
139+
if (to_pose in ls(fg)) == false
140+
addVariable!(fg, to_pose, Pose3)
141+
end
142+
143+
#FIXME conversion between U(1,ℍ) and SO3 covariances?
144+
@error "3D covariance from Quaternion is not done yet!" maxlog=1
145+
# dq = Manifolds.Quaternion(qvec...)
146+
147+
# Add a factor between the two poses with the relative measurement.
148+
measurement = MvNormal([dt;Xc], cov_mat)
149+
rel_pose_factor = Pose3Pose3(measurement)
150+
addFactor!(fg, [from_pose, to_pose], rel_pose_factor)
89151
end
90152
return fg
91153
end

0 commit comments

Comments
 (0)