欢迎大家阅读2345VOR的博客【6. 激光雷达接入ROS】🥳🥳🥳
2345VOR鹏鹏主页: 已获得CSDN《嵌入式领域优质创作者》称号👻👻👻,座右铭:脚踏实地,仰望星空🛹🛹🛹
🎏🎏主要开发专栏🎏🎏
《arduino学习》:学习最简单开源便利的单片机Arduino,与时俱进😆😆😆
《Arduino编程参考》:本专栏围绕Arduino语法和Arduino库使用开发;🌻🌻🌻
《 Arduino小项目开发》:本专栏围绕Arduino生态结合实际需求设计综合的小项目开发。🌼🌼🌼
《HomeAssistant》:介绍homeassistant中基本开发, 重点设计esphome和nodered开发,包含小爱同学打印机等诸多设备添加。🎉🎉🎉
本文章属于《Ubuntu学习》和《ROS机器人学习》
:围绕Ubuntu系统基本配置及相关命令行学习记录!机器人操作系统 (ROS) 是一组软件库和工具,可帮助您构建机器人应用程序。👍👍👍
1. 前言
Ubuntu环境搭建
 【经典Ubuntu20.04版本U盘安装双系统教程】
 【Windows10安装或重装ubuntu18.04双系统教程】
 【Ubuntu同步系统时间】
 【Ubuntu中截图工具】
 【Ubuntu安装QQ】
 【Ubuntu安装后基本配置】
 【Ubuntu启动菜单的默认项】
 【ubuntu系统中修改hosts配置】
 【18.04Ubuntu中解决无法识别显示屏】
 ROS学习笔记
 【1. Ubuntu18.04安装ROS Melodic】
 【2. 在Github上寻找安装ROS软件包】
 【3. 初学ROS,年轻人的第一个Node节点】
 【4. ROS的主要通讯方式:Topic话题与Message消息】
 【5. ROS机器人的运动控制】
接下来学习激光雷达如何接入ros机器人,激光雷达是用来探测周围障碍物的分布状况!
 
2. 激光雷达分类
其按照测量的维度可以分为单线雷达和多线雷达

 按照测量原理分为三角测距雷达和TOF雷达

 根据工作方式分为机械旋转雷达和固态雷达

 激光雷达虽各有不同,但是在ROS中呈现的数据格式是一样的,只是在数据完整度和精度上会有所差异。下面就选取TOF激光雷达作为例子
3. TOF和三角测距激光雷达
3.1 何为飞行时间测距(TOF)?
简单来说,就是计算光的“飞行时间”。

由激光器发射一个激光脉冲,通过计时器记录下光的出射和回返的时间,两个时间相减即可得到光的“飞行时间”,而光速是固定的,根据已知速度和时间就可以计算出距离。
3.2 何为三角测距?
三角测距采用激光器发射激光,在照射到物体之后,反射光会由线性CCD接收,因为激光器和探测器间隔了一段距离,所以根据光学路径,不同距离的物体将会在CCD上成像在不同的位置,按照三角公式进行计算,就可以推导出被测物体的距离。
 
3.3 激光雷达测距
TOF激光雷达计算如下
 

4. 使用RViz观测传感器数据
RViz这个工具的全名叫做 The Robot Visualization Tool

4.1 运行模板样机
打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rviz
 
首先把这个Fixed Frame修改成base_footprint

 状态栏添加机器人模型,最后点击ok
 
 选择激光雷达的话题名称/scan

 调整size为0.03
 
 调整RViz和Gazebo分屏

 Gazebo是模拟真实机器人发出传感器数据的工具
 RViz显示的是机器人实际能探测到的环境状况
 
 
 另外一点就是RViz并不参与机器人算法的运行,它只是一个为了方便人类进行观测的工具而已
 即使没有RViz,也不影响机器人的ROS系统的运行
 只有需要观察某些数据实时变化的时候,才会打开RViz
 下面添加虚拟环境的圆柱体障碍物
 

4.2 保存RViz配置
点击file菜单,选择Save Config As
 
 选择保存地址,方便后期直接加载
 
 然后关闭所有终端
 打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rviz
 
然后在RViz中的file菜单,选择Open Config
 
 然后选择刚保存的位置

4.3 自动加载rviz配置文件
还可以在launch文件里自动加载rviz配置文件
 先关闭RViz,然后打开终端输入
roslaunch wpr_simulation wpb_rviz.launch
 

 关闭摄像头,保留激光雷达
 
 调整视角
 
5. ROS系统中的激光雷达消息包格式
5.1 运行模板样机
打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
roslaunch wpr_simulation wpb_rviz.launch
 

