ROS2从入门到精通1-3:详解ROS2动作通信机制与自定义动作

目录

  • 0 专栏介绍
  • 1 动作通信模型
  • 2 动作模型实现(C++)
  • 3 动作模型实现(Python)
  • 4 自定义动作

0 专栏介绍

本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。

🚀详情:《ROS2从入门到精通》


1 动作通信模型

在ROS2中,动作通信机制提供了一种用于执行长时间运行任务的方式,由三个部分组成:

  • 目标(goal):对客户端的请求进行处理和响应
  • 反馈(feedback):对监控任务的动作执行过程提供反馈数据
  • 结果(result):对监控任务的执行结果提供反馈

举个机器人导航的任务说明

假设有一个机器人需要从起始点导航到目标点。通过使用动作通信机制,可以定义一个导航动作,其中目标是目标位置。机器人将发送导航目标给动作服务器,服务器将返回连续的反馈,例如机器人的当前位置,障碍物检测等。最终,当机器人到达目标位置时,服务器将返回导航任务的结果。

再比如机械臂控制

通过定义动作目标和提供连续的反馈,可以实现对机械臂的精确控制。例如,可以定义一个动作来控制机械臂移动到特定位置,反馈可以包括当前位置、力传感器的读数等。一旦机械臂到达目标位置,服务器将返回控制任务的结果

在这里插入图片描述

动作是应用级通信机制,建立在话题和服务之上,但却与话题和服务通信不同:

  • 动作通信更适合描述一项任务的执行过程,而话题通信更适合传输实时数据;
  • 动作通信返回一系列的反馈和一个最终结果,而服务通常只返回单个响应;
  • 动作通信是可中断的,即在执行过程中可以取消,而服务通信通常是一次性的请求-响应模式;

总之,通过使用动作通信,可以实现更复杂的交互和反馈,并灵活地处理长时间运行的任务

2 动作模型实现(C++)

实验目标:客户端提交请求给turtlesim功能包的/rotate_absolute动作,在界面上使乌龟旋转,并不断监听乌龟的实时旋转数据,以及到达目标角度的反馈。

  • 服务器

    本实验中无需编程,为turtlesim::Action定义的/rotate_absolute服务

  • 客户端

    1. 注册一个客户端
      client_ptr_ = rclcpp_action::create_client<TurtleAction>(get_node_base_interface(),get_node_graph_interface(),get_node_logging_interface(),get_node_waitables_interface(),"/turtle1/rotate_absolute"
      );
      
    2. 定义目标响应回调函数
      void OnGoalResponseCallback(GoalHandle::SharedPtr goal_message) {if (!goal_message) {RCLCPP_ERROR(get_logger(), "Client: Goal was rejected by server");rclcpp::shutdown();} elseRCLCPP_INFO(get_logger(), "Client: Goal accepted by server, waiting for result");
      }
      
    3. 定义过程反馈回调函数
      void OnFeedbackCallback(GoalHandle::SharedPtr, const std::shared_ptr<const TurtleAction::Feedback> feedback_message) {std::stringstream ss;ss << "Client: Received feedback: " << feedback_message->remaining;RCLCPP_INFO(this->get_logger(), "%s", ss.str().c_str());
      }
      
    4. 定义结果回调函数
      void OnResultCallback(const GoalHandle::WrappedResult & result_message) {switch (result_message.code) {case rclcpp_action::ResultCode::SUCCEEDED:break;case rclcpp_action::ResultCode::ABORTED:RCLCPP_ERROR(get_logger(), "Client: Goal was aborted");rclcpp::shutdown();return;case rclcpp_action::ResultCode::CANCELED:RCLCPP_ERROR(get_logger(), "Client: Goal was canceled");rclcpp::shutdown();return;default:RCLCPP_ERROR(get_logger(), "Client: Unknown result code");rclcpp::shutdown();return;}RCLCPP_INFO(get_logger(), "Client: Result received: %.2f", (result_message.result->delta));rclcpp::shutdown();
      }
      

