当前位置: 首页 > news >正文

ROS2 学习(五)接口,动作

接口

通信双方统一规定好接口。比如图像 img,控制运动的线速度和角速度……

我们也不用了解具体实现,基本就是了解接口会去用就行。

1692625169102

$ ros2 interface list # 展示所有 interfaces
$ ros2 interface show ... # 显示具体一个 interface
$ ros2 package show ... # 查看一个 package 里所有的 interface

添加接口

不是说我们写一个接口文件就算添加好了,我们也要通过读取文件。

在 CMakeList.txt 中可以看到:

rosidl_generate_interfaces(${PROJECT_NAME}"msg/ObjectPosition.msg""srv/AddTwoInts.srv""srv/GetObjectPosition.srv""action/MoveCircle.action")

指从相应的相对目录文件中找接口。

在文件中使用对应接口时,则需要先引入:

from File_Path import interface_name

这个引入文件的路径位于系统生成的 .py 文件中,编译成功即生成。

后面创建对象的时候就可以使用接口了。

动作

比如想让小乌龟转一圈,我们需要不停发送指令,根据当前状态调整指令,在一定条件时取消指令。使用动作比这样一点点写服务方便得多。

实际使用的时候我们也很少直接用话题和服务,都是用封装好的动作接口。

动作就是可以一边发运动指令,一边收到反馈信息。

实现方法还是基于话题和服务,话题是服务端(比如要控制运动的机器人)周期性反馈当前状态,服务是客户端给服务端发的指令请求。

比如打开小乌龟,打开键盘控制后,我们可以尝试发送如下指令:

$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 3.14}"
$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 0}" --feedback 

在接口中可以看到动作接口的三部分:发起动作的目标,动作完成的结束标志,动作的反馈状态。

添加动作

前面的步骤和添加接口一样,编写对应 .action 文件,在 CMakeList.txt 中添加。

服务端:在程序里注意如何添加 action_server:

import rclpy                                      # ROS2 Python接口库
from rclpy.node   import Node                     # ROS2 节点类
from rclpy.action import ActionServer             # ROS2 动作服务器类
from learning_interface.action import MoveCircle  # 自定义的圆周运动接口class MoveCircleActionServer(Node):def __init__(self, name):super().__init__(name)                   # ROS2节点父类初始化self._action_server = ActionServer(      # 创建动作服务器(接口类型、动作名、回调函数)self,MoveCircle,'move_circle',self.execute_callback)def execute_callback(self, goal_handle):            # 执行收到动作目标之后的处理函数self.get_logger().info('Moving circle...')feedback_msg = MoveCircle.Feedback()            # 创建一个动作反馈信息的消息for i in range(0, 360, 30):                     # 从0到360度,执行圆周运动,并周期反馈信息feedback_msg.state = i                      # 创建反馈信息,表示当前执行到的角度self.get_logger().info('Publishing feedback: %d' % feedback_msg.state)goal_handle.publish_feedback(feedback_msg)  # 发布反馈信息time.sleep(0.5)goal_handle.succeed()                           # 动作执行成功result = MoveCircle.Result()                    # 创建结果消息result.finish = True                            return result                                   # 反馈最终动作执行的结果def main(args=None):                                       # ROS2节点主入口main函数rclpy.init(args=args)                                  # ROS2 Python接口初始化node = MoveCircleActionServer("action_move_server")    # 创建ROS2节点对象并进行初始化rclpy.spin(node)                                       # 循环等待ROS2退出node.destroy_node()                                    # 销毁节点对象rclpy.shutdown()                                       # 关闭ROS2 Python接口

反馈函数每30度标记一次发布反馈信息。

客户端:先启动,然后发送动作请求并注册自己的回调函数、收到目标后的回调函数。

