博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在ros中使用rplidar Laser发布scan数据--25
阅读量:5243 次
发布时间:2019-06-14

本文共 7758 字,大约阅读时间需要 25 分钟。

原创博客:转载请表明出处:http://www.cnblogs.com/zxouxuewei/

由于市面上买的激光雷达价格太贵了。所以在学习时会造成很大的经济压力。但是最近好多做机器人核心组件的公司都开发有廉价的雷达;

本博客教你如何 使用rplidar发布scan数据,在rviz视图中查看scan数据。

1.首先确保你的rplidar水平放置在你的机器人上:(注意安装方向)

2.然后下载rplidar的rosSDK开发包,

3.初步测试:

运行roscore

roscore &

直接运行rplidar的launch文件

roslaunch rplidar_ros view_rplidar.launch

 查看view_rplidar.launch文件

 主要是查看rplidar.launch文件

 在这个launch文件中打开了rplidarNode这个节点,然后我们分析一下节点源码:

#include "ros/ros.h"#include "sensor_msgs/LaserScan.h"#include "std_srvs/Empty.h"#include "rplidar.h" //RPLIDAR standard sdk, all-in-one header#ifndef _countof#define _countof(_Array) (int)(sizeof(_Array) / sizeof(_Array[0]))#endif#define DEG2RAD(x) ((x)*M_PI/180.)using namespace rp::standalone::rplidar;RPlidarDriver * drv = NULL;void publish_scan(ros::Publisher *pub,                   rplidar_response_measurement_node_t *nodes,                   size_t node_count, ros::Time start,                  double scan_time, bool inverted,                   float angle_min, float angle_max,                   std::string frame_id){    static int scan_count = 0;    sensor_msgs::LaserScan scan_msg;    scan_msg.header.stamp = start;    scan_msg.header.frame_id = frame_id;    scan_count++;    scan_msg.angle_min =  M_PI - angle_min;    scan_msg.angle_max =  M_PI - angle_max;    scan_msg.angle_increment =         (scan_msg.angle_max - scan_msg.angle_min) / (double)(node_count-1);    scan_msg.scan_time = scan_time;    scan_msg.time_increment = scan_time / (double)(node_count-1);    scan_msg.range_min = 0.15;    scan_msg.range_max = 6.;    scan_msg.intensities.resize(node_count);    scan_msg.ranges.resize(node_count);    if (!inverted) { // assumes scan window at the top        for (size_t i = 0; i < node_count; i++) {            float read_value = (float) nodes[i].distance_q2/4.0f/1000;            if (read_value == 0.0)                scan_msg.ranges[i] = std::numeric_limits
::infinity(); else scan_msg.ranges[i] = read_value; scan_msg.intensities[i] = (float) (nodes[i].sync_quality >> 2); } } else { for (size_t i = 0; i < node_count; i++) { float read_value = (float)nodes[i].distance_q2/4.0f/1000; if (read_value == 0.0) scan_msg.ranges[node_count-1-i] = std::numeric_limits
::infinity(); else scan_msg.ranges[node_count-1-i] = read_value; scan_msg.intensities[node_count-1-i] = (float) (nodes[i].sync_quality >> 2); } } pub->publish(scan_msg);}bool checkRPLIDARHealth(RPlidarDriver * drv){ u_result op_result; rplidar_response_device_health_t healthinfo; op_result = drv->getHealth(healthinfo); if (IS_OK(op_result)) { printf("RPLidar health status : %d\n", healthinfo.status); if (healthinfo.status == RPLIDAR_STATUS_ERROR) { fprintf(stderr, "Error, rplidar internal error detected." "Please reboot the device to retry.\n"); return false; } else { return true; } } else { fprintf(stderr, "Error, cannot retrieve rplidar health code: %x\n", op_result); return false; }}bool stop_motor(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res){ if(!drv) return false; ROS_DEBUG("Stop motor"); drv->stop(); drv->stopMotor(); return true;}bool start_motor(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res){ if(!drv) return false; ROS_DEBUG("Start motor"); drv->startMotor(); drv->startScan();; return true;}int main(int argc, char * argv[]) { ros::init(argc, argv, "rplidar_node"); std::string serial_port; int serial_baudrate = 115200; std::string frame_id; bool inverted = false; bool angle_compensate = true; ros::NodeHandle nh; ros::Publisher scan_pub = nh.advertise
("scan", 1000); ros::NodeHandle nh_private("~"); nh_private.param
("serial_port", serial_port, "/dev/ttyUSB0"); nh_private.param
("serial_baudrate", serial_baudrate, 115200); nh_private.param
("frame_id", frame_id, "laser_frame"); nh_private.param
("inverted", inverted, "false"); nh_private.param
("angle_compensate", angle_compensate, "true"); u_result op_result; // create the driver instance drv = RPlidarDriver::CreateDriver(RPlidarDriver::DRIVER_TYPE_SERIALPORT); if (!drv) { fprintf(stderr, "Create Driver fail, exit\n"); return -2; } // make connection... if (IS_FAIL(drv->connect(serial_port.c_str(), (_u32)serial_baudrate))) { fprintf(stderr, "Error, cannot bind to the specified serial port %s.\n" , serial_port.c_str()); RPlidarDriver::DisposeDriver(drv); return -1; } // check health... if (!checkRPLIDARHealth(drv)) { RPlidarDriver::DisposeDriver(drv); return -1; } ros::ServiceServer stop_motor_service = nh.advertiseService("stop_motor", stop_motor); ros::ServiceServer start_motor_service = nh.advertiseService("start_motor", start_motor); // start scan... drv->startScan(); ros::Time start_scan_time; ros::Time end_scan_time; double scan_duration; while (ros::ok()) { rplidar_response_measurement_node_t nodes[360*2]; size_t count = _countof(nodes); start_scan_time = ros::Time::now(); op_result = drv->grabScanData(nodes, count); end_scan_time = ros::Time::now(); scan_duration = (end_scan_time - start_scan_time).toSec() * 1e-3; if (op_result == RESULT_OK) { op_result = drv->ascendScanData(nodes, count); float angle_min = DEG2RAD(0.0f); float angle_max = DEG2RAD(359.0f); if (op_result == RESULT_OK) { if (angle_compensate) { const int angle_compensate_nodes_count = 360; const int angle_compensate_multiple = 1; int angle_compensate_offset = 0; rplidar_response_measurement_node_t angle_compensate_nodes[angle_compensate_nodes_count]; memset(angle_compensate_nodes, 0, angle_compensate_nodes_count*sizeof(rplidar_response_measurement_node_t)); int i = 0, j = 0; for( ; i < count; i++ ) { if (nodes[i].distance_q2 != 0) { float angle = (float)((nodes[i].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f); int angle_value = (int)(angle * angle_compensate_multiple); if ((angle_value - angle_compensate_offset) < 0) angle_compensate_offset = angle_value; for (j = 0; j < angle_compensate_multiple; j++) { angle_compensate_nodes[angle_value-angle_compensate_offset+j] = nodes[i]; } } } publish_scan(&scan_pub, angle_compensate_nodes, angle_compensate_nodes_count, start_scan_time, scan_duration, inverted, angle_min, angle_max, frame_id); } else { int start_node = 0, end_node = 0; int i = 0; // find the first valid node and last valid node while (nodes[i++].distance_q2 == 0); start_node = i-1; i = count -1; while (nodes[i--].distance_q2 == 0); end_node = i+1; angle_min = DEG2RAD((float)(nodes[start_node].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f); angle_max = DEG2RAD((float)(nodes[end_node].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f); publish_scan(&scan_pub, &nodes[start_node], end_node-start_node +1, start_scan_time, scan_duration, inverted, angle_min, angle_max, frame_id); } } else if (op_result == RESULT_OPERATION_FAIL) { // All the data is invalid, just publish them float angle_min = DEG2RAD(0.0f); float angle_max = DEG2RAD(359.0f); publish_scan(&scan_pub, nodes, count, start_scan_time, scan_duration, inverted, angle_min, angle_max, frame_id); } } ros::spinOnce(); } // done! RPlidarDriver::DisposeDriver(drv); return 0;}

 

 主要是打开串口读取rplidar的数据,然后发布scan话题。

查看rqt_graph节点视图。

 

转载于:https://www.cnblogs.com/zxouxuewei/p/5319899.html

你可能感兴趣的文章
CF E2 - Array and Segments (Hard version) (线段树)
查看>>
Linux SPI总线和设备驱动架构之四:SPI数据传输的队列化
查看>>
SIGPIPE并产生一个信号处理
查看>>
CentOS
查看>>
Linux pipe函数
查看>>
java equals 小记
查看>>
爬虫-通用代码框架
查看>>
2019春 软件工程实践 助教总结
查看>>
YUV 格式的视频呈现
查看>>
Android弹出框的学习
查看>>
现代程序设计 作业1
查看>>
在android开发中添加外挂字体
查看>>
Zerver是一个C#开发的Nginx+PHP+Mysql+memcached+redis绿色集成开发环境
查看>>
多线程实现资源共享的问题学习与总结
查看>>
Learning-Python【26】:反射及内置方法
查看>>
torch教程[1]用numpy实现三层全连接神经网络
查看>>
java实现哈弗曼树
查看>>
转:Web 测试的创作与调试技术
查看>>
python学习笔记3-列表
查看>>
程序的静态链接,动态链接和装载 (补充)
查看>>