实验结果如下所示,在本实验中,theta表示发送的目标角度;remaining是过程反馈的目标角度差值信息;delta是结果响应,表示距离初始位置的角度偏差

在这里插入图片描述

3 动作模型实现(Python)

实验目标:客户端提交请求给turtlesim功能包的/rotate_absolute动作,在界面上使乌龟旋转,并不断监听乌龟的实时旋转数据,以及到达目标角度的反馈。

  • 服务器

    本实验中无需编程,为turtlesim::Action定义的/rotate_absolute服务

  • 客户端

    1. 注册一个客户端
      self.client_ = ActionClient(self, RotateAbsolute, '/turtle1/rotate_absolute')
      
    2. 定义目标响应回调函数
      def OnGoalResponseCallback(self, future):goal_handle = future.result()  if not goal_handle.accepted: self.get_logger().info('Client: Goal was rejected by server')returnself.get_logger().info('Client: Goal accepted by server, waiting for result')self._get_result_future = goal_handle.get_result_async()self._get_result_future.add_done_callback(self.OnResultCallback)
      
    3. 定义过程反馈回调函数
      def OnFeedbackCallback(self, feedback_msg):feedback = feedback_msg.feedbackself.get_logger().info(f'Received feedback: {feedback.remaining:.2f}') 
      
    4. 定义结果回调函数
      def OnResultCallback(self, future):if future.done():self.get_logger().info(f'Action done!')result = future.result().resultself.get_logger().info(f'Result: {result.delta:.2f}')elif future.cancelled():self.get_logger().info(f"Client: Goal was canceled")else:raise RuntimeWarning("Client: Unknown result code") 
      

实验结果如下所示,在本实验中,theta表示发送的目标角度;remaining是过程反馈的目标角度差值信息;delta是结果响应,表示距离初始位置的角度偏差

在这里插入图片描述

4 自定义动作

自定义动作的通用流程如下:

  • 功能包下新建action文件夹,在其中添加自定义服务xxx.action,注意目标、反馈和结果数据结构使用---分割
  • 功能包package.xml中添加编译依赖与执行依赖
    <buildtool_depend>rosidl_default_generators</buildtool_depend>
    <exec_depend>rosidl_default_runtime</exec_depend>
    <member_of_group>rosidl_interface_packages</member_of_group>
    
  • 功能包CMakeLists.txt中添加编译消息相关依赖
    find_package(rosidl_default_generators REQUIRED)
    rosidl_generate_interfaces(${PROJECT_NAME}"xxx.action"DEPENDENCIES xxx_actions
    )ament_export_dependencies(rosidl_default_runtime)
    
  • 编译自定义动作,在install/<pkg_name>/include中生成由xxx.action编译的C++可识别的xxx.hpp头文件
  • 引入xxx.hpp即可调用自定义动作

下面给出一个实例

实现一个自定义动作,请求机器人开始圆周运动,反馈机器人的实时运动角度,并返回最终结果

添加如下自定义动作,并按上面步骤配置依赖

bool enable     # goal
---
bool finish     # result
---
int32 state     # feedback

定义一个服务器、一个客户端,限于篇幅只贴出部分代码,完整代码见文末。

  • 服务器
    class OwnActionServerNode : public rclcpp::Node
    {public:using OwnAction = own_action_lab::action::MoveCircle;using GoalHandle = rclcpp_action::ServerGoalHandle<OwnAction>;explicit OwnActionServerNode(const rclcpp::NodeOptions & action_server_options = rclcpp::NodeOptions()): Node("own_action_server", action_server_options) {action_server_ = rclcpp_action::create_server<OwnAction>(get_node_base_interface(),get_node_clock_interface(),get_node_logging_interface(),get_node_waitables_interface(),"/move",std::bind(&OwnActionServerNode::OnHandleGoal, this, std::placeholders::_1, std::placeholders::_2),std::bind(&OwnActionServerNode::OnHandleCancel, this, std::placeholders::_1),std::bind(&OwnActionServerNode::OnHandleAccepted, this, std::placeholders::_1));}
    }
    
  • 客户端
    class OwnActionClientNode : public rclcpp::Node
    {public:using OwnAction = own_action_lab::action::MoveCircle;using GoalHandle = rclcpp_action::ClientGoalHandle<OwnAction>;explicit OwnActionClientNode(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions()): Node("own_action_client", node_options) {client_ptr_ = rclcpp_action::create_client<OwnAction>(get_node_base_interface(),get_node_graph_interface(),get_node_logging_interface(),get_node_waitables_interface(),"/move");}
    }
    

