资讯详情

基于扩展卡尔曼滤波的多传感器融合定位

基于扩展卡尔曼滤波器的多传感器集成定位

??根据本文,多传感器集成是一个复杂的问题ROS中的robot localization功能包解释了多传感器集成定位的实现。

卡尔曼滤波

??卡尔曼滤波器并不复杂,分为预测和更新两部分: ??预测: X ^ k 1 = A X ^ k ? 1 B u k P k 1 = A P k ? 1 A T Q \hat{X}_{k}^{1} =A\hat{X}_{k-1} Bu_{k}\\ P_{k}^{1}=AP_{k-1}A^{T} Q X^k1=AX^k?1 BukPk1​=APk−1​AT+Q   更新: K k = P k 1 H T H P k 1 H T + R X ^ k = X ^ k 1 + K k ( Z k − H X ^ k 1 ) P k = ( I − K k H ) P k 1 K_{k}=\frac{P_{k}^{1}H^{T}}{HP_{k}^{1}H^{T}+R}\\ \hat{X}_{k}=\hat{X}_{k}^{1}+K_{k}(Z_{k}-H \hat{X}_{k}^{1})\\ P_{k}=(I-K_{k}H)P_{k}^{1} Kk​=HPk1​HT+RPk1​HT​X^k​=X^k1​+Kk​(Zk​−HX^k1​)Pk​=(I−Kk​H)Pk1​   在实际使用卡尔曼滤波时,第一是确定状态变量和控制变量,一般在机器人定位中,8个状态变量 [ x , y , θ , v x , v y , ω , a x , a y ] [x,y,\theta,v_{x},v_{y},\omega,a_{x},a_{y}] [x,y,θ,vx​,vy​,ω,ax​,ay​]都可以看成是状态变量,也可以把加速度看成是控制变量,得到加速度的方法可以通过上一篇文章讲的动力学控制中得到,也可以通过速度做差分。如果是都看成状态变量,那么加速度的更新是通过更新步的第二个式子进行更新,预测步的第一个式子是无法更新加速度的,只会保留加速度。   第二个问题是,状态变量的选取,一般来说定位是机器人在地图上的定位,使用的是世界坐标系,即 [ x , y , θ ] [x,y,\theta] [x,y,θ]是世界坐标系下的变量,而速度、角速度、加速度等都是通过传感器计算得到的,是机器人坐标系下的变量。从机器人坐标系转到世界坐标系需要通过旋转变换,即会引入三角函数,这样状态方程就是非线性的了,因此需要使用扩展卡尔曼滤波,这时公式需要做修改, A A A矩阵为雅可比矩阵 x k 1 = f ( x ^ k − 1 , u k ) z = h ( x k ) H = ∂ h ∂ x k ∣ x ^ k 1 , A = ∂ f ∂ x k − 1 ∣ x ^ k − 1 1 x_{k}^{1}=f(\hat{x}_{k-1},u_{k})\\ z=h(x_{k})\\ H=\frac{\partial h}{\partial x_{k}}|_{\hat{x}_{k}^{1} },A=\frac{\partial f}{\partial x_{k-1}}|_{\hat{x}_{k-1}^{1} } xk1​=f(x^k−1​,uk​)z=h(xk​)H=∂xk​∂h​∣x^k1​​,A=∂xk−1​∂f​∣x^k−11​​例如: 在这里插入图片描述

  第三个问题是 P 0 , Q , R P_{0},Q,R P0​,Q,R矩阵应该如何选取。首先是 R R R矩阵,测量噪声协方差矩阵,一般是传感器的测量噪声,常用的传感器有IMU,激光雷达,摄像头,编码器等,网上都有常用的噪声协方差矩阵,这个不难找。然后是 P 0 P_{0} P0​和 Q Q Q,初始的先验误差协方差矩阵和过程噪声矩阵,这个可以参考一些论文或开源的ekf包,里边有。本文参考的robot localization中,这两个矩阵为:

这里的矩阵是15维的: [ x , y , z , r o l l , p i t c h , y a w , v x , v y , v z , θ r o l l , θ p i t c h , θ y a w , a x , a y , a z ] [x,y,z,roll, pitch, yaw, v_{x}, v_{y}, v_{z}, \theta_{roll}, \theta_{pitch}, \theta_{yaw}, a_{x}, a_{y}, a_{z}] [x,y,z,roll,pitch,yaw,vx​,vy​,vz​,θroll​,θpitch​,θyaw​,ax​,ay​,az​]

