-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: 更新:ROS2-006-通信机制:动作通信 (Part 1)
- Loading branch information
1 parent
0cf7a47
commit f53e19d
Showing
5 changed files
with
250 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
--- | ||
title: ROS2-006-通信机制:动作通信 | ||
icon: 'handshake-simple' | ||
date: 2024-10-15 | ||
category: | ||
- Computer | ||
- robot | ||
- ROS | ||
--- | ||
|
||
## 简介 | ||
|
||
**动作通信** (Action Communication) 同样是一种基于 `请求响应` 的方式,以实现不同节点之间数据传输的通信模式。其中发送请求数据的对象称为 **客户端**,接受请求并发送数据相应的对象称之为 **服务端**。为了与前文的 [服务通信](./2024_10_03.md) 相区分,将这里的客户端称为动作客户端,服务端称为动作服务端。 | ||
|
||
在结构上,动作通信由目标、反馈和结果三个部分组成,因此和 **服务通信** 不同的是,**动作通信** 可以在请求响应过程中获取连续反馈,并且也可以向动作服务端发送任务取消请求。 | ||
|
||
在底层实现上,动作通信是建立在话题通信和服务通信之上的,目标的发送与结果的获取是通过对服务通信封装来实现的,而连续反馈则是通过对话题通信的封装来实现的,动作通信本质上是话题通信和服务通信的结合体。因此与前两种通信一样,动作客户端和动作服务端通过话题(Topic)相关联,动作客户端和动作服务端可以互相进行数据传输交互。在服务通信中,消息的流向也是双向的。 | ||
|
||
对于两个使用动作通信进行交流的节点(以下称为A、B)而言,这两个节点的动作通信整体流程如下: | ||
|
||
1. 节点A的动作客户端发送 **目标请求**(即动作目标)至节点B的动作服务端。动作服务端会基于当前状态、资源是否可用等条件,决定该目标是否可以被节点B自身接受。若可以,节点B的动作服务端返回 **目标接受响应** 至节点A的动作客户端,并生成一个 **Goal ID** 作为唯一标识符,以标识该任务。 | ||
|
||
 | ||
|
||
2. 节点A的动作客户端发送目标执行请求至节点B的动作服务端。节点B开始执行相关请求,并且节点B的动作服务端在执行过程中返回连续的处理结果给节点A的动作客户端作为实时反馈。 | ||
|
||
 | ||
|
||
3. 节点B执行相关请求完毕,将最终结果通过节点B的动作服务端返回至节点A的动作客户端。流程结束。 | ||
|
||
 | ||
