这篇文章实现了《概率机器人》第10章中提到的EKF-SLAM算法,更确切的说是实现了已知一致性的EKF-SLAM算法。
ArUco EKF SLAM
https://www.zhihu.com/video/1027276196236513280
EKF-SLAM一般是基于路标的SLAM系统。本文使用了一种人工路标——ArUco码。每个ArUco码有一个独立的ID,通过PnP方法还可以计算出码和相机之间的相对位姿。OpenCV中集成了ArUco码库,提供了检测和位姿估计的功能。大家可以参考:
https://docs.opencv.org/3.3.0/d9/d6d/tutorial_table_of_content_aruco.html。
Aruco Marker
首先在房间的地面上贴若干ArUco码作为路标,然后遥控一个带有摄像头+编码器的机器人在房间内运动。本文的目标就是通过EKF算法同时估计出这些码的位置和机器人的位姿。
实验环境
要实现EKF-SLAM,最关键的就是建立运动模型和观测模型,将这两个模型直接带进EKF算法框架就是EKF-SLAM。EKF-SLAM算法使用扩展的状态空间:
X=[xyθmx,1my,1mx,2my,2⋯mx,Nmy,N]T
前3项是机器人位姿,后2N项是 N个路标点的位置。
1. 运动模型
1.1 里程计模型
我比较喜欢采用《自主移动机器人导论》中的里程计模型作为运动模型。具体的,如果t-1时刻机器人的位姿是 ξt−1=[xyθ]t−1T ,那么t时刻的机器人位姿为:
xyθt=xyθt−1+Δscos(θ+Δθ/2)Δssin(θ+Δθ/2)Δθ,{Δθ=bΔsr−ΔslΔs=2Δsr+Δsl,Δsl/r=kl/r⋅Δel/rΔsl/r∼N(Δsl/r,kΔsl/r2).
kl/r 为左右轮系数,把编码器增量Δel/r转化为左右轮的位移, b 是轮间距。左右轮位移的增量Δsl/r服从高斯分布,均值就是编码器计算出的位移增量,标准差与增量大小成正比。如果t-1时刻机器人位姿的协方差为Σξ,t−1,控制的协方差也就是左右轮位移增量的协方差为Σu,那么机器人位姿在t时刻的协方差就是: Σξ,t=GξΣξ,t−1GξT+G′uΣuG′uT (2) Gξ 是(1)式关于机器人位姿ξt−1的雅克比:
Gξ=∂ξt−1∂ξt=100010−Δssin(θ+Δθ/2)Δscos(θ+Δθ/2)1 (3)
G′u 是(1)式关于控制)u=[ΔsrΔsl]T的雅克比:
G′u=∂u∂ξt=21cos(θ+2Δθ)−2bΔssin(θ+2Δθ)21sin(θ+2Δθ)+2bΔscos(θ+2Δθ)b121cos(θ+2Δθ)+2bΔssin(θ+2Δθ)21sin(θ+2Δθ)−2bΔscos(θ+2Δθ)−b1 (4)
1.2 EKF-SLAM运动更新
上面说的还是只考虑机器人位姿的情况,但是SLAM系统还需要考虑路标点。扩展路标点之后,运动方程为:
Xtxyθmx,1my,1⋮mx,Nmy,Nt=g(Xt−1,ut)Xt−1xyθmx,1my,1⋮mx,Nmy,Nt−1+F10000⋮0001000⋮0000100⋮00Δscos(θ+Δθ/2)Δssin(θ+Δθ/2)Δθ (5)
系统状态的均值 uˉt更新利用(5)式,下面看状态的方差 Σt 更新。
Σt=GtΣt−1GtT+GuΣuGuT (6)
Gt 是 g(Xt−1,ut) 关于 Xt−1 的雅克比:
Gt=[Gξ00I] (7)
Gu是g(Xt−1,ut)关于 ut 的雅克比:
Gu=FG′u (8)
把(6)式展开看一下:
Σt=[Gξ00I]Σt[GξT00I]+FG′uΣuG′uTFT=[GξΣxxGξT(GξΣxm)TGξΣxmΣmm]+FG′uΣuG′uTFT
可以看出,运动更新同时影响了机器人位姿的协方差,以及位姿与地图之间的协方差。
2. 测量模型
首先解决测量值的问题。虽然可以获得ArUco码相对于机器人的6自由度位姿信息,但是为了与书上的观测统一,本文还是把相机作为Range-bearing传感器使用,也就是转换成距离r和角度ϕ。1个ArUco码作为一个路标点 m ,坐标为 [mxmy]T。
先说一下如何转化成距离和角度。下图是示意图,码与相机的相对位姿为mcT,相机与机器人的相对位姿为 crT ,那么码相对于机器人的位姿为 mrT=crTmcT 。mrT的平移项x和 y 就是码的原点在机器人坐标系下的坐标。转化成距离信息就是r=x2+y2,角度就是 ϕ=atan2(y,x) 。这样就得到了测量值z=[rϕ]T。这里再做一个近似假设,认为观测的方差与距离和角度成线性关系:
Q=[∥krr∥2∥kϕϕ∥2] (10)

