ROS2使用Python开发动作通信
1.创建接口节点
cd chapt4_ws/
 ros2 pkg create robot_control_interfaces --build-type ament_cmake --destination-directory src --maintainer-name "joe" --maintainer-email "1027038527@qq.com"
 mkdir -p src/robot_control_interfaces/action
 touch src/robot_control_interfaces/action/MoveRobot.action
# Goal: 要移动的距离
 float32 distance
 ---
 # Result: 最终的位置
 float32 pose
 ---
 # Feedback: 中间反馈的位置和状态
 float32 pose
 uint32 status
 uint32 STATUS_MOVEING = 3
 uint32 STATUS_STOP = 4
修改package.xml
  <depend>rosidl_default_generators</depend>
   <member_of_group>rosidl_interface_packages</member_of_group>
 修改CMakeLists.txt
 find_package(rosidl_default_generators REQUIRED)
 rosidl_generate_interfaces(${PROJECT_NAME}
   "action/MoveRobot.action"
 )
编译节点
colcon build --packages-select robot_control_interfaces
  
2.创建Python Action节点
cd chapt4_ws/
 ros2 pkg create example_action_rclpy --build-type ament_python --dependencies rclpy robot_control_interfaces --destination-directory src --node-name action_robot_02   --maintainer-name "joe" --maintainer-email "1027038527@qq.com"
# 手动再创建action_control_02节点文件
 touch src/example_action_rclpy/example_action_rclpy/action_control_02.py
import rclpy
 from rclpy.action import ActionClient
 from rclpy.node import Node
 # 导入Action接口
 from robot_control_interfaces.action import MoveRobot
