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写作平台,以其强大的语言理解和生成能力,为用户提供了从文本生成到编辑、优化等一系列服务。本文将介绍如何…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...