from rclpy.action import ActionClient             # ROS2 动作客户端类from learning_interface.action import MoveCircle  # 自定义的圆周运动接口class MoveCircleActionClient(Node):def __init__(self, name):super().__init__(name)                   # ROS2节点父类初始化self._action_client = ActionClient(      # 创建动作客户端(接口类型、动作名)self, MoveCircle, 'move_circle') def send_goal(self, enable):                 # 创建一个发送动作目标的函数goal_msg = MoveCircle.Goal()             # 创建一个动作目标的消息goal_msg.enable = enable                 # 设置动作目标为使能,希望机器人开始运动self._action_client.wait_for_server()    # 等待动作的服务器端启动self._send_goal_future = self._action_client.send_goal_async(   # 异步方式发送动作的目标goal_msg,                                                   # 动作目标feedback_callback=self.feedback_callback)                   # 处理周期反馈消息的回调函数self._send_goal_future.add_done_callback(self.goal_response_callback) # 设置一个服务器收到目标之后反馈时的回调函数def goal_response_callback(self, future):           # 创建一个服务器收到目标之后反馈时的回调函数goal_handle = future.result()                   # 接收动作的结果if not goal_handle.accepted:                    # 如果动作被拒绝执行self.get_logger().info('Goal rejected :(')returnself.get_logger().info('Goal accepted :)')                            # 动作被顺利执行self._get_result_future = goal_handle.get_result_async()              # 异步获取动作最终执行的结果反馈self._get_result_future.add_done_callback(self.get_result_callback)   # 设置一个收到最终结果的回调函数 def get_result_callback(self, future):                                    # 创建一个收到最终结果的回调函数result = future.result().result                                       # 读取动作执行的结果self.get_logger().info('Result: {%d}' % result.finish)                # 日志输出执行结果def feedback_callback(self, feedback_msg):                                # 创建处理周期反馈消息的回调函数feedback = feedback_msg.feedback                                      # 读取反馈的数据self.get_logger().info('Received feedback: {%d}' % feedback.state) def main(args=None):                                       # ROS2节点主入口main函数rclpy.init(args=args)                                  # ROS2 Python接口初始化node = MoveCircleActionClient("action_move_client")    # 创建ROS2节点对象并进行初始化node.send_goal(True)                                   # 发送动作目标rclpy.spin(node)                                       # 循环等待ROS2退出node.destroy_node()                                    # 销毁节点对象rclpy.shutdown()                                       # 关闭ROS2 Python接口

发送动作请求成功了,服务器端先发一个应答反馈,触发的是 goal_response_callback 中的 ‘Goal accepted 😃’ ,后续收到反馈信息是输出 (‘Received feedback: {%d}’ .

$ ros2 run learning_action action_move_server 
[INFO] [1692636260.811751032] [action_move_server]: Moving circle...
[INFO] [1692636260.812184742] [action_move_server]: Publishing feedback: 0
[INFO] [1692636261.313871989] [action_move_server]: Publishing feedback: 30
[INFO] [1692636261.817491663] [action_move_server]: Publishing feedback: 60
[INFO] [1692636262.319652946] [action_move_server]: Publishing feedback: 90
[INFO] [1692636262.822605205] [action_move_server]: Publishing feedback: 120
[INFO] [1692636263.325196016] [action_move_server]: Publishing feedback: 150
[INFO] [1692636263.826669745] [action_move_server]: Publishing feedback: 180
[INFO] [1692636264.328210660] [action_move_server]: Publishing feedback: 210
[INFO] [1692636264.829900461] [action_move_server]: Publishing feedback: 240
[INFO] [1692636265.331746904] [action_move_server]: Publishing feedback: 270
[INFO] [1692636265.833479902] [action_move_server]: Publishing feedback: 300
[INFO] [1692636266.335957841] [action_move_server]: Publishing feedback: 330$ ros2 run learning_action action_move_client 
[INFO] [1692636260.807239104] [action_move_client]: Goal accepted :)
[INFO] [1692636260.815466218] [action_move_client]: Received feedback: {0}
[INFO] [1692636261.315441690] [action_move_client]: Received feedback: {30}
[INFO] [1692636261.820438299] [action_move_client]: Received feedback: {60}
[INFO] [1692636262.320808661] [action_move_client]: Received feedback: {90}
[INFO] [1692636262.827049792] [action_move_client]: Received feedback: {120}
[INFO] [1692636263.326864092] [action_move_client]: Received feedback: {150}
[INFO] [1692636263.827891348] [action_move_client]: Received feedback: {180}
[INFO] [1692636264.332103011] [action_move_client]: Received feedback: {210}
[INFO] [1692636264.831075874] [action_move_client]: Received feedback: {240}
[INFO] [1692636265.332972986] [action_move_client]: Received feedback: {270}
[INFO] [1692636265.834606029] [action_move_client]: Received feedback: {300}
[INFO] [1692636266.337943178] [action_move_client]: Received feedback: {330}
[INFO] [1692636266.848281638] [action_move_client]: Result: {1}

