💥💥💞💞欢迎来到本博客❤️❤️💥💥
🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。
⛳️座右铭:行百里者,半于九十。
📋📋📋本文目录如下:🎁🎁🎁
目录
⛳️赠与读者
👨💻做科研,涉及到一个深在的思想系统,需要科研者逻辑缜密,踏实认真,但是不能只是努力,很多时候借力比努力更重要,然后还要有仰望星空的创新点和启发点。当哲学课上老师问你什么是科学,什么是电的时候,不要觉得这些问题搞笑。哲学是科学之母,哲学就是追究终极问题,寻找那些不言自明只有小孩子会问的但是你却回答不出来的问题。建议读者按目录次序逐一浏览,免得骤然跌入幽暗的迷宫找不到来时的路,它不足为你揭示全部问题的答案,但若能让人胸中升起一朵朵疑云,也未尝不会酿成晚霞斑斓的别一番景致,万一它居然给你带来了一场精神世界的苦雨,那就借机洗刷一下原来存放在那儿的“躺平”上的尘埃吧。
或许,雨过云收,神驰的天地更清朗.......🔎🔎🔎
💥1 概述
从可观测性角度研究基于扩展卡尔曼滤波器(EKF)的同时定位与地图构建(SLAM)中的不一致性问题研究
摘要
本文从可观测性的角度研究了基于扩展卡尔曼滤波器(EKF)的同时定位与地图构建(SLAM)中的不一致性问题。我们通过分析证明,当过程和测量模型的雅可比矩阵在每个时间步骤中根据最新的状态估计值进行评估时,EKF中使用的线性化误差状态系统具有比实际非线性SLAM系统更高维度的可观测子空间。因此,EKF的协方差估计在状态空间中无信息可用的方向上会减小,这是不一致性的主要原因之一。基于这些理论结果,我们提出了一个改进EKF SLAM一致性的通用框架。在这个框架中,EKF的线性化点被选择以确保得到的线性化系统模型具有适当维度的可观测子空间。我们描述了两种算法,它们是这一范式的实例。第一种算法称为可观测性约束(OC)-EKF,其选择线性化点以最小化它们的预期误差(即线性化点与真实状态之间的差异),并满足可观测性约束。第二种算法中,滤波器的雅可比矩阵使用所有状态变量的第一次可用估计进行计算。这种方法称为第一估计雅可比矩阵(FEJ)-EKF。提出的算法经过了仿真和实验测试,显示出在准确性和一致性方面明显优于标准EKF。
关键词:同时定位与地图构建,非线性估计,扩展卡尔曼滤波器,线性化误差,估计器不一致性,可观测性
扩展卡尔曼滤波器(EKF)作为SLAM领域的经典算法,因计算效率高被广泛应用。然而,EKF-SLAM在处理非线性系统时存在固有的不一致性问题,表现为估计协方差矩阵系统性低估真实误差,导致滤波器对自身估计过于自信。这种不一致性会降低定位精度和地图质量,甚至引发系统发散。本文从可观测性理论出发,深入剖析EKF-SLAM不一致性的根本原因,提出改进策略,并通过仿真验证改进算法的有效性。
1. 引言
SLAM技术是移动机器人自主导航的核心,其目标是在未知环境中实时构建地图并确定自身位姿。EKF凭借其相对简单的计算过程和较低的计算复杂度,成为早期SLAM系统中的主流算法。然而,EKF-SLAM算法基于线性化假设,当系统具有显著的非线性特性时,线性化误差会逐渐累积,导致机器人姿态估计和地图构建结果出现偏差,甚至发散,最终引发严重的不一致性问题。
2. EKF-SLAM基本原理与不一致性机制
2.1 EKF-SLAM概述
EKF-SLAM将机器人位姿和环境中观测到的特征点状态作为状态向量的一部分进行估计。系统模型包括运动模型和观测模型:
- 运动模型:描述机器人位姿随时间的变化规律,通常采用匀速或匀加速运动模型。
- 观测模型:描述传感器观测值与机器人位姿及地图特征之间的关系,例如激光雷达的测距和测角模型。
2.2 不一致性产生机制
EKF-SLAM的不一致性主要源于以下因素:
- 线性化误差:EKF通过一阶泰勒展开将非线性系统近似为线性系统,这种近似在系统高度非线性或估计误差较大时引入显著误差,导致协方差矩阵低估真实误差。
- 数据关联错误:错误的观测数据与地图特征点匹配会导致状态估计和协方差错误更新,加剧不一致性。
- 特征初始化不准确:新观测到的特征点初始化误差会扩散到整个状态向量,影响后续估计。
3. 可观测性对EKF-SLAM一致性的影响
3.1 可观测性理论
可观测性描述了从系统输出中推断系统内部状态的能力。对于EKF-SLAM而言,良好的可观测性是确保一致性估计的前提。
3.2 机器人轨迹的可观测性
- 直线运动或纯旋转运动:若缺少足够的特征点观测,机器人位姿可能存在退化,导致轨迹可观测性不足。
- 特征点分布:特征点分布稀疏或对称时,机器人位姿估计的唯一性受到影响,降低可观测性。
3.3 地图特征的可观测性
- 观测视角:特征点仅被短暂观测或观测视角变化不大时,其位置估计精度较低,影响地图一致性。
- 多视角观测:通过多视角观测提高特征点位置的可观测性,可减少初始化误差。
4. 解决EKF-SLAM不一致性问题的策略
4.1 改进线性化方法
- 高阶泰勒展开:采用更高阶的泰勒展开减少线性化误差,但计算复杂度增加。
- 无迹卡尔曼滤波(UKF):使用确定性采样点(sigma points)近似非线性函数的均值和协方差,避免雅可比矩阵计算,减少线性化误差。
- 容积卡尔曼滤波(CKF):采用球面-径向容积规则选择采样点,在某些情况下性能优于UKF。
4.2 改进数据关联方法
- 多假设跟踪(MHT):考虑多个数据关联假设,使用概率评估可能性,通过延迟决策减少错误关联风险。
- 动态调整门限:根据不确定性动态调整数据关联门限,降低错误关联概率。
- 鲁棒特征描述子:使用更具辨识度的特征描述子,降低相似特征点混淆风险。
4.3 基于子地图的SLAM
- 子地图划分:将地图划分为多个子地图,分别进行SLAM,再进行全局融合,减少计算量并提高精度。
- 局部一致性保障:在子地图内部保障一致性,减少全局不一致性传播。
4.4 可观测性约束方法
- 可观测性约束EKF(OC-EKF):选择线性化点以满足可观测性约束,减少协方差低估。
- 第一估计雅可比矩阵EKF(FEJ-EKF):使用所有状态变量的第一次可用估计计算雅可比矩阵,避免协方差矩阵膨胀。
5. 仿真验证与结果分析
5.1 仿真环境设置
- 机器人模型:采用两轮差速驱动机器人模型,运动模型为匀速模型。
- 传感器模型:激光雷达模型,包含测距和测角噪声。
- 环境设置:包含多个特征点的二维平面环境,特征点分布均匀。
5.2 算法实现
- 标准EKF:实现标准EKF-SLAM算法,作为基准对比。
- FEJ-EKF:实现第一估计雅可比矩阵EKF,改进线性化点选择。
- UKF-SLAM:实现无迹卡尔曼滤波SLAM,避免线性化误差。
5.3 仿真结果
- 定位精度:FEJ-EKF和UKF-SLAM的定位精度显著高于标准EKF,尤其在长时间运行后。
- 地图一致性:FEJ-EKF和UKF-SLAM构建的地图特征点位置误差更小,地图一致性更高。
- 协方差估计:标准EKF的协方差矩阵系统性低估真实误差,而FEJ-EKF和UKF-SLAM的协方差估计更接近真实值。
6. 结论与展望
6.1 研究结论
本文从可观测性角度深入分析了EKF-SLAM中的不一致性问题,提出FEJ-EKF和UKF-SLAM等改进方法。仿真结果表明,改进算法显著提高了定位精度和地图一致性,验证了可观测性约束和改进线性化方法的有效性。
6.2 未来展望
- 多传感器融合:结合视觉、激光、IMU等多种传感器信息,提高SLAM系统的鲁棒性和精度。
- 深度学习应用:利用深度学习技术提高地图匹配和数据关联精度,解决不一致性问题。
- 分布式SLAM:针对大型环境,研究分布式SLAM算法,提高效率和鲁棒性。
📚2 运行结果
部分代码:
sigma_v = sigma/sqrt(2); %.1*v_true; %
sigma_w = 2*sqrt(2)*sigma; %.1*omega_true; 1*pi/180; %
Q = diag([sigma_v^2 sigma_w^2]);
sigma_p = .1; %noise is the percentagae of distance measurement, BUT double check rws.m since sometimes we use this as a constant absolute sigma
sigma_r = 1; %range measmnt noise
sigma_th = 10*pi/180;%bearing measuremnt noise
nL = 20; %number of landmarks
nSteps = 2500; %nubmer of time steps
nRuns = 5; %number of monte carlo runs
if nL==1
max_range = 200;%always observe this landmark
else
max_range = 5;%env_size/10;%.5*v_true/omega_true;%
end
min_range = .5;
init_steps = 0;%3
max_delay = 10;%for delayed initial
NIncr = 0; %increment number of incremental MAP: 0 - not runing
%% preallocate memory for saving resutls
% Ideal EKF
xRest_id = zeros(3,nSteps,nRuns); %estimated traj
xRerr_id = zeros(3,nSteps,nRuns); %all err state
Prr_id = zeros(3,nSteps,nRuns); %actually diag of Prr
neesR_id = zeros(1,nSteps,nRuns); %nees (or mahalanobis distance)
rmsRp_id = zeros(1,nSteps,nRuns); %rms of robot position
rmsRth_id = zeros(1,nSteps,nRuns); %rms of robot orientation
xLest_id = zeros(2,nL,nSteps,nRuns);
xLerr_id = zeros(2,nL,nSteps,nRuns);
Pll_id = zeros(2,nL,nSteps,nRuns);
neesL_id = zeros(1,nL,nSteps,nRuns);
rmsL_id = zeros(1,nL,nSteps,nRuns);
nees_id = zeros(1,nSteps,nRuns); %nees for the whole state
% Standard EKF
xRest_std = zeros(3,nSteps,nRuns); %estimated traj
xRerr_std = zeros(3,nSteps,nRuns); %all err state
Prr_std = zeros(3,nSteps,nRuns); %actually diag of Prr
neesR_std = zeros(1,nSteps,nRuns); %nees (or mahalanobis distance)
rmsRp_std = zeros(1,nSteps,nRuns); %rms of robot position
rmsRth_std = zeros(1,nSteps,nRuns); %rms of robot orientation
xLest_std = zeros(2,nL,nSteps,nRuns);
xLerr_std = zeros(2,nL,nSteps,nRuns);
Pll_std = zeros(2,nL,nSteps,nRuns);
neesL_std = zeros(1,nL,nSteps,nRuns);
rmsL_std = zeros(1,nL,nSteps,nRuns);
nees_std = zeros(1,nSteps,nRuns); %nees for the whole state
kld_std = zeros(1,nSteps,nRuns); % KLD
% FEJ-EKF
xRest_fej = zeros(3,nSteps,nRuns); %estimated traj
xRerr_fej = zeros(3,nSteps,nRuns); %all err state
Prr_fej = zeros(3,nSteps,nRuns); %actually diag of Prr
neesR_fej = zeros(1,nSteps,nRuns); %nees (or mahalanobis distance)
rmsRp_fej = zeros(1,nSteps,nRuns); %rms of robot position
rmsRth_fej = zeros(1,nSteps,nRuns); %rms of robot orientation
xLest_fej = zeros(2,nL,nSteps,nRuns);
xLerr_fej = zeros(2,nL,nSteps,nRuns);
Pll_fej = zeros(2,nL,nSteps,nRuns);
neesL_fej = zeros(1,nL,nSteps,nRuns);
rmsL_fej = zeros(1,nL,nSteps,nRuns);
nees_fej = zeros(1,nSteps,nRuns); %nees for the whole state
kld_fej = zeros(1,nSteps,nRuns); % KLD
% OC-EKF
xRest_ocekf_1 = zeros(3,nSteps,nRuns); %estimated traj
xRerr_ocekf_1 = zeros(3,nSteps,nRuns); %all err state
Prr_ocekf_1 = zeros(3,nSteps,nRuns); %actually diag of Prr
neesR_ocekf_1 = zeros(1,nSteps,nRuns); %nees (or mahalanobis distance)
rmsRp_ocekf_1 = zeros(1,nSteps,nRuns); %rms of robot position
rmsRth_ocekf_1 = zeros(1,nSteps,nRuns); %rms of robot orientation
xLest_ocekf_1 = zeros(2,nL,nSteps,nRuns);
xLerr_ocekf_1 = zeros(2,nL,nSteps,nRuns);
Pll_ocekf_1 = zeros(2,nL,nSteps,nRuns);
neesL_ocekf_1 = zeros(1,nL,nSteps,nRuns);
rmsL_ocekf_1 = zeros(1,nL,nSteps,nRuns);
nees_ocekf_1 = zeros(1,nSteps,nRuns); %nees for the whole state
kld_ocekf_1 = zeros(1,nSteps,nRuns); % KLD
%% LANDMARK GENERATION: same landmarks in each run
if nL==1
xL_true_fixed = [0;v_true/omega_true];
elseif nL==2
xL_true_fixed = [5 -5; 5 15];
else
xL_true_fixed = gen_map(nL,v_true,omega_true,min_range, max_range, nSteps,dt);%max_range=5
end
%% Monte Carlo Simulations
tic
for kk = 1:nRuns
kk
% % real world simulation data % %
xL_true(:,:,kk) = xL_true_fixed;
[v_m,omega_m, v_true_all,omega_true_all, xR_true(:,:,kk), z,R] = rws(nSteps, dt,v_true,omega_true,sigma_v,sigma_w,sigma_r,sigma_th,sigma_p,xL_true(:,:,kk),max_range,min_range);
% % INITIALIZATION
x0 = zeros(3,1);
if init_steps
P0 = zeros(3);
else
P0 = diag([(.0001)^2,(.0001)^2,(.0001)^2]);
end
for k=1:init_steps
[x0,P0] = propagate_std(x0,P0,dt,v_m(k),omega_m(k),sigma_v,sigma_w);
end
% Ideal EKF
xe_id = x0;
Pe_id = P0;
V_id = [];
% Standard EKF
xe_std = x0;
Pe_std = P0;
V_std = [];
% FEJ-EKF
xe_fej = x0;
Pe_fej = P0;
xL_fej_1 = [];
xR_fej_k_k1 = xe_fej(1:3,1);
PHI_mult_fej = eye(1); %propagation jacobian product
V_fej = [];
% OC-EKF
xe_ocekf_1 = x0;
Pe_ocekf_1 = P0;
xL_ocekf_1_1 = [];
xR_oc_k_k1_1 = xe_ocekf_1(1:3,1);
dpR_star_prev_1 = zeros(2,1);
pR_star_prev = x0(1:2,1);
dpR_ocekf_1 = zeros(2,1);
V_ocekf_1 = [];
PHI_mult_ocekf_1 = eye(1);
lambda_1 = zeros(2,nL);
% list of landmark ids that sequentially appear in the state vector
lm_seq_id = [];
lm_seq_std = [];
lm_seq_fej = [];
lm_seq_ocekf_1 = [];
🎉3 参考文献
文章中一些内容引自网络,会注明出处或引用为参考文献,难免有未尽之处,如有不妥,请随时联系删除。
🌈4 Matlab代码、文章
资料获取,更多粉丝福利,MATLAB|Simulink|Python资源获取