type
status
date
slug
summary
tags
category
icon
password
文章前言:
本文主要介绍ROS的一些内容。
⭐ 主旨内容
ROS:类似于安卓,本质上是通过不同node(APP)组合而成的,通过不同node实现不同的效果。——一种分布式、搭积木方式的机器人操作系统。
- 构建环境:Ubuntu
- 版本选择
- 项目要求(版本一致)
- 硬件驱动(最新信号)
- 实验环境
- 机器人厂家
- 仿真平台
安装与环境配置
- 安装网址:www.ros.org。安装过程参考官网。
- 如果安装卡主了,需要终止安装过程。(大概率是网络问题)
Node节点和Package安装包
ROS节点的不同功能都是通过不同的节点来实现完成的。
node节点必须要使用包为单位进行安装。
创建package软件包
- catkin_create_pkg ssr_pkg rospy roscpp std_msga
- catkin_create_pkg:用catkin工具创建一个package包。
- ssr_pkg:是包的名字。
- rospy、roscpp、std_maga:相当于标准库的包。
创建node节点
- 创建一个chao_node.cpp文件
- 编写节点代码
- 添加头文件#include<ros/ros.h>
- 主函数main中去掉const
- 设置中文环境setlocale(LC_ALL,"zh_CN.UTF-8”)
- 编写节点代码:具体功能实现
- 描述编译条件的配置文件CMakeLists.txt
- 为新建的节点增加编译规则

node节点初始化
- 函数里增加ros::init(argc,argv,”chao_node”)。
- 如果希望一直保存运行应该使用while(ros::ok),这样在循环的时候才能响应各种外部信号。(区别于while(true))
编译运行
- 启动ros系统:roscore
- 编译
- Vscode:Ctrl+Shift+B编译
- 终端:进入工作目录cd catkin_ws/编译catkin_make
- 启动仿真环境roslaunch wpr_simulation wpb_simple.launch
- 启动节点rosrun lidar_pkg lidar_node
节点通讯方式:Topic话题与Message消息
类似于mqtt?
Topic话题
- 话题Topic是节点间进行持续通讯的一种形式。
- 话题通讯的两个节点是通过话题的名称建立起话题通讯连接。
- 消息的发送方叫做话题的发布者Publisher。
- 消息的接收方叫做话题的订阅者Subscriber。
- 话题中通讯的数据叫做message。
- 消息Message通常会按照一定的频率持续不断的发送,以保证消息数据的实时性。
- 各种复杂的消息类型都是由各种基础的消息类型组成,可以将消息类型理解为结构体。
外延补充
- 一个ROS节点网络中可以同时存在多个话题。
- 不同的传感器通常会有各自独立的话题。
- 一个话题通常由一个发布者发布,被多个订阅者订阅,但是当存在多个发布者时,同一时间只存在一个发言人。
常用指令
- rostopic list:列出当前系统中所有活跃着的话题。
- rostopic echo 主题名称:显示指定话题中发送的消息包内容。
- rostopic hz 主题名称:统计指定话题中消息包发送频率
Publisher发布者的C++实现
- include消息类型对应的头文件<std_msgs/String.h>
- 通过NodeHandler大管家发布一个话题并得到消息发送对象
- ros::NodeHandle nh;
- ros::Publisher pub=nh.advertise<std_msgs::String>("话题名称”,缓存长度)
- 生成要发送的消息包,并进行发送数据的赋值。
- std_msgs::String msg;
- msg.data="消息内容”
- 调用消息发送对象的publish()函数将消息包发送到话题当中。
- pub.publish(msg);
- 频率控制
- 定义ros::Rate loop_rate(频率);
- 在while里阻塞loop_rate.sleep();
Subscriber订阅者的C++实现
- include消息类型对应的头文件<std_msgs/String.h>
- 通过NodeHandler大管家发布一个话题并得到消息发送对
- ros::NodeHandle nh;
- ros::Subscriber pub=nh.advertise<std_msgs::String>("话题名称”,缓存长度,回调函数)
- 在main函数前定义回调函数(对到达消息包的响应)
- void chao_callback(std_msgs::String msg)
- printf(msg.data.c_str());这里String类型与printf的char*类型不匹配所以要进行转换
- printf("\n”);
- 这里也可以使用ROS_INFO和ROS_WARN进行消息的显示
- while
- ros::spinOnce();轮询接收消息
图形化显示话题通讯关系rqt_graph


话题是谁的话题?
话题并不只属于创建者和发布者,而是由ros系统创建并发布的。
使用launch文件启动节点
- 一种遵循XML的描述文件
- 功能之一:批量启动ROS节点

ROS机器人控制
矢量运动
- 矢量运动:坐标系方向上的位移,具体的位移方向要看机器的底盘支持哪些方向,可能是一维、二维或者三维。
- 矢量单位:m/s
- 矢量坐标:以机器人的底牌中心点为坐标远点,使用右手定则建立一个笛卡尔坐标系,食指指向X轴,中指指向Y轴,大拇指指向Z轴。
旋转运动
旋转运动:包括普通的旋转运动,以及滚转运动和俯仰运动。
旋转单位:rad/s
旋转坐标:使用右手螺旋定则,右手比一个点赞。
- 将大拇指指向X轴的方向,此时四指的方向就是机器人滚转运动的正方向。
- 将大拇指指向Y轴的方向,此四指的方向就是机器人俯仰运动的正方向。
- 将大拇指指向Z轴的方向,此四指的方向就是机器人自转运动的正方向。

在ROS的机器人运动控制中,Twist定义为旋量,是一个六维的向量,可以同时描述矢量运动和旋转运动。

速度控制节点通过/cmd_vel话题来控制机器人核心节点。

用C++实现机器人的运动控制
- 构建一个软件包vel_pkg
- 新建节点vel_node
- 在节点中向ROS大管家NodeHandle申请发布话题/cmd_vel,并拿到发布对象vel_pub。
- 构建一个geometry_msgs/Twist类型的消息包vel_msg,用来承载要发送的速度值。
- 开启一个while循环,不停的使用vel_pub对象发送速度消息包vel_msg。

激光雷达
分类
- 按测量的维度:单线雷达和多线雷达
- 按测量的原理:三角测距雷达和TOF雷达
- 按工作方式:机械旋转雷达和固态雷达
TOF雷达
工作原理:机器人发出一道激光,当遇到障碍物的时候,激光反射回来。机器人360度探测一周,就完成了一次对周围障碍物的探测。
- 时长×光速=飞行长度
- 飞行长度÷2=障碍物距离

RViz:The Robot visualization Tool
一个方便我们对机器人数据进行实时观测的可视化工具。
- Cazebo是模拟机器人发出传感器数据,所观测到的是虚拟机器人所处的环境状况。
- 启动rosaunch wpr_simulation wpb_simple.launch
- RViz是接收传感器数据并进行显示的工具,它显示的是机器人实际能探测的数据。
- 启动rosaunch wpr_simulation wpb_rviz.launch
激光雷达消息包格式

scan_time即单次扫描的持续时间,即雷达旋转一周所耗费的时间。

range即雷达扫描的直径距离。

range[n]即第几个测距点的距离,对于超过range_max的点,记作INF。
intensities即测距返回的信号强度。
用C++实现激光雷达测距
- 构建一个软件包lidar_pkg
- 新建节点lidar_node
- 在节点中向ROS大管家NodeHandle申请订阅话题/scan,并设置回调函数为LidarCallback()
- 构建回调函数LidarCallback(),用来接收和处理雪达数据。
- 调用ROS_INFO()显示雷达检测到的前障碍物距离。
用C++实现激光雷达避障
- 让大管家NodeHandle发布速度控制话题/cmd_vel
- 构建速度控制消息包
- 根据激光雷达的测距数值,实时调整机器人运动速度,避开障碍物。
IMU消息包
IMU,Inertial Measuremet Unit惯性测量单元,用于测量机器人的空间姿态。

使用C++实现IMU数据获取
- 构建一个软件包imu_pkg
- 新建一个节点imu_node
- 向ROS大管家NodeHandle申请订阅话题/imu/data,并设置回调函数为IMUCallback()
- 构建回调函数IMUCallback(),用来接收和处理IMU数据。
- void IMUCallback(sensor_msgs::Imu msg)
- 使用TF工具将四元数转换成欧拉角。


- 调用ROS_INFO()显示转换后的欧拉角数值。

消息包
标准消息包std_maga

常规消息包common_msgs

几何消息包geometry_msgs

其中含有Stamped的消息包多了时间和坐标系ID,即将空间量和时间量进行了绑定。
传感器消息包sensor_msgs

自定义消息包
生成自定义消息
- 创建新软件包,增加依赖项message_generation,message_runtime。
- 软件包添加msg目录,新建自定义消息文件,以.msg结尾。

- 修改CMakeLists.txt
- 依赖包
- 添加新的消息包文件
- 新消息包文件的依赖包
- 使依赖我们的新消息包的其他软件包在运行时能够使用我们新定义的消息类型




- 修改package.xml

- 检查是否修改成功
- Ctrl+Shift+B编译/catkin_make编译
- rosmsg show qq_msgs/Carry

自定义消息类型在C++节点中的应用
栅格地图
栅格尺寸,即栅格边长,栅格尺寸体现了地图的精细程度,常常被用来表示栅格地图的分辨率。
C++节点发布地图
栅格数值
- 100:障碍物占据
- 0:无障碍物
- -1:栅格里的障碍物状况未知
发布地图
- 构建软件包map_pkg,依赖项加上nav_msgs
- 创建新节点map_pub_node
- 在节点中发布话题/map,消息类型为nav_msgs::OccupancyGrid
- 构建一个nav_msgs::OccupancyGrid地图消息包,并对其赋值
- 将地图消息包发送到话题/map
- 编译并运行节点
- 启动RViz,订阅话题/map,显示地图
SLAM
Hector_mapping
即SLAM在ROS中的实现方法之一。
launch启动Hector_mapping
- 创建slam_pkg软件包,创建launch文件夹,创建hector.launch文件
- 包含依赖项lanuch文件
- <include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch” />
- 节点启动指令
- <node pkg="包名” type="节点名” name="hector_mapping” />
- 参数args="-d $(find slam_pkg)/rviz/slam.rivz”加入到node中即可使rviz自动读取配置文件启动。
- 启动launch文件:roslaunch slam_pkg hector.launch
Hector_mapping参数设置
TF系统
机器人在地图中的位置描述方式。
map:地图坐标系——父坐标系
base_footprint:机器人坐标系——子坐标系
TF,即TransForm,主要描述两个坐标系的空间关系,即坐标系变换
- TF发布节点 ——> TF话题/TF ——> TF订阅节点
- 查看TF的消息格式的类型rostopic type /tf为tf2_msgs
- rosrun tf_tree tf_tree查看TF树获取所有的空间坐标关系
里程计odometry
里程计,原理是通过电机转速计算机器人的位移,在驱动节点运行,输送到/tf节点。
- 圈数 * 周长 = 距离
但是由于存在轮子打滑等情况,实际上我们计算得到的结果必然会与实际情况存在一定的偏差,误差累计过多会出现严重错误。
障碍物点云配准的定位算法,当激光雷达所在位置得到的雷达点云和里程计估算位置得到的点云未重合,说明存在误差需要进行修正。由于base_footprint被里程计占用,因此我们在map后增加一个odom来修正,如下图所示,构成一个平行四边形,就形成了map到base_footprint的TF。
Gmapping核心算法
- 通过里程计推算机器人的位移。
- 通过雷达点云贴合障碍物的轮廓,确定base_footprint的位置。
- 增加map到odom的修正值,通过构建平行四边形得到map到base_footprint的完整TF。
区别于HectorMapping
- HectorMapping输出的这段map到odom的TF,目的不是为了修正里程计的误差,而是为了让base_footprint的位置始终和scanmatcher_frame保持一致。
- Gmaping算法中,机器人的位移主要是由里程计推算,激光雷达配准算法修正里程计的误差。
- HectorMapping,丝毫不考虑里程计的数据,只使用雷达点云和障碍物配准的方法来进行定位。
- 但是为了RViz里能显示地图和机器人模型,勉为其难输出一段map到dodom的TF。
Gmapping的使用
需求列表
- rostopic list查找:/scan
- rostopic echo /scan --noarr查找话题中雷达坐标系的名称laser
- laser ——> base_link
- base_link ——> odom
- rosrun rqt_tf_tree rqt_tf_tree确认含有上述两条即可运行Gmapping
运行
- rosrun gmappig slam_gmapping
- rosrun rviz rviz
- 键盘控制指令
- wasd控制移动方向
- qe控制左右旋转
- 空格刹车
- x退出
launch启动Gmapping建图
- 创建新软件包slam_pkg
- 创建一个launch文件夹
- 创建gmapping.launch文件
- 编写launch文件
- 编译后运行gmapping文件rolaunch slam_pkg gmapping.launch
- 注:运行后rviz需要重新配置,在slam_pkg中新建rviz文件夹保存gmapping.rviz配置文件,通过args使用-d指令即可使用该配置。
Gmapping参数设置


地图的保存与加载
- 在地图运行的情况下使用指令rosrun map_server map_saver -f [文件名]保存得到.pgm和.yaml文件
- map.pgm是地图图片文件
- map.yaml保存相关的地图参数
- rosrun map_server map_server mymap.yaml
- 启动rviz
- 添加地图显示项目map
📎 参考文章
【机器人操作系统 ROS 快速入门教程】 https://www.bilibili.com/video/BV1BP4y1o7pw/?share_source=copy_web&vd_source=cb3b4606945b28b2ebce47d533fdd41d
有关问题,欢迎您在底部评论区留言,一起交流~
- Author:Koreyoshi
- URL:https://tangly1024.com/article/2c0c7b13-c6a7-80ec-a76f-d89589f16844
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts









