1. 简介
ROS 全称为 Robot Operating System (机器人操作系统)
- ROS 是适用于机器人的开源元操作系统
- ROS 集成了大量的工具,库,协议,提供类似 OS 所提供的功能,简化对机器人的控制
- ROS 还提供了用于在多台计算机上获取,构建,编写和运行代码的工具和库,ROS 在某些方面类似于“机器人框架”
- ROS 设计者将 ROS 表述为 “ROS = Plumbing + Tools + Capabilities + Ecosystem”,即 ROS 是通讯机制、工具软件包、机器人高层技能以及机器人生态系统的集合体
1.1. 系统架构
ROS 的系统架构可分为三层
- OS 层,也即经典意义的操作系统。ROS 只是元操作系统,需要依托真正意义的操作系统,目前兼容性最好的是 Linux 的 Ubuntu,Mac、Windows 也支持 ROS 的较新版本
- 中间层。是 ROS 封装的关于机器人开发的中间件,比如:
- 基于 TCP/UDP 继续封装的 TCPROS/UDPROS 通信系统
- 用于进程间通信 Nodelet,为数据的实时性传输提供支持
- 大量的机器人开发实现库,如:数据类型定义、坐标变换、运动控制…
- 应用层。功能包,以及功能包内的节点,比如: master、turtlesim的控制与运动节点。
1.2. 文件系统
WorkSpace --- 自定义的工作空间
|--- build:编译空间,用于存放CMake和catkin的缓存信息、配置信息和其他中间文件。
|--- devel:开发空间,用于存放编译后生成的目标文件,包括头文件、动态&静态链接库、可执行文件等。
|--- src: 源码
|-- CMakeLists.txt: 编译的基本配置
|-- package:功能包(ROS 基本单元)包含多个节点、库与配置文件,包名所有字母小写,只能由字母、数字与下划线组成
|-- CMakeLists.txt 配置编译规则,比如源文件、依赖项、目标文件
|-- package.xml 包信息,比如:包名、版本、作者、依赖项...(以前版本是 manifest.xml)
|-- scripts 存储 python 文件
|-- src 存储 C++ 源文件
|-- include 头文件
|-- msg 消息通信格式文件
|-- srv 服务通信格式文件
|-- action 动作格式文件
|-- launch 可一次性运行多个节点
|-- config 配置信息
|-- package
ROS 的文件系统本质上都还是操作系统文件,因此可以使用 Linux 命令来操作这些文件。不过,在 ROS 中为了更好的用户体验,ROS 专门提供了一些类似于 Linux 的命令,这些命令较之于 Linux 原生命令,更为简洁、高效。
- 增
# 创建新的ROS功能包
catkin_create_pkg 自定义包名 依赖包
# 安装 ROS 功能包
sudo apt install xxx
- 删
# 删除某个功能包
sudo apt purge xxx
- 查
# 列出所有功能包
rospack list
# 查找某个功能包是否存在,如果存在返回安装路径
rospack find 包名
# 进入某个功能包
roscd 包名
# 列出某个包下的文件
rosls 包名
# 搜索某个功能包
apt search xxx
- 改
# 修改功能包文件(需要安装 vim)
rosed 包名 文件名
- 执行
# 必须运行 roscore 才能使 ROS 节点进行通信,他是 ROS 的系统先决条件节点和程序的集合。运行 roscore 会运行 ros master、ros 参数服务器、rosout 日志节点
roscore
# 或(指定端口号)
roscore -p xxxx
# 运行指定的ROS节点
rosrun 包名 可执行文件名
# 执行某个包下的 launch 文件
roslaunch 包名 launch文件名
1.3. 计算图
ROS 文件结构是磁盘上 ROS 程序的存储结构,是静态的,而 ros 程序运行之后,不同的节点之间是错综复杂的,ROS 中提供了一个实用的工具:rqt_graph
rqt_graph 能够创建一个显示当前系统运行情况的动态图形。ROS 分布式系统中不同进程需要进行数据交互,计算图可以以点对点的网络形式表现数据交互过程。rqt_graph 是 rqt 程序包中的一部分
运行 rat_graph 可通过下面命令执行:
rosrun rqt_graph rqt_graph
# 或者直接输入
rqt_graph
1.4. Source
- 下面命令是使得能够在任意终端都能使用 ROS
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
- 下面命令是使得能够在任意终端都能使用当前工作空间
echo "source ~/工作空间/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc
1.5. helloworld
ROS 可是使用 C++ 或者 Python,但是具体选择哪种语言需要视需求而定:C++ 运行效率高但是编码效率低,而 Python 则反之。基于二者互补的特点,ROS 设计者分别设计了 roscpp 与 rospy 库,前者旨在成为 ROS 的高性能库,而后者则一般用于对性能无要求的场景,旨在提高开发效率
1.5.1. C++ 实现
- 进入 ros 包的 src 目录编辑源文件
#include "ros/ros.h"
int main(int argc, char *argv[]) {
//执行 ros 节点初始化,输入所有参数并对节点命名。注意,节点名称是一个标识符,需要保证在 ROS 网络拓扑中唯一
ros::init(argc,argv,"hello");
//创建 ros 节点句柄。注意,因为一个进程上运行一个节点,所以句柄是自动绑定到当前的进程,即节点上的
ros::NodeHandle n;
//控制台输出 hello world
ROS_INFO("hello world!");
return 0;
}
- 编辑 ros 包下的 Cmakelist.txt 文件
add_executable(可执行文件名
src/步骤3的源文件名.cpp
)
target_link_libraries(可执行文件名
${catkin_LIBRARIES}
)
-
返回顶层工作空间目录并编译(生成 build 和 devel):
catkin_make
-
执行
- 在一个终端输入命令启动 ROS 核心:
roscore
- 再在另一个终端输入命令刷新环境变量并运行节点:
- 在一个终端输入命令启动 ROS 核心:
source ./devel/setup.bash
rosrun 包名 可执行文件名
命令行输出: HelloWorld!
1.5.2. Python 实现
- 进入 ros 包的 scripts 目录编辑 python 文件(C++是进入同级的 src 目录)
#! /usr/bin/env python
import rospy
if __name__ == "__main__":
rospy.init_node("Hello")
rospy.loginfo("HelloWorld!")
- 为 python 文件添加可执行权限
chmod +x 文件名.py
- 编辑 ros 包下的 CamkeList.txt 文件
catkin_install_python(PROGRAMS
scripts/文件名.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
-
返回顶层工作空间目录并编译:
catkin_make
-
执行
- 在一个终端输入命令启动 ROS 核心:
roscore
- 再在另一个终端输入命令刷新环境变量并运行节点:
- 在一个终端输入命令启动 ROS 核心:
source ./devel/setup.bash
rosrun 包名 文件名.py
输出结果:HelloWorld!
另外,因为 Python 文件运行不需要编译,所以在编写完脚本后,可以直接运行节点
rosrun 包名 文件名.py
或者直接运行 Python 文件
python 文件名.py
2. 通信
机器人是一种高度复杂的系统性实现,在机器人上可能集成各种传感器(雷达、摄像头、GPS…)以及运动控制实现,为了解耦合,在 ROS 中每一个功能点都是一个单独的进程,每一个进程都是独立运行的。更确切的讲,ROS 是进程(也称为 Nodes)的分布式框架。 因为这些进程甚至还可分布于不同主机,不同主机协同工作,从而分散计算压力。而为了实现不同进程之间的通信,ROS 提供了三种方式:
- 话题通信(发布订阅模式)
- 服务通信(请求响应模式)
- 参数服务器(参数共享模式)
2.1. 话题通信
2.1.1. 简介
- ROS 中使用最多的通信方式
- ROS 中的异步通信方式
- 通过 TCP/IP 通信
- Node 之间通过 publish-subscribe 机制通信
- 能够进行多对多通信
- 常用于连续、高频的数据发布:激光雷达、里程计发布数据
- Message:
- topic 内容的数据格式
- 定义在 .msg 文件中
- 可以看作是一个结构体或者类
2.1.2. 理论模型
话题通信理论模型中涉及到三个角色。其中,ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接&#x