Loading [MathJax]/jax/output/CommonHTML/jax.js
DSO

DSO - Schur Complement

Posted by Tong on April 17, 2020

Direct sparse odometry

Foreknowledge about Schur complement can be found here

Initialization

Preparation

As introduced here, we have

J=[r1txr1tyr1tzr1ϕxr1ϕyr1ϕzr1ar1br1ρ10...0r2txr2tyr2tzr2ϕxr2ϕyr2ϕzr2ar2b0r2ρ2...0..........................................rNtxrNtyrNtzrNϕxrNϕyrNϕzrNarNb00...rNρN] e=[r1r2...rN]

x=[txtytzϕxϕyϕzabρ1ρ2...ρN]=[x1x2], where x1=[txtytzϕxϕyϕzab], x2=[ρ1ρ2...ρN]

In Gauss-Newton, our Hessian matrix can be formulated as

H=JTJ=[r1txr2tx...rNtxr1tyr2ty...rNtyr1tzr2tz...rNtzr1ϕxr2ϕx...rNϕxr1ϕyr2ϕy...rNϕyr1ϕzr2ϕz...rNϕzr1ar2a...rNar1br2b...rNbr1ρ10...00r2ρ2...00....00....00....00...0rNρN][r1txr1tyr1tzr1ϕxr1ϕyr1ϕzr1ar1br1ρ10...0r2txr2tyr2tzr2ϕxr2ϕyr2ϕzr2ar2b0r2ρ2...0..........................................rNtxrNtyrNtzrNϕxrNϕyrNϕzrNarNb00...rNρN]=[H11H12HT12H22] H11=Ni=1[(ritxritx)(ritxrity)(ritxritz)(ritxriϕx)(ritxriϕy)(ritxriϕz)(ritxria)(ritxrib)(rityritx)(rityrity)(rityritz)(rityriϕx)(rityriϕy)(rityriϕz)(rityria)(rityrib)(ritzritx)(ritzrity)(ritzritz)(ritzriϕx)(ritzriϕy)(ritzriϕz)(ritzria)(ritzrib)(riϕxritx)(riϕxrity)(riϕxritz)(riϕxriϕx)(riϕxriϕy)(riϕxriϕz)(riϕxria)(riϕxrib)(riϕyritx)(riϕyrity)(riϕyritz)(riϕyriϕx)(riϕyriϕy)(riϕyriϕz)(riϕyria)(riϕyrib)(riϕzritx)(riϕzrity)(riϕzritz)(riϕzriϕx)(riϕzriϕy)(riϕzriϕz)(riϕzria)(riϕzrib)(riaritx)(riarity)(riaritz)(riariϕx)(riariϕy)(riariϕz)(riaria)(riarib)(ribritx)(ribrity)(ribritz)(ribriϕx)(ribriϕy)(ribriϕz)(ribria)(ribrib)] H12=[(r1txr1ρ1)(r2txr2ρ2)...(rNtxrNρN)(r1tyr1ρ1)(r2tyr2ρ2)...(rNtyrNρN)(r1tzr1ρ1)(r2tzr2ρ2)...(rNtzrNρN)(r1ϕxr1ρ1)(r2ϕxr2ρ2)...(rNϕxrNρN)(r1ϕyr1ρ1)(r2ϕyr2ρ2)...(rNϕyrNρN)(r1ϕzr1ρ1)(r2ϕzr2ρ2)...(rNϕzrNρN)(r1ar1ρ1)(r2ar2ρ2)...(rNarNρN)(r1br1ρ1)(r2br2ρ2)...(rNbrNρN)] H22=[(r1ρ1)20...00(r2ρ2)2...000...000...000..0(rNρN)2] b=JTe=[r1txr2tx...rNtxr1tyr2ty...rNtyr1tzr2tz...rNtzr1ϕxr2ϕx...rNϕxr1ϕyr2ϕy...rNϕyr1ϕzr2ϕz...rNϕzr1ar2a...rNar1br2b...rNbr1ρ10...00r2ρ2...00....00....00....00...0rNρN][r1r2...rN]=[Ni=1(ritxri)Ni=1(rityri)Ni=1(ritzri)Ni=1(riϕxri)Ni=1(riϕyri)Ni=1(riϕzri)Ni=1(riari)Ni=1(ribri)r1ρ1r1r2ρ2r2...rNρNrN]

Schur complement

Obviously, we can exploit the spartsiy in H22 to solve δx1 with

(H11H12H122HT12)δx1=(b1H12H122b2)

and solve δx2 with

δx2=H122(b2+HT12δx1)

Remember,

H122=[(r1ρ1)20...00(r2ρ2)2...000...000...000..0(rNρN)2]

Codes

