ROS2教程06 ROS2行动

本文涉及的产品
资源编排,不限时长
简介: 这篇文章是关于ROS2(Robot Operating System 2)行动(Action)通信机制的教程,包括行动的概念、特点、命令行工具的使用,以及如何编写行动的客户端和服务器代码,并介绍了如何测试行动通信。

ROS2行动

版权信息

Copyright 2023 Herman Ye@Auromix. All rights reserved.

This course and all of its associated content, including but not limited to text, 
images, videos, and any other materials, are protected by copyright law. 
The author holds all rights to this course and its contents.

Any unauthorized use, reproduction, distribution, or modification of this course 
or its contents is strictly prohibited and may result in legal action. 
This includes, but is not limited to:
Copying or distributing course materials without express written permission.
Reposting, sharing, or distributing course content on any platform without proper attribution and permission.
Creating derivative works based on this course without permission.
Permissions and Inquiries

If you wish to use or reproduce any part of this course for purposes other than personal learning, 
please contact the author to request permission.

The course content is provided for educational purposes, and the author makes no warranties or representations 
regarding the accuracy, completeness, or suitability of the course content for any specific purpose. 
The author shall not be held liable for any damages, losses, 
or other consequences resulting from the use or misuse of this course.

Please be aware that this course may contain materials or images obtained from third-party sources. 
The author and course creator diligently endeavor to ensure that these materials 
are used in full compliance with copyright and fair use regulations. 
If you have concerns about any specific content in this regard, 
please contact the author for clarification or resolution.

By enrolling in this course, you agree to abide by the terms and conditions outlined in this copyright notice.

学习目标

  • 熟悉ROS2的行动概念
  • 了解ROS2行动相关的命令行工具操作
  • 熟悉行动通信中的动作客户端和动作服务器代码编写
  • 熟悉行动通信的测试手段

难度级别

初级 中级 高级

预计耗时

45 mins

学习前提

对象 类型 状态
ROS2 Humble 软件 已安装
Ubuntu22.04操作系统 软件 已确认
Shell的基本使用 知识 已了解
ROS2 节点 知识 已了解
ROS2 话题 知识 已了解
ROS2 服务 知识 已了解

什么是行动?

在ROS2中,除了常见的话题通信和服务通信,还存在一种重要通信机制,称为Action通信。

根据牛津词典的定义,“action"一词的核心释义是"process”,即过程,表明它具有持续性。因此,可以将Action翻译为"行动"。

the process of doing something in order to make something happen or to deal with a situation

在这里插入图片描述

虽然这个定义抽象,但在ROS2中,可以将机器人的某些行为称为"Action"。以turtlesim为例,它包含一种称为"rotate_absolute"的行动,可用于让海龟机器人在当前位置绕绝对指定的角度旋转。
使用话题机制(Topic)时,无法知道海龟机器人是否已到达目的地,而使用服务机制(Service)时,可以知道目标已完成,但无法获取过程中的信息。因此,Action通信机制被引入,以提供关于行动执行过程的反馈信息。

Action通信适用于涉及跨足时间的目标任务,在此时间跨度内需要连续的过程反馈。

另一个典型的场景是机器人系统可能会使用动作进行导航。行动目标可以告诉机器人前往某个位置。当机器人导航到该位置时,它可以沿途发送更新(即反馈),然后在到达目的地后发送最终结果消息。
在这里插入图片描述

行动的特点

行动(Action)具有以下几个关键特点:

  • 可中断性
    行动可以随时中断。例如,通过Action控制轮子旋转,可以在执行过程中随时停止旋转,即可中断正在进行的行动。
    不仅如此,还可以通过新的目标(goal)来覆盖旧的目标,在未完成旧目标时开始执行新目标。例如,如果轮子正以5m/s逐渐减速,但尚未完全停止,可以请求它以1m/s的目标速度旋转,这将导致速度趋向1m/s而不是立即停止。
    不过,动作服务器可以选择其他目标,例如拒绝新目标或在第一个目标完成后执行第二个目标。不要假设每个动作服务器在获得新目标时都会选择中止当前目标。

  • 长时间运行
    行动可持续运行,适用于需要执行时间相对较长的任务。

  • 提供过程反馈
    行动提供定期的过程反馈,以让客户端了解操作的进展情况。这是与服务通信不同之处,服务通常只提供一次性的响应。

在这里插入图片描述

