odom&imu融合用于Cartographer建图

任务动机:使用odom&imu融合用于Cartographer建图,提高Cartographer建图时的匹配精度,同时降低运算消耗。

任务描述:使用odom&imu融合用于Cartographer建图,实验对比验证融合对建图匹配精度的影响。

1. odom的作用

        里程计是记录机器人与起始位置相对pose的模块,同时它还提供了机器人实时的线速度、角速度以及这些状态量的不确定性。一个精准的里程计对于建图和定位性能的提高有着重要作用。它不仅可以提供先验位姿,提高建图时的匹配精度,还可以降低运算消耗。

2. 原始odom

2.1 航迹推演

        以平面轮式移动机器人为例,通常会在机器人的每个轮子上安装编码器,它可以记录轮子转动的角度。在此基础上,结合机器人的轮子半径就可以计算出轮子的线速度,再使用轮间距进而计算得到机器人的速度和角速度。使用该速度在较短时间dt内进行积分即可以得到机器人在该dt内的运动累积[1]。如图1所示,记Vr,Vr分别为左右轮的线速度,V为机器人底盘的线速度,W为机器人底盘的角速度,l为机器人底盘的轮间距,r为机器人的运动半径。

图1(来自参考文献1)
图1(来自参考文献1)

        可以得到以下关系:

图2(来自参考文献1)

2.2 弊端

        单纯地使用编码器和底盘参数进行航迹推演,由于经过了多层的递进,过程中必然会累积较多的误差,随着时间的积累,里程计的积累误差会越来越大。如图3是使用激光slam建图得到的机器人真实路线(紫)和编码器里程计的路线(红)。

图3

2.3 融合imu

        在里程计航迹推演的误差中,航向角的误差是影响较为严重的一项。原因在于它不仅体现了机器人的朝向,还影响着机器人坐标(x,y)的计算。因此计算出一个比较精准的角度信息对于提高里程计的准确度来说至关重要。IMU可以提供较为准确的角度和角速度,因此一种提高里程计准确度的思路是将IMU和编码器里程计融合。EKF(扩展卡尔曼滤波)是一种较为常见的传感器融合方法。

3. EKF

        卡尔曼滤波(Kalman filtering)是一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。由于观测数据中包括系统中的噪声和干扰的影响,所以最优估计也可看作是滤波过程。数据滤波是去除噪声还原真实数据的一种数据处理技术,Kalman滤波在测量方差已知的情况下能够从一系列存在测量噪声的数据中,估计动态系统的状态。[2]

        首先要计算预测值、预测值和真实值之间误差协方差矩阵。下式中,是k时刻系统状态的预测,A是状态转移矩阵,B控制矩阵,uk-1是控制量。是k时刻系统的状态最终的估计结果。P’k是K时刻机器人状态的不确定性的预测,Pk-1是k-1时刻机器人的不确定性,Q是状态转移过程中引入的不确定性。

        有了这两个就能计算卡尔曼增益K,再然后得到估计值,其中H是观测矩阵,指的是观测量和状态量之间的关系,R是指观测时引入的不确定性。

        最后还要计算估计值和真实值之间的误差协方差矩阵,为下次递推做准备。

        由于卡尔曼滤波只适用于线性系统,而很多待估计的场景都是非线性的,比如我们常见的机器人运动模型,其运动数学模型符合牛顿第二定律:Xt+1=Vt+1/2*a*t2,另外航迹推演部分还包含了求正弦余弦的部分,因此其模型是非线性的,需要对此模型进行线性化的近似。

ROS&EKF:ROS navigation stack中集成了使用ekf融合里程计和imu的package。

3.1 robot_pose_ekf

        robot_pose_ekf是最初的ekf融合package,但由于代码可读性差、可扩展性差以及使用不方便,已经被robot_localization替代了。

3.2 robot_localization

        https://github.com/cra-ros-pkg/robot_localization

        相比robot_pose_ekf,robot_localization支持更多的传感器类型,支持更多的传感器数量,不仅使用方便,而且代码结构清爽,可读性强。

3.3 安装

1. 安装ros-kinetic-geographic-msgs

sudo apt-get install ros-kinetic-geographic-msgs
sudo apt-get remove --purge geographiclib-doc geographiclib-tools

2. 下载 https://sourceforge.net/projects/geographiclib/  并cmake 安装(默认路径usr/local)

3. 改写robot_localization的CMakeLists.txt

# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/usr/share/cmake/geographiclib/")                   
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "/usr/local/share/cmake/GeographicLib/")

