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

news2024/11/15 21:37:26

目录

  • 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();
          } else
              RCLCPP_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')
              return
          self.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.feedback
          self.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().result
              self.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.coloradmin.cn/o/1595570.html

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

相关文章

【论文阅读——SplitFed: When Federated Learning Meets Split Learning】

级别CCFA 1.摘要 联邦学习&#xff08;FL&#xff09;和分割学习&#xff08;SL&#xff09;是两种流行的分布式机器学习方法。两者都采用了模型对数据的场景&#xff1b;客户端在不共享原始数据的情况下训练和测试机器学习模型。由于机器学习模型的架构在客户端和服务器之间…

vue.config.js跨域问题解决

讲解视频 问题背景 目标地址&#xff1a; 而当前项目启动是http&#xff0c;协议名不同&#xff0c;所以跨域了 解决步骤和解答 1. 新建vue.config.js文件 2. 添加如下代码&#xff1a; 一般目标路径target写 域名 就可以了 但其实&#xff0c;写路径也可以&#xff0c;…

移动应用安全合规动态:网信办、金管局发文强调数据安全;3月个人信息违规抽查结果出炉!(第五期)

一、监管部门动向&#xff1a;国家互联网信息办公室公布《促进和规范数据跨境流动规定》; 工信部发布《关于网络安全保险典型服务方案目录的公示》 二、安全新闻&#xff1a;恶意软件警报&#xff01;黑客利用软件即服务攻击印度安卓用户&#xff1b;Cerberus银行恶意软件的虚…

Linux内核常见的丢包场景有哪些

目录 摘要 1 收发包处理流程 2 硬件网卡相关 2.1 ring buffer满 2.2 利用 ntuple 保证关键业务 3 arp丢包 3.1 neighbor table overflow 3.2 unresolved drops 4 conntrack丢包&#xff1a;nf_conntrack: table full 5 udp接收buffer满 6 丢包定位 6.1 dropwatch 查看丢包 6.2…

ERROR 1052 (23000): Column ‘deptno‘ in field list is ambiguous

错误原因&#xff1a; 这个错误通常是在多表查询中&#xff0c;因为你的SQL查询中包含了多个表&#xff0c;并且这些表中都有一个名为deptno的列。这会导致数据库无法确定你要引用哪个表中的 deptno列&#xff0c;从而产生歧义。 解决方法&#xff1a; 为了解决这个问…

【数据结构(六)】队列

❣博主主页: 33的博客❣ ▶️文章专栏分类:数据结构◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你学更多数据结构知识 目录 1.前言2.概念3.队列的使用4.循环队列5.双端队列6.经典习题6.1队列实现栈6.2栈实现队…

Windows Edge 兼容性问题修复:提升用户体验的关键步骤

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

Laravel/Lumen 中使用 Echo + Socket.IO-Client 实现网页即时通讯广播

此处以 Lumen 9 框架为例说明如何调试通过 Echo 服务端以及客户端 如果你是 Laravel/Lumen 10.47 用户&#xff0c;可以先了解官方的 Laravel Reverb。注意 Laravel Reverb 仅支持 Laravel/Lumen 10.47 以及 PHP 8.2Laravel Reverb 参考官网&#xff1a;https://laravel.com/d…

【C 数据结构】双向链表

文章目录 【 1. 基本原理 】【 2. 双向链表的 创建 】实例 - 输出双向链表 【 3. 双向链表 添加节点 】【 4. 双向链表 删除节点 】【 5. 双向链表查找节点 】【 7. 双向链表更改节点 】【 8. 实例 - 双向链表的 增删查改 】 【 1. 基本原理 】 表中各节点中都只包含一个指针&…

排序算法-基数排序

基数排序是一种非比较排序算法&#xff0c;它将待排序的数字按照位数进行排序。基数排序的思想是先按照个位数进行排序&#xff0c;然后按照十位数进行排序&#xff0c;接着按照百位数进行排序&#xff0c;以此类推&#xff0c;直到最高位排序完成。 基数排序的步骤如下&#x…