|
||
其中,在节点B执行相关请求的场合下,节点A的动作客户端可以通过对节点B的动作服务端发送 **取消目标请求** 取消正在执行的任务,并在节点B的动作服务端检查当前任务的状态,决定可以取消任务后,取消相关任务并结束相关动作通信。 | ||
|
||
因此,动作通信一般更适用于长时间运行的任务以及相对耗时的请求响应场景,用以获取连续的状态反馈信息。 | ||
|
||
## 动作通信的简单实现 | ||
|
||
现在,我们通过针对以下案例需求进行C++与Python的分别实现,以更加深入了解动作通信。 | ||
|
||
### 案例需求&案例分析 | ||
|
||
需求:编写动作通信,动作客户端提交一个整型数据N,动作服务端接收请求数据并累加1-N之间的所有整数,将最终结果返回给动作客户端,且每累加一次都需要计算当前运算进度并反馈给动作客户端。 | ||
|
||
分析:在上述需求中,我们需要关注以下三个要素: | ||
|
||
1. 动作客户端; | ||
2. 动作服务端; | ||
3. 消息载体。 | ||
|
||
### 流程简介 | ||
|
||
案例实现前需要自定动作接口。 | ||
|
||
在接口准备完毕后,动作通信实现的主要步骤如下: | ||
|
||
1. 编写动作服务端实现; | ||
2. 编写动作客户端实现; | ||
3. 编辑配置文件; | ||
4. 编译; | ||
5. 执行。 | ||
|
||
案例会采用C++和Python分别实现,且二者都遵循上述实现流程。 | ||
|
||
### 准备工作 | ||
|
||
终端下创建工作空间: | ||
|
||
```shell | ||
mkdir -p ws01_plumbing/src | ||
cd ws01_plumbing/src | ||
colcon build | ||
``` | ||
|
||
进入工作空间的src目录: | ||
|
||
```shell | ||
cd src/ | ||
``` | ||
|
||
调用如下命令创建之后会用到的接口功能包: | ||
|
||
```shell | ||
ros2 pkg create --build-type ament_cmake base_interfaces_demo | ||
|
||
``` | ||
|
||
调用如下两条命令分别创建C++功能包、Python功能包及其所需服务端节点: | ||
|
||
**C++:** | ||
|
||
```shell | ||
ros2 pkg create cpp03_action --build-type ament_cmake --dependencies rclcpp rclcpp_action base_interfaces_demo --node-name demo01_action_server | ||
``` | ||
|
||
**Python:** | ||
|
||
```shell | ||
ros2 pkg create py03_action --build-type ament_python --dependencies rclpy base_interfaces_demo --node-name demo01_action_server_py | ||
``` | ||
|
||
在接口功能包中自定义服务接口消息文件: | ||
|
||
具体实现请参考[这里](./2024_10_15_002.md) | ||
|
||
准备工作到此完毕。 | ||
|
||
--- | ||
|
||
接下来你便可以通过 [C++](./2024_10_15_003.md) 和 [Python](./2024_10_15_004.md) 来分别实现服务通信了。 | ||
|
||
## 总结 | ||
|
||
在这一节中,我们系统的阐述了如何依据服务通信相关原理,通过自行操作,实现节点之间简单的服务通信。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
--- | ||
title: ROS2-006-通信机制:动作通信Extra:如何实现自定义动作通信接口消息 | ||
icon: 'handshake-simple' | ||
date: 2024-10-15 | ||
category: | ||
- Computer | ||
- robot | ||
- ROS | ||
--- | ||
|
||
## 简介 | ||
|
||
实现自定义动作接口消息的流程与[实现自定义话题接口消息](./2024_09_25.md)的流程类似,其主要步骤如下: | ||
|
||
1. 创建并编写 `.action` 文件; | ||
2. 编辑配置文件; | ||
3. 编译; | ||
4. 测试。 | ||
|
||
因此,我们现在会在[之前](./2024_10_03.md#准备工作)创建的接口功能包 `base_interfaces_demo` 里,尝试编写一个 `.action` 文件。该文件中包含请求数据(两个整型字段)与响应数据(一个整型字段)。 | ||
|
||
## 创建并编辑 .action 文件 | ||
|
||
在功能包 `base_interfaces_demo` 下新建 `action` 文件夹,`action` 文件夹下新建 `Progress.action` 文件,文件中输入如下内容: | ||
|
||
```action | ||
int64 num | ||
--- | ||
int64 sum | ||
--- | ||
float64 progress | ||
``` | ||
|
||
## 编辑配置文件 | ||
|
||
### 1. `package.xml` 文件 | ||
|
||
在package.xml中需要添加一些依赖包,具体内容如下: | ||
|
||
```xml | ||
<!-- 编译依赖 --> | ||
<build_depend>rosidl_default_generators</build_depend> | ||
<!-- 依赖 --> | ||
<depend>action_msgs</depend> | ||
<!-- 声明当前包所属的功能包组 --> | ||
<member_of_group>rosidl_interface_packages</member_of_group> | ||
``` | ||
|
||
::: tip 看起来有些重复? | ||
|
||
`action` 文件所需的依赖包与前文 [实现自定义接口消息](./2024_09_25.md#编辑配置文件)中 `msg` 文件所需的依赖包基本一致,如果是在新建的功能包中添加 `action` 文件,那么有些依赖可以直接参考定义 `msg` 文件时 `package.xml` 的配置。 | ||
|
||
如果你在之前[实现自定义接口消息](./2024_09_25.md#编辑配置文件)时,已经创建了 `base_interfaces_demo` 功能包,且已经为 `msg` 文件配置过了依赖包,那么这里的 `package.xml` 只需要新增如下代码即可: | ||
|
||
```xml | ||
<!-- 依赖 --> | ||
<depend>action_msgs</depend> | ||
``` | ||
|
||
::: | ||
|
||
### 2. `CMakeLists.txt` 文件 | ||
|
||
为了将 `.action` 文件转换成对应的 `C++` 和 `Python` 代码,还需要在 `CMakeLists.txt` 中添加如下配置: | ||
|
||
```txt | ||
find_package(rosidl_default_generators REQUIRED) | ||
# 为接口文件生成源代码 | ||
rosidl_generate_interfaces(${PROJECT_NAME} | ||
"action/Progress.action" | ||
) | ||
``` | ||
|
||
::: tip 看起来又有些重复? | ||
|
||
`action` 文件所需的对`CMakeLists.txt` 文件的新配置与前文 [实现自定义接口消息](./2024_09_25.md#编辑配置文件)中对`CMakeLists.txt` 文件的配置基本一致,如果是在新建的功能包中添加对`CMakeLists.txt` 文件的新配置,那么直接参考上述配置即可。 | ||
|
||
如果你在之前[实现自定义接口消息](./2024_09_25.md#编辑配置文件)时,已经对`CMakeLists.txt` 文件进行了该配置,那么这里只需要为 `rosidl_generate_interfaces` 函数新增一个参数即可,修改后的内容如下: | ||
|
||
```txt | ||
# 为接口文件生成源代码 | ||
rosidl_generate_interfaces(${PROJECT_NAME} | ||
"msg/Student.msg" | ||
"action/Progress.action" | ||
) | ||
``` | ||
|
||
::: | ||
|
||
## 编译 | ||
|
||
终端中进入当前工作空间,编译功能包: | ||
|
||
```shell | ||
colcon build --packages-select base_interfaces_demo | ||
``` | ||
|
||
## 测试 | ||
|
||
编译完成之后,在工作空间下的 `install` 目录下将生成 `Progress.action` 文件对应的 `C++` 和 `Python` 文件,我们也可以在终端下进入工作空间,通过如下命令查看文件定义以及编译是否正常: | ||
|
||
```shell | ||
. install/setup.bash | ||
ros2 interface show base_interfaces_demo/action/Progress.action | ||
``` | ||
|
||
到此,创建工作结束。 | ||
|
||
::: tip 包含自定义接口文件时可能会报错 | ||
创建工作结束后,你会需要在 `C++` 文件中包含自定义消息相关头文件。在那时,VSCode可能会抛出异常。你可以打开 VSCode 中的 `c_cpp_properties.json` 文件,在文件中的 `includePath` 属性下添加一行路径: | ||
|
||
`"${workspaceFolder}/install/base_interfaces_demo/include/**"` | ||
|
||
添加完毕后,包含相关头文件时,异常就不会被抛出。 | ||
其他接口文件或接口包的使用也与此同理。 | ||
::: | ||
|
||
::: tip Python文件导包自定义 | ||
Python文件中导入自定义消息相关的包时,为了方便使用,可以配置 `VSCode` 中的 `settings.json` 文件,在文件中的 `python.autoComplete.extraPaths` 和 `python.analysis.extraPaths` 属性下添加一行: | ||
|
||
`"${workspaceFolder}/install/base_interfaces_demo/lib/python3.12/site-packages"` | ||
|
||
添加完毕后,代码便可以高亮显示且可以自动补齐,其他接口文件或接口包的使用也与此同理. | ||
|
||
(注意:这里所使用的 ROS2 版本为 Jazzy,Python 为 3.12,因此路径结构不一定一致,请依据文件项目树自行修改创建) | ||
::: | ||
|
||
--- | ||
|
||
::: tip | ||
如果你是从 **ROS2-006-通信机制:动作通信** 来的, 可以从[这里](./2024_10_15.md#准备工作)导航回去。 | ||
::: |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.