在Gazebo中围绕机器人堆积障碍物
 
5.2 sensor_msgs中Laserscan_msgs消息属性
进入ROS Index官网搜索sensor_msgs
 

 进入website
 
 在消息中找到LaserScan
 
 这就打开了激光雷达消息包的格式定义

 
5.3 查看scan消息
新开终端输入
rostopic echo /scan --noarr
 

 显示对比

 
 
 
 
 
 
 
 
6. 用C++获取ROS激光雷达数据节点
6.1 运行模板样机
采用wpr_simulation开源工程,打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rosrunwpr_simulation deno_lidar_data
 

6.2 构思功能的思路和步骤
构思
 
 实现步骤
- 构建一个新的软件包,包名叫做lidar_pkg。
 - 在软件包中新建一个节点,节点名叫做lidar_node。
 - 在节点中,向ROS大管家NodeHandle申请订阅话题/scan,并设置回调函数为LidarCallback()。
 - 构建回调函数LidarCallback(),用来接收和处理雷达数据。
 - 调用ROS_INFO()显示雷达检测到的前方障碍物距离。
 
6.3 创建lidar_pkg包
在工作空间src文件创建基于sensor_msgs模板的lidar_pkg
cd ~/catkin_ws/src/
catkin_create_pkg lidar_pkg roscpp rospy sensor_msgs
 

 在lidar_pkg文件夹下src中创建lidar_node.cpp
 

6.4 编写订阅者节点
lidar_node源码
#include <ros/ ros.h>
#include <sensor msgs/Laserscan.h>
void Lidarcallback(const sensor_msgs::LaserScan msg)
{
	float fMidDist = msg.ranges[180] ;
	ROS_INFO("前方测距ranges [180]=%f 米", 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();
	return 0;
}
 
ctrl+s快捷保存
6.5 设置C++编译规则
打开CMake文件
add_executable(lidar_node src/lidar_node.cpp)
target_link_libraries(lidar_node
	${catkin_LIBRARIES}
)
 
ctrl+s快捷保存
 
 ctrl+shift+b快捷编译
6.6 编译运行lidar_node节点
编译,打开终端
cd ~/catkin_ws/
catkin_make
 
采用wpr_simulation开源工程,打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rosrun lidar_pkg lidar_node
 

 前方距离2.6m,然后在Gazebo中调整书柜,选择移动靠近机器人
 
 
 
 可参照可以打开.wpr_simulation里的demo_lidar_data.cpp文件

7. 用python获取ROS激光雷达数据节点
7.1 运行模板样机
采用wpr_simulation开源工程,打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rosrun wpr_simulation deno_lidar_data.py
 

7.2 构思功能的思路和步骤
构思
 
 实现步骤
- 构建一个新的软件包,包名叫做lidar_pkg。
 - 在软件包中新建一个节点,节点名叫做lidar_node.py。
 - 在节点中,向ROS大管家rospy申请订阅话题/scan,并设置回调函数为LidarCallback()。
 - 构建回调函数LidarCallback(),用来接收和处理雷达数据。
 - 调用loginfo()显示雷达检测到的前方障碍物距离。
 
7.3 创建lidar_pkg包
在工作空间src文件创建基于sensor_msgs模板的lidar_pkg,编译
cd ~/catkin_ws/src/
catkin_create_pkg lidar_pkg roscpp rospy sensor_msgs
cd ..
catkin_make
 

在lidar_pkg文件夹下新建script文件夹中创建lidar_node.py
 

7.4 编写订阅者节点
先引入python包,设置中文utf-8显示
- ros>=20.04,采用python3
 - ros<20.04,采用python
 
lidar_node.py源码
#!/usr/bin/env python3
#coding=utf-8
import rospy
from sensor_msgs.msg import LaserScan
def Lidarcallback(msg):
	dist = msg.ranges [ 180]
	rospy.loginfo("前方测距 ranges [ 180] = %f 米" , dist)
if _name ="_main_":
	rospy.init_node( "lidar_node" )
	lidar_sub = rospy.Subscriber( " /scan" ,LaserScan,Lidarcallback,queue_size=10)
	rospy.spin()
 
ctrl+s快捷保存
7.5 添加可执行的权限
在所在文件夹打开终端
cd catkin_ws/src/lidar_pkg/scripts/
ls
chmod +x lidar_node.py
ls
 
文件名变成绿色表示权限添加成功

7.6 运行lidar_node节点
采用wpr_simulation开源工程,打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rosrun lidar_pkg lidar_node.py
 

前方距离2.6m,然后在Gazebo中调整书柜,选择移动靠近机器人
 
 
 
 可参照可以打开wpr_simulation里的script文件夹中创建lidar_node.py

8. 用C++编写激光雷达避障节点

 基于前面学习的机器人运动控制和激光雷达数据,下面将联系这两点编写激光雷达避障节点
8.1 构思功能的思路和步骤
- 让大管家NodeHandle 发布速度控制话题/cmd_vel 。
 - 构建速度控制消息包vel_cmd。
 - 根据激光雷达的测距数值,实时调整机器人运动速度,避开障碍物。
 
8.2 修改lidar_node.cpp

 见6.4源码
 修改成如下lidar_node源码
#include <ros/ ros.h>
#include <sensor msgs/Laserscan.h>
#include <geometry msgs/Twist.h>
ros::Publisher vel_pub;
void Lidarcallback(const sensor_msgs::LaserScan msg)
{
	float fMidDist = msg.ranges[180] ;
	ROS_INFO("前方测距ranges [180]=%f 米", fMidDist);
	geometry msgs::Twist vel_cmd ;
	if( fMidDist< 1.5)
	{
		vel_cmd.angular.z = 0.3;
	}
	else
	{
		vel_cmd.linear.x = 0.05;
	}
	vel_pub.publish(vel_cmd);
}
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();
	return 0;
}
 