实测效果如下:

在这里插入图片描述

完整代码通过下方博主名片联系获取


🔥 更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

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

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

相关文章

蓝桥杯嵌入式2021年第十二届第一场省赛主观题解析

1 题目 2 代码 /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "tim.h" #include "usart.h" #include "gpio.h"/* Private includes…

武汉星起航助力跨境电商,专业选品与全方位服务引领行业新风尚

在全球跨境电商浪潮的推动下&#xff0c;越来越多的卖家纷纷将目光投向了这片广阔的市场。然而&#xff0c;如何在这片蓝海中脱颖而出&#xff0c;成为众多卖家关注的焦点。武汉星起航电子商务有限公司以其专业的选品建议和全方位的服务&#xff0c;为卖家们提供了一条成功的捷…

新零售行业门店管理方案详解,人人都可以是好店长

在之前的文章中&#xff0c;我们分别介绍了新零售业的全面解决方案&#xff0c;包括门店管理解决方案、商品经营方案、会员管理解决方案&#xff0c;以及这些方案所包含的分析指标&#xff0c;吸引了不少对新零售转型感兴趣的企业主。 后续我们会将这些内容拆解开来&#xff0…

LeetCode-热题100:104. 二叉树的最大深度

题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a; root [3,9,20,null,null,15,7] 输出&#xff1a; 3 示例 2&#xff1a; 输入&#xff1a; root …

【数字IC/FPGA】什么是无符号数?什么是有符号数?

进制 虽然在日常生活中&#xff0c;我们已经习惯了使用10进制数字&#xff0c;但在由数字电路构成的数字世界中&#xff0c;2进制才是效率更高的选择。 10进制与2进制 10进制&#xff08;decimal&#xff09;计数法&#xff08;一般也叫阿拉伯计数法&#xff09;是在日常生活…

LLM生成模型在生物单细胞single cell的应用:scGPT

参考&#xff1a; https://github.com/bowang-lab/scGPT https://www.youtube.com/watch?vXhwYlgEeQAs 主要是把单细胞测序出来的基因表达量的拼接起来构建成的序列&#xff0c;这里不是用的基因的ATCG&#xff0c;是直接用的基因名称 训练数据&#xff1a;scGPT全人模型是在3…

第⑫讲:Ceph集群OSD扩缩容中Reblanceing数据的重分布

文章目录 1.Reblanceing数据重分布的概念2.验证Reblanceing触发的过程3.Reblanceing细节4.临时关闭Reblanceing机制 1.Reblanceing数据重分布的概念 当集群中OSD进行扩缩容操作后&#xff0c;会触发一个Reblanceing数据重分布的机制&#xff0c;简单的理解就是将扩缩容前后OSD…

【Hello算法】 > 第 1 关 > 初识 算法 与 复杂度分析

初识 算法 与 复杂度分析 What are algorithms and data structures ?-什么是算法与数据结构&#xff1f;How to conduct complexity analysis ?-如何进行复杂性分析&#xff1f;时间复杂度空间复杂度 小结Tips&#xff1a; ————————————————————————…

Day101:漏洞发现-漏扫项目篇NucleiYakitGobyAfrogXrayAwvs联动中转被动

