【学习笔记】通过雷达获取某一角度的距离信息
【知识储备】
雷达传感器消息类型一般为sensor_msgs/LaserScan
通过rosmsg show sensor_msgs/LaserScan来查看消息本身的规范:
#
# 测量的激光扫描角度,逆时针为正
# 设备坐标帧的0度面向前(沿着X轴方向)
#Header header
float32 angle_min # scan的开始角度 [弧度]
float32 angle_max # scan的结束角度 [弧度]
float32 angle_increment # 测量的角度间的距离 [弧度]
float32 time_increment # 测量间的时间 [秒]
float32 scan_time # 扫描间的时间 [秒]
float32 range_min # 最小的测量距离 [米]
float32 range_max # 最大的测量距离 [米]
float32[] ranges # 测量的距离数据 [米] (注意: 值 < range_min 或 > range_max 应当被丢弃)
float32[] intensities # 强度数据 [device-specific units]
此处感谢ROS之发布传感器数据(LaserScan和PointCloud)_ZONGXP的博客-CSDN博客_laserscan
若想要某一角度上的距离信息,即将算出angle总和,根据angle_increment(每一角度间的间隔),得到被平均分为多少个角度(单元),同时,我们可以得知,这些角度(单元)会依次存放在ranges这个数组中,其值就是每个角度对应的距离值。我们只需要找到角度在这个数组中的位置,将其值输出就可以了。
【添加输出代码】
我采用的是ydlidar_g2雷达
查看在ros中的输出接口,位于/lidar/ydlidar_g2/src/ydlidar_node.cpp
/** YDLIDAR SYSTEM* YDLIDAR ROS Node Client ** Copyright 2015 - 2018 EAI TEAM* http://www.ydlidar.com* */#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"
#include "CYdLidar.h"
#include <vector>
#include <iostream>
#include <string>
#include <signal.h>using namespace ydlidar;#define ROSVerision "1.4.2"std::vector<float> split(const std::string &s, char delim) {std::vector<float> elems;std::stringstream ss(s);std::string number;while(std::getline(ss, number, delim)) {elems.push_back(atof(number.c_str()));}return elems;
}int main(int argc, char * argv[]) {ros::init(argc, argv, "ydlidar_node"); printf("__ ______ _ ___ ____ _ ____ \n");printf("\\ \\ / / _ \\| | |_ _| _ \\ / \\ | _ \\ \n");printf(" \\ V /| | | | | | || | | |/ _ \\ | |_) | \n");printf(" | | | |_| | |___ | || |_| / ___ \\| _ < \n");printf(" |_| |____/|_____|___|____/_/ \\_\\_| \\_\\ \n");printf("\n");fflush(stdout);std::string port;int baudrate=230400;std::string frame_id;bool reversion, resolution_fixed;bool auto_reconnect;double angle_max,angle_min;result_t op_result;std::string list;std::vector<float> ignore_array; double max_range, min_range;double frequency;ros::NodeHandle nh;ros::Publisher scan_pub = nh.advertise<sensor_msgs::LaserScan>("scan", 1000);ros::NodeHandle nh_private("~");nh_private.param<std::string>("port", port, "/dev/ydlidar"); nh_private.param<int>("baudrate", baudrate, 230400); nh_private.param<std::string>("frame_id", frame_id, "laser_frame");nh_private.param<bool>("resolution_fixed", resolution_fixed, "true");nh_private.param<bool>("auto_reconnect", auto_reconnect, "true");nh_private.param<bool>("reversion", reversion, "true");nh_private.param<double>("angle_max", angle_max , 180);nh_private.param<double>("angle_min", angle_min , -180);nh_private.param<double>("range_max", max_range , 12.0);nh_private.param<double>("range_min", min_range , 0.1);nh_private.param<double>("frequency", frequency , 10.0);nh_private.param<std::string>("ignore_array",list,"");ignore_array = split(list ,',');if(ignore_array.size()%2){ROS_ERROR_STREAM("ignore array is odd need be even");}for(uint16_t i =0 ; i < ignore_array.size();i++){if(ignore_array[i] < -180 && ignore_array[i] > 180){ROS_ERROR_STREAM("ignore array should be between 0 and 360");}}CYdLidar laser;if(frequency<5){frequency = 7.0; }if(frequency>12){frequency = 12;}if(angle_max < angle_min){double temp = angle_max;angle_max = angle_min;angle_min = temp;}ROS_INFO("[YDLIDAR INFO] Now YDLIDAR ROS SDK VERSION:%s .......", ROSVerision);laser.setSerialPort(port);laser.setSerialBaudrate(baudrate);laser.setMaxRange(max_range);laser.setMinRange(min_range);laser.setMaxAngle(angle_max);laser.setMinAngle(angle_min);laser.setReversion(reversion);laser.setFixedResolution(resolution_fixed);laser.setAutoReconnect(auto_reconnect);laser.setScanFrequency(frequency);laser.setIgnoreArray(ignore_array);bool ret = laser.initialize();if (ret) {ret = laser.turnOn();if (!ret) {ROS_ERROR("Failed to start scan mode!!!");}} else {ROS_ERROR("Error initializing YDLIDAR Comms and Status!!!");}ros::Rate rate(20);while (ret&&ros::ok()) {bool hardError;LaserScan scan;if(laser.doProcessSimple(scan, hardError )){sensor_msgs::LaserScan scan_msg;ros::Time start_scan_time;start_scan_time.sec = scan.system_time_stamp/1000000000ul;start_scan_time.nsec = scan.system_time_stamp%1000000000ul;scan_msg.header.stamp = start_scan_time;scan_msg.header.frame_id = frame_id;scan_msg.angle_min =(scan.config.min_angle);scan_msg.angle_max = (scan.config.max_angle);scan_msg.angle_increment = (scan.config.angle_increment);scan_msg.scan_time = scan.config.scan_time;scan_msg.time_increment = scan.config.time_increment;scan_msg.range_min = (scan.config.min_range);scan_msg.range_max = (scan.config.max_range);scan_msg.ranges = scan.ranges;int num = (scan_msg.angle_max-scan_msg.angle_min)/scan_msg.angle_increment;//choose the direction and range you want to testdouble expect_angle = 180;int range = 3;// get the direction valueint test_direction = (expect_angle/360)*num;// get the distance valuefor (int i = -range; i <= num+range ; i++){//determine if in the range we wantif(i >test_direction-range && i<test_direction+range){double sum;int test_angle = i*360/num;//determine if direct angle close to the zeroif(i<=0){int pre_i = i;i = num + i;sum += scan_msg.ranges[i];//printf("angle[%d]=%lf\n",test_angle,scan_msg.ranges[i]);i = pre_i;}//determine if direct angle close to the last angleelse if (i > num && i<test_direction+range-1){int pre_i = i;i = i-num;sum += scan_msg.ranges[i];//printf("angle[%d]=%lf\n",test_angle,scan_msg.ranges[i]);i = pre_i;}//Exclude the above situation,calculation average value of sumelse if(i == test_direction+range-1){sum += scan_msg.ranges[i];printf("aver_angle[%d]=%lf\n",test_angle,sum/(2*range-1));sum = 0;}else{sum += scan_msg.ranges[i];}} }scan_msg.intensities = scan.intensities;scan_pub.publish(scan_msg);} rate.sleep();ros::spinOnce();}laser.turnOff();ROS_INFO("[YDLIDAR INFO] Now YDLIDAR is stopping .......");laser.disconnecting();return 0;
}
添加了以下部分
作简单的注释
1)int num = (scan_msg.angle_max-scan_msg.angle_min)/scan_msg.angle_increment;
获取被分割的角度(单元)数
2)double expect_angle = 180; int range = 3;
输入(更改)想要获取的角度值,还有范围值
3)int test_direction = (expect_angle/360)*num;
角度值在实际扫描中的值
4)for (int i = -range; i <= num+range ; i++)
for循环遍历range[]数组
5)if(i >test_direction-range && i<test_direction+range)
达到想要的角度范围
6)if(i<=0) else if (i > num && i<test_direction+range-1) else if(i == test_direction+range-1)
因为当角度在0度和359度会有一个突变,所以进行分开判断处理
7)sum += scan_msg.ranges[i];
printf("aver_angle[%d]=%lf\n",test_angle,sum/(2*range-1));
sum将期望角度范围内的距离值进行相加,最后输出平均距离值
【创建订阅者接受处理雷达数据】
为避免占用雷达串口,也可以采用创建一个订阅者来接受雷达数据
#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"
#include <vector>
#include <iostream>
#include <string>
#include <signal.h>void callback(const sensor_msgs::LaserScan::ConstPtr &scan_msg){int num = (scan_msg->angle_max-scan_msg->angle_min)/scan_msg->angle_increment;//choose the direction and range you want to testdouble expect_angle = 180;int range = 3;// get the direction valueint test_direction = (expect_angle/360)*num;// get the distance valuefor (int i = -range; i <= num+range ; i++){//determine if in the range we wantif(i >test_direction-range && i<test_direction+range){double sum;int test_angle = i*360/num;//determine if direct angle close to the zeroif(i<=0){int pre_i = i;i = num + i;sum += scan_msg->ranges[i];//printf("angle[%d]=%lf\n",test_angle,scan_msg.ranges[i]);i = pre_i;}//determine if direct angle close to the last angleelse if (i > num && i<test_direction+range-1){int pre_i = i;i = i-num;sum += scan_msg->ranges[i];//printf("angle[%d]=%lf\n",test_angle,scan_msg.ranges[i]);i = pre_i;}//Exclude the above situation,calculation average value of sumelse if(i == test_direction+range-1){sum += scan_msg->ranges[i];printf("aver_angle[%d]=%lf\n",test_angle,sum/(2*range-1));sum = 0;}else{sum += scan_msg->ranges[i];}} }
}int main(int argc, char * argv[]) {ros::init(argc, argv, "ydlidar_recept_node"); ros::NodeHandle n;ros::Subscriber scan_sub = n.subscribe("scan",10,callback);ros::spin(); return 0;}
同时在CMakeList.txt上添加add_executable(recept_laser src/recept_laser.cpp)和target_link_libraries(recept_laser ${catkin_LIBRARIES}),新建了cpp文件都要有此操作
主要留意接收数据后,如何指向消息内容
我在编写的时候,一开始将接收来的数据用scan_msg.angle_max(其他也是用scan.xxx)来表示,编译的时候就会报 has no member named ‘angle_max’等等这类没有找到成员的错误
将其更改成scan_msg->angle_max,下面报的错也是用此种方法修改,就可以顺利编译了
在启动雷达的launch文件上添加启动刚刚编写好的程序
<node name="recept_laser" pkg="ydlidar_g2" type="recept_laser" output="screen" />
运行launch文件,查看实际运行效果
【学习笔记】通过雷达获取某一角度的距离信息相关推荐
- Kinect+OpenNI学习笔记之6(获取人体骨架并在Qt中显示)
前言 MS的kinec SDK和OpenNI都提供了人体骨骼跟踪的算法,人体骨骼跟踪算法在kinect人体行为识别中非常重要,该识别过程通常被用来作为行为识别的第一步, 比如说,通过定位人体中的骨骼支 ...
- 查看oracle 导出进程,【学习笔记】Oracle 通过v$session查看imp进程信息的案例
天萃荷净 运维DBA反映需求在执行Oracle imp导入时需要查看导入的进程信息,通过v$session分析imp导入进程在服务器端v$session中的username列不是imp登陆用户名,而是 ...
- Proximity模块管理设备距离传感器,可获取当前设备的接近距离信息,通过plus.proximity可获取设备距离传感管理对象
方法: getCurrentProximity: 获取当前设备的接近距离信息 watchProximity: 监听设备接近距离的变化 clearWatch: 关闭监听设备接近距离变化 回调方法: Pr ...
- 【Linux学习笔记】Linux获取CPU使用率,内存使用率和磁盘使用率
实现目标: 在Linux上使用shell脚本回显系统当前的CPU使用率.内存使用率和磁盘空间使用率 1.CPU使用率: 使用top命令能够实时显示系统中各个进程的资源占用状况,所以这边可以使用top命 ...
- spring-狂神学习笔记-联系我获取md文档
1.Spring(概述) 1.1.简介 Spring:春---->给软件行业带来了春天 2002,首次推出了Spring框架的雏形: interface21框架 Spring框架即以interf ...
- onvif学习笔记10:获取RTSP流地址
有网友购买了我的ONVIF视频课程 (注:CSDN已经把课程下架了,说不符合要求),问了我几个问题,其中一个是实现ONVIF服务器的获取RTSP地址功能,本文整理出一个思路,愿帮到在学习ONVIF路上 ...
- Tableau学习笔记①②(雷达图、凹凸图)
一.雷达图 雷达图主要是用来进行多个维度的比较和分析. 1. 数据表处理 步骤: 原始数据: 在Excel表中是有两个进攻能力的,但是在导入Tableau时,为了区分方便,自动转换成上图所示. Exc ...
- 无人驾驶学习笔记——摄像头雷达联合标定
最近在弄摄像头雷达的联合标定,一开始参考的是我师兄的博客,写的非常好: 无人驾驶汽车系统入门(二十二)--使用Autoware实践激光雷达与摄像机组合标定 版权声明:本文为博主原创文章,遵循 CC 4 ...
- 初学视觉学习笔记----用摄像头获取图片
目标: 想要A,B两个窗口,A窗口实时显示相机的画面,当我按下照相按钮的时候,B窗口显示我捕获到的图片. 遇到的问题: 在A窗口 实时显示的时候 用到了while (true){ //视频显示} 因为 ...
- 获得代理ippython_Python学习笔记六(免费获取代理IP)
1 importrequests2 importurllib.request3 from bs4 importBeautifulSoup4 importrandom,time,re5 importra ...
最新文章
- Oracle触发器和new、old特殊变量
- [转]开发网路游戏的延迟处理方法,广播
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(7.2) 模块管理,模块的添加、修改、删除...
- java在frame怎么计时_java – 退出jframe时的Swing stop计时器
- android王者调不了界面,王者荣耀登录界面怎么改?登录界面更改教程[多图]
- 为什么使用数据库从库
- C语言实现ICMP协议,并进行PING测试
- php统计网站 / html页面 浏览访问次数程序
- 关于stata软件的一些问题
- tensorflow pb ckpt pbtxt
- 第二步:创建html模板及文件目录等
- EKMA 曲线及大气 O3 来源解析
- PCB多层板每层厚度及材质
- 确定十二星座的日期范围
- input验证邮箱 css,jquery验证邮箱格式并显示提交按钮
- 属性级情感分析(于restaurant14和laptop14数据集上使用LSTM和GRU、 MemNet和IAN以及CNN等)的对比分析
- 游戏鼠标的dpi测试软件,自己就可以测试鼠标的DPI
- iscroll.js的使用
- 浅入浅出keepalived+nginx实现高可用双机热备
- 软件构造|GRASP模式
热门文章
- 《春秋·战国》大事年表
- 我面试过没有上万人也有十几个,简历要这么写才有hr要你
- PyTorch-04梯度、常见函数梯度、激活函数Sigmoid;Tanh;ReLU及其梯度、LOSS及其梯度、感知机(单层感知机)、感知机2(多输出的)、链式法则、MLP反向传播推导、2D函数优化实例
- POI 设置Word表格边框、表格文字水平居中
- 【HCIE-RS 天梯路】MSDP
- 互联网晚报 | 9月18日 星期六 | 微信发布外部链接内容管理规范调整声明;知乎宣布月活破亿;京东宣布双11节奏提前...
- 解决word2016复制粘贴后一直未响应
- echarts横向柱形图显示不同类别所占整体百分比
- ROC曲线的绘制过程/AUC/TPR、FPR、敏感度和特异度
- Ansible中的jinjia2模板