当前位置:网站首页>ROS学习(23)action通信机制
ROS学习(23)action通信机制
2022-07-06 18:12:00 【敲代码的雪糕】
前言
ROS中常用的通信机制是话题和服务,但是很多场景下,这两种通信机制往往满足不了所有需求。
action通信机制,是一种带有连续反馈的上层通信机制,底层基于ROS话题通信。
一、什么是action
ROS中的actionlib功能包,用于实现action的通信机制。action类似于服务通信机制,不同之处在于action带有连续反馈,可以不断的反馈任务进度,也可以在任务过程中中止运行。
二、action的工作机制
action采用客户端/服务器的工作模式,如下:
Action客户端与Action服务端之间通过actionlib定义的action protocol进行通信,这种协议基于ROS的消息机制实现。
客户端向服务端发布任务目标以及在必要的时候取消任务,服务端会向客户端发布当前状态、实时反馈和任务执行的结果。如图:
三、action的定义
action通过.action文件定义,放置在功能包中的action文件夹下,格式如下:
#定义目标信息
uint32 dishwasher_id
#定义结果信息
uint32 total_dishes_cleaned
#定义周期反馈的消息
float32 percent_complete
可见,一个action的定义需要三部分:goal、result、feedback。
四、代码实现
主要实现action的客户端和服务端节点,新建名为action_tutorials功能包。
1、创建客户端
在action的定义中,描述了一个洗盘子的任务。客户端节点负责发出action请求,DoDishes_client.cpp文件内容如下:
#include <actionlib/client/simple_action_client.h>
#include "action_tutorials/DoDishesAction.h"
typedef actionlib::SimpleActionClient<action_tutorials::DoDishesAction> Client;
// 当action完成后会调用该回调函数一次
void doneCb(const actionlib::SimpleClientGoalState& state,
const action_tutorials::DoDishesResultConstPtr& result)
{
ROS_INFO("Yay! The dishes are now clean");
ros::shutdown();
}
// 当action激活后会调用该回调函数一次
void activeCb()
{
ROS_INFO("Goal just went active");
}
// 收到feedback后调用该回调函数
void feedbackCb(const action_tutorials::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.");
// 创建一个action的goal
action_tutorials::DoDishesGoal goal;
goal.dishwasher_id = 1;
// 发送action的goal给服务器端,并且设置回调函数
client.sendGoal(goal, &doneCb, &activeCb, &feedbackCb);
ros::spin();
return 0;
}
2、创建服务端
服务器节点负责完成洗盘子的任务,并且反馈洗盘子的实时进度,DoDishes_server.cpp文件内容如下:
#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
#include "action_tutorials/DoDishesAction.h"
typedef actionlib::SimpleActionServer<action_tutorials::DoDishesAction> Server;
// 收到action的goal后调用该回调函数
void execute(const action_tutorials::DoDishesGoalConstPtr& goal, Server* as)
{
ros::Rate r(1);
action_tutorials::DoDishesFeedback feedback;
ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id);
// 假设洗盘子的进度,并且按照1hz的频率发布进度feedback
for(int i=1; i<=10; i++)
{
feedback.percent_complete = i * 10;
as->publishFeedback(feedback);
r.sleep();
}
// 当action完成后,向客户端返回结果
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;
}
3、配置
在CMakeLists.txt中添加如下规则:
find_package(catkin REQUIRED genmsg actionlib_msgs actionlib)
add_action_files(DIRECTORY action FILES DoDishes.action)
generate_messages(DEPENDENCIES actionlib_msgs)
在功能包的package.xml文件中添加如下配置:
<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<build_depend>roscpp</build_depend>
<run_depend>actionlib</run_depend>
<run_depend>actionlib_msgs</run_depend>
<run_depend>roscpp</run_depend>
然后编译功能包,如下:
从编译后生成的这些文件看,action确实是一种基于消息的、更加高层的通信机制。
4、运行
先启动master节点,命令如下:
roscore
启动服务端节点,命令如下:
rosrun action_tutorials DoDishes_server
再启动客户端节点,命令如下:
rosrun action_tutorials DoDishes_client
效果如下:
边栏推荐
- Drag to change order
- ZOJ problem set – 2563 long dominoes [e.g. pressure DP]
- JS ES5也可以創建常量?
- 场景实践:基于函数计算快速搭建Wordpress博客系统
- Public key \ private SSH avoid password login
- AcWing 1140. Shortest network (minimum spanning tree)
- Long press the button to execute the function
- Yunna | work order management measures, how to carry out work order management
- Sword finger offer II 035 Minimum time difference - quick sort plus data conversion
- Use nodejs to determine which projects are packaged + released
猜你喜欢
刨析《C语言》【进阶】付费知识【一】
LeetCode:1175. 质数排列
Can't you understand the code of linked list in C language? An article allows you to grasp the secondary pointer and deeply understand the various forms of parameter passing in the function parameter
[signal and system]
Today's question -2022/7/4 modify string reference type variables in lambda body
shell脚本快速统计项目代码行数
Appium基础 — Appium Inspector定位工具(一)
Scenario practice: quickly build wordpress blog system based on function calculation
Transplant DAC chip mcp4725 to nuc980
黑马笔记---异常处理
随机推荐
js如何快速创建一个长度为 n 的数组
JS Es5 can also create constants?
dvajs的基础介绍及使用
图片打水印 缩放 和一个输入流的转换
ZOJ Problem Set – 2563 Long Dominoes 【如压力dp】
AcWing 345. 牛站 题解(floyd的性质、倍增)
Hutool post requests to set the body parameter to JSON data
刨析《C语言》【进阶】付费知识【二】
Baidu flying general BMN timing action positioning framework | data preparation and training guide (Part 2)
蓝桥杯2022年第十三届省赛真题-积木画
JS how to quickly create an array with length n
Drag to change order
修改px4飞控的系统时间
Get to know MySQL for the first time
New job insights ~ leave the old and welcome the new~
AcWing 904. 虫洞 题解(spfa求负环)
Yunna | work order management software, work order management software app
What does front-end processor mean? What is the main function? What is the difference with fortress machine?
Dark horse notes - create immutable sets and streams
增加 pdf 标题浮窗