Continuous time
trajectory estimation for 3D SLAM
from an actuated 2D laser scanner
Adrian Haarbach's master's thesis defense
Improved version as of March 28th, 2017
Link to original version from December 19th, 2016
abstract
“
This thesis aims at estimating trajectories for 3D SLAM applications. A continuous time formulation
allows solving multiple problems inherent to the traditional discrete time approaches seamlessly, such
as sensor fusion of actuated 2D laser scanner data with inertial measurements. Special care is taken when
choosing an appropriate trajectory representation . The well-known ICP algorithm used for rigid registration
is extended significantly so it can deal with continuous-time, multi-view registration of deformable scans.
The resulting algorithm can be employed online in a time-windowed fashion to get an open-loop trajectory
estimate and offline for global optimization to further reduce the drift. In contrast to previous work we
are able to provide ground truth data for evaluation by extending an existing simulator so that it can simulate
actuated 2D laser scanner data with corresponding inertial measurements. Experiments on synthetic data with
different scenarios, noise levels and parameter settings show the versatility, stability and adaptability of
our algorithm as well as its high overall accuracy.”
\[
\newcommand{\real}{\mathbb{R}}
\newcommand{\rthree}{\real^3}
\newcommand{\SOthree}{\mathrm{SO}(3)}
\newcommand{\sothree}{\mathfrak{so}(3)}
\newcommand{\SUtwo}{\mathrm{SU}(2)}
\newcommand{\sutwo}{\mathfrak{su}(2)}
\newcommand{\spherethree}{\mathbb{S}^3}
\newcommand{\spheretwo}{\mathbb{S}^2}
\newcommand{\norm}[1]{\left\|#1\right\|}
\newcommand{\quat}{\vecb{q}}
\newcommand{\vecb}[1]{\mathbf{#1}}
\newcommand{\quatreal}{q_w} %scalar normal
\newcommand{\quatvec}{\quat_{x:z}} %vector bold
\newcommand{\point}{\vecb{p}}
\newcommand{\pos}{\vecb{t}}
\newcommand{\vel}{\vecb{v}}
\newcommand{\acc}{\vecb{a}}
\newcommand{\angVel}{{\Vecb{\omega}}}
\newcommand{\Vecb}[1]{\boldsymbol{#1}}
\newcommand{\real}{\mathbb{R}}
\newcommand{\rthree}{\real^3}
\newcommand{\rthreebythree}{\real^{3 \times 3}}
\newcommand{\rtwo}{\real^2}
\newcommand{\cloud}[1]{\mathcal{#1}}
\newcommand{\cloudsize}[1]{N_{\cloud{#1}}}
\newcommand{\cloudi}[1]{\left\{\MakeLowercase{#1}_i\right\}}
\newcommand{\cloudr}[1]{\{\MakeLowercase{#1}_1,\MakeLowercase{#1}_2,...,\MakeLowercase{#1}_{\cloudsize{#1}}\}}
\newcommand{\clouddef}[1]{\cloud{#1}=\cloudi{#1}=\cloudr{#1}}
\newcommand{\cloudfull}[1]{\clouddef{#1}, \MakeLowercase{#1}_i \in \rthree}
\newcommand{\scalarfull}[1]{\clouddef{#1}, \MakeLowercase{#1}_i \in \real}
\def\firstToLow#1{\expandafter\firstToLowA#1!!}
\def\firstToLowA#1#2!!{\MakeLowercase{#1}#2}
%chapter 2
%vector bold in math mode
\newcommand{\vecb}[1]{\mathbf{#1}}
%http://tex.stackexchange.com/questions/3535/bold-math-automatic-choice-between-mathbf-and-boldsymbol-for-latin-and-greek
%\newcommand{\vect}[1]{\boldsymbol{\mathbf{#1}}}
\newcommand{\Vecb}[1]{\boldsymbol{#1}}
%matrix not italic in math mode
%\newcommand{\matr}[1]{\mathrm{#1}}
\newcommand{\mean}{{\Vecb{\mu}}} %\bar{p}
\newcommand{\Cov}{\Sigma}
%normal with error
\newcommand{\normal}{\vec{\vecb{n}}}
\newcommand{\eigsmall}{\lambda_0}
\newcommand{\eigmiddle}{\lambda_1}
\newcommand{\eiglarge}{\lambda_2}
\newcommand{\eigVals}{\eigsmall \leq \eigmiddle \leq \eiglarge}
\newcommand{\eigsum}{\eigsmall + \eigmiddle + \eiglarge}
\newcommand{\eigVecSmall}[1][]{\vecb{e}_{0#1}}
\newcommand{\eigVecMiddle}[1][]{\vecb{e}_{1#1}}
\newcommand{\eigVecLarge}[1][]{\vecb{e}_{2#1}}
\newcommand{\eigVecs}{\eigVecSmall,\eigVecMiddle,\eigVecLarge}
%NLS
\newcommand{\res}{\vecb{r}} %e
\newcommand{\eres}{\vecb{e}} %e for our residuals
\newcommand{\factor}{}%\frac{1}{2}}
%%motion
\newcommand{\SOthree}{\mathrm{SO}(3)}
\newcommand{\sothree}{\mathfrak{so}(3)}
\newcommand{\SUtwo}{\mathrm{SU}(2)}
\newcommand{\sutwo}{\mathfrak{su}(2)}
\newcommand{\spherethree}{\mathbb{S}^3}
\newcommand{\spheretwo}{\mathbb{S}^2}
%https://en.wikipedia.org/wiki/Rotation_group_SO(3)#Quaternions_of_unit_norm
%SU(2) is isomorphic to the quaternions of unit norm via a map given by
%https://en.wikipedia.org/wiki/Special_unitary_group
%Therefore, as a manifold S3 is diffeomorphic to SU(2) and so SU(2) is a compact, connected Lie group.
\newcommand{\SEthree}{\mathrm{SE}(3)}
\newcommand{\sethree}{\mathfrak{se}(3)}
%interpolation
\def\Bezier{B\'ezier}
\def\Bspline{B-spline}
%chapter 3
\newcommand{\der}{\dot}
\newcommand{\dder}{\ddot}
\newcommand{\derFull}[1]{\frac{d #1}{d\timeVar}}
\newcommand{\dderFull}[1]{\frac{d^2 #1}{d\timeVar^2}}
\newcommand{\Der}[1]{#1'}
\newcommand{\Dder}[1]{#1''}
\newcommand{\timeVar}{\tau}
\newcommand{\curr}{(\timeVar)}
\newcommand{\diff}{\Delta \timeVar}
\newcommand{\tnext}{(\timeVar+\diff)}
\newcommand{\midpoint}{(\timeVar+ \frac{1}{2}\diff)}
\newcommand{\world}{{_w}}
\newcommand{\base}{{_s}}
\newcommand{\point}{\vecb{p}}
\newcommand{\pos}{\vecb{t}}
\newcommand{\vel}{\vecb{v}}
\newcommand{\acc}{\vecb{a}}
\newcommand{\angVel}{{\Vecb{\omega}}}
\newcommand{\quat}{\vecb{q}}
\newcommand{\ori}{\quat}
\newcommand{\matrixn}[1]{\mathrm{#1}}
\newcommand{\R}{\matrixn{R}}
\newcommand{\I}{\matrixn{I}}
\newcommand{\T}{\matrixn{T}} %SE(3) homogeneous matrix
\newcommand{\rr}{\vecb{r}} %linear rotation bosse slot
\newcommand{\bias}{\base\vecb{b}}%\mathrm{bias}}
\newcommand{\gravity}{\world\vecb{g}}%\mathrm{gravity}}%\vecb{g}}
%continuity
\newcommand{\C}[1]{C\textsuperscript{#1}}
%icp correspondenced
\newcommand{\pp}{\point}
\newcommand{\pq}{\point'}
\newcommand{\np}{\normal}
\newcommand{\nq}{\normal'}
\newcommand{\Covp}{\Cov}
\newcommand{\Covq}{\Cov'}
\newcommand{\mup}{\mean}
\newcommand{\muq}{\mean'}
%sweeps
\newcommand{\pa}{\vecb{a}}
\newcommand{\pb}{\vecb{b}}
%chapter 4 approach
\newcommand{\NC}{
\frac{1}{6}
\begin{bmatrix*}[r]
0 & 1 & -2 & 1 \\
0 & -3 & 3 & 0 \\
0 & 3 & 3 & 0 \\
6 & 5 & 1 & 0
\end{bmatrix*}
}
\newcommand{\N}[1]{\widetilde{\mathbf{N}}_{#1}}
\newcommand{\Ndot}[1]{\der{\widetilde{\mathbf{N}}}_{#1}}
\newcommand{\Ndotdot}[1]{\dder{\widetilde{\mathbf{N}}}_{#1}}
\newcommand{\laserScans}{\mathcal{L}}
\newcommand{\imuMeas}{\mathcal{M}}
\newcommand{\sweeps}{\mathcal{S}}
\newcommand{\sweepDur}{\Delta\timeVar_{Sweep}}
\newcommand{\taus}{\Delta\timeVar_{basePoses}}
\newcommand{\timeNow}{\timeVar_{curr}}
\newcommand{\matchesSurfel}{\text{surfelMatches}}
\newcommand{\matchesIMU}{\text{imuMatches}}
\newcommand{\expi}[1]{\exp(\N{#1}\angVel_{#1})}
\newcommand{\deri}[1]{(\Ndot{#1}\angVel_{#1})}
\newcommand{\veli}[1]{\N{#1}\vel_{#1}}
\newcommand{\velidot}[1]{\Ndot{#1}\vel_{#1}}
\newcommand{\velidotdot}[1]{\Ndotdot{#1}\vel_{#1}}
% norm
\newcommand{\norm}[1]{\left\|#1\right\|}
%\newcommand{\normtwo}[1]{\left\|\left\|#1\right\|\right\|^2}
%\newcommand{\abs}[1]{ \left\lvert#1\right\rvert} % absolute value: single vertical bars
\newcommand{\Norm}[1]{\left\lVert#1\right\rVert} % norm: double vertical bars
\newcommand{\determinant}[1]{|#1|}
% un demi
\newcommand{\half}{\frac{1}{2}}
% parantheses
\newcommand{\parenth}[1]{ \left( #1 \right) }
\newcommand{\bracket}[1]{ \left[ #1 \right] }
\newcommand{\accolade}[1]{ \left\{ #1 \right\} }
%\newcommand{\angle}[1]{ \left\langle #1 \right\rangle }
% partial derivative: %#1 function, #2 which variable
% simple / single line version
\newcommand{\pardevS}[2]{ \delta_{#1} f(#2) }
% fraction version
\newcommand{\pardevF}[2]{ \frac{\partial #1}{\partial #2} }
% render vectors: 3 and 4 dimensional
\newcommand{\veciii}[3]{\left[ \begin{array}[h]{c} #1 \\ #2 \\ #3 \end{array} \right]}
\newcommand{\veciv}[4]{\left[ \begin{array}[h]{c} #1 \\ #2 \\ #3 \\ #4 \end{array} \right]}
\newcommand{\bfrac}[2]{\genfrac{}{}{0pt}{}{#1}{#2}}
\newcommand{\rightleftlie}{\bfrac{\xrightarrow[]{\log}}{\xleftarrow[\exp]{}}}
%chapter 4 approach
\]
Introduction
stationary 3D scanner
actuated 2D scanner
Simultaneous Localization And Mapping (SLAM)
Hardware sensors
LiDAR
Light Detection And Ranging
\( \begin{pmatrix}
x \\
y
\end{pmatrix}
=
\begin{pmatrix}
r\cos(\phi)\\
r\sin(\phi)
\end{pmatrix}
\\
\phi = \phi_0 + i\Delta\phi \)
IMU
Inertial Measurement Unit
\(
\newcommand{\angVelMeas}{\base\tilde\angVel\curr & = \base\angVel\curr + \bias_\angVel\curr + \mathcal{N}(\vecb{0},\vecb{\sigma}_\angVel)}
\newcommand{\accMeas}{\base\tilde\acc\curr & = \base\acc\curr + \bar{\ori}\curr \gravity + \bias_\acc\curr + \mathcal{N}(\vecb{0},\vecb{\sigma}_\acc)}
\begin{align}
\angVelMeas &\text{angVel}\\
\accMeas &\text{linAcc}
\end{align}
\)
Rotational motion as a manifold
Lie group
e.g.
rotation matrices
\[\mathrm{SO}(3)\]
\[\rightleftlie\]
Lie algebra
e.g.
skew-symmetric matrices
\[\mathfrak{so}(3)\]
unit quaternions
\(\boxed{\SUtwo \cong \spherethree \cong \mathbb{H}_1 = \{\quat \in \mathbb{H} | \norm{\quat} = 1 \}}\)
pure quaternions
\(\boxed{\sutwo \cong \rthree \cong \mathbb{H}_0 = \{\quat \in \mathbb{H} | \quatreal = 0 \}} \)
Interpolation
Interpolation vs approximation
Continuity
Global vs local control
Complexity LERP, Bezier curve, Bspline
PCA
Prinical Component Analysis
NLS
Non-linear Least Squares:
\( E(x) = \factor\sum_{i}^N \left\|f_i\left(x_{i_1}, ... ,x_{i_j}\right)\right\|^2 = \factor\sum_{i=1}^N \res_i^T \res_i = \factor\res^T\res \)
Levenberg-Marquardt step:
\( \Delta x = -(J^TJ + \lambda I)^{-1}J^T\res \)
composite cubic Bezier curve
0
1
2
cubic B-spline
Interpolating orientations
\(
\newcommand{\slerpDef}{slerp(\quat_0, \quat_1, u)}
\newcommand{\slerp}{\quat_0(\bar{\quat}_0\quat_1)^{u}}
\newcommand{\Slerp}{\quat_0 \exp(u\log(\bar{\quat}_0\quat_1))}
\slerpDef = \slerp = \Slerp
\)
SLERP: Shoemake (1985) Animating rotation with quaternion curves
SQUAD: Shoemake (1987) Quaternion calculus and fast animation
cumulative quaternion B-spline
\(
\quat\curr = \quat_0 \prod_{i=1}^n \exp \big( \tilde{N}_i^k\curr \log(\quat_{i-1}^{-1}\quat_{i}) \big) \\
\newcommand{\NC}{
\frac{1}{6}
\begin{bmatrix}
0 & 1 & -2 & 1 \\
0 & -3 & 3 & 0 \\
0 & 3 & 3 & 0 \\
6 & 5 & 1 & 0
\end{bmatrix}
}
\tilde{N}(u) = [u^3, u^2, u, 1] \NC \\
\)
Kim (1995) A general construction scheme for unit quaternion curves with simple high order derivatives
Bezier
Slerp
Squad
B-spline
Algorithm
//in: L Lidar scans M IMU measurements
//out: T Trajectory
T = initializeFromIMU(M)
for (i=0 , i < nsweeps , i++ ){
S[i] = unprojectAndAccumulate(L[i*k],...,L[i*k+k])
S[i].undistordAndComputeSurfel(T)
if(i>0){
imuMatches = imuDeviations(T,M[i-1],...,M[i+1])
for (j=0 , j < nicp , j++){
surfelMatches = kdTreeNNLookup(S[i],S[i-1])
T = NLS(T,surfelMatches,imuMatches)
S[i].updateSurfelWorldPositions(T)
}
}
}
Voxels and Surfels
\(
P(\{\point_i\} \text{ describes plane}) = 2\frac{\eigmiddle-\eigsmall}{\eigsum}
\)
Surfel Matches
Model Optimization
imuMatches:
\(
\newcommand{\ppDistAbsSurfel}{\bar{d}(a_i,b_i)}
\newcommand{\surfelTuple}{(\mean,\normal,\hat\Cov)}
\begin{align}
\base \eres_\angVel &= \base\tilde\angVel(\timeVar_k) - \base\angVel(\timeVar_k) - \bias_\angVel(\timeVar_k) \\
\base \eres_\acc &= \base\tilde\acc(\timeVar_k) - \bar\quat(\timeVar_k)\gravity - \base\acc(\timeVar_k) - \bias_\acc(\timeVar_k)
\end{align}
\)
surfelMatches:
\(
\begin{align}
\ppDistAbsSurfel &= \R_{a_i}\mean_{a_i} + \pos_{a_i} - (\R_{b_i}\mean_{b_i}+\pos_{b_i} )\nonumber \\
\eres_{a_i,b_i} &= \ppDistAbsSurfel^T (\R_h \hat\Cov_{a_i}\R_h^T + \R_k \hat\Cov_{b_i} \R_k^T)^{-1} \ppDistAbsSurfel \\ \\
\end{align}
\)
combined:
\(
E = (1-\alpha)\sum_{i=0}^{N} \eres_{a_i,b_i} + \alpha\sum_{j=1}^M\left( \eres_{\angVel_j}^T\Sigma_\angVel^{-1}\eres_{\angVel_j} + \eres_{\acc_j}^T\Sigma_\acc^{-1}\eres_{\acc_j} \right)
\)
Time-windowed optimization
Global optimization
Noise and knot spacing
box
loop
stairs