行动可以被视为一种新类型,由话题(Topic)和服务(Service)组成。它可以简化地看作包含两个服务:Goal Service(目标服务)和Result Service(结果服务),以及一个话题(Feedback Topic)。
整体的流程为:

  • 动作客户端(Action Client)向动作服务器(Action Server)发出目标请求(Goal Request)
  • 动作服务器(Action Server)向动作客户端(Action Client)返还目标反馈(Goal Response)
  • 动作客户端(Action Client)向动作服务器(Action Server)请求目标任务的结果(Result Request)
  • 动作服务器(Action Server)不断地发送过程反馈的话题(Feedback Topic)给动作客户端(Action Client),直到目标任务达成、中止、或被覆盖
  • 目标任务达成后,动作服务器(Action Server)向动作客户端(Action Client)返还结果反馈(Result Response)

行动的命令行使用

查看行动的列表

要查看当前可用的行动列表,可以执行以下命令:

ros2 action list

在这里插入图片描述

查看行动的类型和具体的结构

如果您需要查看行动的类型以及其详细结构,可以使用-t选项来同时输出行动的结构类型。执行以下命令:

ros2 action list -t

在这里插入图片描述

根据返回的结构类型,进一步查看特定结构类型的详细内容,可以执行以下命令:

ros2 interface show turtlesim/action/RotateAbsolute

这将显示选定行动的具体结构,分为三个部分,使用三个短横线分隔开。这三个部分依次是目标部分 (Goal Request),结果部分 (Result Response),和反馈部分 (Feedback)。在小乌龟的 “RotateAbsolute” 动作中,它们分别表示目标角度、相对于起始位置的角度,以及剩余旋转角度。
在这里插入图片描述

查看行动的具体信息

要查看特定行动的详细信息,可以使用以下命令:

ros2 action info /turtle1/rotate_absolute

此命令将显示与该行动连接的客户端和服务器的信息。
请注意,我们使用“连接”一词,因为客户端和服务器通过行动建立的关系不仅仅是简单的订阅或请求与反馈,而是一种更为复杂的关系。以下是命令的输出示例:
在这里插入图片描述

设置行动的目标

要在命令行中发送行动目标,请使用以下命令:

ros2 action send_goal <action_name> <action_type> <values>

以小乌龟为例,发送一个旋转绝对角度为1.57弧度的目标:

ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"

每个Goal都有独立的ID,这是因为行动是可以被中断和覆盖的。

下方的result字段用于返回执行目标任务的结果,当目标成功执行后会返回相应的结果信息。
在这里插入图片描述

当需要在执行过程中显示反馈信息时,可以加入--feedback选项,如下所示:

ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}" --feedback

在这里插入图片描述

思考:
如果打断行动,会发生什么?
如果中途取消行动,会发生什么?
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

行动的编程使用

自定义行动的消息类型接口

1.建立接口功能包

在ROS2中,自定义的接口通常被放在一个独立的功能包下,通常以_interfaces的方式命名。这个功能包包含三个子文件夹,分别用于存放自定义消息、服务和行动接口类型,他们是msgsrvaction。这些细节会在后续课程中详细介绍,这里只是简要提及。

# Go to your src
cd ~/ros2_workspace/src
# Create interfaces package
ros2 pkg create ros2_learning_interfaces

2.建立自定义的动作消息类型文件

自定义行动消息的形式与自定义消息和服务相似,但它由三个部分组成:

  • 动作客户端(Client)发送的目标请求(Goal Request)
  • 动作服务器(Server)完成请求后的执行结果(Result Response)
  • 动作服务器定期向动作客户端发送有关目标执行情况的反馈(Feedback)
# Request
---
# Result
---
# Feedback

在接口功能包的目录下创建一个名为"action"的文件夹,通常采用大写字母开头的命名规则。

# Go to your interfaces package
cd ros2_learning_interfaces
# Create action directory
mkdir action
# Go to action directory
cd action
# Create custom action
touch Fibonacci.action

以斐波那契行动为例,定义了三个字段:order 用于指定目标,sequence 用于存储执行结果,partial_sequence 用于在计算过程中提供反馈信息。

int32 order
---
int32[] sequence
---
int32[] partial_sequence

3.修改CMakeLists.txt

将以下内容添加到CMakeLists.txt文件中:

find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "action/Fibonacci.action"
)

在这里插入图片描述

相关解释
find_package(rosidl_default_generators REQUIRED)