ctrl+s快捷保存
ctrl+shift+b快捷编译
 
8.4 运行lidar_node节点
采用wpr_simulation开源工程,打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rosrun lidar_pkg lidar_node
 

 机器人撞到障碍物,机器人有宽度
8.4 优化避障策略
当机器人检测前方障碍物时,最简单把转弯角度调大一点,原地转弯
 lidar_node源码
#include <ros/ ros.h>
#include <sensor msgs/Laserscan.h>
#include <geometry msgs/Twist.h>
ros::Publisher vel_pub;
int ncount = 0;
void Lidarcallback(const sensor_msgs::LaserScan msg)
{
	float fMidDist = msg.ranges[180] ;
	ROS_INFO("前方测距ranges [180]=%f 米", fMidDist);
	if(ncount > 0)
	{
		ncount--;
		return;
	}
	
	geometry msgs::Twist vel_cmd ;
	if( fMidDist< 1.5)
	{
		vel_cmd.angular.z = 0.3;
		ncount = 50;
	}
	else
	{
		vel_cmd.linear.x = 0.05;
	}
	vel_pub.publish(vel_cmd);
}
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();
	return 0;
}
 
ctrl+s快捷保存
ctrl+shift+b快捷编译
 然后在调试就OK啦
 可参照开源项目wpr_simulation下的src文件夹的demo_lidar_behavior.cpp

9. 用python编写激光雷达避障节点
9.1 构思功能的思路和步骤
构思
 
 实现步骤
- 让大管家rospy 发布速度控制话题/cmd_vel 。
 - 构建速度控制消息包vel_cmd。
 - 根据激光雷达的测距数值,实时调整机器人运动速度,避开障
碍物。 
9.2 修改lidar_node.py
打开7.4编写lidar_node.py
 
lidar_node.py源码
#!/usr/bin/env python3
#coding=utf-8
import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist
count =0
def Lidarcallback(msg):
	global vel_pub
	global count
	dist = msg.ranges [ 180]
	rospy.loginfo("前方测距 ranges [ 180] = %f 米" , dist)
	
	if count > 0:
		count = count - 1
		return
	
	vel_cmd = Twist()
	if dist< 1.5:
		vel_cmd .angular.z = 0.3
	else:
		vel_cmd.linear.x = 0.05
	vel_pub.publish(vel_cmd)
	
if _name ="_main_":
	rospy.init_node( "lidar_node" )
	lidar_sub = rospy.Subscriber( " /scan" ,LaserScan,Lidarcallback,queue_size=10)
	vel_pub = rospy.Publisher( " /cmd_vel" ,Twist , queue_size=10)
	rospy.spin()
 
ctrl+s快捷保存
6.6 运行lidar_node节点
采用wpr_simulation开源工程,打开三个终端分别运行三条指令
roscore
roslaunch wpr_simulation wpb_simple.launch
rosrun lidar_pkg lidar_node.py
 

 可参照可以打开wpr_simulation里的script文件夹中demo_lidar_behavior.py
 
10. 总结
本节学习了ROS机器人的激光雷达原理和数据查看,尝试C++和python两种语言编写,并且结合前面的机器人运动编写了避障节点,接下来会介绍机器人的IMU传感器的操作。🎉🎉🎉

















