当前位置:网站首页>ROS Action通信
ROS Action通信
2022-07-31 01:06:00 【2021 Nqq】
文章目录
应用场景:需要使用服务通信,但需要及时进行反馈。
在ROS中提供了actionlib功能包集,用于实现 action 通信。action 是一种类似于服务通信的实现,其实现模型也包含请求和响应,但是不同的是,在请求和响应的过程中,服务端还可以连续的反馈当前任务进度,客户端可以接收连续反馈并且还可以取消任务。
action通信接口
- goal:目标任务
- cacel:取消任务
- status:服务端状态
- result:最终执行结果(只会发布一次)
- feedback:连续反馈(可以发布多次)
自定义action文件(类似msg和service)
服务端 action01_server.cpp
/* 需求: 创建两个ROS节点,服务器和客户端, 客户端可以向服务器发送目标数据N(一个整型数据) 服务器会计算1到N之间所有整数的和,这是一个循环累加的过程,返回给客户端, 这是基于请求响应模式的, 又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s, 为了良好的用户体验,需要服务器在计算过程中, 每累加一次,就给客户端响应一次百分比格式的执行进度,使用action实现。 流程: 1.包含头文件; 2.初始化ROS节点; 3.创建 NodeHandle; 4.创建 action 服务对象; 5.处理请求(a. 解析提交的目标值;b. 产生连续反馈;c. 最终结果响应)产生反馈与响应; 回调函数实现 6.spin()回旋 */
#include"ros/ros.h"
#include"actionlib/server/simple_action_server.h"
#include"demo01_action/AddIntsAction.h"
// 重命名
typedef actionlib::SimpleActionServer<demo01_action::AddIntsAction> Server;
// 5.处理请求(a. 解析提交的目标值;b. 产生连续反馈;c. 最终结果响应)——回调函数实现 客户端提供的goal 和 服务端的server对象
void cb(const demo01_action::AddIntsGoalConstPtr &goalPtr,Server* server){
// a. 解析提交的目标值
int goal_num = goalPtr->num;
ROS_INFO("客户端提交的目标值是:%d",goal_num);
// b. 产生连续反馈 累加
ros::Rate rate(10);// 10Hz
int result = 0;
ROS_INFO("开始连续反馈.....");
for(int i = 1; i <= goal_num; i++)
{
// 累加
result += i;
// 休眠
rate.sleep();
// 产生连续反馈
// void publishFeedback(const demo01_action::AddIntsFeedback &feedback)
demo01_action::AddIntsFeedback fb;
fb.progress_bar = i / (double)goal_num;
server->publishFeedback(fb);
}
ROS_INFO("最终响应结果:%d",result);
// c. 最终结果响应
demo01_action::AddIntsResult r;
r.result = result;
server->setSucceeded(r);
}
int main(int argc, char *argv[])
{
// 2.初始化ROS节点;
setlocale(LC_ALL,"");
ros::init(argc,argv,"addInts_server");// 节点
// 3.创建 NodeHandle;
ros::NodeHandle nh;
// 4.创建 action 服务对象;
/* SimpleActionServer(ros::NodeHandle n, NodeHandle std::string name, 话题名称 boost::function<void (const demo01_action::AddIntsGoalConstPtr &)> execute_callback, 回调函数 bool auto_start 是否自动启动 参数1: NodeHandle 参数2: 话题名称 参数3: 回调函数 参数4: 是否自动启动 */
Server server(nh,"addInts",boost::bind(&cb,_1,&server),false); // 话题,_1是用来占位,传入的是回调函数goal的参数
server.start();// 如果 atuto_start 为false, 那么需要手动调用该函数启动服务
ROS_INFO("服务启动......");
// 6.spin()回旋
ros::spin();
return 0;
}
客户端 action02_client.cpp
#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.发送请求 a. 连接建立: --- 回调函数 b. 处理连续反馈:--- 回调函数 c. 处理最终响应:--- 回调函数 6.spin(). */
typedef actionlib::SimpleActionClient<demo01_action::AddIntsAction> Client;
// 响应成功时的回调,处理最终结果(第3步)状态、结果诉讼诉讼
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("请求失败!");
}
}
// 激活回调,服务已经激活(第1步)
void active_cb(){
ROS_INFO("客户端与服务端连接建立....");
}
// 连续反馈的回调,处理连续反馈(第2步)
void feedback_cb(const demo01_action::AddIntsFeedbackConstPtr &feedback){
ROS_INFO("当前进度:%.2f",feedback->progress_bar);
}
int main(int argc, char *argv[])
{
// 2.初始化ROS节点
setlocale(LC_ALL,"");
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");// 话题
// 5.发送请求
// 注意: 判断服务器状态,等待服务启动
ROS_INFO("等待服务器启动.....");
client.waitForServer();
// a. 连接建立: --- 回调函数
// b. 处理连续反馈:--- 回调函数
// c. 处理最终响应:--- 回调函数
/* 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) 处理反馈 */
// 参数1: 设置目标值
demo01_action::AddIntsGoal goal;
goal.num = 100;
client.sendGoal(goal,&done_cb,&active_cb,&feedback_cb);
// 6.spin().
ros::spin();
return 0;
}
服务端 action01_server_p.py
#! /usr/bin/env python
""" 需求: 创建两个ROS 节点,服务器和客户端, 客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和, 这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的, 又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s, 为了良好的用户体验,需要服务器在计算过程中, 每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。 流程: 1.导包 2.初始化 ROS 节点 3.单独使用类封装, 4.类中创建 action 服务端对象 5.处理请求(a.解析目标值 b. 发送连续反馈 c. 响应最终结果)--- 回调函数 6.spin()回旋 """
import rospy
import actionlib
from demo01_action.msg import *
# 4.类中创建 action 服务端对象
# 5.处理请求(a.解析目标值 b. 发送连续反馈 c. 响应最终结果)--- 回调函数
class MyAction:
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):
# a.解析目标值
goal_num = goal.num
rospy.loginfo("目标值:%d",goal_num)
# b.循环累加,连续反馈
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)
# c.响应最终结果
rospy.loginfo("响应结果:%d",sum)
result = AddIntsResult()
result.result = sum
self.server.set_succeeded(result)
if __name__ == "__main__":
# 2.初始化 ROS 节点
rospy.init_node("action_server_p")
# 3.单独使用类封装
myAction = MyAction()
# 6.spin()回旋
rospy.spin()
客户端 action02_client_p.py
#! /usr/bin/env python
""" 需求: 创建两个ROS 节点,服务器和客户端, 客户端可以向服务器发送目标数据N(一个整型数据)服务器会计算 1 到 N 之间所有整数的和, 这是一个循环累加的过程,返回给客户端,这是基于请求响应模式的, 又已知服务器从接收到请求到产生响应是一个耗时操作,每累加一次耗时0.1s, 为了良好的用户体验,需要服务器在计算过程中, 每累加一次,就给客户端响应一次百分比格式的执行进度,使用 action实现。 流程: 1.导包 2.初始化 ROS 节点 3.单独使用类封装, 4.类中创建 action 服务端对象 5.处理请求(a.解析目标值 b. 发送连续反馈 c. 响应最终结果)--- 回调函数 6.spin()回旋 """
import rospy
import actionlib
from demo01_action.msg import *
# 4.类中创建 action 服务端对象
# 5.处理请求(a.解析目标值 b. 发送连续反馈 c. 响应最终结果)--- 回调函数
class MyAction:
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):
# a.解析目标值
goal_num = goal.num
rospy.loginfo("目标值:%d",goal_num)
# b.循环累加,连续反馈
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)
# c.响应最终结果
rospy.loginfo("响应结果:%d",sum)
result = AddIntsResult()
result.result = sum
self.server.set_succeeded(result)
if __name__ == "__main__":
# 2.初始化 ROS 节点
rospy.init_node("action_server_p")
# 3.单独使用类封装
myAction = MyAction()
# 6.spin()回旋
rospy.spin()
边栏推荐
- DOM系列之 client 系列
- 小黑leetcode之旅:104. 二叉树的最大深度
- Zabbix干啥用?
- TiCDC 架构和数据同步链路解析
- 解决:Parameter 0 of method ribbonServerList in com.alibaba.cloud.nacos.ribbon.NacosRibbonClientConfigu
- Xiaohei's leetcode journey: 104. The maximum depth of a binary tree
- 华为“天才少年”稚晖君又出新作,从零开始造“客制化”智能键盘
- How to Add a Navigation Menu on Your WordPress Site
- typescript12 - union types
- Oracle has a weird temporary table space shortage problem
猜你喜欢

