ROS:action通信

目录

  • 一、前言
  • 二、概念
  • 三、作用
  • 四、实际案例
    • 4.1需求
    • 4.2action通信自定义action文件
      • 4.2.1定义action文件
      • 4.2.2编辑配置文件
      • 4.2.3编译
    • 4.3action通信自定义action文件调用(C++)
      • 4.3.1流程
      • 4.3.2vscode配置
      • 4.3.3服务端
      • 4.3.4客户端
      • 4.3.5编译配置文件
      • 4.3.6执行
    • 4.4action通信自定义action文件调用(Python)
      • 4.4.1流程
      • 4.4.2vscode配置
      • 4.4.3服务端
      • 4.4.4客户端
      • 4.4.5编辑配置文件
      • 4.4.6执行

一、前言

关于action通信,先从之前导航中的应用场景开始介绍,描述如下:
机器人导航到某个目标点,此过程需要一个节点A发布目标信息,然后一个节点B接收到请求并控制移动,最终响应目标达成状态信息。
这好像是服务通信实现,因为需求中要A发送目标,B执行并返回结果,这是一个典型的基于请求响应的应答模式,不过,如果只是使用基本的服务通信实现,存在一个问题:导航是一个过程,是耗时操作,如果使用服务通信,那么只有在导航结束时,才会产生响应结果,而在导航过程中,节点A是不会获取到任何反馈的,从而可能出现程序"假死"的现象,过程的不可控意味着不良的用户体验,以及逻辑处理的缺陷(比如:导航中止的需求无法实现)。更合理的方案应该是:导航过程中,可以连续反馈当前机器人状态信息,当导航终止时,再返回最终的执行结果。在ROS中,该实现策略称之为:action 通信。

二、概念

在ROS中提供了actionlib功能包集,用于实现 action 通信。action 是一种类似于服务通信的实现,其实现模型也包含请求和响应,但是不同的是,在请求和响应的过程中,服务端还可以连续的反馈当前任务进度,客户端可以接收连续反馈并且还可以取消任务。

action结构图解:
在这里插入图片描述
action通信接口图解:
在这里插入图片描述
goal:目标任务;
cacel:取消任务;
status:服务端状态;
result:最终执行结果(只会发布一次);
feedback:连续反馈(可以发布多次)。

三、作用

一般适用于耗时的请求响应场景,用以获取连续的状态反馈。

四、实际案例

4.1需求

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

4.2action通信自定义action文件

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

按照固定格式创建action文件;
编辑配置文件;
编译生成中间文件。

4.2.1定义action文件

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

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

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

#目标值
int32 num
---
#最终结果
int32 result
---
#连续反馈
float64 progress_bar

4.2.2编辑配置文件

CMakeLists.txt

