当前位置: 首页 > java >正文

激光雷达运动畸变去除方法

文章目录

    • 一、激光雷达运动畸变产生的原因
    • 二、为什么需要解决这个问题?
    • 三、去除运动畸变的原理
    • 四、运动去畸变的方法
    • 1、纯估计方法(ICP / VICP)
    • 2、传感器辅助的方法(odom,IMU)
    • 3、融合的方法

本文针对二维激光雷达产生的运动畸变进行了分析,如有错误请指正!

一、激光雷达运动畸变产生的原因

在机器人运动过程中,每个激光点都在不同的基准位姿上产生(就是在不同的时刻发出激光时机器人的位置是不同的(由于机器人自身的运动),这也是运动畸变产生的根源所在)。
激光扫描时伴随着机器人的运动,每个角度的激光数据都不是瞬时获得的,当激光雷达扫描的频率比较低的时候,机器人运动带来的激光帧的运动误差是不能被忽略的。
当扫描频率是5Hz的激光雷达,一帧数据的收尾时间差是200ms,如果机器人以0.5m/s的速度沿着x方向行走并扫描前面的墙体,那么200ms后尾部的测量距离和首部的测量距离在x方向上就差10cm。
综上:激光雷达产生畸变的原因有三:

  • 激光点数据不是瞬时获得
  • 激光测量时伴随着机器人的运动
  • 激光帧率较低时,机器人的运动不能忽略(目前 国产的激光雷达 旋转的频率大约在是10Hz ~~100ms)
    在这里插入图片描述
    蓝色是产生运动畸变之后轨迹。

二、为什么需要解决这个问题?

一般激光雷达驱动封装一帧数据时, 默认一帧激光数据的所有激光点是在同一个时刻和同一个位姿下采集的,在低频率扫描的激光雷达应用中(5-10Hz),该问题是不可忽视的。当频率比较高时,我们默认激光数据是在同一个时刻同一个位姿下采集的,可忽视该问题。

三、去除运动畸变的原理

去除激光雷达运动畸变的原理是把一帧激光雷达数据的每个激光点对应的激光雷达坐标转换到不同时刻的机器人里程计上(近似对应的里程计的位置,达到尽可能去除畸变的目的)

四、运动去畸变的方法

1、纯估计方法(ICP / VICP)

  • 《1》ICP(Iterative Cloest Point)方法
    目的:ICP方法是最通用的用来求解两个点云集合转换关系的方法。简单的理解:就是匹配两幅点云,通过ICP算法实现,我们需要求解点云配准的误差最小即可。
    在这里插入图片描述
    已知对应点的求解方法(解析解)
    当我们知道了两幅点云的点对时(也就是两幅点云的对应点),我们会有解析解(不需要最小二乘去求解):
    数学描述:
    在这里插入图片描述

未知对应点的求解方法
在这里插入图片描述
ICP算法的缺点:
没有考虑激光的运动畸变,因此得到的激光数据是错误的(计算的时候假设是正确的),从而造成点云匹配发生错误,通过不断的迭代,虽然能够收敛,能够求解,但是存在误差。
在这里插入图片描述

  • 《2》VICP方法介绍

VICP算法考虑了激光的运动畸变,也就是考虑了机器人的运动和速度的存在。

  • ICP算法的变种
  • 考虑了机器人的运动
  • 匀速运动(假设是匀速运动)
  • 进行匹配的同时估计机器人的速度
    在这里插入图片描述
    在这里插入图片描述
    矫正后的结果
    在这里插入图片描述
    VICP 方法的缺点:(1)低频率情况下(5Hz),匀速运动假设不成立 (2)数据预处理和状态估计过程耦合
    如何解决上述问题呢?
    我们尽可能的反应运动情况,实现预处理和状态估计的解耦,我们提出了传感器辅助的方法。

2、传感器辅助的方法(odom,IMU)

传感器辅助的方法就是极高的位姿更新频率(200Hz),可以比较准确的反应运动情况,以及较高精度的局部位姿估计和状态估计完全解耦

《1》惯性测量单元IMU

  • 直接测量角速度和线加速度
  • 具有较高的角速度测量精度(比较准确)
  • 测量频率极高(1kHz~8kHz)
  • 线加速度精度太差,二次积分在局部的精度依然很差(这一点我们就可以否定他在移动机器人上面的使用,主要原因是精度不高)

《2》轮式里程计odom

  • 直接测量机器人的位移和角度
  • 具有较高的局部角度测量精度
  • 具有较高的局部位置测量精度
  • 更新速度较高(100Hz~200Hz)

如何使用odom去除运动畸变?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
COde

