激光雷达
测试雷达启动
官方的激光雷达功能包为ydlidar,主要的启动文件为ydlidar.launch
roslaunch ydlidar ydlidar.launch
终端有如下输出并且听到雷达转起来说明启动正常。
rviz的使用
rviz是ROS的一个可视化工具,熟练使用rviz可以大大提高我们的调试效率。接下来我们将尝试使用rviz查看雷达数据。
在激光雷达启动的同时,另一个终端执行rviz,这时桌面会弹出rviz窗口。
在右上方Fixed Frame中选择base_link,然后点击右下方add选择LaserScan。
你会发现LaserScan被添加到了右边栏,接着点击LaserScan中的Topic选择/scan话题,这相当于rviz订阅了雷达话题并且可视化显示出来。接着右边就会显示出激光点。上方点击Move Camera后,就可以用鼠标在图中移动视角,鼠标滚轮可以缩放,按住shift移动可以平移视角。你也可以将Size设置大一点看得更清楚,其他的参数不再赘述。
这里解释一下:
Fixed Frame是全局参考坐标系,选择baselink相当于以小车底盘中心为全局参考坐标系。你也可以选择为laser_frame为全局参考坐标系,会发现激光点没有什么区别。这是因为雷达安装在小车头部,其坐标原点的偏移量很小,所以看不出来区别。
可以在雷达启动文件ydlidar.launch的末尾发现:
<node pkg="tf" type="static_transform_publisher" name="base_link_to_laser"
args="0.11 0.0 0.13 -0.07 0.0 0.0 /base_link /laser_frame 40" />
这其实就是发布了雷达与小车底盘的位置关系,args中定义的就是相对位置和偏移量等。你可以这么来理解TF:小车上安装了许多传感器,那么ROS如何知道这些传感器安装在哪呢?所以你需要设定一个全局参考坐标系(通常为小车底盘中心),然后发布每个传感器与小车底盘中心的相对位置关系。这样ROS就知道每个传感器的安装位置了。
为什么要这么做呢?比如雷达是安装在小车头部而并非中心的,那么测出前方障碍物的距离就是相对于头部的距离。如果我们知道雷达与base_link的TF关系,就可以用TF变换将障碍物的位置换算到小车中心。
你可以在rviz中添加TF,就可以直观的看到雷达和底盘的位置关系。
雷达可视化启动
我们知道,一个launch文件可以包含多个节点。这里我们将编写自己的launch文件,同时启动雷达和rviz,这样就不用每次开很多终端一个一个开节点。在以后,你也可以将需要的节点全部放到一个launch文件中,就可以实现一键启动。
在我们自己的功能包benz下创建一个launch目录,再新建一个show_laser.launch,添加以下代码:
<launch>
<include file="$(find ydlidar)/launch/ydlidar.launch" />
<node name="rviz" pkg="rviz" type="rviz" args="" output="screen"/>
</launch>
运行会发现同时启动了雷达和rviz,但是rviz没有任何配置。
roslaunch benz show_laser.launch
在rviz上将需要的配置添加后,你可以在功能包下创建一个config目录,然后点击右上角File选择save config as将文件保存到该目录下。此后你可以在launch文件中添加这个参数文件,可以直接打开需要的配置。注意在修改rviz配置后需要ctrl+S保存。
<launch>
<include file="$(find ydlidar)/launch/ydlidar.launch" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find benz)/config/show_lidar.rviz" output="screen"/>
</launch>
获取激光雷达数据
启动雷达后,在终端执行
rosmsg show sensor_msgs/LaserScan
可以看到雷达数据格式如下,其中比较重要的是angle_min,angle_max,angle_increment:
std_msgs/Header header
uint32 seq
time stamp
string frame_id
float32 angle_min # 扫描开始角度(弧度)
float32 angle_max # 扫描结束角度(弧度)
float32 angle_increment # 两个测量点之间的角度间隔(弧度)
float32 time_increment # 两个测量点之间的时间间隔(秒)
float32 scan_time # 一次扫描所用时间(秒)
float32 range_min # 最小可测距离(米)
float32 range_max # 最大可测距离(米)
float32[] ranges # 距离数组(米)
float32[] intensities # 反射强度数组(可选)
执行以下命令查看具体数据的值。
rostopic echo /scan --noarr
可以从其中一条中看到类似。
angle_min: -3.1415927410125732
angle_max: 3.1415927410125732
angle_increment: 0.00691219512373209
通过这三个值以及激光数组ranges的长度我们就可以计算出角度与数组索引的关系(具体计算交给AI)。下面用一个demo获取小车正前方障碍物的距离。
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import rospy
from sensor_msgs.msg import LaserScan
def scan_callback(msg):
"""
获取正前方障碍物距离
"""
# 计算正前方索引
# angle_min + i * angle_increment = 0
# i = round(-angle_min / angle_increment)
i = round(-msg.angle_min / msg.angle_increment)
# 防止索引越界
if i < 0 or i >= len(msg.ranges):
rospy.logwarn("前方索引越界")
return
front_distance = msg.ranges[i]
rospy.loginfo("正前方障碍物距离: {:.2f} m".format(front_distance))
def main():
rospy.init_node('front_lidar_distance')
rospy.Subscriber('/scan', LaserScan, scan_callback)
rospy.spin()
if __name__ == '__main__':
main()
更多关于全国大学生智能汽车的分享,请访问个人主页。
期待你的评论与交流!