find_package(GeographicLib REQUIRED COMPONENTS STATIC) 中的STATIC去掉

4. catkin_make

3.4 使用

1. 准备好要融合的数据

1.1 由编码器和底盘参数推演得到的odom

1.1.1 odom数据的格式为nav_msgs/Odometry

1.1.2 协方差矩阵的配置:用户可以在完成航迹推演后,在地面上设定一定的长度,控制机器人行走该长度然后读取odom的推演结果,多次实验然后统计数据,得到odom的不确定性。

1.2 imu数据

1.2.1 imu的数据格式为ensor_msgs/Imu

1.2.2 一般imu模块厂商会在驱动中给出imu的协方差,因此不需要用户自己统计

1.2.3 发布imu的tf:imu在车身上的位置要以静态tf的形式发布出来,子坐标系为imu的topic中的frame_id。

2. 配置yaml

        以ekf_template.yaml为例

frequency: 30 #表示状态更新的频率

silent_tf_failure: false

sensor_timeout: 0.1

#我们使用的是2d车,因此开启2d模式

two_d_mode: true

transform_time_offset: 0.0

transform_timeout: 0.0

print_diagnostics: true

debug: false

debug_out_file: /path/to/debug/file.txt

publish_tf: false

publish_acceleration: false

#我们只用此package来融合odom和imu作为更准的odom,因此world_frame配置为 odom,将map_frame注释掉。如果在地图中定位,那map_frame就配成map,world也配成map,如果在地球上定位,那map_frame就配成map,world配成world。

#map_frame: map                  # Defaults to "map" if unspecified

odom_frame: odom                 # Defaults to "odom" if unspecified

base_link_frame: base_footprint  # Defaults to "base_link" if unspecified

world_frame: odom                # Defaults to the value of odom_frame if unspecified

odom0: /odom

# values is x, y, z, roll, pitch, yaw, vx, vy, vz, vroll, vpitch, vyaw, ax, ay, az.

建议:

  • 如果里程计同时提供位置(Position)和线速度(Linear Velocities),就将线速度信息融合进来。
  • 如果里程计同时提供方向(Orentation)和角速度(Angular Velocties),就将方向信息融合进来。

        实测证实确实如此。如果底盘航迹推演的position和odom速度角速度都来自同一个传感器:编码器,因此不适合都用上。

odom0_config: [false,  false,  false,

                              false, false, true,

                             true, true, false, #y的速度肯定是0,所以他是个挺好的观测数据,用上也不错

                              false, false, false,

       false, false, false]

odom0_queue_size: 2

odom0_nodelay: false

#differential :比如有两个传感器,他们都带有朝向信息,但是相差比较多,这时候我们可以用比较准的那个。而剩下的那个传感器就把differential模式打开,意思是用这个朝向结合delta_t计算出速度再用上。由于imu的朝向角比编码器积分得到的角度准很多,因此我们融合imu的yaw,odom的yaw作为速度使用。

odom0_differential: true

#不管odom自身的pose相关的数值是多少,我们的用法都是和第一帧数据的相对值

odom0_relative: true

odom0_pose_rejection_threshold: 5

odom0_twist_rejection_threshold: 1

imu0: /imu

imu0_config: [false, false, false,

             false, false,  true,

             false, false, false,

             false,  false,  true,

             true,  false,  false]

imu0_nodelay: false

imu0_differential: true

#应该打开。机器人上电时刻应为0

imu0_relative: true  

imu0_queue_size: 5

imu0_pose_rejection_threshold: 0.8                 # Note the difference in parameter names

imu0_twist_rejection_threshold: 0.8                #

imu0_linear_acceleration_rejection_threshold: 0.8  #

imu0_remove_gravitational_acceleration: true

use_control: false

stamped_control: false

control_timeout: 0.2

control_config: [true, false, false, false, false, true]

acceleration_limits: [1.3, 0.0, 0.0, 0.0, 0.0, 3.4]

deceleration_limits: [1.3, 0.0, 0.0, 0.0, 0.0, 4.5]

acceleration_gains: [0.8, 0.0, 0.0, 0.0, 0.0, 0.9]

deceleration_gains: [1.0, 0.0, 0.0, 0.0, 0.0, 1.0]

process_noise_covariance: [0.1, 0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0.1, 0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0.1, 0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0.1, 0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0.1, 0,    0,     0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0.1, 0,     0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0.1, 0,     0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0.1, 0,    0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0.1, 0,    0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0,    0.1, 0,    0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0.1, 0,    0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0.1, 0,    0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0.1, 0,    0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0.1, 0,

                          0,    0,    0,    0,    0,    0,    0,     0,     0,    0,    0,    0,    0,    0,    0.1]