MySQL database (basic)
Go study notes (84) - Go project directory structure

Huawei's "genius boy" Zhihui Jun has made a new work, creating a "customized" smart keyboard from scratch

Yolov7实战,实现网页端的实时目标检测

小程序-全局数据共享

typescript9 - common base types

Sping.事务的传播特性

typescript13 - type aliases

仿牛客网项目总结

九州云入选“可信云最新评估体系及2022年通过评估企业名单”
随机推荐
ShardingSphere's unsharded table configuration combat (6)
In Google Cloud API gateway APISIX T2A and T2D performance test
Problem record in the use of TypeScript
MySQL (6)
ShardingSphere之水平分库实战(四)
87. Convert String to Integer
深度学习可以求解特定函数的参数么?
The level of ShardingSphere depots in actual combat (4)
Mysql systemized JOIN operation example analysis
typescript10-commonly used basic types
Detailed explanation of 9 common reasons for MySQL index failure
《实战》基于情感词典的文本情感分析与LDA主题分析
WMware Tools installation failed segmentation fault solution
SWM32 Series Tutorial 6 - Systick and PWM
API 网关 APISIX 在Google Cloud T2A 和 T2D 的性能测试
解决:Parameter 0 of method ribbonServerList in com.alibaba.cloud.nacos.ribbon.NacosRibbonClientConfigu
调度中心xxl-Job
822. Walk the Grid
ShardingSphere之公共表实战(七)
VS warning LNK4099: No solution found for PDB