这一行代码用于查找并导入 ROS 2 中与消息和动作生成相关的默认生成器。这些生成器将帮助你生成用于编译和使用自定义消息和动作的代码。
rosidl全称可能是 "ROS Interface Definition Language"。它用于定义和生成ROS消息、服务和动作的接口以及相关代码。
rosidl 通过一种IDL(接口定义语言)的方式,允许开发者定义消息结构、服务接口和动作接口,然后生成与这些接口相关的代码,以便在ROS 2中进行消息通信、服务调用和动作执行。
rosidl_default_generators 是一个用于生成ROS消息、服务和动作接口代码的工具,它在构建过程中会生成必要的代码以便你的软件包可以与其他ROS节点进行通信。

rosidl_generate_interfaces(${PROJECT_NAME} "action/Fibonacci.action")

这一行代码告诉 ROS 2 生成器为你的项目生成与自定义动作类型 "Fibonacci.action" 相关的代码。这包括自动生成的 C++ 源代码和头文件,以及与动作相关的其他文件,这些文件可以帮助你创建、发送和接收动作消息。

4.修改package.xml

添加以下部分到package.xml:

<buildtool_depend>rosidl_default_generators</buildtool_depend>

<depend>action_msgs</depend>

<member_of_group>rosidl_interface_packages</member_of_group>

在这里插入图片描述

相关解释
<buildtool_depend>rosidl_default_generators</buildtool_depend>

这行代码指示你的ROS软件包在构建时需要依赖于 rosidl_default_generators

<member_of_group>rosidl_interface_packages</member_of_group>

这一行代码将你的软件包添加到 rosidl_interface_packages 组中。这是一种组织ROS软件包的方式,通常包含定义消息、服务和动作接口的软件包。
ROS系统中有许多不同类型的软件包,包括节点、库、工具等。rosidl_interface_packages组是一种用于标识特定类型软件包的方式,即包含ROS接口(消息、服务和动作)定义的软件包。这有助于将具有相似功能和目的的软件包进行组织,使开发者更容易找到与ROS接口相关的软件包。

<depend>action_msgs</depend>

这一行代码将软件包添加了对 action_msgs的依赖。这是因为在ROS 2 Humble中,动作(Actions)的定义包含一些额外的元数据,其中包括目标(goal)的标识(ID)等信息。这些元数据与 action_msgs 软件包相关,因此软件包需要依赖于它,以确保在定义和使用动作时有必要的元数据支持。
提示:
值得注意的是,这个缺点在ROS2更新的版本中(例如Iron)被优化,不再需要添加对 action_msgs的依赖,但在Humble中,这条是需要的,相关问题请参考Iron action

5.编译工作空间

在最后,编译工作空间,相关命令在之后的课程里会讲解,此处不涉及。

# Go to your workspace
cd ~/ros2_workspace
# Build workspace
colcon build --symlink-install

动作服务器

1.建立动作服务器源文件

在这一步,你需要进入你的ROS 2工作空间中的包目录,并创建一个名为action_demo_server.py的Python文件。

# Go to your package
cd ros2_workspace/src/ros2_learning/ros2_learning
# Create file
touch action_demo_server.py

2.编写动作服务器

在这一部分,我们创建了一个用于计算斐波那契数列的ROS 2动作服务器。服务器将一直计算,直到斐波那契数列的长度达到用户指定的order。在执行回调函数中,我们设置反馈并将其发布到客户端,然后使用time.sleep(1)模拟计算的延迟。最后,我们将目标标记为成功,并返回结果。

import rclpy  # 引入rclpy库
import time
from rclpy.action import ActionServer  # 引入ActionServer类
from rclpy.node import Node  # 引入Node类

from ros2_learning_interfaces.action import Fibonacci


class FibonacciActionServer(Node):
    def __init__(self):
        super().__init__("action_demo_server")
        # 创建一个ActionServer self,消息类型接口名称,动作名,回调函数
        self._action_server = ActionServer(
            self, Fibonacci, "fibonacci_action", self.execute_callback
        )
        self.get_logger().info("action_demo_server start")  # 表明节点已经启动

    def execute_callback(self, goal_handle):  # 动作被调用的回调函数
        self.get_logger().info("Executing goal...")  # 表明开始执行

        feedback_msg = Fibonacci.Feedback()  # 构建反馈信息
        feedback_msg.partial_sequence = [0, 1]  # 初始斐波那契数
        # order是斐波那契数列的长度
        for i in range(
            1, goal_handle.request.order - 1
        ):  # 遍历1到goal_handle.request.order-2
            # 将下一个斐波那契数填入反馈的列表
            feedback_msg.partial_sequence.append(
                feedback_msg.partial_sequence[i] + feedback_msg.partial_sequence[i - 1]
            )
            # 打印过程反馈
            self.get_logger().info(
                "Feedback: {0}".format(feedback_msg.partial_sequence)
            )
            # 发布过程反馈
            goal_handle.publish_feedback(feedback_msg)
            # 休眠
            time.sleep(1)

        # 直到完成了用户要求的斐波那契长度
        # 在目标句柄上指示目标成功
        goal_handle.succeed()

        result = Fibonacci.Result()  # 构建结果反馈
        result.sequence = feedback_msg.partial_sequence  # 将最后的过程反馈列表值赋给结果反馈
        return result  # 返还结果


