[轉]ROS 傳感器消息及RVIZ可視化Laserscan和PointCloud


https://blog.csdn.net/yangziluomu/article/details/79576508

https://answers.ros.org/question/60239/how-to-extract-and-use-laser-data-from-scan-topic-in-ros-using-c/

https://answers.ros.org/question/149256/subscribe-laserscan/

目錄

 

 

ROS 傳感器消息

在使用ROS各個傳感器消息之前,弄清楚各個傳感器在ROS是如何表示的顯得極為重要。特別是,Laserscan, PointCloud等用了很久之后,感覺已經很熟悉了,但是一些細節行的東西一直沒有深究,並且對某些參數難以形成直覺上的認識,很大程度上影響了在與其他算法或者硬件銜接時的問題。這里,我單獨的將Laserscan,PointCloud發布在rviz中,通過修改不同的ROS消息參數,直觀的觀察其在參數的作用。整個工程代碼可以在此處下載:https://download.csdn.net/download/ziqian0512/10289936

ROS 傳感器消息之Laserscan

消息定義

首先,查看一下sensor_msgs/LaserScan.msg的定義,見ros.org/LaserScan.“`

Header header
float32 angle_min # start angle of the scan [rad] float32 angle_max # end angle of the scan [rad] float32 angle_increment # angular distance between measurements [rad] float32 time_increment # time between measurements [seconds] float32 scan_time # time between scans [seconds] float32 range_min # minimum range value [m] float32 range_max # maximum range value [m] float32[] ranges # range data [m] (Note: values < range_min or > range_max should be discarded) float32[] intensities # intensity data [device-specific units]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在消息中需要特別說明的主要是ranges和intensities,ranges表示在某一個角度時,掃描到物體離自己的距離,這很容易理解。intensities則表示測量的強度,也就是激光所反射的亮度,通常來說,值越大,光反射越亮。也就可以用intensities做一些假設,推薦掃描到物體的材料。比如,Hokyuo Laser scanner就提供了反射的所有強度,而 Sick S300則只檢測是否由反光帶。

測試代碼

以下為測試Laserscan源碼,需要特別關注的num_readings(點數),ranges(距離),intensities(強度)參數在調節過程中,rviz中Laserscan的變化。 
編譯以下代碼后,還需要選擇sensor_frame坐標系,和消息/scan。效果圖如下: 
Laserscan
代碼:

#include <ros/ros.h> #include <sensor_msgs/LaserScan.h> int main(int argc, char** argv){ ros::init(argc, argv, "laser_scan_publisher"); ros::NodeHandle n; ros::Publisher scan_pub = n.advertise<sensor_msgs::LaserScan>("scan", 50); unsigned int num_readings = 100; double laser_frequency = 40; double ranges[num_readings]; double intensities[num_readings]; int count = 10; ros::Rate r(1.0); while(n.ok()){ //generate some fake data for our laser scan for(unsigned int i = 0; i < num_readings; ++i){ ranges[i] = count; intensities[i] = 10*i; } ros::Time scan_time = ros::Time::now(); //populate the LaserScan message sensor_msgs::LaserScan scan; scan.header.stamp = scan_time; scan.header.frame_id = "sensor_frame"; scan.angle_min = -1.57; scan.angle_max = 1.57; scan.angle_increment = 3.14 / num_readings; scan.time_increment = (1 / laser_frequency) / (num_readings); scan.range_min = 0.0; scan.range_max = 100.0; scan.ranges.resize(num_readings); scan.intensities.resize(num_readings); for(unsigned int i = 0; i < num_readings; ++i){ scan.ranges[i] = ranges[i]; scan.intensities[i] = intensities[i]; } scan_pub.publish(scan); // ++count; ROS_WARN_STREAM("count"<<count); r.sleep(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

ROS 傳感器消息之PointCloud

消息定義

PointCloud 描述如下:

Header header
geometry_msgs/Point32[] points # Array of 3d points ChannelFloat32[] channels # channel name, value
  • 1
  • 2
  • 3

channels可以進一步解釋為:

#   "rgb" - For point clouds produced by color stereo cameras. uint8 (R,G,B) values packed into the least significant 24 bits,in order. # "intensity" - laser or pixel intensity. # The channel name should give the semantics of the channel (e.g. "intensity" instead of "value"). string name # The values array should be 1-1 with the elements of the associated PointCloud. float32[] values
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

name表示不同的表示方式,可以是像素值,亮度等。values則是典型的依賴於傳感器的亮度值返回,表示測量的質量,可以是灰度圖像的灰度值,也可以是類似laserscan的強度。

測試代碼

在以下代碼中,重點需要調節num_points(點數),channels(設置通道,以及強度),points(位置)參數來觀察PointCloud的變化。編譯以下代碼后,還需要選擇sensor_frame坐標系,和消息/cloud。效果圖如下: 
cloud
代碼

#include <ros/ros.h> #include <sensor_msgs/PointCloud.h> int main(int argc, char** argv){ ros::init(argc, argv, "point_cloud_publisher"); ros::NodeHandle n; ros::Publisher cloud_pub = n.advertise<sensor_msgs::PointCloud>("/cloud", 50); unsigned int num_points = 2000; int count = 0; ros::Rate r(1.0); while(n.ok()){ sensor_msgs::PointCloud cloud; cloud.header.stamp = ros::Time::now(); cloud.header.frame_id = "sensor_frame"; cloud.points.resize(num_points); //we'll also add an intensity channel to the cloud cloud.channels.resize(1); cloud.channels[0].name = "intensities"; cloud.channels[0].values.resize(num_points); //generate some fake data for our point cloud for(unsigned int i = 0; i < num_points; ++i){ cloud.points[i].x = 1 + i/100; cloud.points[i].y = 1; cloud.points[i].z = 1; cloud.channels[0].values[i] = 100 * i; } cloud_pub.publish(cloud); // ++count; r.sleep(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

小結

詳細的介紹需要已經有很多了,自己動手調試並觀察rviz中傳感器數據的變化可以加強對使用傳感器以及研究其算法增加直觀的體驗。目的是為了自己更加方便的查詢和使用。

Reference

  1. Publishing Sensor Streams Over ROS


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM