在ros中使用rplidar Laser发布scan数据--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文件
<!--
Used for visualising rplidar in action. It requires rplidar.launch.
-->
<launch>
<include file="$(find rplidar_ros)/launch/rplidar.launch" /> <node name="rviz" pkg="rviz" type="rviz" args="-d $(find rplidar_ros)/rviz/rplidar.rviz" />
</launch>
主要是查看rplidar.launch文件
<launch>
<node name="rplidarNode" pkg="rplidar_ros" type="rplidarNode" output="screen">
<param name="serial_port" type="string" value="/dev/ttyUSB0"/>
<param name="serial_baudrate" type="int" value=""/>
<param name="frame_id" type="string" value="laser"/>
<param name="inverted" type="bool" value="false"/>
<param name="angle_compensate" type="bool" value="true"/>
</node>
</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 = ;
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-); scan_msg.scan_time = scan_time;
scan_msg.time_increment = scan_time / (double)(node_count-); scan_msg.range_min = 0.15;
scan_msg.range_max = .; scan_msg.intensities.resize(node_count);
scan_msg.ranges.resize(node_count);
if (!inverted) { // assumes scan window at the top
for (size_t i = ; i < node_count; i++) {
float read_value = (float) nodes[i].distance_q2/4.0f/;
if (read_value == 0.0)
scan_msg.ranges[i] = std::numeric_limits<float>::infinity();
else
scan_msg.ranges[i] = read_value;
scan_msg.intensities[i] = (float) (nodes[i].sync_quality >> );
}
} else {
for (size_t i = ; i < node_count; i++) {
float read_value = (float)nodes[i].distance_q2/4.0f/;
if (read_value == 0.0)
scan_msg.ranges[node_count--i] = std::numeric_limits<float>::infinity();
else
scan_msg.ranges[node_count--i] = read_value;
scan_msg.intensities[node_count--i] = (float) (nodes[i].sync_quality >> );
}
} 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 = ;
std::string frame_id;
bool inverted = false;
bool angle_compensate = true; ros::NodeHandle nh;
ros::Publisher scan_pub = nh.advertise<sensor_msgs::LaserScan>("scan", );
ros::NodeHandle nh_private("~");
nh_private.param<std::string>("serial_port", serial_port, "/dev/ttyUSB0");
nh_private.param<int>("serial_baudrate", serial_baudrate, );
nh_private.param<std::string>("frame_id", frame_id, "laser_frame");
nh_private.param<bool>("inverted", inverted, "false");
nh_private.param<bool>("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 -;
} // 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 -;
} // check health...
if (!checkRPLIDARHealth(drv)) {
RPlidarDriver::DisposeDriver(drv);
return -;
} 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[*];
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-; 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 = ;
const int angle_compensate_multiple = ;
int angle_compensate_offset = ;
rplidar_response_measurement_node_t angle_compensate_nodes[angle_compensate_nodes_count];
memset(angle_compensate_nodes, , angle_compensate_nodes_count*sizeof(rplidar_response_measurement_node_t));
int i = , j = ;
for( ; i < count; i++ ) {
if (nodes[i].distance_q2 != ) {
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) < ) angle_compensate_offset = angle_value;
for (j = ; 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 = , end_node = ;
int i = ;
// find the first valid node and last valid node
while (nodes[i++].distance_q2 == );
start_node = i-;
i = count -;
while (nodes[i--].distance_q2 == );
end_node = i+; 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 +,
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 ;
}
主要是打开串口读取rplidar的数据,然后发布scan话题。
查看rqt_graph节点视图。
在ros中使用rplidar Laser发布scan数据--25的更多相关文章
- ROS中发布激光扫描消息
激光雷达工作时会先在当前位置发出激光并接收反射光束,解析得到距离信息,而后激光发射器会转过一个角度分辨率对应的角度再次重复这个过程.限于物理及机械方面的限制,激光雷达通常会有一部分“盲区”.使用激光雷 ...
- Rplidar学习(四)—— ROS下进行rplidar雷达数据采集源码分析
一.子函数分析 1.发布数据子函数 (1)雷达数据数据类型 Header header # timestamp in the header is the acquisition time of # t ...
- ROS中利用V-rep进行地图构建仿真
V-rep中显示激光扫描点 在VREP自带的场景中找到practicalPathPlanningDemo.ttt文件,删除场景中多余的物体只保留静态的地图.然后在Model browser→comp ...
- 对比几种在ROS中常用的几种SLAM算法
在此因为要总结写一个文档,所以查阅资料,将总结的内容记录下来,欢迎大家指正! 文章将介绍使用的基于机器人操作系统(ROS)框架工作的SLAM算法. 在ROS中提供的五种基于2D激光的SLAM算法分别是 ...
- 将ROS中的/sensor_msgs/NavSatFix数据导入google earth显示轨迹
将ros中的gps_msg数据导入google earth显示轨迹 [TOC] 1. 获取GPS数据 将ros中发布的gps topic输出到文本中 rostopic echo -p /gpsData ...
- 如何在ROS中使用PCL(2)
记录关于我们运行roslaunch openni_launch openni.launch 命令时生成的话题以及这些话题的数据类型便于后期的处理,只有知道它们的数据结构,才能很好的对数据进行处理,我 ...
- 如何在ROS中使用PCL—数据格式(1)
在ROS中点云的数据类型 在ROS中表示点云的数据结构有: sensor_msgs::PointCloud sensor_msgs::PointCloud2 pcl::PointCl ...
- 在ROS中使用OpenCV
1.在工作空间下创建程序包 $ cd ~/catkin_ws/src$ catkin_create_pkg robot_vision roscpp std_msgs cv_bridge image_t ...
- ROS中的日志(log)消息
学会使用日志(log)系统,做ROS大型项目的主治医生 通过显示进程的运行状态是好的习惯,但需要确定这样做不会影响到软件的运行效率和输出的清晰度.ROS 日志 (log) 系统的功能就是让进程生成一些 ...
随机推荐
- Scss sass
http://www.ruanyifeng.com/blog/2012/06/sass.htmlscss 声明:1,$blue : #1875e7;2,.class1 { border: 1px so ...
- HDU 1358 简单kmp
题目大意: 找到所有的可组成连续字符串相连的位置,和循环字符串的个数 #include <cstdio> #include <cstring> #include <alg ...
- Android 圆形ProgressBar风格设置
Android系统自带的ProgressBar风格不是很好,如果想自己设置风格的话,一般有几种方法.首先介绍一下第一种方法通过动画实现.在res的anim下创建动画资源loading.xml: < ...
- hashmap和hashtable,arraylist和vector的区别
hashmap线程不安全,hashtable线程安全 hashmap允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同. ...
- SharePoint 2013 Nintex Workflow 工作流帮助(四)
博客地址 http://blog.csdn.net/foxdave 接上篇点击打开链接 我们来看下一个配置标签Ribbon Option: Task Notification(用于配置分配任务时的提醒 ...
- MyQQ 前言
从接触IOS以来也将近8个月了,学习了不少知识. 看了一系列的书籍如: <objective-c 开发入门>--语法介绍,学习一门语言是开发的基础.所以这是我大致对语法语句学习的锻炼地方, ...
- Javascript 基础(二)
一.js运算符: +.-.*./.% %(去模 就是计算两个数的余数,通常判断是否能整除),主要用于整数. var a=90; var b=8; if(a%b==0) window.alert(&qu ...
- lightoj1027
//Accepted 1688 KB 0 ms //概率简单题 //假设我们在n个门前加个起点,在n个门后加个终点,起点可以到达n个门, //为正的门可以到达终点,为负的回到起点 //则假设我们从起点 ...
- (转)mysql各个主要版本之间的差异
原文:http://blog.csdn.net/z1988316/article/details/8095407 一.各版本的常用命令差异 show innodb status\G mysql-5 ...
- IOS 作业项目 TableView两个section中cell置顶功能实现
点击cell会置顶,其他的下移