ROS Action通信

2023-05-16

文章目录

  • 自定义action文件(类似msg和service)
    • 服务端 action01_server.cpp
    • 客户端 action02_client.cpp
    • 服务端 action01_server_p.py
    • 客户端 action02_client_p.py

应用场景:需要使用服务通信,但需要及时进行反馈。

在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()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS Action通信 的相关文章

随机推荐

  • 下划线在 Python 中的特殊含义

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 Python 中的下划线 下划线在 Python 中是有特殊含义的 xff0c 它们在 Python 的不同地方使用 下面是 Pyth
  • UFA-FUSE:一种用于多聚焦图像融合的新型深度监督混合模型

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 小白导读 论文是学术研究的精华和未来发展的明灯 小白决心每天为大家带来经典或者最新论文的解读和分享 xff0c 旨在帮助各位读者快速了
  • 实战 | 如何制作一个SLAM轨迹真值获取装置?

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 本文知乎作者杨小东授权转载 xff0c 未经授权禁止二次转载 原文 xff1a https zhuanlan zhihu com p
  • 通俗易懂理解朴素贝叶斯分类的拉普拉斯平滑

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 这个男生的四个特征是长相不帅 xff0c 性格不好 xff0c 身高矮 xff0c 不上进 xff0c 我们最终得出的结论是女生不嫁
  • 综述 | 激光与视觉融合SLAM

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 SLAM包含了两个主要的任务 xff1a 定位与构图 xff0c 在移动机器人或者自动驾驶中 xff0c 这是一个十分重要的问题 xf
  • KITTI数据集简介与使用

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 摘要 xff1a 本文融合了Are we ready for Autonomous Driving The KITTI Vision
  • DBSCAN聚类算法原理总结

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 DBSCAN是基于密度空间的聚类算法 xff0c 在机器学习和数据挖掘领域有广泛的应用 xff0c 其聚类原理通俗点讲是每个簇类的密度
  • 深度学习GPU最全对比,到底谁才是性价比之王?

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 本文转自AI新媒体量子位 xff08 公众号 ID QbitAI xff09 搞AI xff0c 谁又没有 GPU之惑 xff1f 张
  • 使用卡尔曼滤波器进行对象跟踪时最容易遗漏什么

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 介绍 卡尔曼滤波器是一种复杂的算法 xff0c 在大多数情况下 xff0c 我们在没有完全理解其方程的情况下使用它 当我开始使用卡尔曼
  • 10分钟掌握异常检测

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 异常检测 也称为离群点检测 是检测异常实例的任务 xff0c 异常实例与常规实例非常不同 这些实例称为异常或离群值 xff0c 而正常
  • 根据图像目标深度测试距离

    clc clear close all warning off addpath 39 func 39 计算物体的深度距离 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61
  • SLAM基础环境配置

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 转自知乎作者 xff1a 佳浩 原文链接 xff1a https zhuanlan zhihu com p 385255026 如今
  • 多传感器融合定位:基于滤波的融合方法

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 SLAM 后端的优化方式大体分为滤波和优化 近些年优化越来越成为主流 xff0c 在学习优化之前 xff0c 掌握滤波的工作原理也十分
  • 不要错过!顶会审稿人带读【大语言模型】前沿论文!

    LLaMA GLM 130B SELF INSTRUCT是三篇最新的语言模型相关的论文 xff0c 它们都展示了语言模型在不同方面的创新和突破 这三篇论文都体现了语言模型在双语 大规模 通用 快速 可复现等方面的重要进展 xff0c 对于语
  • 收藏 | 最全深度学习训练过程可视化工具

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 仅作学术分享 xff0c 不代表本公众号立场 xff0c 侵权联系删除 转载于 xff1a 编辑丨极市平台 机器学习实验室 深度学习训
  • 为什么建议大家使用 Linux 开发?真的很很很优雅!

    点击上方 小白学视觉 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 编者荐语 Linux 开发不算简单 xff0c 要求同学们掌握的知识广且复杂 xff0c 有一定难度 但是同学们只要静下心来 xff0
  • favicon.ico不显示

    静态页面中 xff0c title前的favicon ico不显示的问题 原因还不详 解决办法 xff1a 清除浏览器缓存或者将favicon ico文件重命名
  • 树莓派系统镜像的下载和烧录

    一 树莓派镜像下载地址 树莓派官网的下载地址 xff1a 树莓派官网 软件安装 可在官网上下载最新的Raspbian树莓派系统 二 树莓派系统镜像烧写 准备 xff1a 一张2G以上的SD卡及读卡器 xff0c 最好是高速卡 xff0c 推
  • TF 坐标变换(已整理)

    文章目录 坐标msg消息静态坐标变换1 C 43 43 实现发布方 demo01 static pub cpp订阅方 demo02 static sub cpp 2 Python实现发布方 demo01 static pub p py订阅方
  • ROS Action通信

    文章目录 自定义action文件 类似msg和service 服务端 action01 server cpp客户端 action02 client cpp服务端 action01 server p py客户端 action02 client