def main(args=None):
    rclpy.init(args=args)  # 初始化ROS接口
    action_demo_server = FibonacciActionServer()  # 实例化ActionServer
    rclpy.spin(action_demo_server)  # 循环


if __name__ == "__main__":
    main()

3.修改package.xml

添加以下内容到package.xml,这是因为这个包依赖于之前创建的自定义动作消息类型接口包和rclpy

<depend>rclpy</depend>
<depend>ros2_learning_interfaces</depend>

在这里插入图片描述

4.修改setup.py

在你的setup.py文件中添加以下行:

"action_server = ros2_learning.action_demo_server:main",

在这里插入图片描述

5.编译工作空间

编译工作空间,相关命令在之后的课程里会讲解,此处不涉及。

# Go to your workspace
cd ~/ros2_workspace
# Build workspace
colcon build --symlink-install

6.测试动作服务器

由于编写行动服务器较为复杂,因此首先进行单个服务器的命令行可行性测试。该动作将计算斐波那契数列,直到列表内的斐波那契数列长度达到用户指定的order:

# Run action server node
ros2 run ros2_learning action_server
# Send action goal
ros2 action send_goal --feedback fibonacci_action ros2_learning_interfaces/action/Fibonacci "{order: 5}"

在这里插入图片描述

动作客户端

1.建立动作客户端源文件

在这一步,你需要进入你的ROS 2工作空间中的包目录,并创建一个名为action_demo_client.py的Python文件。

# Go to your package
cd ros2_workspace/src/ros2_learning/ros2_learning
# Create file
touch action_demo_client.py

2.编写动作客户端

import rclpy  # 引入rclpy
from rclpy.action import ActionClient  # 引入ActionClient类
from rclpy.node import Node  # 引入Node类

from ros2_learning_interfaces.action import Fibonacci  # 引入自定义的动作消息类型


class FibonacciActionClient(Node):
    def __init__(self):
        super().__init__("action_demo_client")
        # 实例化ActionClient(self,行动的消息类型,行动名)
        self._action_client = ActionClient(self, Fibonacci, "fibonacci_action")
        self.get_logger().info("action client start")

    def send_goal(self, order):  # 发布目标的方法
        goal_msg = Fibonacci.Goal()  # 构建目标消息
        goal_msg.order = order  # 填入order值
        self.get_logger().info("Waiting for action server...")
        self._action_client.wait_for_server()  # 等待服务器出现
        self.get_logger().info("Action server found!")
        # 发送异步目标并将结果存储在_send_goal_future中
        self._send_goal_future = self._action_client.send_goal_async(goal_msg)
        # 为_send_goal_future添加一个回调函数,当收到ActionServer的goal_response时调用self.goal_response_callback
        self._send_goal_future.add_done_callback(self.goal_response_callback)

    def goal_response_callback(self, future):  # 收到ActionServer的Goal Response时的回调
        goal_handle = future.result()  # 创建句柄
        if not goal_handle.accepted:  # 若Goal Request未被接收,打印“拒绝”消息
            self.get_logger().info("Goal rejected :(")
            return
        # 若Goal Request被接收,打印“接收”消息
        self.get_logger().info("Goal accepted :)")
        # 创建一个异步操作 _get_result_future 用于获取动作服务器的执行结果
        self._get_result_future = goal_handle.get_result_async()
        # 将 get_result_callback 作为回调函数添加到 _get_result_future,当收到结果时调用self.get_result_callback
        self._get_result_future.add_done_callback(self.get_result_callback)

    def get_result_callback(self, future):
        result = future.result().result  # 获取Result
        self.get_logger().info("Result: {0}".format(result.sequence))  # 打印Result
        rclpy.shutdown()  # 关闭ROS