相关文章:

ROS2 学习(五)接口,动作

接口 通信双方统一规定好接口。比如图像 img,控制运动的线速度和角速度…… 我们也不用了解具体实现,基本就是了解接口会去用就行。 $ ros2 interface list # 展示所有 interfaces $ ros2 interface show ... # 显示具体一个 interface $ ros2 package…...

Vue学习之Vue组件的核心概念

组件是什么 vue组件就是一个个独立的小型的ui模块,整个大型的系统就是由一个个小型的UI模块拼接而成的 vue组件就是vue实例,通过new Vue函数来创建的一个vue实例,不同的组件只不过是options的不同,我们基本百分之90的开发工作都…...

Web自动化测试-Selenium语法入门到精通

前言 说到自动化测试,就不得不提大名鼎鼎的Selenium。Selenium 是如今最常用的自动化测试工具之一,支持快速开发自动化测试框架,且支持在多种浏览器上执行测试。 Selenium学习难度小,开发周期短。对测试人员来说,如果…...

封装axios及简单应用举例

第一步:具体封装工具: 在项目根目录下创建utils目录,然后在其中创建文件http.js: // 二次封装axios import axios from axios// 全局配置 // 根据环境变量区分接口默认地址(前缀) switch (process.env.NO…...

Django(3)-创建第一个数据模型-ORM映射

数据库配置 根目录下settings.py 。这是个包含了 Django 项目设置的 Python 模块。 通常,这个配置文件使用 SQLite 作为默认数据库。如果你不熟悉数据库,或者只是想尝试下 Django,这是最简单的选择。Python 内置 SQLite,所以你无…...

C++ vector

前言&#xff1a; vector的部分源码&#xff1a; &#xff08;做过删除&#xff0c;留下关键信息&#xff09; vector的使用 构造函数&#xff1a; 1 无参构造 vector<int> v1; 2 构造并初始化n个val vector<int> v2(5,1);3 拷贝构造 vector<int> v3…...

Spring+redis集成redis缓存

1、引入maven依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.7.0</version></dependency><dependency><groupId>org.springframework.data</groupId><art…...

聊聊springboot的启动事件