多传感器融合

  多传感器融合是一个复杂的方向,具体可以分为紧耦合和松耦合两种融合方式。紧耦合是将各传感器的数据汇总,然后计算出一个位姿,松耦合是各传感器的数据分别计算出一个位姿,然后再进行汇总得到最终位姿。这么说好像有点不太直观,总之紧耦合的特点是各传感器的数据需要同步,而松耦合的传感器是异步的,不需要同步。robot localization功能包中的EKF是松耦合的融合方式。   多传感器融合的第一个问题是数据处理,由于robot localization包是松耦合的方式,因此对每一个传感器数据单独进行处理。ROS中的协方差矩阵分为三类,位姿、速度和加速度,因此所有传感器的原始数据也会拆分成这三类。举例平面机器人如下:   编码器里程计可以计算位置和速度,使用 [ θ , v x , v y ] [\theta,v_{x},v_{y}] [θ,vx​,vy​]数据进行融合,首先先对一个传感器的数据进行分类, θ \theta θ是一组, v x , v y v_{x},v_{y} vx​,vy​是一组,前者是pose类型的数据,后者是twist类型的数据,处理pose时,将角度值和其协方差放入一个结构体中,作为其中一组测量数据;处理twist时,将两个速度和对应的协方差矩阵放入另一个结构体中,作为另一组测量数据。   数据处理完后进行卡尔曼滤波,预测步没啥好说的,在更新步中,由于第一组测量数据只有角度值,因此进行更新时只更新角度值,即H矩阵只在角度对应的行,斜对角线上的值为1,其余为0。更新完角度后,协方差矩阵P更新,然后不进行预测了,因为都是同一个时间戳的数据,继续更新速度,H矩阵的值改一下,进行第二次更新。

robot localization功能包运行原理

  该功能包分为主函数和传感器数据接收回调函数两个线程。   主函数部分:首先是ekf_localization_node.cpp下的main函数:看代码没啥好说的吧,然后进入这个ekf.run()函数。

int main(int argc, char **argv)
{ 
        
ros::init(argc, argv, "ekf_navigation_node"); //创建节点

RobotLocalization::RosEkf ekf;//类

ekf.run();//进入这个函数

return EXIT_SUCCESS;
}

  ekf.run()这个函数在ros_filter.cpp下1742行(行数可能不一样,因为我的robot localization包原代码被我修改过,但大概就是上下几行)。这个函数中第一个重要的部分就是,这个是读取参数,具体读了什么,可以进去看看,主要是你ekf_params.yaml这里设置的内容。注意这里加载了参数后,回调函数就开始起作用了,具体的内容放后边说。

loadParams();

  然后下边就是发布者,tf变换啥的,tf变换是把测量数据从一个坐标系变换到另一个坐标系,还有打印一些东西,主要是让你知道的程序为什么报错的,我们直接忽略,接下来是时间。时间的问题在该包中十分重要,这里是获取当前时间戳,ROS的传感器消息都自带时间戳,储存在header中。

ros::Time curTime;
ros::Time lastDiagTime = ros::Time::now();

  以上是初始化的一部分内容,然后就进入死循环进行不断的更新和预测了。接下来先说说回调函数的内容。   回调函数,说的是接收到传感器数据后进入回调处理的过程。具体的处理方式函数在ros_filter.h 105行的类中有详细的说明,这里列一部分比较有用的。

template<class T> class RosFilter
{ 
        
    /*控制量回调:这部分就是前文讲的,将加速度看成是控制量还是状态变量, 如果是看成控制量,那就会根据速度差分的方法计算加速度,同时也会加载 最大最小加速度限制、加加速度限制的相关参数,该包默认是不使用控制量。*/
    void controlCallback(const geometry_msgs::Twist::ConstPtr &msg);
    void controlCallback(const geometry_msgs::TwistStamped::ConstPtr &msg);

    /*三种类型数据的回调处理,这里和前文说的差不多,但是除了测量值和协 

标签: at三维激光传感器传感器kin0280217518传感器tftf14传感器pk1接近传感器sc1204hpk无功功率变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台