#include <ros/ros.h>
#include <tf/tf.h>
#include <tf/transform_broadcaster.h>
#include <tf/transform_listener.h>
#include <sensor_msgs/LaserScan.h>
#include <iostream>
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <string>
//如果使用调试模式,可视化点云,需要安装PCL
#define debug_ 0#if debug_
#include <pcl-1.7/pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl-1.7/pcl/visualization/cloud_viewer.h>
pcl::visualization::CloudViewer g_PointCloudView("PointCloud View");//初始化一个pcl窗口
#endifclass LidarMotionCalibrator
{
public://构造函数,初始化tf_、订阅者、回调函数ScanCallBackLidarMotionCalibrator(tf::TransformListener* tf){tf_ = tf;scan_sub_ = nh_.subscribe(scan_sub_name_, 10, &LidarMotionCalibrator::ScanCallBack, this);scan_pub_ = nh_.advertise<sensor_msgs::LaserScan>(scan_pub_name_, 1000);}//析构函数,释放tf_~LidarMotionCalibrator(){if(tf_!=NULL)delete tf_;}// 拿到原始的激光数据来进行处理void ScanCallBack(const sensor_msgs::LaserScanConstPtr& scan_msg){//转换到矫正需要的数据ros::Time startTime, endTime;//一帧scan数据到来首先得出,开始结束的时间戳、数据的sizestartTime = scan_msg->header.stamp;sensor_msgs::LaserScan laserScanMsg = *scan_msg;//得到最终点的时间int beamNum = laserScanMsg.ranges.size();endTime = startTime + ros::Duration(laserScanMsg.time_increment * beamNum);// 将数据复制出来std::vector<double> angles,ranges;for(int i = 0; i < beamNum;i++){double lidar_dist = laserScanMsg.ranges[i];//单位米double lidar_angle = laserScanMsg.angle_min + laserScanMsg.angle_increment * i;//单位弧度ranges.push_back(lidar_dist);angles.push_back(lidar_angle);}#if debug_visual_cloud_.clear();//转换为pcl::pointcloud for visuailization//数据矫正前、封装打算点云可视化、红色visual_cloud_scan(ranges,angles,255,0,0);#endif//进行矫正Lidar_Calibration(ranges,angles,startTime,endTime,tf_);//数据矫正后、封装打算点云可视化、绿色//转换为pcl::pointcloud for visuailization#if debug_visual_cloud_scan(ranges,angles,0,255,0);#endif//发布矫正后的scan//ROS_INFO("scan_time:%f",ros::Duration(laserScanMsg.time_increment * beamNum).toSec());scan_cal_pub(ranges,startTime,ros::Duration
http://www.xdnf.cn/news/11158.html

相关文章:

  • Citrix VDI实战攻略之五:vDisk配置
  • CDN加速原理详解
  • 嵌入式TCP硬件设计--------LAN8720芯片使用记录
  • 开源web终端ssh解决方案-gateone简介
  • 创龙TMS320C6748开发板———EDMA简介及配置
  • 启动应用程序出现dxdiag.exe找不到问题解决
  • 路由器不能端口映射什么原因?如何设置内网映射?
  • 汇川触摸屏IT7000E和汇川中小型系列PLC连接及MW寄存器说明
  • 安装虚拟机(VMware)保姆级教程及配置虚拟网络编辑器和安装WindowsServer以及宿主机访问虚拟机和配置服务器环境
  • 用CSS绘制最常见的40种形状和基本图形
  • C#实现使用Timer组件实现世界杯倒计时(附完整源码)
  • 标准布朗运动的定义、代码和图像
  • 服务器端口怎么开放?
  • 动态发布站点的并发访问升级简易方案
  • 网工配置命令基础总结(2)----VRRP配置
  • 魔兽世界台服被大陆玩家挤爆
  • STM32单片机——看门狗(独立看门狗窗口看门狗)
  • Ajax的使用(详解)
  • linux命令、vi命令、vim命令、shell语法(完整详细)
  • Notepad++ 下载与安装教程(非常详细),从零基础入门到精通,看完这一篇就够了(附安装包)
  • 有哪些靠谱的短链接服务?主流大平台短链接优劣对比分析
  • 不知道怎么下载原版系统,这几个原版系统下载网站可以帮你
  • install 命令用法详解
  • Android NDK开发(一)环境搭建及运行示例
  • 货代专业术语中英文对照
  • Sim3求解
  • @PersistenceContext和@Resource
  • 越狱第一至五季/全集迅雷下载
  • 三勾java商城-java多用户商城系统-SaaS多套部署商城
  • 最全Eclipse安装和配置环境教程(图文详解)