Action通信学习记录(一)

1.action通信自定义action文件

action、srv、msg 文件内的可用数据类型一致,且三者实现流程类似:

  1. 按照固定格式创建action文件;

  2. 编辑配置文件;

  3. 编译生成中间文件。

1.定义action文件

首先新建功能包,并导入依赖: roscpp rospy std_msgs actionlib actionlib_msgs

然后功能包下新建 action 目录,新增 Xxx.action(比如:AddInts.action)。

action 文件内容组成分为三部分:请求目标值、最终响应结果、连续反馈,三者之间使用---分割示例内容如下:

#目标值
int32 num
---
#最终结果
int32 result
---
#连续反馈
float64 progress_bar
2.编辑配置文件

CMakeLists.txt

find_package
(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  actionlib
  actionlib_msgs
)
add_action_files(
  FILES
  AddInts.action
)
generate_messages(
  DEPENDENCIES
  std_msgs
  actionlib_msgs
)
catkin_package(

#  INCLUDE_DIRS include
#  LIBRARIES demo04_action

 CATKIN_DEPENDS roscpp rospy std_msgs actionlib actionlib_msgs

#  DEPENDS system_lib

)
3.编译

编译后会生成一些中间文件。

msg文件(…/工作空间/devel/share/包名/msg/xxx.msg):

Action通信学习记录(一)_第1张图片

C++ 调用的文件(…/工作空间/devel/include/包名/xxx.h):

Action通信学习记录(一)_第2张图片

Python 调用的文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg/xxx.py):

Action通信学习记录(一)_第3张图片

2. action通信自定义action文件调用(Python)

需求:

创建两个ROS 节点,服务器和客户端,客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和,这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,为了良好的用户体验,需要服务器在计算过程中,每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。

流程:

  1. 编写action服务端实现;
  2. 编写action客户端实现;
  3. 编辑CMakeLists.txt;
  4. 编译并执行。
0.vscode配置

需要像之前自定义 msg 实现一样配置settings.json 文件,如果以前已经配置且没有变更工作空间,可以忽略,如果需要配置,配置方式与之前相同:

{
    "python.autoComplete.extraPaths": [
        "/opt/ros/noetic/lib/python3/dist-packages",
        "/xxx/yyy工作空间/devel/lib/python3/dist-packages"
    ]
}
1.服务端
#! /usr/bin/env python3

import rospy
import actionlib
from demo01_action.msg import *


class MyAction:
    
    def __init__(self) -> None:
        self.server = actionlib.SimpleActionServer("addInts", AddIntsAction, self.cb, False)
        self.server.start()
        rospy.loginfo("服务器启动中...")
          
    def cb(self, goal):
        goal_num = goal.num
        rospy.loginfo("目标值 %d", goal_num)
        rate = rospy.Rate(10)
        sum = 0
        rospy.loginfo("请求处理中...")
        for i in range(1, goal_num + 1):
            sum = sum + i
            rate.sleep()
            fb_obj = AddIntsFeedback()
            fb_obj.progress_bar = i / goal_num
            self.server.publish_feedback(fb_obj)
            
        result = AddIntsResult()
        result.result = sum
        rospy.loginfo("result: %d", result.result)
        self.server.set_succeeded(result)
        
if __name__ == "__main__":
    rospy.init_node("action_server_p")
    myAction = MyAction()
    rospy.spin()

PS:

可以先配置CMakeLists.tx文件并启动上述action服务端,然后通过 rostopic 查看话题,向action相关话题发送消息,或订阅action相关话题的消息。

代码解读:

类定义:MyAction

这个类定义了动作服务器的行为和功能。

构造函数 __init__(self)

在构造函数中,创建了一个SimpleActionServer对象。这个服务器监听名为"addInts"的动作话题,使用AddIntsAction动作类型,并定义了一个回调函数self.cb来处理接收到的目标请求。服务器启动后,会打印一条日志信息。

回调函数 cb(self, goal)

这是处理接收到的动作目标的函数。它执行以下步骤:

  1. 从目标消息中提取目标值 (goal.num)。
  2. 初始化累加和 (sum) 和ROS的速率控制对象 (rospy.Rate(10))。
  3. 对从1到目标值的每个整数进行累加,并在每次迭代中通过publish_feedback方法发送进度反馈。
  4. 累加完成后,创建一个AddIntsResult对象,设置结果值,并通过set_succeeded方法通知客户端任务完成

AddInts.action编译生成文件

在 ROS (Robot Operating System) 中,当你创建一个 .action 文件,比如 AddInts.action,用于定义一个动作(Action),ROS 的构建系统会自动为你生成一系列相关的类。这些类是根据 .action 文件的内容创建的,用于在 ROS 中实现动作的目标、反馈和结果。下面是关于 AddInts.action 自动生成的类的详细解释:

  1. AddIntsAction:

    • 这个类是整个动作的总体表示。它封装了动作的所有方面:目标(Goal)、反馈(Feedback)和结果(Result)。
    • 在动作服务器端,这个类用于接收目标,处理动作,并返回结果。
    • 在动作客户端端,这个类用于发送目标并接收结果和反馈。
  2. AddIntsActionGoal:

    • 这个类代表动作的目标部分。
    • 它包含了触发动作所需的所有输入数据。在 AddInts 的情况下,这可能是两个要相加的整数。
    • 当动作客户端向服务器发送一个新目标时,这个类被用作消息的类型。
  3. AddIntsActionResult:

    • 这个类代表动作的结果部分。
    • 它包含了动作完成后的输出数据。对于 AddInts,这可能是相加后的和。
    • 当动作完成时,服务器使用这个类来发送结果给客户端。
  4. AddIntsActionFeedback:

    • 这个类代表动作的反馈部分。
    • 它包含了动作执行过程中服务器可能提供的实时更新或状态信息。
    • 如果动作的执行需要一些时间,并且服务器配置为在执行过程中提供反馈,那么这个类将被用来发送这些信息。

这些类是自动生成的,是基于你在 AddInts.action 文件中定义的目标、结果和反馈的数据结构。例如,如果你的 AddInts.action 文件定义了目标为两个整数,结果为一个整数(和),并且没有定义任何反馈,则相应的 AddIntsActionGoal 类将包含两个整数的字段,AddIntsActionResult 类将包含一个整数字段,而 AddIntsActionFeedback 类可能会很简单或根本不被使用(如果没有定义反馈)。

这些类使得在 ROS 中实现复杂的动作逻辑变得简单,因为它们为动作的每个方面提供了清晰的结构和数据类型。

你可能感兴趣的:(学习,python,笔记)