ROS机器人操作系统在机器人应用领域很流行,依托代码开源和模块间协作等特性,给机器人开发者带来了很大的方便。我们的机器人“miiboo”中的大部分程序也采用ROS进行开发,所以本文就重点对ROS基础知识进行详细的讲解,给不熟悉ROS的朋友起到一个抛砖引玉的作用。本章节主要内容:
1.ROS是什么
2.ROS系统整体架构
3.在ubuntu16.04中安装ROS kinetic
4.如何编写ROS的第一个程序hello_world
5.编写简单的消息发布器和订阅器
6.编写简单的service和client
7.理解tf的原理
8.理解roslaunch在大型项目中的作用
9.熟练使用rviz
10.在实际机器人上运行ROS高级功能预览
本篇文章已经收录在我最新出版的书籍《机器人SLAM导航核心技术与实战》,感兴趣的读者可以购买纸质书籍来进行更加深入和系统性的学习,购买链接如下:
点这里购买:《机器人SLAM导航核心技术与实战》购买链接
既然ROS已经成功安装好了,大家一定很想亲自动动手编一个通过起手式例程hello_world,可以学到工作空间的创建、功能包的创建、功能包的源代码编写、功能包的编译配置、功能包的编译、功能包的启动运行等知识。ROS的小程序试试手,没错,这一节就隆重请出程序界的起手式例程hello_world。
通过起手式例程hello_world,可以学到工作空间的创建、功能包的创建、功能包的源代码编写、功能包的编译配置、功能包的编译、功能包的启动运行等知识。
(1)工作空间的创建
打开命令行终端,分别输入如下命令:
#先切回主目录
cd ~/
#新建工作空间文件夹
mkdir catkin_ws
#在catkin_ws目录下新建src文件夹
cd catkin_ws
mkdir src
#初始化src目录,生成的CMakeLists.txt为功能包编译配置
cd src
catkin_init_workspace
#切回catkin_ws目录,对该工作空间执行一次编译
cd ~/catkin_ws
catkin_make
#环境变量配置,使新建的catkin_ws工作空间可用
source devel/setup.bash
这时,便已经创建好了一个ROS的工作空间了,接下来就是在catkin_ws工作空间下的src目录下新建功能包并进行功能包程序编写了,如果想了解工作空间的详细目录结构,请参考本章节(二)ROS入门——2.ROS系统整体架构这有对ROS的文件组织结构进行详解。
(2)功能包的创建
继续在命令行终端中,输入如下命令:
#在catkin_ws/src/下创建取名为hello_world的功能包,
#ROS功能包命名规范:只允许使用小写字母、数字和下划线,
#且首字符必须为一个小写字母。
cd ~/catkin_ws/src/
catkin_create_pkg hello_world
这时候在~/catkin_ws/src/目录下能看到一个叫hello_world的文件夹,文件夹名称就是功能包的名称以及功能包的唯一标识符,这个说明功能包创建成功了。
(3)功能包的源代码编写
由于我们只是要编写一个能打印“hello world”的程序,所以就很简单了,这里先以c++代码作为示范,后面会讲解python的。一些在线教程建议在你的功能包目录中创建src目录用来存放c++源文件,这个附加的组织结构是很有益处的,特别是对含有很多种类型文件的大型功能包,不过不是严格必要的。出于编程规范,我这里也会采用这样的建议把c++源文件放在功能包中的src目录下。
所以,首先在hello_world目录下新建src目录,再在新建的src目录下新建一个my_hello_world_node.cpp文件。这里的新建目录和文件的方法可以在图形界面下直接操作会更方便一点,如图11。
(图11)在功能包中新建文件夹及文件
用文本编辑器gedit打开my_hello_world_node.cpp文件,并输入如下内容。
#include “ros/ros.h”
int main(int argc,char **argv)
{
ros::init(argc,argv,"hello_node");
ros::NodeHandle nh;
ROS_INFO_STREAM("hello world!!!");
}
这里对代码做一个解析:
#include “ros/ros.h”
这一句是包含头文件ros/ros.h,这是ROS提供的C++客户端库,是必须包含的头文件,在后面的编译配置中要添加相应的依赖库roscpp。
ros::init(argc,argv,"hello_node");
这一句是初始化ros节点并指明节点的名称,这里给节点取名为hello_node,一旦程序运行后就可以在ros的计算图中被注册为hello_node名称标识的节点。
ros::NodeHandle nh;
这一句是声明一个ros节点的句柄,初始化ros节点必须的。
ROS_INFO_STREAM("hello world!!!");
这一句是调用了roscpp库提供的方法ROS_INFO_STREAM来打印信息,这里打印字符串"hello world!!!"。
(4)功能包的编译配置
声明依赖库:
对于我们的my_hello_world_node.cpp程序来说,我们包含了
首先,用文本编辑器gedit打开功能包目录下的CMakeLists.txt文件,在find_package(catkin REQUIRED ...)字段中添加roscpp,添加后的字段如下:
find_package(catkin REQUIRED COMPONENTS roscpp)
同时,找到include_directories(...)字段,去掉${catkin_INCLUDE_DIRS}前面的注释,如下:
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
添加好后的效果如图12所示。
(图12)在CMakeLists.txt中添加roscpp依赖库
然后,用文本编辑器gedit打开功能包目录下的package.xml文件,找到这样一句话
roscpp
roscpp
roscpp
添加好后的效果如图13所示。
(图13)在package.xml中添加roscpp依赖库
声明可执行文件:
就接下来,我们需要在CMakeLists.txt中添加两句,我的习惯在文件最后一行添加就好了,来声明我们需要创建的可执行文件。
add_executable(my_hello_world_node src/my_hello_world_node.cpp)
target_link_libraries(my_hello_world_node ${catkin_LIBRARIES})
第一行声明了我们想要的可执行文件的文件名,以及生成此可执行文件所需的源文件列表。如果你有多个源文件,把它们列在此处,并用空格将其区分开。
第二行告诉 Cmake 当链接此可执行文件时需要链接哪些库(在上面的 find_package 中定义)。如果你的包中包括多个可执行文件,为每一个可执行文件复制和修改上述两行代码。
添加好后的效果如图14所示。
(图14)在CMakeLists.txt声明可执行文件
(5)功能包的编译
功能包的编译配置好后,就可以开始编译了,这里有两种编译方式,一种是编译工作空间内的所有功能包,另一种是编译工作空间内的指定功能包,两种编译方式各有用处,下面分别讲解。
第一种,编译工作空间内的所有功能包:
cd ~/catkin_ws/
catkin_make
第二种,编译工作空间内的指定功能包:
其实就是加入参数 -DCATKIN_WHITELIST_PACKAGES=””,在双引号中填入需要编译的功能包名字,用空格分割。
cd ~/catkin_ws/
catkin_make -DCATKIN_WHITELIST_PACKAGES="hello_world"
(6)功能包的启动运行
首先,需要用roscore命令来启动ROS节点管理器,ROS节点管理器是所有节点运行的基础。
打开命令行终端,输入命令:
roscore
然后,用source devel/setup.bash激活catkin_ws工作空间,用rosrun
再打开一个命令行终端,分别输入命令:
cd ~/catkin_ws/
source devel/setup.bash
rosrun hello_world my_hello_world_node
看到有输出hello world!!!就说明程序已经正常执行了,按照我们的设计程序正常打印后会自动结束,如图15。
(图15)hello_world功能包中my_hello_world_node节点执行结果
到这里,恭喜你已经学会了ROS的第一个程序hello world!!!
如果大家对博文的相关类容感兴趣,或有什么技术疑问,欢迎加QQ技术交流群(117698356)
[1] 张虎,机器人SLAM导航核心技术与实战[M]. 机械工业出版社,2022.
购书链接:https://item.jd.com/13041503.html
下载更多资料:www.xiihoo.com
QQ技术讨论群: 117698356
B站视频教程:https://space.bilibili.com/66815220
Github源码:https://github.com/xiihoo/Books_Robot_SLAM_Navigation
Gitee源码(国内访问速度快):https://gitee.com/xiihoo-robot/Books_Robot_SLAM_Navigation
序
前言
编程基础篇
第1章 ROS入门必备知识
1.1 ROS简介 2
1.1.1 ROS的性能特色 2
1.1.2 ROS的发行版本 3
1.1.3 ROS的学习方法 3
1.2 ROS开发环境的搭建 3
1.2.1 ROS的安装 4
1.2.2 ROS文件的组织方式 4
1.2.3 ROS网络通信配置 5
1.2.4 集成开发工具 5
1.3 ROS系统架构 5
1.3.1 从计算图视角理解ROS架构 6
1.3.2 从文件系统视角理解ROS架构 7
1.3.3 从开源社区视角理解ROS架构 8
1.4 ROS调试工具 8
1.4.1 命令行工具 9
1.4.2 可视化工具 9
1.5 ROS节点通信 10
1.5.1 话题通信方式 12
1.5.2 服务通信方式 15
1.5.3 动作通信方式 19
1.6 ROS的其他重要概念 25
1.7 ROS 2.0展望 28
1.8 本章小结 28
第2章 C++编程范式
2.1 C++工程的组织结构 29
2.1.1 C++工程的一般组织结构 29
2.1.2 C++工程在机器人中的组织结构 29
2.2 C++代码的编译方法 30
2.2.1 使用g++编译代码 31
2.2.2 使用make编译代码 32
2.2.3 使用CMake编译代码 32
2.3 C++编程风格指南 33
2.4 本章小结 34
第3章 OpenCV图像处理
3.1 认识图像数据 35
3.1.1 获取图像数据 35
3.1.2 访问图像数据 36
3.2 图像滤波 37
3.2.1 线性滤波 37
3.2.2 非线性滤波 38
3.2.3 形态学滤波 39
3.3 图像变换 40
3.3.1 射影变换 40
3.3.2 霍夫变换 42
3.3.3 边缘检测 42
3.3.4 直方图均衡 43
3.4 图像特征点提取 44
3.4.1 SIFT特征点 44
3.4.2 SURF特征点 50
3.4.3 ORB特征点 52
3.5 本章小结 54
硬件基础篇
第4章 机器人传感器
4.1 惯性测量单元 56
4.1.1 工作原理 56
4.1.2 原始数据采集 60
4.1.3 参数标定 65
4.1.4 数据滤波 73
4.1.5 姿态融合 75
4.2 激光雷达 91
4.2.1 工作原理 92
4.2.2 性能参数 94
4.2.3 数据处理 96
4.3 相机 100
4.3.1 单目相机 101
4.3.2 双目相机 107
4.3.3 RGB-D相机 109
4.4 带编码器的减速电机 111
4.4.1 电机 111
4.4.2 电机驱动电路 112
4.4.3 电机控制主板 113
4.4.4 轮式里程计 117
4.5 本章小结 118
第5章 机器人主机
5.1 X86与ARM主机对比 119
5.2 ARM主机树莓派3B+ 120
5.2.1 安装Ubuntu MATE 18.04 120
5.2.2 安装ROS melodic 122
5.2.3 装机软件与系统设置 122
5.3 ARM主机RK3399 127
5.4 ARM主机Jetson-tx2 128
5.5 分布式架构主机 129
5.5.1 ROS网络通信 130
5.5.2 机器人程序的远程开发 130
5.6 本章小结 131
第6章 机器人底盘
6.1 底盘运动学模型 132
6.1.1 两轮差速模型 132
6.1.2 四轮差速模型 136
6.1.3 阿克曼模型 140
6.1.4 全向模型 144
6.1.5 其他模型 148
6.2 底盘性能指标 148
6.2.1 载重能力 148
6.2.2 动力性能 148
6.2.3 控制精度 150
6.2.4 里程计精度 150
6.3 典型机器人底盘搭建 151
6.3.1 底盘运动学模型选择 152
6.3.2 传感器选择 152
6.3.3 主机选择 153
6.4 本章小结 155
SLAM篇
第7章 SLAM中的数学基础
7.1 SLAM发展简史 158
7.1.1 数据关联、收敛和一致性 160
7.1.2 SLAM的基本理论 161
7.2 SLAM中的概率理论 163
7.2.1 状态估计问题 164
7.2.2 概率运动模型 166
7.2.3 概率观测模型 171
7.2.4 概率图模型 173
7.3 估计理论 182
7.3.1 估计量的性质 182
7.3.2 估计量的构建 183
7.3.3 各估计量对比 190
7.4 基于贝叶斯网络的状态估计 193
7.4.1 贝叶斯估计 194
7.4.2 参数化实现 196
7.4.3 非参数化实现 202
7.5 基于因子图的状态估计 206
7.5.1 非线性最小二乘估计 206
7.5.2 直接求解方法 206
7.5.3 优化方法 208
7.5.4 各优化方法对比 218
7.5.5 常用优化工具 219
7.6 典型SLAM算法 221
7.7 本章小结 221
第8章 激光SLAM系统
8.1 Gmapping算法 223
8.1.1 原理分析 223
8.1.2 源码解读 228
8.1.3 安装与运行 233
8.2 Cartographer算法 240
8.2.1 原理分析 240
8.2.2 源码解读 247
8.2.3 安装与运行 258
8.3 LOAM算法 266
8.3.1 原理分析 266
8.3.2 源码解读 267
8.3.3 安装与运行 270
8.4 本章小结 270
第9章 视觉SLAM系统
9.1 ORB-SLAM2算法 274
9.1.1 原理分析 274
9.1.2 源码解读 310
9.1.3 安装与运行 319
9.1.4 拓展 327
9.2 LSD-SLAM算法 329
9.2.1 原理分析 329
9.2.2 源码解读 334
9.2.3 安装与运行 337
9.3 SVO算法 338
9.3.1 原理分析 338
9.3.2 源码解读 341
9.4 本章小结 341
第10章 其他SLAM系统
10.1 RTABMAP算法 344
10.1.1 原理分析 344
10.1.2 源码解读 351
10.1.3 安装与运行 357
10.2 VINS算法 362
10.2.1 原理分析 364
10.2.2 源码解读 373
10.2.3 安装与运行 376
10.3 机器学习与SLAM 379
10.3.1 机器学习 379
10.3.2 CNN-SLAM算法 411
10.3.3 DeepVO算法 413
10.4 本章小结 414
自主导航篇
第11章 自主导航中的数学基础
11.1 自主导航 418
11.2 环境感知 420
11.2.1 实时定位 420
11.2.2 环境建模 421
11.2.3 语义理解 422
11.3 路径规划 422
11.3.1 常见的路径规划算法 423
11.3.2 带约束的路径规划算法 430
11.3.3 覆盖的路径规划算法 434
11.4 运动控制 435
11.4.1 基于PID的运动控制 437
11.4.2 基于MPC的运动控制 438
11.4.3 基于强化学习的运动控制 441
11.5 强化学习与自主导航 442
11.5.1 强化学习 443
11.5.2 基于强化学习的自主导航 465
11.6 本章小结 467
第12章 典型自主导航系统
12.1 ros-navigation导航系统 470
12.1.1 原理分析 470
12.1.2 源码解读 475
12.1.3 安装与运行 479
12.1.4 路径规划改进 492
12.1.5 环境探索 496
12.2 riskrrt导航系统 498
12.3 autoware导航系统 499
12.4 导航系统面临的一些挑战 500
12.5 本章小结 500
第13章 机器人SLAM导航综合实战
13.1 运行机器人上的传感器 502
13.1.1 运行底盘的ROS驱动 503
13.1.2 运行激光雷达的ROS驱动 503
13.1.3 运行IMU的ROS驱动 504
13.1.4 运行相机的ROS驱动 504
13.1.5 运行底盘的urdf模型 505
13.1.6 传感器一键启动 506
13.2 运行SLAM建图功能 506
13.2.1 运行激光SLAM建图功能 507
13.2.2 运行视觉SLAM建图功能 508
13.2.3 运行激光与视觉联合建图功能 508
13.3 运行自主导航 509
13.4 基于自主导航的应用 510
13.5 本章小结 511
附录A Linux与SLAM性能优化的探讨
附录B 习题