【Java】xxl-job的快速入门

目录 什么是xxl-job&#xff1f; XXL-Job-环境搭建 1 调度中心环境要求 2.XXL-Job(源码说明) 3.初始化“调度数据库” 3启动调度中心xxl-job-admin docker安装-配置调度中心 1.创建mysql容器&#xff0c;初始化xxl-job的SQL脚本 2.拉取镜像 3.创建容器 xxl-jo…

手机号三要素实名验证,为您打造安全可靠的账户环境

在互联网时代&#xff0c;手机号码成为了我们生活中必不可少的一部分。我们几乎所有的社交账号、银行账号、网购账号&#xff0c;都需要绑定手机号码进行认证。然而&#xff0c;随着互联网的发展&#xff0c;越来越多的账号被盗用、个人信息被泄露的案例频频发生&#xff0c;让…

ros2 launch gazebo_ros gazebo.launch.py无法启动

我的系统是ubuntu20.04&#xff0c;ros2的版本是humble&#xff0c;当运行gazebo仿真时&#xff0c;运行 ros2 launch gazebo_ros gazebo.launch.py命令&#xff0c;会出现以下问题&#xff1a; 此时&#xff0c;这个页面会卡死在第六行&#xff0c;gazebo也不会打开 但最后单…

软件无线电安全之HackRF One初探

HackRF介绍 HackRF是一款开源软件无线电&#xff08;SDR&#xff09;平台&#xff0c;由Great Scott Gadgets公司推出。它具有广泛的频率覆盖范围&#xff0c;从1 MHz到6 GHz&#xff0c;支持大部分常见的无线通信频段。采用软件定义无线电技术&#xff0c;HackRF提供了自定义…

香港服务器如何更换域名?

更换香港服务器的域名是一个相对复杂的过程&#xff0c;涉及到多个步骤和注意事项。 准备工作&#xff1a; 备份网站数据&#xff1a;在进行任何更改之前&#xff0c;务必备份您的网站数据&#xff0c;以防止数据丢失或损坏。 购买新的域名&#xff1a;如果您还没有购买新的…

职场如何有效学习充电

在现在的工作中&#xff0c;需要接触和了解各式各样的内容&#xff0c;但很多时候我自己没遇到过。而平时有感觉没什么时间&#xff0c;因此产生了这个疑问&#xff0c;看完这个课程后&#xff0c;对这块有了较为体系化的了解。 对我来说&#xff0c;学习的最终目的是充实自己…

【AI 斯坦福 STORM】基于互联网搜索,帮你从零开始撰写文章

今天介绍斯坦福出品的系统&#xff0c;STORM。 STORM是一个基于互联网搜索的LLM系统&#xff0c;可以从零开始撰写类似维基百科的文章。 技术栈&#xff1a; dspy 一个用于算法优化LM提示和权重的框架You.com搜索API YOU APIs利用实时网络数据使LLMs和搜索体验更加真实和及时…

力扣 | 148. 排序链表

和数组里面的归并排序思想一致 class Solution {public ListNode sortList(ListNode head) {//过滤条件if(head null || head.next null)return head;ListNode slow head;ListNode fast head.next;while (fast ! null && fast.next ! null){slow slow.next;fast …

【Maven工具】

maven Maven是一个主要用于Java项目的构建自动化工具。它有助于管理构建过程&#xff0c;包括编译源代码、运行测试、将编译后的代码打包成JAR文件以及管理依赖项。Maven使用项目对象模型&#xff08;POM&#xff09;文件来描述项目配置和依赖关系。 Maven通过提供标准的项目…

酷开系统让用户在方方面面享受科技进步带来的美好体验

电视本身的特性&#xff0c;再有人工智能和全时AI的加持&#xff0c;让搭载了酷开系统的电视有能力成为一个“家庭智慧管控中心”。互联网的存在让大家能更懒地完成事情&#xff0c;满足宅家的愿望&#xff0c;有话说&#xff0c;科技因懒人而进步。打个简单的比方&#xff0c;…