Variable used in CoarseInitializer Variable used here Meaning
JbBuffer_new[i][0] ritxriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][1] rityriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][2] ritzriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][3] riϕxriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][4] riϕyriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][5] riϕzriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][6] riariρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][7] ribriρi i个点提供的计算H12所需的中间量
JbBuffer_new[i][8] ririρi i个点提供的计算b所需的中间量
JbBuffer_new[i][9] (riρi)2 i个点提供的计算H22以及H122所需的中间量
Accumulator9 acc9   计算H11b1
Accumulator9 acc9SC   计算H12H122HT12H12H122b2
Accumulator11 E   计算总的光度误差

Sliding Window Optimization

Preparation

For convenience, we consider only one residual (which is DEFINITELY IMPOSSIBLE) wrt. two frames in the following sections.

As introduced here, we have

J=[rCrξiwrairξjwrajrρ] e=[r]

x=[Cξiwaiξjwajρ]=[x1x2], where x1=[Cξiwaiξjwaj], x2=[ρ]

Variable Meaning
r single residual
C=[fxfycxcy] intrinsic parameters (4 x 1)
ξiw pose Tiw of frame i (6 x 1)
ai=[aibi] photometric parameters of frame i (2 x 1)
ξjw pose Tjw of frame j (6 x 1)
aj=[ajbj] photometric parameters of frame j (2 x 1)
ρ inverse depth (1 x 1)

Hessian

H=JTJ=[(rC)T(rξiw)T(rai)T(rξjw)T(raj)T(rρ)T][rCrξiwrairξjwrajrρ]=[(rC)TrC(rC)Trξiw(rC)Trai(rC)Trξjw(rC)Traj(rC)Trρ(rξiw)TrC(rξiw)Trξiw(rξiw)Trai(rξiw)Trξjw(rξiw)Traj(rξiw)Trρ(rai)TrC(rai)Trξiw(rai)Trai(rai)Trξjw(rai)Traj(rai)Trρ(rξjw)TrC(rξjw)Trξiw(rξjw)Trai(rξjw)Trξjw(rξjw)Traj(rξjw)Trρ(raj)TrC(raj)Trξiw(raj)Trai(raj)Trξjw(raj)Traj(raj)Trρ(rρ)TrC(rρ)Trξiw(rρ)Trai(rρ)Trξjw(rρ)Traj(rρ)Trρ]=[H11H12HT12H22] H11=[(rC)TrC(rC)Trξiw(rC)Trai(rC)Trξjw(rC)Traj(rξiw)TrC(rξiw)Trξiw(rξiw)Trai(rξiw)Trξjw(rξiw)Traj(rai)TrC(rai)Trξiw(rai)Trai(rai)Trξjw(rai)Traj(rξjw)TrC(rξjw)Trξiw(rξjw)Trai(rξjw)Trξjw(rξjw)Traj(raj)TrC(raj)Trξiw(raj)Trai(raj)Trξjw(raj)Traj] H12=[(rC)Trρ(rξiw)Trρ(rai)Trρ(rξjw)Trρ(raj)Trρ] H22=[(rρ)Trρ]=[(rρ)2]

b

b=JTe=[(rC)T(rξiw)T(rai)T(rξjw)T(raj)T(rρ)T]r b1=[r(rC)Tr(rξiw)Tr(rai)Tr(rξjw)Tr(raj)T] b2=[r(rρ)T]

Implementation

In the real implementation, the author didn’t directly compute rξiw, rξjw, rai and raj. Instead, he used the chain rules

rξiw=rξjiξjiξiw rξjw=rξjiξjiξjw rai=r[eajibji][eajibji]ai raj=r[eajibji][eajibji]aj

And their tranposes are

(rξiw)T=(ξjiξiw)T(rξji)T (rξjw)T=(ξjiξjw)T(rξji)T (rai)T=([eajibji]ai)T(r[eajibji])T (raj)T=([eajibji]aj)T(r[eajibji])T

Details about these Jacobians can be found in this post.

Schur Complement

(H11H12H122HT12)δx1=(b1H12H122b2) Hsc=H12H122HT12=[(rC)Trρ(rξiw)Trρ(rai)Trρ(rξjw)Trρ(raj)Trρ][(rρ)2][(rρ)TrC(rρ)Trξiw(rρ)Trai(rρ)Trξjw(rρ)Traj]=[(rC)TrC(rC)Trξiw(rC)Trai(rC)Trξjw(rC)Traj(rξiw)TrC(rξiw)Trξiw(rξiw)Trai(rξiw)Trξjw(rξiw)Traj(rai)TrC(rai)Trξiw(rai)Trai(rai)Trξjw(rai)Traj(rξjw)TrC(rξjw)Trξiw(rξjw)Trai(rξjw)Trξjw(rξjw)Traj(raj)TrC(raj)Trξiw(raj)Trai(raj)Trξjw(raj)Traj] bsc=H12H122b2=[(rC)Trρ(rξiw)Trρ(rai)Trρ(rξjw)Trρ(raj)Trρ][(rρ)2][r(rρ)T]=[(rC)Tr(rξiw)Tr(rai)Tr(rξjw)Tr(raj)Tr]