class ActionControl02(Node):
     """Action客户端"""
    def __init__(self, name):
         super().__init__(name)
         self.get_logger().info(f"节点已启动:{name}!")
         self.action_client_ = ActionClient(self, MoveRobot, 'move_robot')
         self.send_goal_timer_ = self.create_timer(1, self.send_goal)
    def send_goal(self):
         """发送目标"""
         self.send_goal_timer_.cancel()
         goal_msg = MoveRobot.Goal()
         goal_msg.distance = 5.0
         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 :(')
             return
         self.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(f'Result: {result.pose}')
    def feedback_callback(self, feedback_msg):
         """获取回调反馈"""
         feedback = feedback_msg.feedback
         self.get_logger().info(f'Received feedback: {feedback.pose}')
 def main(args=None):
     """主函数"""
     rclpy.init(args=args)
     action_robot_02 = ActionControl02("action_control_02")
     rclpy.spin(action_robot_02)
     rclpy.shutdown()
  
 #手动创建机器人类robot.py
 touch src/example_action_rclpy/example_action_rclpy/robot.py
  
#!/usr/bin/env python3
import time
 # 导入rclpy相关库
 import rclpy
 from rclpy.node import Node
 from rclpy.action import ActionServer
 from rclpy.action.server import ServerGoalHandle
 # 导入接口
 from robot_control_interfaces.action import MoveRobot
 # 导入机器人类
 from example_action_rclpy.robot import Robot
 #from rclpy.executors import MultiThreadedExecutor
 #from rclpy.callback_groups import MutuallyExclusiveCallbackGroup
class ActionRobot02(Node):
     """机器人端Action服务"""
    def __init__(self,name):
         super().__init__(name)
         self.get_logger().info(f"节点已启动:{name}!")
self.robot_ = Robot()
        self.action_server_ = ActionServer(
             self, MoveRobot, 'move_robot', self.execute_callback
             # ,callback_group=MutuallyExclusiveCallbackGroup()
         )
    def execute_callback(self, goal_handle: ServerGoalHandle):
         """执行回调函数,若采用默认handle_goal函数则会自动调用"""
         self.get_logger().info('执行移动机器人')
         feedback_msg = MoveRobot.Feedback()
         self.robot_.set_goal(goal_handle.request.distance)
        # rate = self.create_rate(2)
         while rclpy.ok() and not self.robot_.close_goal():
             # move
             self.robot_.move_step()
             # feedback
             feedback_msg.pose = self.robot_.get_current_pose()
             feedback_msg.status = self.robot_.get_status()
             goal_handle.publish_feedback(feedback_msg)
             # cancel check
             if goal_handle.is_cancel_requested:
                 result = MoveRobot.Result()
                 result.pose = self.robot_.get_current_pose()
                 return result
             # rate.sleep() # Rate会造成死锁,单线程执行器时不能使用
             time.sleep(0.5)
        goal_handle.succeed()
         result = MoveRobot.Result()
         result.pose = self.robot_.get_current_pose()
         return result
        
 def main(args=None):
     """主函数"""
     rclpy.init(args=args)
     action_robot_02 = ActionRobot02("action_robot_02")
     # 采用多线程执行器解决rate死锁问题
     # executor = MultiThreadedExecutor()
     # executor.add_node(action_robot_02)
     # executor.spin()
     rclpy.spin(action_robot_02)
     rclpy.shutdown()
  
touch src/example_action_rclpy/example_action_rclpy/robot.py
from robot_control_interfaces.action import MoveRobot
 import math
class Robot():
     """机器人类,模拟一个机器人"""
    def __init__(self) -> None:
         self.current_pose_ = 0.0
         self.target_pose_ = 0.0
         self.move_distance_ = 0.0
         self.status_ = MoveRobot.Feedback
    def get_status(self):
         """获取状态"""
         return self.status_
    def get_current_pose(self):
         """获取当前位置"""
         return self.current_pose_
    def close_goal(self):
         """接近目标"""
         return math.fabs(self.target_pose_ - self.current_pose_) < 0.01
    def stop_move(self):
         """停止移动"""
         self.status_ = MoveRobot.Feedback.STATUS_STOP
    def move_step(self):
         """移动一小步"""
         direct = self.move_distance_ / math.fabs(self.move_distance_)
         step = direct * math.fabs(self.target_pose_ - self.current_pose_) * 0.1
         self.current_pose_ += step  # 移动一步
         print(f"移动了:{step}当前位置:{self.current_pose_}")
         return self.current_pose_
    def set_goal(self, distance):
         """设置目标"""
         self.move_distance_ = distance
         self.target_pose_ += distance  # 更新目标位置
        if self.close_goal():
             self.stop_move()
             return False
        self.status_ = MoveRobot.Feedback.STATUS_MOVEING  # 更新状态为移动
         return True
编辑package.xml
<depend>robot_control_interfaces</depend>
编辑setup.py
    'action_robot_02 = example_action_rclpy.action_robot_02:main',
     'action_control_02 = example_action_rclpy.action_control_02:main'
3.编译、运行节点
 colcon build --packages-up-to example_action_rclpy
 # 运行机器人节点
 source install/setup.bash 
 ros2 run example_action_rclpy  action_robot_02

 # 新终端
 source install/setup.bash 
 ros2 run example_action_rclpy  action_control_02

  
相关文章:
ROS2使用Python开发动作通信
1.创建接口节点 cd chapt4_ws/ ros2 pkg create robot_control_interfaces --build-type ament_cmake --destination-directory src --maintainer-name "joe" --maintainer-email "1027038527qq.com" mkdir -p src/robot_control_interfaces/action touch…...
Bug记录:【com.fasterxml.jackson.databind.exc.InvalidDefinitionException】
bug记录 序列化错误 异常com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 完整错误(主要是FAIL_ON_EMPTY_BEANS) 00:15:20.250 [http-nio-3000-exec-1] ERROR org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - S…...
Mongodb索引的删除
学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第87篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关…...
科研绘图系列:R语言径向柱状图(Radial Bar Chart)
介绍 径向柱状图(Radial Bar Chart),又称为雷达图或蜘蛛网图(Spider Chart),是一种在极坐标系中绘制的柱状图。这种图表的特点是将数据点沿着一个或多个从中心向外延伸的轴来展示,这些轴通常围绕着一个中心点均匀分布。 特点: 极坐标系统:数据点不是在直角坐标系中展…...
鸿蒙开发管理:【@ohos.account.distributedAccount (分布式帐号管理)】
分布式帐号管理 本模块提供管理分布式帐号的一些基础功能,主要包括查询和更新帐号登录状态。 说明: 本模块首批接口从API version 7开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档ÿ…...
【图书推荐】《HTML5+CSS3 Web前端开发与实例教程(微课视频版)》
本书用来干什么 详解HTML5、CSS3、Flex布局、Grid布局、AI技巧,通过两个网站设计案例提升Web前端开发技能,为读者深入学习Web前端开发打下牢固的基础。 配套资源非常齐全,可以当Web前端基础课的教材。 内容简介 本书秉承“思政引领&#…...
【04】微服务通信组件Feign
1、项目中接口的调用方式 1.1 HttpClient HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的 URLConnectio…...
为什么要设计DTO类
为什么要使用DTO类,下面以新增员工接口为例来介绍。 新增员工 1.1 需求分析和设计 1.1.1 产品原型 一般在做需求分析时,往往都是对照着产品原型进行分析,因为产品原型比较直观,便于我们理解业务。 后台系统中可以管理员工信息…...
流批一体计算引擎-11-[Flink]实战使用DataStream对接kafka
1 消费kafka[DataStreamAPI] 参考官网DataStream API 教程 参考官网DataStream中的Apache Kafka 连接器 flink 1.14版本及以前,不支持python flink 1.15版本为FlinkKafkaConsumer和FlinkKafkaProducer flink 1.16版本及以后为KafkaSource和KafkaSink pip install apache-flin…...
数据仓库面试题
一、ODS、DWD、DWS、ADS划分与职责 数据仓库中的ODS、DWD、DWS、ADS分别代表以下层次,并各自承担不同的职责:--ODS(Operational Data Store): 名称:贴源层 主要职责:作为数据仓库的第一层&…...
SQL 创建一个actor表,包含如下列信息
系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 描述 创建一个acto…...
STM32+ESP8266连接阿里云
完整工程文件(百度网盘免费下载,提取码:0625)在文章末尾,需要请移步至文章末尾。 目录 宏定义配置 串口通信配置 消息解析及数据发送 ESP8266初始化 注意事项 完整工程文件 经过基础教程使用AT指令连接阿里云后…...
shark云原生-日志体系-ECK
文章目录 0. ECK 介绍1. 部署 CRDS & Opereator2. 部署 Elasticsearch 集群3. 配置存储4. 部署示例 0. ECK 介绍 ECK(Elastic Cloud on Kubernetes)是Elasticsearch官方提供的一种方式,用于在Kubernetes上部署、管理和扩展Elasticsearch…...
第二次作业
一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo 一、数据库(步骤) 1、登陆数据库 mysql -hlocalhost -uadmin -p123456 2、创建…...
Java8 新特性stream、forEach常用方法总结
1、去重 List<Long> list new ArrayList<>();list.add(1L);list.add(2L);list.add(3L);list.add(3L);list.stream().distinct().collect(Collectors.toList()); 2、筛选出符合条件的数据 1)单条件筛选 筛选出性别为男的学生: List<…...
C语言4 运算符
目录 1. 算术运算符 2. 关系运算符 3. 逻辑运算符 4. 位运算符 5. 赋值运算符 6. 自增和自减运算符 7. 条件运算符(三元运算符) 8. 逗号运算符 9. sizeof 运算符 10. 取地址和解引用运算符 11.运算符的优先级 1. 算术运算符 (加法)࿱…...
【数据分析】Pandas_DataFrame读写详解:案例解析(第24天)
系列文章目录 一、 读写文件数据 二、df查询数据操作 三、df增加列操作 四、df删除行列操作 五、df数据去重操作 六、df数据修改操作 文章目录 系列文章目录前言一、 读写文件数据1.1 读写excel文件1.2 读写csv文件1.3 读写mysql数据库 二、df查询数据操作2.1 查询df子集基本方…...
quill编辑器使用总结
一、vue-quill-editor 与 quill 若使用版本1.0,这两个组件使用哪个都是一样的,无非代码有点偏差;若需要使用表格功能,必须使用 quill2.0 版本,因为 vue-quill-editor 不支持table功能。 二、webpack版本问题 在使用 q…...
快手矩阵管理系统:引领短视频运营新潮流
在短视频行业蓬勃发展的今天,如何高效运营和优化内容创作已成为企业和创作者关注的焦点。快手矩阵管理系统以其强大的核心功能,为短视频内容的创作、发布和管理提供了一站式解决方案。 智能创作:AI自动生成文案 快手矩阵管理系统的智能创作…...
文心一言:探索AI写作的新境界
在人工智能飞速发展的今天,AI写作助手已经成为许多写作者、内容创作者和营销专家的重要工具。"文心一言"作为一个先进的AI写作平台,以其强大的语言理解和生成能力,为用户提供了从文本生成到编辑、优化等一系列服务。本文将介绍如何…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
