action、srv、msg 文件内的可用数据类型一致,且三者实现流程类似:
按照固定格式创建action文件;
编辑配置文件;
编译生成中间文件。
首先新建功能包,并导入依赖: roscpp rospy std_msgs actionlib actionlib_msgs
;
然后功能包下新建 action 目录,新增 Xxx.action(比如:AddInts.action)。
action 文件内容组成分为三部分:请求目标值、最终响应结果、连续反馈,三者之间使用---
分割示例内容如下:
#目标值
int32 num
---
#最终结果
int32 result
---
#连续反馈
float64 progress_bar
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
)
编译后会生成一些中间文件。
msg文件(…/工作空间/devel/share/包名/msg/xxx.msg):
C++ 调用的文件(…/工作空间/devel/include/包名/xxx.h):
Python 调用的文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg/xxx.py):
需求:
创建两个ROS 节点,服务器和客户端,客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和,这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,为了良好的用户体验,需要服务器在计算过程中,每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。
流程:
需要像之前自定义 msg 实现一样配置settings.json 文件,如果以前已经配置且没有变更工作空间,可以忽略,如果需要配置,配置方式与之前相同:
{
"python.autoComplete.extraPaths": [
"/opt/ros/noetic/lib/python3/dist-packages",
"/xxx/yyy工作空间/devel/lib/python3/dist-packages"
]
}
#! /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)
这是处理接收到的动作目标的函数。它执行以下步骤:
goal.num
)。sum
) 和ROS的速率控制对象 (rospy.Rate(10)
)。publish_feedback
方法发送进度反馈。AddIntsResult
对象,设置结果值,并通过set_succeeded
方法通知客户端任务完成在 ROS (Robot Operating System) 中,当你创建一个 .action
文件,比如 AddInts.action
,用于定义一个动作(Action),ROS 的构建系统会自动为你生成一系列相关的类。这些类是根据 .action
文件的内容创建的,用于在 ROS 中实现动作的目标、反馈和结果。下面是关于 AddInts.action
自动生成的类的详细解释:
AddIntsAction
:
AddIntsActionGoal
:
AddInts
的情况下,这可能是两个要相加的整数。AddIntsActionResult
:
AddInts
,这可能是相加后的和。AddIntsActionFeedback
:
这些类是自动生成的,是基于你在 AddInts.action
文件中定义的目标、结果和反馈的数据结构。例如,如果你的 AddInts.action
文件定义了目标为两个整数,结果为一个整数(和),并且没有定义任何反馈,则相应的 AddIntsActionGoal
类将包含两个整数的字段,AddIntsActionResult
类将包含一个整数字段,而 AddIntsActionFeedback
类可能会很简单或根本不被使用(如果没有定义反馈)。
这些类使得在 ROS 中实现复杂的动作逻辑变得简单,因为它们为动作的每个方面提供了清晰的结构和数据类型。