目录 特征类-三方Poc调用&模版Poc调用 案例1&#xff1a;单点对某特征点进行安全评估 Goby-综合类 Nuclei-较综合类 Afrog-特征类 Yakit-可特征可综合 案例2&#xff1a;新型对某特征点进行安全评估 综合类-主动漏扫&中转联动&被动联动 案例1&#xff1a;…

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑&#xff0c;这些问题可能会影响我们的开发效率和代码质量&#xff0c;因此我们需要不断总结和学习&#xff0c;以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结&#xff0c;以提高大家的开发质量。本系列文章…

03-进程-网络命令-软件安装-SSH免密登录

软件安装-网络命令-SSH免密登录 一 软件安装 1 在线安装 命令&#xff1a; yum 作用&#xff1a;yum会从指定的服务器自动下载rpm包并且进行安装&#xff0c;优点是可以自动处理依赖关系&#xff0c;并且一次安装所有的软件包。 配置yum的镜像源 yum源有个统一的下载服务…

剖析 SPI 在 Spring 中的应用

一、概述 SPI&#xff08;Service Provider Interface&#xff09;&#xff0c;是Java内置的一种服务提供发现机制&#xff0c;可以用来提高框架的扩展性&#xff0c;主要用于框架的开发中&#xff0c;比如Dubbo&#xff0c;不同框架中实现略有差异&#xff0c;但核心机制相同…

精确号码比例放通算法的设计与实现

精确号码比例放通算法的设计与实现 引言背景问题定义算法设计1. 数据结构2. 算法流程3. 伪代码4. C语言实现 结论参考文献 引言 随着通信技术的飞速发展&#xff0c;呼叫中心和电信运营商面临着日益增长的呼叫管理需求。在某些情况下&#xff0c;为了确保服务质量或者遵守特定…

方案分享 | 嵌入式指纹方案

随着智能设备的持续发展&#xff0c;指纹识别技术成为了现在智能终端市场和移动支付市场中占有率最高的生物识别技术。凭借高识别率、短耗时等优势&#xff0c;被广泛地运用在智能门锁、智能手机、智能家居等设备上。 我们推荐的品牌早已在2015年进入指纹识别应用领域&#xff…

[dvwa] sql injection

sql injection 0x01 low sql语句没有过滤 经典注入&#xff0c;通过逻辑or为真相当于select * from users where true&#xff0c;99换成1也成 用union select 对齐列数&#xff0c;查看数据库信息 1’ union select 1,2# order by探测对齐列数更方便 1’ or 11 order b…

05.MySQL索引事务

1. 索引 1.1 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。 可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现 1.2 作用 数据库中的表、数据、索引之间的关系&#xff0c;类似于书架上的…

Spring AI 应用 - 智能记者

参考实现&#xff1a; https://github.com/mshumer/ai-journalist 上面是通过 Claude 配合 SERP 搜索 API&#xff0c;使用 Python 语言实现的&#xff0c;本文通过 GitHub Copilot 辅助改为了基于 Spring AI 的 Java 版本&#xff0c;本文使用的 OpenAI。 AIJournalist 实现…

Tomcat源码解析——源码环境搭建

一、源码下载 在进行源码阅读前&#xff0c;先下载源码包&#xff0c;这样便于做笔记和debug。 我所用的版本是Tomcat7.0.68&#xff0c; Tomcat7.0.68下载地址&#xff1a;Index of /dist/tomcat/tomcat-7/v7.0.68/src 所有Tomcat的源码包下载地址&#xff1a;Index of /dist/…

第6章:6.4.2 案例二:爬取成语网站数据 (MATLAB入门课程)

讲解视频&#xff1a;可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇&#xff08;数学建模清风主讲&#xff0c;适合零基础同学观看&#xff09;_哔哩哔哩_bilibili 本案例用到的网址为&#xff1a;成语大全列表成语大全列表https…

NSA发布《在数据支柱中推进零信任成熟度》报告

4月9日&#xff0c;美国国家安全局&#xff08;NSA&#xff09;发布了题为《在数据支柱中推进零信任成熟度》的报告&#xff0c;旨在于数据安全层面提供指导&#xff0c;以增强数据整体安全性并保护静态和传输中的数据。(如下图&#xff09; 一、主要内容 报告中的建议侧重于将…