initial_estimate_covariance: [1e-9, 0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,

                             0,    1e-9, 0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,

                             0,    0,    1e-9, 0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,

                             0,    0,    0,    1e-9, 0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    0,

                             0,    0,    0,    0,    1e-9, 0,    0,    0,    0,    0,     0,     0,     0,    0,    0,

                             0,    0,    0,    0,    0,    1e-9, 0,    0,    0,    0,     0,     0,     0,    0,    0,

                             0,    0,    0,    0,    0,    0,    1e-9, 0,    0,    0,     0,     0,     0,    0,    0,

                             0,    0,    0,    0,    0,    0,    0,    1e-9, 0,    0,     0,     0,     0,    0,    0,

                             0,    0,    0,    0,    0,    0,    0,    0,    1e-9, 0,     0,     0,     0,    0,    0,

                             0,    0,    0,    0,    0,    0,    0,    0,    0,    1e-9,  0,     0,     0,    0,    0,

                             0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     1e-9,  0,     0,    0,    0,

                             0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     1e-9,  0,    0,    0,

                             0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     1e-9, 0,    0,

                             0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    1e-9, 0,

                             0,    0,    0,    0,    0,    0,    0,    0,    0,    0,     0,     0,     0,    0,    1e-9]

3.5 融合实验效果

参数\融合效果\融合对象

odom

结论:角度只用imu的,可见首尾交错了,也不是很准。

结论:角度用imu和odom的融合,效果比较好。

结论:imu的vyaw作用不大。

        以得出结论,角度用imu和odom的融合,效果比较好。跟原始的odom相比,融合后的odom可以首尾接近相连,相比直接只使用编码器得到的里程计准确了很多。

4. 融合的odom用于cartographer建图

4.1 用于前端

        以Cartographer为例,cartographer中使用三种数据源去做位姿预估:odom、imu、匹配的pose。当使用纯激光建图时,某时刻预估的pose本身就依赖于前几个关键帧的pose,它由前几个pose的首尾之差除以时间计算得来。假如前几个关键帧的pose是错误的话,那么会恶性循环地影响匹配定位。例如,机器人在一个长走廊环境中,由于激光观测到的特征不够丰富,激光帧间匹配会容易形成定位停留在原地的现象。如图所示。

        不使用odom且激光特征不丰富时:

        使用odom进行位姿预测:

4.2 用于后端

        Cartographer中还将odom用在了后端优化,在node和node之间算对应的odom的差,对比node之间的delta pose得到残差。但是odom本身就是一种不太准确的信息,放入后端去优化node的pose,反而会引入多余的误差。因此经过测试,在将odom从后端删除之后,可以得到较好的建图效果。

5. 参考文献

[1]航迹推演(Odometry) https://blog.csdn.net/heyijia0327/article/details/47021861

[2]How a kalmanfilter works, in pictures https://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/

 

  • 19
    点赞
  • 194
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
EKF(Extended Kalman Filter)是一种常用的传感器数据融合算法,用于将多个传感器的测量结果进行联合估计,以获得更准确、稳定的状态估计值。 在融合Odom(里程计)和IMU(惯性测量单元)数据时,EKF可以用来校正和补偿两者的测量误差和漂移问题。Odom通常用于测量机器人的运动速度和位移,但由于累计误差和轮胎滑动等问题,其测量结果可能不够准确。IMU则可以提供机器人的加速度和角速度信息,但长时间使用会导致积分漂移问题。 为了融合这两种传感器的数据,首先需要建立它们之间的状态方程和观测方程。状态方程描述了系统的动态演化规律,观测方程描述了测量结果与真实状态之间的关系。 在EKF中,状态方程和观测方程通常采用非线性的形式。然后通过状态预测和观测更新两个步骤,不断迭代地更新状态估计值。状态预测通过使用IMU测量结果来更新机器人的位置和姿态估计值,同时考虑机器人的运动模型和环境因素。观测更新则使用Odom测量结果来修正状态估计值,以补偿Odom的累计误差。 通过将OdomIMU数据融合,可以充分利用它们各自的优势,提高机器人的定位和导航性能。由于EKF对非线性问题的适应能力较强,能够处理IMU的积分漂移和Odom的累计误差问题,因此在实际应用中被广泛使用。 总而言之,通过EKF融合OdomIMU数据,可以实现更精确、稳定的机器人状态估计和导航功能,并提高机器人在复杂环境中的定位精度和鲁棒性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值