1.ROS概述
1.1 ROS安装
这部分建议完全参考ROS官网的安装教程,非常详细也非常清晰。 需要注意的是,安装时候中文页面与英文页面的安装教程是不同的,建议将语言选择为中文再进行安装。 此外,它们的链接地址也是不同的。以我使用的ubuntu18.04下的melodic版本为例: 中文页面的链接为http://wiki.ros.org/cn/melodic/Installation/Ubuntu 英文页面的链接为http://wiki.ros.org/melodic/Installation/Ubuntu
1.2 ROS架构
一般我们可以从设计者、维护者、系统结构与自身结构4个角度来描述ROS结构:
-
设计者 ROS设计者将ROS表述为“ROS = Plumbing + Tools + Capabilities + Ecosystem” Plumbing: 通讯机制(实现ROS不同节点之间的交互) Tools :工具软件包(ROS中的开发和调试工具) Capabilities :机器人高层技能(ROS中某些功能的集合,比如:导航) Ecosystem:机器人生态系统(跨地域、跨软件与硬件的ROS联盟) -
维护者 立足维护者的角度: ROS 架构可划分为两大部分 main:核心部分,主要由Willow Garage 和一些开发者设计、提供以及维护。它提供了一些分布式计算的基本工具,以及整个ROS的核心部分的程序编写。 universe:全球范围的代码,有不同国家的ROS社区组织开发和维护。一种是库的代码,如OpenCV、PCL等;库的上一层是从功能角度提供的代码,如人脸识别,他们调用下层的库;最上层的代码是应用级的代码,让机器人完成某一确定的功能。 -
系统架构 立足系统架构: ROS 可以划分为三层
- OS 层,也即经典意义的操作系统
ROS 只是元操作系统,需要依托真正意义的操作系统,目前兼容性最好的是 Linux 的 Ubuntu,Mac、Windows 也支持 ROS 的较新版本 - 中间层
是 ROS 封装的关于机器人开发的中间件,比如: 基于 TCP/UDP 继续封装的 TCPROS/UDPROS 通信系统 用于进程间通信 Nodelet,为数据的实时性传输提供支持 另外,还提供了大量的机器人开发实现库,如:数据类型定义、坐标变换、运动控制… - 应用层
功能包,以及功能包内的节点,比如: master、turtlesim的控制与运动节点…
- 自身结构
就 ROS 自身实现而言: 也可以划分为三层
- 文件系统
ROS文件系统级指的是在硬盘上面查看的ROS源代码的组织形式 - 计算图
ROS 分布式系统中不同进程需要进行数据交互,计算图可以以点对点的网络形式表现数据交互过程,计算图中的重要概念: 节点(Node)、消息(message)、通信机制_主题(topic)、通信机制_服务(service) - 开源社区
ROS的社区级概念是ROS网络上进行代码发布的一种表现形式 发行版(Distribution):ROS发行版是可以独立安装、带有版本号的一系列综合功能包。ROS发行版像Linux发行版一样发挥类似的作用。这使得ROS软件安装更加容易,而且能够通过一个软件集合维持一致的版本。 软件库(Repository):ROS依赖于共享开源代码与软件库的网站或主机服务,在这里不同的机构能够发布和分享各自的机器人软件与程序。 ROS维基(ROS Wiki):ROS Wiki是用于记录有关ROS系统信息的主要论坛。任何人都可以注册账户、贡献自己的文件、提供更正或更新、编写教程以及其他行为。网址是http://wiki.ros.org/。 Bug提交系统(Bug Ticket System):如果你发现问题或者想提出一个新功能,ROS提供这个资源去做这些。 邮件列表(Mailing list):ROS用户邮件列表是关于ROS的主要交流渠道,能够像论坛一样交流从ROS软件更新到ROS软件使用中的各种疑问或信息。网址是http://lists.ros.org/。 ROS问答(ROS Answer):用户可以使用这个资源去提问题。网址是https://answers.ros.org/questions/。 博客(Blog):你可以看到定期更新、照片和新闻。网址是https://www.ros.org/news/,不过博客系统已经退休,ROS社区取而代之,网址是https://discourse.ros.org/。
1.2.1 ROS文件系统架构
ROS文件系统架构大致如下图所示 WorkSpace — 自定义的工作空间
|--- build:编译空间,用于存放CMake和catkin的缓存信息、配置信息和其他中间文件。
|--- devel:开发空间,用于存放编译后生成的目标文件,包括头文件、动态&静态链接库、可执行文件等。
|--- src: 源码
|-- package:功能包(ROS基本单元)包含多个节点、库与配置文件,包名所有字母小写,只能由字母、数字与下划线组成
|-- CMakeLists.txt 配置编译规则,比如源文件、依赖项、目标文件
|-- package.xml 包信息,比如:包名、版本、作者、依赖项...(以前版本是 manifest.xml)
|-- scripts 存储python文件
|-- src 存储C++源文件
|-- include 头文件
|-- msg 消息通信格式文件
|-- srv 服务通信格式文件
|-- action 动作格式文件
|-- launch 可一次性运行多个节点
|-- config 配置信息
|-- CMakeLists.txt: 编译的基本配置
- package.xml
该文件定义有关软件包的属性,例如软件包名称,版本号,作者,维护者以及对其他catkin软件包的依赖性。请注意,该概念类似于旧版 rosbuild 构建系统中使用的manifest.xml文件。 - CMakelists.txt
文件CMakeLists.txt是CMake构建系统的输入,用于构建软件包。任何兼容CMake的软件包都包含一个或多个CMakeLists.txt文件,这些文件描述了如何构建代码以及将代码安装到何处。
1.2.2 ROS文件系统相关命令
- 增
catkin_create_pkg 自定义包名 依赖包 — 创建新的ROS功能包 sudo apt install xxx — 安装 ROS功能包 - 删
sudo apt purge xxx — 删除某个功能包 - 查
rospack list — 列出所有功能包 rospack find 包名 — 查找某个功能包是否存在,如果存在返回安装路径 roscd 包名 — 进入某个功能包 rosls 包名 — 列出某个包下的文件 apt search xxx — 搜索某个功能包 - 改
rosed 包名 文件名 — 修改功能包文件 需要安装 vim 比如:rosed turtlesim Color.msg - 执行
- roscore
roscore — 是 ROS 的系统先决条件节点和程序的集合, 必须运行 roscore 才能使 ROS 节点进行通信。 roscore 将启动: ros master ros 参数服务器 rosout 日志节点 - rosrun
rosrun 包名 可执行文件名 — 运行指定的ROS节点 比如:rosrun turtlesim turtlesim_node\ - roslaunch
roslaunch 包名 launch文件名 === 执行某个包下的 launch 文件
1.2.3 ROS计算图(rqt)
sudo apt install ros-<melodic>-rqt
sudo apt install ros-<melodic>-rqt-common-plugins
rosrun rqt_graph rqt_graph
以小海龟的程序为例,就可以看到下面的计算图
2.ROS通信机制
ROS 中的基本通信机制主要有如下三种实现策略:
- 话题通信(发布订阅模式)
- 服务通信(请求响应模式)
- 参数服务器(参数共享模式)
2.1话题通信
话题通信基于发布订阅模式,即:一个节点发布消息,另一个节点订阅该消息。
2.1.1话题通信理论模型
该模型中涉及到三个角色: ROS Master (管理者) Talker (发布者) Listener (订阅者)
ROS Master 负责保管 Talker 和 Listener 注册的信息,并匹配话题相同的 Talker 与 Listener,帮助 Talker 与 Listener 建立连接,连接建立后,Talker 可以发布消息,且发布的消息会被 Listener 订阅。
具体流程:
-
Talker注册 Talker启动后,会通过RPC在 ROS Master 中注册自身信息,其中包含所发布消息的话题名称。ROS Master 会将节点的注册信息加入到注册表中。 -
Listener注册 Listener启动后,也会通过RPC在 ROS Master 中注册自身信息,包含需要订阅消息的话题名。ROS Master 会将节点的注册信息加入到注册表中。 -
ROS Master实现信息匹配 ROS Master 会根据注册表中的信息匹配Talker 和 Listener,并通过 RPC 向 Listener 发送 Talker 的 RPC 地址信息。 -
Listener向Talker发送请求 Listener 根据接收到的 RPC 地址,通过 RPC 向 Talker 发送连接请求,传输订阅的话题名称、消息类型以及通信协议(TCP/UDP)。 -
Talker确认请求 Talker 接收到 Listener 的请求后,也是通过 RPC 向 Listener 确认连接信息,并发送自身的 TCP 地址信息。 -
Listener与Talker件里连接 Listener 根据步骤4 返回的消息使用 TCP 与 Talker 建立网络连接。 -
Talker向Listener发送消息 连接建立后,Talker 开始向 Listener 发布消息。
注意:
- Talker 与 Listener 的启动无先后顺序要求
- Talker 与 Listener 都可以有多个
- Talker 与 Listener 连接建立后,不再需要 ROS Master。也即,即便关闭ROS Master,Talker 与 Listern 照常通信。
2.1.2 使用C++代码实现话题通信
需求: 编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布文本消息,订阅方订阅消息并将消息内容打印输出。
流程:
-
编写发布方实现; -
编写订阅方实现; -
编辑配置文件; -
编译并执行。 -
发布方
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"talker");
ros::NodeHandle nh;
ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);
std_msgs::String msg;
std::string msg_front = "Hello 你好!";
int count = 0;
ros::Rate r(1);
while (ros::ok())
{
std::stringstream ss;
ss << msg_front << count;
msg.data = ss.str();
pub.publish(msg);
ROS_INFO("发送的消息:%s",msg.data.c_str());
r.sleep();
count++;
ros::spinOnce();
}
return 0;
}
- 订阅方
#include "ros/ros.h"
#include "std_msgs/String.h"
void doMsg(const std_msgs::String::ConstPtr& msg_p){
ROS_INFO("我听见:%s",msg_p->data.c_str());
}
int main(int argc, char *argv[])
{
setlocale(LC_ALL,"");
ros::init(argc,argv,"listener");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);
ros::spin();
return 0;
}
- 配置 CMakeLists.txt
add_executable(Hello_pub
src/Hello_pub.cpp
)
add_executable(Hello_sub
src/Hello_sub.cpp
)
target_link_libraries(Hello_pub
${catkin_LIBRARIES}
)
target_link_libraries(Hello_sub
${catkin_LIBRARIES}
)
- 执行
1.启动 roscore; 2.启动发布节点; 3.启动订阅节点。
2.1.3 话题通信自定义msg
在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如: 激光雷达的信息… std_msgs 由于描述性较差而显得力不从心,这种场景下可以使用自定义的消息类型
msgs只是简单的文本文件,每行具有字段类型和字段名称,可以使用的字段类型有: int8, int16, int32, int64 (或者无符号类型: uint*) float32, float64 string time, duration other msg files variable-length array[] and fixed-length array[C]
ROS中还有一种特殊类型:Header,标头包含时间戳和ROS中常用的坐标帧信息。会经常看到msg文件的第一行具有Header标头。
- 流程:
按照固定格式创建 msg 文件 编辑配置文件 编译生成可以被 Python 或 C++ 调用的中间文件
- 定义msg文件
功能包下新建 msg 目录,添加文件 Person.msg
string name
uint16 age
float64 height
2.编辑配置文件 package.xml中添加编译依赖与执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!--
exce_depend 以前对应的是 run_depend 现在非法
-->
CMakeLists.txt编辑 msg 相关配置
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
## 配置 msg 源文件
add_message_files(
FILES
Person.msg
)
# 生成消息时依赖于 std_msgs
generate_messages(
DEPENDENCIES
std_msgs
)
#执行时依赖
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES demo02_talker_listener
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
- 编译
2.2 服务通信
服务通信基于请求响应模式,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。
2.2.1服务通信理论模型
该模型中涉及到三个角色: ROS master(管理者) Server(服务端) Client(客户端)
ROS Master 负责保管 Server 和 Client 注册的信息,并匹配话题相同的 Server 与 Client ,帮助 Server 与 Client 建立连接,连接建立后,Client 发送请求信息,Server 返回响应信息。 整个流程由以下步骤实现:
-
Server注册 Server 启动后,会通过RPC在 ROS Master 中注册自身信息,其中包含提供的服务的名称。ROS Master 会将节点的注册信息加入到注册表中。 -
Client注册 Client 启动后,也会通过RPC在 ROS Master 中注册自身信息,包含需要请求的服务的名称。ROS Master 会将节点的注册信息加入到注册表中。 -
ROS Master实现信息匹配 ROS Master 会根据注册表中的信息匹配Server和 Client,并通过 RPC 向 Client 发送 Server 的 TCP 地址信息。 -
Client发送请求 Client 根据步骤2 响应的信息,使用 TCP 与 Server 建立网络连接,并发送请求数据。 -
Server发送响应 Server 接收、解析请求的数据,并产生响应结果返回给 Client。
注意: 1.客户端请求被处理时,需要保证服务器已经启动; 2.服务端和客户端都可以存在多个。
2.2.2 服务通信自定义srv
- 定义srv文件
服务通信中,数据分成两部分,请求与响应,在 srv 文件中请求和响应使用—分割,具体实现如下: 功能包下新建 srv 目录,添加 xxx.srv 文件,内容:
# 客户端请求时发送的两个数字
int32 num1
int32 num2
---
# 服务器响应发送的数据
int32 sum
- 编辑配置文件
package.xml中添加编译依赖与执行依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<!--
exce_depend 以前对应的是 run_depend 现在非法
-->
CMakeLists.txt编辑 srv 相关配置
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)
# 需要加入 message_generation,必须有 std_msgs
add_service_files(
FILES
AddInts.srv
)
generate_messages(
DEPENDENCIES
std_msgs
)
- 编译
2.3 参数服务器
参数服务器在ROS中主要用于实现不同节点之间的数据共享。参数服务器相当于是独立于所有节点的一个公共容器,可以将数据存储在该容器中,被不同的节点调用,当然不同的节点也可以往其中存储数据。
2.3.1 参数服务器理论模型
该模型中涉及到三个角色: ROS Master (管理者) Talker (参数设置者) Listener (参数调用者)
ROS Master 作为一个公共容器保存参数,Talker 可以向容器中设置参数,Listener 可以获取参数。 流程如下:
-
Talker 设置参数 Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值),ROS Master 将参数保存到参数列表中。 -
Listener 获取参数 Listener 通过 RPC 向参数服务器发送参数查找请求,请求中包含要查找的参数名。 -
ROS Master 向 Listener 发送参数值 ROS Master 根据步骤2请求提供的参数名查找参数值,并将查询结果通过 RPC 发送给 Listener。
参数可使用数据类型: 32-bit integers booleans strings doubles iso8601 dates lists base64-encoded binary data 字典
注意: 参数服务器不是为高性能而设计的,因此最好用于存储静态的非二进制的简单数据
2.4 ROS通信中常用的命令
在 ROS 同提供了一些实用的命令行工具,可以用于获取不同节点的各类信息,常用的命令如下:
- rosnode : 操作节点
- rostopic : 操作话题
- rosservice : 操作服务
- rosmsg : 操作msg消息
- rossrv : 操作srv消息
- rosparam : 操作参数
ROS Tutoriasls 相关资料 http://wiki.ros.org/ROS/CommandLineTools
2.4.1 rosnode
rosnode 是用于获取节点信息的命令
- rosnode ping 测试到节点的连接状态
- rosnode list 列出活动节点
- rosnode info 打印节点信息
- rosnode machine 列出指定设备上节点
- rosnode kill 杀死某个节点
- rosnode cleanup 清除不可连接的节点,例如启动乌龟节点,然后 ctrl + c 关闭,该节点并没被彻底清除,可以使用 cleanup 清除节点
2.4.2 rostopic
rostopic包含rostopic命令行工具,用于显示有关ROS 主题的调试信息,包括发布者,订阅者,发布频率和ROS消息。
rostopic bw 显示主题使用的带宽 rostopic delay 显示带有 header 的主题延迟 rostopic echo 打印消息到屏幕 rostopic find 根据类型查找主题 rostopic hz 显示主题的发布频率 rostopic info 显示主题相关信息 rostopic list 显示所有活动状态下的主题 rostopic pub 将数据发布到主题 rostopic type 打印主题类型
rostopic pub /主题名称 消息类型 消息内容
rostopic pub /chatter std_msgs gagaxixi
为 小乌龟发布一条运动信息
rostopic pub /turtle1/cmd_vel geometry_msgs/Twist
"linear:
x: 1.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 2.0"
rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist
"linear:
x: 1.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 2.0"
2.4.3 rosmsg
rosmsg是用于显示有关 ROS消息类型的 信息的命令行工具。
-
rosmsg list 会列出当前 ROS 中的所有 msg -
rosmsg packages 列出包含消息的所有包 -
rosmsg package 列出某个包下的所有msg
rosmsg package turtlesim
rosmsg show turtlesim/Pose
结果:
float32 x
float32 y
float32 theta
float32 linear_velocity
float32 angular_velocity
rosmsg info
作用与 rosmsg show 一样
2.4.4 rosservice
rosservice包含用于列出和查询ROSServices的rosservice命令行工具。
调用部分服务时,如果对相关工作空间没有配置 path,需要进入工作空间调用 source ./devel/setup.bash
rosservice args 打印服务参数
rosservice call 使用提供的参数调用服务
rosservice find 按照服务类型查找服务
rosservice info 打印有关服务的信息
rosservice list 列出所有活动的服务
rosservice type 打印服务类型
rosservice uri 打印服务的 ROSRPC uri
2.4.5 rossrv
rossrv是用于显示有关ROS服务类型的信息的命令行工具,与 rosmsg 使用语法高度雷同。
rossrv show 显示服务消息详情
rossrv info 显示服务消息相关信息
rossrv list 列出所有服务信息
rossrv md5 显示 md5 加密后的服务消息
rossrv package 显示某个包下所有服务消息
rossrv packages 显示包含服务消息的所有包
2.4.6 rosparam
rosparam包含rosparam命令行工具,用于使用YAML编码文件在参数服务器上获取和设置ROS参数。
rosparam set 设置参数
rosparam get 获取参数
rosparam load 从外部文件加载参数
rosparam dump 将参数写出到外部文件
rosparam delete 删除参数
rosparam list 列出所有参数
|