序 本文主要研究一下springboot的启动事件 SpringApplicationEvent org/springframework/boot/context/event/SpringApplicationEvent.java public abstract class SpringApplicationEvent extends ApplicationEvent {private final String[] args;public SpringApplicatio…...

jmeter HTTP请求默认值

首先&#xff0c;打开JMeter并创建一个新的测试计划。 右键单击测试计划&#xff0c;选择"添加" > “配置元件” > “HTTP请求默认值”。 在HTTP请求默认值中&#xff0c;您可以设置全局的HTTP请求属性&#xff0c;例如&#xff1a; 服务器地址&#xff1a…...

CSS选择器-CSS3属性

CSS选择器-CSS3属性 持续更新… 1、CSS3的概念和优势 css3概念:是css的升级版本,新增加了一些模块 css3优点:完全向后兼容,可使用新的选择器和属性,能实现新的设计效果CSS3是CSS技术的升级版本&#xff0c;CSS3语言开发是朝着模块化发展的。以前的规范作为一个模块实在是太庞…...

线性代数的学习和整理8:行列式相关

目录 1 从2元一次方程组求解说起 1.1 直接用方程组消元法求解 1.2 有没有其他方法呢&#xff1f;有&#xff1a;比如2阶行列式方法 1.3 3阶行列式 2 行列式的定义 2.1 矩阵里的方阵 2.2 行列式定义&#xff1a;返回值为标量的一个函数 2.3 行列式的计算公式 2.4 克拉…...

java+springboot+mysql农业园区管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的农业园区管理系统&#xff0c;系统包含超级管理员、管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff1b;土地管理&#xff08;租赁&#xff09;&#x…...

IDEA远程开发

IDEA远程开发 前期准备 IDEA的远程开发是在本地去操昨远程服务器上的代码&#xff0c;所以我们先需要准备一台服务器,在此我使用vmware虚拟出ubuntu-20.04.6的Server版本,以便后面演示。 Ubuntu的Java环境配置 JDK8 sudo apt install openjdk-8-jdkmaven sudo apt instal…...

Redis 工作总结

1.Redis是什么 Redis是互联网技术领域使用最为广泛的存储中间件&#xff0c;它是Remote Dictionary Service的首字母缩写&#xff0c;也就是远程字典服务。 2.Redis的用途&#xff1f; 2.1 计数器 2.2 缓存 2.3 分布式锁 2.4 消息中间件 3.Redis的数据类型 3.1 string&am…...

GO学习之 数据库(Redis)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…...

谈一谈浏览器与Node.js中的JavaScript事件循环,宏任务与微任务机制

JavaScript中的异步代码 JavaScript是一个单线程非阻塞的脚本语言。这代表代码是执行在一个主线程上面的。但是JavaScript中有很多耗时的异步操作&#xff0c;例如AJAX&#xff0c;setTimeout等等&#xff1b;也有很多事件&#xff0c;例如用户触发的点击事件&#xff0c;鼠标…...

User Java bean的命名规范

Java Bean 是一种用于表示简单的、可重用的组件的规范。它是一个符合特定命名和约定的 Java 类&#xff0c;通常用于封装数据和提供访问方法。以下是关于 Java Bean 命名规范的一些准则&#xff1a; 类名&#xff1a; 类名应该使用驼峰命名法&#xff08;Camel Case&#xff09…...

ajax和fetch的区别

ajax 和 fetch的相同点和区别是什么&#xff1f; 以前我们都用ajax去做请求&#xff0c; 但是原生的ajax不好用&#xff0c;我们会用$.ajax或者axios插件去请求&#xff0c;他们都是ajax的封装 最近出来个fetch是什么&#xff1f; 问到这里的时候&#xff0c;你就已经入坑了&am…...

java+springboot+mysql村务档案管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的村务档案管理系统&#xff0c;系统包含超级管理员、工作人员角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;系统用户管理&#xff08;工作人员管理&#xff09;&#xff1b;公开资料&#xff1b;会议记录&…...

windows查看/删除DNS缓存

一、查看DNS缓存 打开CMD&#xff0c;输入ipconfig/displaydns 二、删除DNS缓存 打开CMD,输入ipconfig/flushdns...

隧道裂缝剥落病害AI识别系统

我国现有公路隧道超2.5万座&#xff0c;总里程超2.8万公里&#xff0c;其中运营超过15年的老旧隧道占比达35%。据交通运输部2025年统计&#xff0c;年均因隧道结构病害导致的交通中断超1200次&#xff0c;直接经济损失超45亿元。传统检测模式暴露四大核心痛点&#xff1a;检测周…...

Unity安卓构建72小时实战指南:从零到真机运行

1. 这不是“又一本Unity教程”&#xff0c;而是我带三个新人从零上线第一款安卓游戏的真实路径你点开这个标题&#xff0c;大概率正站在两个路口之间&#xff1a;一边是满屏“30天速成Unity”“零基础做爆款”的短视频封面&#xff0c;一边是你刚下载完Unity Hub、卡在Android …...

别再手动点菜单了!用这招让Cadence Virtuoso Schematic效率翻倍(附Net高亮快捷键配置)

电路设计效率革命&#xff1a;Cadence Virtuoso Schematic高阶快捷键配置指南 在集成电路设计的浩瀚宇宙中&#xff0c;Cadence Virtuoso如同设计师手中的光刻机&#xff0c;每一次精准操作都直接影响最终芯片的性能与可靠性。然而&#xff0c;当面对数百个晶体管组成的复杂模…...

苏州创新药20年,站上全球产业洗牌暴风眼

一个城市的创新药产业集群如何从无到有&#xff0c;又如何在全球化临界点寻找自己的位置。文&#xff5c;徐鑫编&#xff5c;任晓渔过去一年多&#xff0c;苏州是全球创新药产业版图中一个绕不过去的城市。大额海外授权交易频繁传出&#xff0c;在中国高端制造走出去的背景下&a…...

孤舟笔记 互联网常用框架篇三 Dubbo是如何动态感知服务下线的?注册中心和服务端双保险

文章目录先说结论机制一&#xff1a;注册中心通知机制二&#xff1a;心跳检测机制三&#xff1a;连接事件感知机制四&#xff1a;定时拉取四种机制的协作回答技巧与点评加分回答面试官点评个人网站微服务环境下&#xff0c;服务实例随时可能上下线——重启、扩容、宕机……调用…...

人类防伪指南:为什么你越写错字,HR越信你是真人?

前言各位码农、算法侠、CtrlC/V十级学者请注意&#xff1a;你有没有过这样的经历&#xff1f;辛辛苦苦肝了一晚上文档&#xff0c;逻辑严密、语法丝滑、连Markdown都对齐得像军训方阵&#xff0c;结果老板幽幽来一句&#xff1a;“这真是你自己写的&#xff1f;”那一刻&#x…...

FairyGUI Unity鼠标悬停与点击对象获取原理与实战

1. 这不是“加个OnMouseEnter就能用”的事&#xff1a;FairyGUI在Unity中处理鼠标交互的真实困境很多人第一次在Unity里集成FairyGUI&#xff0c;想实现“鼠标悬停显示提示”或“点击高亮当前按钮”&#xff0c;下意识就去翻Unity的MonoBehaviour文档&#xff0c;找OnMouseEnte…...

打造XBEE封装BLE112蓝牙模块:硬件设计、射频布局与调试全攻略

1. 项目概述&#xff1a;为什么我们需要一个“XBEE格式”的蓝牙模块&#xff1f;在嵌入式开发和物联网项目中&#xff0c;无线通信模块的选择往往决定了项目的成败。对于很多工程师和创客来说&#xff0c;Silicon Labs&#xff08;芯科科技&#xff09;的BLE112/113模块是蓝牙4…...

简单学习 --> SSE

我们使用AI时&#xff0c;AI对我们说的话不会一次性把全部内容弹出来&#xff0c;而是会像流水一样&#xff0c;一点点吐出来&#xff0c;那么这种丝滑的交互体验&#xff0c;背后的核心就是 SSE (Server-Sent Events)。 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent …...

ModernWMS核心功能详解:从ASN入库到Dispatch出库的完整工作流

ModernWMS核心功能详解&#xff1a;从ASN入库到Dispatch出库的完整工作流 【免费下载链接】ModernWMS The open source simple and complete warehouse management system is derived from our many years of experience in implementing erp projects. We stripped the origin…...