【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
lidar是机器人用的比较多的一种传感器。从前可能单线lidar用的比较多,现在多线lidar则开始慢慢崛起了。这里面最主要的原因还是价格。之前3d lidar动则十几万、几万的价格,这是大多数厂家都负担不起的。而现在,随着越来越多的国产厂家参与到了3d lidar的研发,这个时候lidar的价格也应声下跌,开始走入大规模商用的时代。
对于不同品牌的厂家来说,它们一般都会提供ros的lidar驱动。因为ros的lidar驱动格式是统一的,所以这个时候,对于使用者来说,拿到了ros包之后,直接rviz查看/scan话题,就可以看到对应的显示效果了。
要知道lidar的数据格式,有好几种办法。最主要的方法,就是直接从ros官方网站去查找。比如,输入inde.ros.org,在查找一栏输入sensor,大概就会看到这样的搜索内容,
这个时候,顺着网页向下查找,我们会发现有很多的选项。直接选择第一个sensor_msgs,进入页面之后,开始往下寻找,查找到laser_scan即可,
这个时候,链接的网页之中就有我们想要的内容了,
# Single scan from a planar laser range-finder
#
# If you have another ranging device with different behavior (e.g. a sonar
# array), please find or create a different message, since applications
# will make fairly laser-specific assumptions about this data
std_msgs/Header header # timestamp in the header is the acquisition time of
# the first ray in the scan.
#
# in frame frame_id, angles are measured around
# the positive Z axis (counterclockwise, if Z is up)
# with zero angle being forward along the x axis
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] - if your scanner
# is moving, this will be used in interpolating position
# of 3d points
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]. If your
# device does not provide intensities, please leave
# the array empty.
当中比较重要的属性有angle_min、angle_max、angle_increment、ranges、intensities这些属性。ranges表示lidar的距离,是一个数组。angle表示lidar角度,angle_increment表示每次lidar的增加角度。这些都是常规变量。比较重要的量还有intensities,这个表示反射强度,某些特定的物体对lidar反射会比较高,它也是一个数组。这样就可以通过它来识别反光柱、反光条,实现基于反光柱、反光条的定位识别算法。
#include
#include
void LidarCallback(const sensor_msgs::LaserScan msg)
{
float fMidDist = msg.ranges[180];
ROS_INFO("front distance ranges[180] = %0.8f m", fMidDist);
}
int main(int argc, char* argv[])
{
setlocale(LC_ALL, "");
ros::init(argc, argv, "lidar_node");
ros::NodeHandle n;
ros::Subscriber lidar_sub = n.subscribe("/scan", 10, &LidarCallback);
ros::spin();
}
代码比较简单,主要就是订阅/scan的数据,同时定期将msg.ranges[180]的数据打印出来。这个数值其实就是机器人前方距离书柜的距离。
add_executable(lidar_node src/lidar_node.cpp)
target_link_libraries(lidar_node ${catkin_LIBRARIES})
add_dependencies(lidar_node beginner_tutorials_generate_messages_cpp)
编译和之前package中的node编译没有什么区别,主要还是直接输入catkin_make即可。
调试的分成三个步骤。第一肯定是利用roslaunch打开wpb_simple.launch文件;第二,启动lidar_node节点,输入rosrun beginner_tutorials lidar_node即可。这个时候,不出意外的话,应该可以看到这些打印,
第三,如果这些打印都没有问题,可以继续启动rosrun rqt_robot_steering,这样通过控制小车的前进和后退,观察lidar_node中的打印数据有没有发生改变。如果一切和预想的一样,那么说明我们的想法是正确的。不然,就要去分析一下失败的原因了。