find_package
(catkin REQUIRED COMPONENTSroscpprospystd_msgsactionlibactionlib_msgs
)
Copy
add_action_files(FILESAddInts.action
)
Copy
generate_messages(DEPENDENCIESstd_msgsactionlib_msgs
)
Copy
catkin_package(#  INCLUDE_DIRS include
#  LIBRARIES demo04_actionCATKIN_DEPENDS roscpp rospy std_msgs actionlib actionlib_msgs#  DEPENDS system_lib)

4.2.3编译

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

msg文件(…/工作空间/devel/share/包名/msg/xxx.msg):
在这里插入图片描述
C++ 调用的文件(…/工作空间/devel/include/包名/xxx.h):
在这里插入图片描述
Python 调用的文件(…/工作空间/devel/lib/python3/dist-packages/包名/msg/xxx.py):
在这里插入图片描述

4.3action通信自定义action文件调用(C++)

4.3.1流程

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

4.3.2vscode配置

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

{"configurations": [{"browse": {"databaseFilename": "","limitSymbolsToIncludedHeaders": true},"includePath": ["/opt/ros/noetic/include/**","/usr/include/**","/xxx/yyy工作空间/devel/include/**" //配置 head 文件的路径 ],"name": "ROS","intelliSenseMode": "gcc-x64","compilerPath": "/usr/bin/gcc","cStandard": "c11","cppStandard": "c++17"}],"version": 4
}

4.3.3服务端

#include "ros/ros.h"
#include "actionlib/server/simple_action_server.h"
#include "demo01_action/AddIntsAction.h"
/*  需求:创建两个ROS节点,服务器和客户端,客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算1到N之间所有整数的和,这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,为了良好的用户体验,需要服务器在计算过程中,每累加一次,就给客户端响应一次百分比格式的执行进度,使用action实现。流程:1.包含头文件;2.初始化ROS节点;3.创建NodeHandle;4.创建action服务对象;5.处理请求,产生反馈与响应;6.spin().*/typedef actionlib::SimpleActionServer<demo01_action::AddIntsAction> Server;void cb(const demo01_action::AddIntsGoalConstPtr &goal,Server* server){//获取目标值int num = goal->num;ROS_INFO("目标值:%d",num);//累加并响应连续反馈int result = 0;demo01_action::AddIntsFeedback feedback;//连续反馈ros::Rate rate(10);//通过频率设置休眠时间for (int i = 1; i <= num; i++){result += i;//组织连续数据并发布feedback.progress_bar = i / (double)num;server->publishFeedback(feedback);rate.sleep();}//设置最终结果demo01_action::AddIntsResult r;r.result = result;server->setSucceeded(r);ROS_INFO("最终结果:%d",r.result);
}int main(int argc, char *argv[])
{setlocale(LC_ALL,"");ROS_INFO("action服务端实现");// 2.初始化ROS节点;ros::init(argc,argv,"AddInts_server");// 3.创建NodeHandle;ros::NodeHandle nh;// 4.创建action服务对象;/*SimpleActionServer(ros::NodeHandle n, std::string name, boost::function<void (const demo01_action::AddIntsGoalConstPtr &)> execute_callback, bool auto_start)*/// actionlib::SimpleActionServer<demo01_action::AddIntsAction> server(....);Server server(nh,"addInts",boost::bind(&cb,_1,&server),false);server.start();// 5.处理请求,产生反馈与响应;// 6.spin().   ros::spin();return 0;
}

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

4.3.4客户端

#include "ros/ros.h"
#include "actionlib/client/simple_action_client.h"
#include "demo01_action/AddIntsAction.h"/*  需求:创建两个ROS节点,服务器和客户端,客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算1到N之间所有整数的和,这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,为了良好的用户体验,需要服务器在计算过程中,每累加一次,就给客户端响应一次百分比格式的执行进度,使用action实现。流程:1.包含头文件;2.初始化ROS节点;3.创建NodeHandle;4.创建action客户端对象;5.发送目标,处理反馈以及最终结果;6.spin().*/
typedef actionlib::SimpleActionClient<demo01_action::AddIntsAction> Client;//处理最终结果
void done_cb(const actionlib::SimpleClientGoalState &state, const demo01_action::AddIntsResultConstPtr &result){if (state.state_ == state.SUCCEEDED){ROS_INFO("最终结果:%d",result->result);} else {ROS_INFO("任务失败!");}}
//服务已经激活
void active_cb(){ROS_INFO("服务已经被激活....");
}
//处理连续反馈
void  feedback_cb(const demo01_action::AddIntsFeedbackConstPtr &feedback){ROS_INFO("当前进度:%.2f",feedback->progress_bar);
}int main(int argc, char *argv[])
{setlocale(LC_ALL,"");// 2.初始化ROS节点;ros::init(argc,argv,"AddInts_client");// 3.创建NodeHandle;ros::NodeHandle nh;// 4.创建action客户端对象;// SimpleActionClient(ros::NodeHandle & n, const std::string & name, bool spin_thread = true)// actionlib::SimpleActionClient<demo01_action::AddIntsAction> client(nh,"addInts");Client client(nh,"addInts",true);//等待服务启动client.waitForServer();// 5.发送目标,处理反馈以及最终结果;/*  void sendGoal(const demo01_action::AddIntsGoal &goal, boost::function<void (const actionlib::SimpleClientGoalState &state, const demo01_action::AddIntsResultConstPtr &result)> done_cb, boost::function<void ()> active_cb, boost::function<void (const demo01_action::AddIntsFeedbackConstPtr &feedback)> feedback_cb)*/demo01_action::AddIntsGoal goal;goal.num = 10;client.sendGoal(goal,&done_cb,&active_cb,&feedback_cb);// 6.spin().ros::spin();return 0;
}

注:等待服务启动,只可以使用client.waitForServer();,之前服务中等待启动的另一种方式ros::service::waitForService("addInts");不适用

4.3.5编译配置文件

add_executable(action01_server src/action01_server.cpp)
add_executable(action02_client src/action02_client.cpp)
...add_dependencies(action01_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
add_dependencies(action02_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
...target_link_libraries(action01_server${catkin_LIBRARIES}
)
target_link_libraries(action02_client${catkin_LIBRARIES}
)

4.3.6执行

首先启动 roscore,然后分别启动action服务端与action客户端。

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

4.4.1流程

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

4.4.2vscode配置

{"python.autoComplete.extraPaths": ["/opt/ros/noetic/lib/python3/dist-packages","/xxx/yyy工作空间/devel/lib/python3/dist-packages"]
}

4.4.3服务端

#! /usr/bin/env python
import rospy
import actionlib
from demo01_action.msg import *
"""需求:创建两个ROS 节点,服务器和客户端,客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和,这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,为了良好的用户体验,需要服务器在计算过程中,每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。流程:1.导包2.初始化 ROS 节点3.使用类封装,然后创建对象4.创建服务器对象5.处理请求数据产生响应结果,中间还要连续反馈6.spin
"""class MyActionServer:def __init__(self):#SimpleActionServer(name, ActionSpec, execute_cb=None, auto_start=True)self.server = actionlib.SimpleActionServer("addInts",AddIntsAction,self.cb,False)self.server.start()rospy.loginfo("服务端启动")def cb(self,goal):rospy.loginfo("服务端处理请求:")#1.解析目标值num = goal.num#2.循环累加,连续反馈rate = rospy.Rate(10)sum = 0for i in range(1,num + 1):# 累加sum = sum + i# 计算进度并连续反馈feedBack = i / numrospy.loginfo("当前进度:%.2f",feedBack)feedBack_obj = AddIntsFeedback()feedBack_obj.progress_bar = feedBackself.server.publish_feedback(feedBack_obj)rate.sleep()#3.响应最终结果result = AddIntsResult()result.result = sum        self.server.set_succeeded(result)rospy.loginfo("响应结果:%d",sum)
if __name__ == "__main__":rospy.init_node("action_server_p")server = MyActionServer()rospy.spin()

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

4.4.4客户端

#! /usr/bin/env pythonimport rospy
import actionlib
from demo01_action.msg import *"""需求:创建两个ROS 节点,服务器和客户端,客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和,这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的,又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s,为了良好的用户体验,需要服务器在计算过程中,每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。流程:1.导包2.初始化 ROS 节点3.创建 action Client 对象4.等待服务5.组织目标对象并发送6.编写回调, 激活、连续反馈、最终响应7.spin
"""def done_cb(state,result):if state == actionlib.GoalStatus.SUCCEEDED:rospy.loginfo("响应结果:%d",result.result)def active_cb():rospy.loginfo("服务被激活....")def fb_cb(fb):rospy.loginfo("当前进度:%.2f",fb.progress_bar)if __name__ == "__main__":# 2.初始化 ROS 节点rospy.init_node("action_client_p")# 3.创建 action Client 对象client = actionlib.SimpleActionClient("addInts",AddIntsAction)# 4.等待服务client.wait_for_server()# 5.组织目标对象并发送goal_obj = AddIntsGoal()goal_obj.num = 10client.send_goal(goal_obj,done_cb,active_cb,fb_cb)# 6.编写回调, 激活、连续反馈、最终响应# 7.spinrospy.spin()

4.4.5编辑配置文件

先为 Python 文件添加可执行权限:chmod +x *.py

catkin_install_python(PROGRAMSscripts/action01_server_p.pyscripts/action02_client_p.pyDESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

4.4.6执行

首先启动 roscore,然后分别启动action服务端与action客户端。

参考视屏:赵虚左ros入门
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字节跳动面试挂在2面,复盘后,决定二战.....

先说下我基本情况&#xff0c;本科不是计算机专业&#xff0c;现在是学通信&#xff0c;然后做图像处理&#xff0c;可能面试官看我不是科班出身没有问太多计算机相关的问题&#xff0c;因为第一次找工作&#xff0c;字节的游戏专场又是最早开始的&#xff0c;就投递了&#xf…

EXCEl——移除单元格中换行符

方法一&#xff1a;使用清除格式功能 步骤如下: 1.选中需要取消换行的单元格 2.在“开始"选项卡中找到"清除”功能&#xff0c;点击下拉菜单中的“清除格式" 3.这时单元格的换行就被取消了。 清除前效果图 清除后效果图 方法一&#xff1a;使用函数功能 步骤…

K8s入门

K8s入门 目录 K8s入门namespacepoddeployment多版本扩缩容治愈能力滚动更新版本回退 serviceClusterIPNodePort ingress域名访问路径重写流量限制 存储抽象PV&PVCConfigMapSecret namespace kubectl get ns # 获取命名空间 kubectl create ns 名字 # 创建命名空间 ku…

自动收小麦机(牛客2023萌新)

题目链接 示例1 输入 复制 4 1 2 1 1 4 5 2 2 2 3 4 输出 复制 10 说明 在第4格放出水流后&#xff0c;水流会流向第3格&#xff0c;由于第3格高度比第4格低&#xff0c;所以水流继续向左流向第2格&#xff0c;因为平地水流只能流2格&#xff0c;所以到达第2格后水流停…

【Fiddler】Fiddler实现mock测试(模拟接口数据)

软件接口测试过程中&#xff0c;经常会遇后端接口还没有开发完成&#xff0c;领导就让先介入测试&#xff0c;然后缩短项目时间&#xff0c;有的人肯定会懵&#xff0c;接口还没开发好&#xff0c;怎么介入测试&#xff0c;其实这就涉及到了我们要说的mock了。 一、mock原理 m…

【ArcGIS Pro二次开发】(49):村规数据入库【福建省】

之前用Arcpy脚本工具做了一个村规数据入库和主要图纸生成工具。 在使用过程中&#xff0c;感觉对电脑环境比较高&#xff0c;换电脑用经常会一些莫名其妙的错误&#xff0c;bug修得很累。近来随着ArcGIS Pro SDK的熟悉&#xff0c;就有了移植的想法。 这里先把村规数据入库工…

QT学习—【属于自己的】串口调试助手

文章目录 一、功能简介二、串口助手实现2.1 创建UI2.2 扫描可用串口2.3 配置波特率2.4 配置数据位2.5 配置停止位2.6 配置校验位2.7 打开/关闭串口2.8 刷新串口2.9 发送新行2.10 串口发送2.11 串口接收显示2.12 清空接收窗口2.13 定时发送2.14 固定窗口大小 三、总结3.1 将信号…

本地前端项目使用gitee仓库外链图片加载失败

错误&#xff1a;本地的前端项目&#xff0c;比如vue&#xff0c;纯html使用<img/>标签加载gitee保存的图片文件的时候&#xff0c;浏览器加载失败。 但是gitee可以正常访问图片 解决办法&#xff1a; 在index.html中加入meta标签就可以完美解决 <meta name"r…

centos升级龙蜥

centos升级龙蜥 龙蜥简介龙蜥官方社区centos升级龙蜥首先确认自己的centos版本下载迁移镜像源安装epel源迁移工具安装i686包查看执行迁移脚本结果查看重启机器查看系统信息 龙蜥简介 2021年10月19日的大会上&#xff0c;阿里云发布全新操作系统“龙蜥”并宣布开源。龙蜥操作系…

python 批量下载图片(协程)

要下载的图片网站 1、总共多少页&#xff0c;得到每页的 url 列表 2、每页的图片详情的 ulr 列表&#xff08;因为该高清大图在图片详情页&#xff0c;因此需要去图片详情页拿图片的url) ​​​​​​​ 3、进入图片详情页&#xff0c;获取到图片url 然后下载。 完整代码如下&…

涂鸦智能打造专业家庭智能生活助手,实现人机交互升级

近年来&#xff0c;智能家居设备的品类不断拓展&#xff0c;同时&#xff0c;人们对AI与智能家居的联动愈发憧憬。自然语言交互是未来人机交互的主要趋势之一&#xff0c;其关键在于使AI具备主动理解信息的能力&#xff0c;让用户的交互更轻松。如何将智能场景的交互变得更“善…

SpringBoot中通过自定义Jackson注解实现接口返回数据脱敏

场景 SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文&#xff0c;查询明文&#xff1a; SpringBoot中整合Sharding Sphere实现数据加解密/数据脱敏/数据库密文&#xff0c;查询明文_霸道流氓气质的博客-CSDN博客 上面讲的是数据库中存储密文&#xff0…

HTML+CSS+JavaScript:渲染柱形统计图

一、需求 用户输入四个季度的数据&#xff0c;根据数据生成柱形统计图&#xff0c;浏览器预览效果如下 二、完整代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content&q…

【图像分割 2023 CVPR】CFNet

文章目录 【图像分割 2023 CVPR】CFNet摘要1. 简介2. 相关工作2.1 稠密预测的主干网设计2.2 多尺度特征融合 3. 方法3.1 整体架构3.2 过渡块3.4 结构变体 【图像分割 2023 CVPR】CFNet 论文题目&#xff1a;CFNet: Cascade Fusion Network for Dense Prediction 中文题目&#…

音视频H265编码; Socket通信实现N对N连接代码示例

H.265编码和Socket通信是两个不同的概念&#xff0c;它们分别涉及视频编码和网络通信。在实现N对N连接时&#xff0c;您可以将它们结合起来&#xff0c;但要注意每个方面的具体实现。 H.265编码&#xff08;视频编码&#xff09;&#xff1a; H.265编码涉及将视频数据进行压缩…

❤️创意网页:打造简洁美观的网页轮播图(HTML简单实现轮播图)操作简单可以直接使用

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

EMC学习笔记(十七)PCB设计中的安规考虑

PCB设计中的安规考虑 1 概述2.安全标识2.1 对安全标示通用准则2.2 电击和能量的危险2.3 PCB上的熔断器2.4 可更换电池 3.爬电距离和电气间隙4.涂覆印制板4.1 PCB板的机械强度4.2 印制电路板的阻燃等级4.3 热循环试验与热老化试验4.4 抗电强度试验4.5 耐划痕试验 5.布线和供电 1…

【智能交互】OPPO接入小布语音技能通关教程:个人开发者实现接口调用

目录 前言实际操作注册OPPO平台账号打开创建技能界面创建技能创建意图槽位解析对话管理对话测试接口代码编写接口创建新建意图对话管理测试猜想测试相关文档前言 适用人群:本教程适合大赛接入小布语音技能的同学以及初次使用小布助手的开发者 本篇文章是博主弄了多次测试才勉…

智慧数据驱动:基于smardaten构建多维数据可视化大屏

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

node基于express+mongodb项目的整体结构搭建和逻辑抽离

一、为什么需要逻辑抽离 这是我用express实现的一个缩减版的注册功能,如下&#xff1a; app.js const express require("express"); const app express();// 连接数据库 const mongoose require("mongoose"); // 连接数据库myTest mongoose.connect(…