actionlib
前言
- Actionlib是ROS中一个很重要的库,类似service通信机制,actionlib也是一种请求响应机制的通信方式,actionlib主要弥补了service通信的一个不足,就是当机器人执行一个长时间的任务时,假如利用service通信方式,那么publisher会很长时间接受不到反馈的reply,致使通信受阻。当service通信不能很好的完成任务时候,actionlib则可以比较适合实现长时间的通信过程,actionlib通信过程可以随时被查看过程进度,也可以终止请求,这样的一个特性,使得它在一些特别的机制中拥有很高的效率
简介
- 那么什么是 action?
- 一种问答通信机制
- 带有连续的反馈
- 可以在任务过程中止运行
- 基于ROS的消息机制实现
- 多对多的action-server与action-client的交互机制
客户端-服务器交互
- actionlib 使用 client-server工作模式,ActionClient 和 ActionServer 通过 "ROS Action Protocol" 进行通信,"ROS Action Protocol" 以 ROS 消息方式进行传输。此外 ActionClient 和 ActionServer 为用户提供了一些简单的接口,用户使用这些接口可以完成 goal 请求(client-side)和 goal 执行(server-side)

- ActionClient 和 ActionServer 之间使用action protocol通信,action protocol 就是预定义的一组 ROS message,这些 message 被放到 ROS topic 上在 ActionClient 和 ActionServer 之间进行传输实现二者的沟通

ROS Message:
- goal:用于向服务器发送任务目标
- cancel:用于向服务器发送取消请求
- status:用于通知客户端系统中每个目标的当前状态
- feedback:用于周期反馈任务运行的监控数据
- result:用于向client发送任务的执行结果,这个topic只会发布一次
创建action功能包
- 依然使用 catkin_simple 功能来创建 package
| catkin_create_pkg dodishes roscpp actionlib actionlib_msgs |
- 然后在新建的package中创建一个action文件夹用来存储action messages的信息,方法与创建service messages一样
- 惯例,在package.xml文件中添加两行生成消息文件的语句
| <build_depend>message_generation</build_depend> |
| <exec_depend>message_runtime</exec_depend> |
定义action文件
- ROS系统在action文件(文件名后缀为.action)中定义了上述 goal、result、feedback 等消息,每部分用 “---” 分隔
- 这些文件被放置在包的 ./action 目录
例如:./action/DoDishes.action
| ./action/DoDishes.action |
| |
| uint32 dishwasher_id |
| --- |
| |
| uint32 total_dishes_cleaned |
| --- |
| |
| float32 percent_complete |
基于这个 .action 文件,需要生成 6 条消息,以便客户端和服务器进行通信
功能包配置
package.xml
| <build_depend>actionlib</build_depend> |
| <build_depend>actionlib_msgs</build_depend> |
| <exec_depend>actionlib</exec_depend> |
| <exec_depend>actionlib_msgs</exec_depend> |
CMakeLists.txt
| find_package(catkin REQUIRED COMPONENTS |
| actionlib_msgs |
| actionlib |
| ) |
| |
| add_action_files(DIRECTORY action |
| FILES |
| DoDishes.action |
| ) |
| |
| generate_messages( |
| DEPENDENCIES |
| actionlib_msgs |
| ) |
| |
| catkin_package( |
| CATKIN_DEPENDS actionlib_msgs |
| ) |
编写action_server
- 在dodishes/src中创建DoDishes_server.cpp文件
| #include <ros/ros.h> |
| #include <actionlib/server/simple_action_server.h> |
| #include "dodishes/DoDishesAction.h" |
| |
| |
| typedef actionlib::SimpleActionServer<dodishes::DoDishesAction> Server; |
| |
| |
| void execute(const dodishes::DoDishesGoalConstPtr & goal, Server * as) |
| { |
| ros::Rate r(1); |
| dodishes::DoDishesFeedback feedback; |
| |
| ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id); |
| |
| |
| for (int i = 1; i <= 10; i++) |
| { |
| feedback.percent_complete = i * 10; |
| |
| |
| as->publishFeedback(feedback); |
| |
| r.sleep(); |
| } |
| |
| |
| ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id); |
| as->setSucceeded(); |
| } |
| |
| int main(int argc, char** argv) |
| { |
| ros::init(argc, argv, "do_dishes_server"); |
| ros::NodeHandle n; |
| |
| |
| Server server(n, "do_dishes", boost::bind(&execute, _1, &server), false); |
| |
| |
| |
| |
| server.start(); |
| |
| ros::spin(); |
| |
| return 0; |
| } |
总结:
- 初始化ROS节点;
- 创建action_server实例;
- 启动服务器,等待action请求;
- 在回调函数中完成动作服务功能的处理,并反馈进度信息;
- action完成,发送结束信息
编写action_client
- 在dodishes/src中创建DoDishes_client.cpp文件
| #include <ros/ros.h> |
| #include <actionlib/client/simple_action_client.h> |
| #include "dodishes/DoDishesAction.h" |
| |
| |
| typedef actionlib::SimpleActionClient<dodishes::DoDishesAction> Client; |
| |
| |
| void doneCb(const actionlib::SimpleClientGoalState & state, |
| const dodishes::DoDishesResultConstPtr & result) |
| { |
| ROS_INFO("Yay! The dishes are now clean"); |
| ros::shutdown(); |
| } |
| |
| |
| void activeCb() |
| { |
| ROS_INFO("Goal just went active"); |
| } |
| |
| |
| void feedbackCb(const dodishes::DoDishesFeedbackConstPtr & feedback) |
| { |
| ROS_INFO(" percent_complete : %f ", feedback->percent_complete); |
| } |
| |
| int main(int argc, char **argv) |
| { |
| ros::init(argc, argv, "do_dishes_client"); |
| |
| |
| Client client("do_dishes", true); |
| |
| ROS_INFO("Waiting for action server to start."); |
| |
| client.waitForServer(); |
| |
| |
| |
| ROS_INFO("Action server started, sending goal."); |
| |
| dodishes::DoDishesGoal goal; |
| |
| goal.dishwasher_id = 1; |
| |
| |
| client.sendGoal(goal, &doneCb, &activeCb, &feedbackCb); |
| |
| ros::spin(); |
| |
| return 0; |
| } |
总结:
- 初始化ROS节点;
- 创建action_client实例;
- 连接action服务端;
- 发送action goal;
- 根据不同类型的服务端反馈处理回调函数
编译配置
CMakeLists.txt
| add_executable(DoDishes_client src/DoDishes_client.cpp) |
| target_link_libraries(DoDishes_client ${catkin_LIBRARIES}) |
| add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS}) |
| |
| add_executable(DoDishes_server src/DoDishes_server.cpp) |
| target_link_libraries(DoDishes_server ${catkin_LIBRARIES}) |
| add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS}) |
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现