第 i 个路标点的观测模型为:
zti=h(Xt)+δti,δt∼N(0,Qt) (11)
展开来看:
{rti=(mx,i−x)2+(my,i−y)2ϕti=atan2(my,i−y, mx,i−x)−θ (12)
根据扩展卡尔曼滤波,需要求解观测 zti 相对于Xt的雅克比Hti,实际上一个路标点观测只涉及到机器人的位姿和这个路标点的坐标,组合在一起就是五个量: ν=[xyθmx,imy,i] 。于是,观测zti相对于ν的雅克比是:
Hν=∂ν∂h=q1[−qδxδy−qδy−δx0−qqδx−δyqδyδx]({δx=mx,i−xδy=my,i−yq=δx2+δy2) (13)
由于实际的状态空间是3+2N维的,要求的观测雅克比应该是2x(3+2N)维的。对(13)进行转换得到观测zti相对于全状态空间 Xt 的雅克比:
Hti=HνFi=q1[−qδxδy−qδy−δx0−qqδx−δyqδyδx]1000001000001000⋯00⋯00⋯00⋯02i−20⋯000010000010⋯00⋯00⋯00⋯02N−2i0⋯0 (14)
下面就可以按照EKF的框架进行操作了。
Kti=ΣtHtiT(HtiΣtHtiT+Qt)−1μt=μˉt+Kti(zti−z^ti)Σt=(I−KtiHti)Σt
其中,
z^ti=[(mˉx,i−xˉ)2+(mˉy,i−yˉ)2atan2(mˉy,i−yˉ, mˉx,i−xˉ)−θˉ] (16)
就是由路标点和机器人位姿的均值获取。对每个观测到的路标点进行上述操作就完成了观测更新。
3. 地图构建
上文所说的操作都是假设路标点的数量是已知的,这个值也可以认为是不知道的,可以边运行边加入路标点:当看到一个新的地图点时就扩展状态空间和协方差。当观测到一个新的路标点,其观测为z=[rϕ]T,根据机器人的位姿可以计算地图点的坐标为:
[mxmy]=[cos(θ)sin(θ)−sin(θ)cos(θ)][rcos(ϕ)rsin(ϕ)]+[xy]=r[cos(θ+ϕ)sin(θ+ϕ)]+[xy] (17)
3.1 新地图点的协方差
地图点的协方差为:
Σm=GpΣξGpT+GzQGzT (18)
Gp 是(17)式关于机器人位姿的雅克比: Gp=[1001−rsin(θ+ϕ)rcos(θ+ϕ)] (19) Gz 是(17)式关于观测 z 的雅克比: Gz=[cos(θ+ϕ)sin(θ+ϕ)−rsin(θ+ϕ)rcos(θ+ϕ)] (20)
3.2 新地图点与原状态之间的协方差
下面,还需要计算新加入的状态(地图点)与原状态(1个机器人位姿+N个地图点)之间的协方差。
Σmx=GfxΣt
Σt为原状态的协方差矩阵,Gfx 为(17)式相对于原状态的雅克比矩阵:
Gfx = [1001−rsin(θ+ϕ)rcos(θ+ϕ)00⋯⋯00]
通过以上各式,算出新路标的均值和协方差,以及新路标与原状态的协方差。加入到均值向量和协方差矩阵中即可。协方差的扩展如下图所示。
协方差扩展
至此,EKF算法中所有的模型都已建立完毕。下面给出具体的实施代码。
4. 算法实现
https://github.com/ydsf16/aruco_ekf_slam
- 我利用Falconbot机器人,采集了两组实验数据,大家可以在这里下载:
https://pan.baidu.com/s/1EX9CYmdEUR2BJh7v5dTNfA
5. 参考文献
《概率机器人》
《自主移动机器人导论》
Freiburg SLAM Course:
http://ais.informatik.uni-freiburg.de/teaching/ws13/mapping/