深度图像转伪激光雷达depthimage_to_laserscan
来源:互联网 发布:java短信验证码代码 编辑:程序博客网 时间:2024/06/09 20:25
本文不仅解释深度图像如何转化为激光雷达,更通过笔者的亲测阐释了为什么kinect深度图像转化的数据只能检测到平行kinect的障碍物,而较低的障碍物或者较高的障碍物检测不到。帮助新手少走弯路,当然有些知识和图片偷袭别人的。
首先先看下原理:
深度图转激光在ROS包depthimage_to_laserscan,代码中实现,本篇讲解其计算过程。
1. 深度图转激光原理
原理如图(1)所示。深度图转激光中,对任意给定的一个深度图像点
,其转换激光的步骤为:
a.将深度图像的点
b.计算直线
,计算公式如下:
c.将叫
可如下计算:
,即
核心代码
我们的想法是取深度图像上每一列最小值依次保存到雷达ranges[]数组中,这样理论上,我们将会获kinect前方纵向上最近的障碍物距离,ranges[]数组体现了横向每个障碍点到kinect距离。但是实际,纵向上扫面的高度极为苛刻,并不能把地面到到0.6米的高度都扫一遍,因为什么呢,请看后面总结。先看核心代码,思路:先行扫描将数据存到ranges[]中,然后再高度扫面,比较下一行与原来数据ranges[],小数据替换原来ranges[]中的大数据,这样就将高度给压缩了。
template<typename T> void convert(const sensor_msgs::ImageConstPtr& depth_msg, const image_geometry::PinholeCameraModel& cam_model, const sensor_msgs::LaserScanPtr& scan_msg, const int& scan_height) const{ // Use correct principal point from calibration使用校正的正确的主要点 float center_x = cam_model.cx(); 中心点 float center_y = cam_model.cy(); // Combine unit conversion (if necessary) with scaling by focal length for computing (X,Y) //在计算(X,Y)的时候,结合单位转换(如果必要的话) double unit_scaling = depthimage_to_laserscan::DepthTraits<T>::toMeters( T(1) ); float constant_x = unit_scaling / cam_model.fx(); float constant_y = unit_scaling / cam_model.fy(); const T* depth_row = reinterpret_cast<const T*>(&depth_msg->data[0]); int row_step = depth_msg->step / sizeof(T); int offset = (int)(cam_model.cy()-scan_height/2); depth_row += offset*row_step; // Offset to center of image for(int v = offset; v < offset+scan_height_; v++, depth_row += row_step){ 高度遍历,层次遍历 for (int u = 0; u < (int)depth_msg->width; u++) // Loop over遍历 each pixel in row{行遍历计算距离r,保存到一维雷达数组中ranges[]中T depth = depth_row[u];double r = depth; // Assign to pass through NaNs and Infsdouble th = -atan2((double)(u - center_x) * constant_x, unit_scaling); // Atan2(x, z), but depth divides outint index = (th - scan_msg->angle_min) / scan_msg->angle_increment; //当前数据所在ranges[]的下标 if (depthimage_to_laserscan::DepthTraits<T>::valid(depth)){ // Not NaN or Inf // Calculate 计算in XYZdouble x = (u - center_x) * depth * constant_x;double z = depthimage_to_laserscan::DepthTraits<T>::toMeters(depth); // Calculate actual distancer = sqrt(pow(x, 2.0) + pow(z, 2.0));//实际距离} // Determine if this point should be used. if(use_point(r, scan_msg->ranges[index], scan_msg->range_min, scan_msg->range_max)){ scan_msg->ranges[index] = r;//此函数进行此障碍点到相机距离r与其列存的当前值ranges[index]比较, }//返回ture,说明r值小,找出了当前此列高度上距离最近的障碍物 } } }理解了核心代码,可能会想,没问题呀,只要把scan_hight设置在规定的范围内,就能从高度offset-scan_hight/2扫描到offset+scan_hight/2呀,不然。
重点
现实世界的实际距离是通过深度图像转化的,而我们的scan_hight是针对深度图像扫描高度,深度图像类似一张照片,如
这张图偏中是下方基本都是地面,当我扫面高度超过一定范围,就会把地面当成障碍物引入。所以如果我想检测相机前方1米高度为10CM的障碍物,你就得把scan_hight设置到200(亲测),这样是可以检测到了,但是再远1米的地面都会被检测,都会引入当成障碍物,这样的结果是,导致全局都是障碍物。可能会想,找到一个合适scan_hight,并没有,通常设置为10。scan_hight对扫面的高度影响极小,但对远处的障碍物影响很大,所以稍微改动,得不到想要的结果,反而影响的全局了规划。
所以,最好的办法就是给机器人另加传感器。
- 深度图像转伪激光雷达depthimage_to_laserscan
- 灰度图像转伪彩色
- kinect1+depthimage_to_laserscan
- 激光雷达
- 深度图像
- 图像深度
- 图像深度
- 图像深度
- 深度图像
- 图像深度
- Depthimage_to_laserscan安装并执行
- C#串口通信 [实战] (读取激光雷达数据,生成图像)
- 生成伪彩色图像
- 像素深度 与 图像深度
- RGB-D(深度图像) & 图像深度
- 图像基本变换---图像伪色彩
- 灰度图像转化为伪彩色图像
- MATLAB 图像伪彩色处理
- 上海-新的开始
- Netty自娱自乐之类Dubbo RPC 框架设计构想 【上篇】
- Python:成员运算符in 、not in
- Logistic回归原理及公式推导
- 古文觀止卷九_種樹郭橐駝傳_柳宗元
- 深度图像转伪激光雷达depthimage_to_laserscan
- PAT-乙级-1036. 跟奥巴马一起编程
- List的用法
- Hsubmit-Window函数库
- Lintcode各位相加
- 如何提高 Java 中锁的性能
- POJ3080 Blue jeans(未完待续,KMP,寻找多个子串的公共串)
- CC COT5 [线段树][Treap]
- Maven项目导入jstl标签库jar包正确方式