def main(args=None):
    goal_value = 10
    rclpy.init(args=args)  # 初始化ROS

    action_client = FibonacciActionClient()  # 实例化ActionClient

    action_client.send_goal(goal_value)  # 发送目标请求

    rclpy.spin(action_client)


if __name__ == "__main__":
    main()

3.修改package.xml

添加以下内容到package.xml,这是因为这个包依赖于之前创建的自定义动作消息类型接口包和rclpy

<depend>rclpy</depend>
<depend>ros2_learning_interfaces</depend>

在这里插入图片描述

4.修改setup.py

在你的setup.py文件中添加以下行:

"action_client = ros2_learning.action_demo_client:main",

在这里插入图片描述

5.编译工作空间

编译工作空间,相关命令在之后的课程里会讲解,此处不涉及。

# Go to your workspace
cd ~/ros2_workspace
# Build workspace
colcon build --symlink-install

测试行动通讯

启动行动客户端

ros2 run ros2_learning action_client

行动客户端启动后将等待行动服务器出现,当行动服务器出现后发送行动的目标,并在收到行动服务器返还的Goal Response后打印目标已被接收的提示信息,直到服务器完成整套动作后,打印最终结果。
在这里插入图片描述

启动行动服务器

ros2 run ros2_learning action_server

行动服务器在接收到行动客户端的目标请求后开始服务,直到整套服务完成。
在这里插入图片描述

相关实践学习
使用ROS创建VPC和VSwitch
本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
目录
相关文章
|
2月前
|
Ubuntu 机器人 Linux
|
2月前
|
传感器 数据可视化 机器人
【ROS速成】半小时入门机器人ROS系统简明教程之可视化系统(三)
半小时入门机器人ROS系统简明教程之可视化系统
110 0
|
2月前
|
机器人
【ROS速成】半小时入门机器人ROS系统简明教程之安装测速(二)
半小时入门机器人ROS系统简明教程之安装测速
|
4月前
|
Ubuntu Shell C++
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
225 1
|
4月前
|
机器人 Shell 开发者
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
这篇文章是关于ROS2(Robot Operating System 2)中功能包、依赖管理、工作空间配置和编译的教程,涵盖了ROS2工作空间的概念、如何获取和安装功能包的依赖、构建工作空间的步骤,以及如何创建和管理ROS2功能包,包括使用命令行工具对功能包进行操作的方法。
551 0
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
|
4月前
|
编解码 机器人 C++
ROS2教程07 ROS2自定义消息接口
这篇文章是关于如何在ROS2(Robot Operating System 2)中创建和使用自定义消息类型的教程,包括消息类型的定义、特点、命令行工具的使用,以及如何编写和测试自定义消息类型接口的步骤。
139 0
ROS2教程07 ROS2自定义消息接口
|
28天前
|
自动驾驶 安全 机器人
ROS2:从初识到深入,探索机器人操作系统的进化之路
前言 最近开始接触到基于DDS的这个系统,是在稚晖君的机器人项目中了解和认识到。于是便开始自己买书学习起来,感觉挺有意思的,但是只是单纯的看书籍,总会显得枯燥无味,于是自己又开始在网上找了一些视频教程结合书籍一起来看,便让我对ROS系统有了更深的认识和理解。 ROS的发展历程 ROS诞生于2007年的斯坦福大学,这是早期PR2机器人的原型,这个项目很快被一家商业公司Willow Garage看中,类似现在的风险投资一样,他们投了一大笔钱给这群年轻人,PR2机器人在资本的助推下成功诞生。 2010年,随着PR2机器人的发布,其中的软件正式确定了名称,就叫做机器人操作系统,Robot Op
70 14
|
1月前
|
XML 算法 自动驾驶
ROS进阶:使用URDF和Xacro构建差速轮式机器人模型
【11月更文挑战第7天】本篇文章介绍的是ROS高效进阶内容,使用URDF 语言(xml格式)做一个差速轮式机器人模型,并使用URDF的增强版xacro,对机器人模型文件进行二次优化。
|
1月前
|
自动驾驶 安全 机器人
ROS2:从初识到深入,探索机器人操作系统的进化之路
【11月更文挑战第4天】ROS2的学习过程和应用,介绍DDS系统的框架和知识。
|
7月前
|
传感器 人工智能 算法
ROS机器人操作系统
ROS机器人操作系统
184 1

推荐镜像

更多