ROS2使用Python开发动作通信

news2024/12/23 18:09:36

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


 

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

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

相关文章

STM32自己从零开始实操08:电机电路原理图

一、LC滤波电路 其实以下的滤波都可以叫低通滤波器。 1.1倒 “L” 型 LC 滤波电路 1.1.1定性分析 1.1.2仿真实验 电感&#xff1a;通低频阻高频的。仿真中高频信号通过电感&#xff0c;因为电感会阻止电流发生变化&#xff0c;故说阻止高频信号 电容&#xff1a;隔直通交。…

MAS1102量产工具下载,MAS1102+N48R固件开卡软件分享

最近买了一款某牌子的固态硬盘&#xff0c;拆开后发现采用的是联云MAS1102主控&#xff0c;闪存颗粒是N48R&#xff0c;如下图。 查了一下MAS1102主控&#xff0c;是联芸科技基于SATA3.2技术开发的DRAM-less SSD控制芯片&#xff0c;支持2.5寸/HalfSlim/M.2/mSATA版型&#xff…

S7-1500PLC控制V90总线伺服报“编码器故障“

S7-1500PLC控制V90总线伺服报编码器故障&#xff0c;如下图所示&#xff1a; 1、编码器故障 2、编码器配置 3、自动选择编码器值

深度解读 OkHttpClient2

介绍 OkHttpClient 是 OkHttp 库的核心类&#xff0c;它管理连接、线程池和配置选项。OkHttpClient 提供了强大的功能和灵活的配置选项&#xff0c;使得它成为 Android 和 Java 应用中广泛使用的 HTTP 客户端。 在本文中&#xff0c;我们将深入解读 OkHttpClient&#xff0c;…

基于PHP安龙县农产品销售网站的设计与实现13137

目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3论文结构与章节安排 2 相关技术介绍 2.1 PHP描述 2.2 MySQL数据库 2.3 Think PHP框架 3网站分析 3.1 可行性分析 3.2 网站流程分析 3.2.1 数据新增流程 3.2.2 数据删除流程 3.3 网站功能分析 3.3.1 功能性分析…

基于SpringBoot民宿管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

HSP_12章 Python面向对象编程oop_多态

文章目录 P128 多态问题的引出P129 多态细节和使用1. 多态介绍&特别说明2. 多态的好处3. 特别说明: Python多态的特点4. 使用多态的机制来解决主人喂食物的问题 P128 多态问题的引出 先看一个问题 # 说明: 先试用传统的方式完成 class Food:name Nonedef __init__(self,…

nginx: [warn] 20240 worker_connections exceed open file resource limit: 1024

nginx: [warn] 20240 worker_connections exceed open file resource limit: 1024 报错翻译过来就是&#xff1a; nginx&#xff1a;[警告] 20240 worker_connections超出打开文件资源限制&#xff1a;1024 解决方法&#xff1a; 1.查看当前文件打开数量的限制 ulimit -S…

深入了解DDoS攻击及其防护措施

深入了解DDoS攻击及其防护措施 分布式拒绝服务&#xff08;Distributed Denial of Service&#xff0c;DDoS&#xff09;攻击是当今互联网环境中最具破坏性和普遍性的网络威胁之一。DDoS攻击不仅危及企业的运营&#xff0c;还可能损害其声誉&#xff0c;造成客户信任度的下降。…

在CAM350中如何删除PCB走线的一部分?

在CAM350中如何删除PCB一条走线的一部分&#xff1f; 在CAM350中如何删除走线&#xff1f; 操作方法如下&#xff1a; 1、因为这是一整条线&#xff0c;如果点击删除&#xff0c;整条线会被全部删除。可以在你想删除的位置增加一个节点。 选择菜单栏→edit 选择→add vertax 2…

【最新综述】医学图像分割深度半监督学习(上)

摘要&#xff1a; 最近&#xff0c;深度学习在各种计算机视觉任务中展现出了巨大的前景。然而&#xff0c;在许多实际应用中&#xff0c;没有大规模的标记数据集&#xff0c;这限制了深度学习的应用。为了解决这个问题&#xff0c;半监督学习引起了计算机视觉界的广泛关注&…

Steam社区101错误代码/steam社区报错、打不开怎么办

Steam社区是很多游戏玩家经常逛的一个互动空间&#xff0c;玩家可以在Steam社区了解游戏的相关评价&#xff0c;也可以在Steam社区和五湖四海的游戏玩家一起讨论最近游戏的心得&#xff0c;分享游玩技巧&#xff0c;探讨游戏战术等等&#xff0c;结识不同地区的玩家。不过很多玩…

WAIC | 斯梅尔数学与计算研究院邀您莅临WAIC 2024“数学与人工智能”论坛

当我们谈论起人工智能这一变革性力量时&#xff0c;就不得不提及数学。人工智能作为当今社会的热门话题&#xff0c;从AlphaGo到ChatGPT&#xff0c;从智能制造到数字文旅&#xff0c;它的发展和应用深刻地影响着行业和人们的生活。然而&#xff0c;人工智能的发展和基础离不开…

跨平台营销的智能协同:Kompas.ai如何整合多渠道策略

引言 在数字化营销的今天&#xff0c;消费者的注意力分散在多个平台上。品牌要想有效地吸引和保持消费者的关注&#xff0c;就必须采取跨平台营销策略。Kompas.ai&#xff0c;作为一款智能营销工具&#xff0c;能够帮助品牌实现这一目标。 跨平台营销的重要性 跨平台营销能够…

Redis哨兵和集群模式

特性哨兵模式集群模式高可用性是是数据分片否是水平扩展否是配置复杂度低高管理复杂度低高多键操作支持是否&#xff08;有限制&#xff09; 哨兵模式 原理&#xff1a; Redis 哨兵模式是一种高可用性解决方案&#xff0c;它通过监控 Redis 主从架构&#xff0c;自动执行故障…

Rust借助dotenv库读取环境变量

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

信息收集---端口服务信息收集

1. 什么是端口 是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口&#xff0c;其中虚拟端口指计算机内部或交换机路由器内的端口&#xff0c;不可见。例如计算机中的80端口、21端口、23端口等。物理端口又称为接口&#xff0c;是可见端口&#xff0c;计算机背板的RJ45…

欧洲智慧能源展揭幕,海博思创闪耀登场展示储能创新

近日&#xff0c;备受瞩目的欧洲智慧能源展&#xff08;The Smarter E Europe&#xff09;盛大开幕&#xff0c;吸引了全球能源行业的目光。在这场国际性的盛会中&#xff0c;中国储能行业的领军企业海博思创凭借卓越的技术实力和创新的解决方案&#xff0c;成为展会上一颗耀眼…

Docker 运行Nacos无法访问地址解决方法

参考我的上一篇文章去配置好镜像加速器&#xff0c;镜像加速器不是配置越多越好&#xff0c;重试次数多了会失败 Dockerhub无法拉取镜像配置阿里镜像加速器-CSDN博客 错误的尝试 最开始按照网上的方式去配了一大堆&#xff0c;发现下不下来。 镜像源地址&#xff1a;https:…

中国网络安全审查认证和市场监管大数据中心数据合规官CCRC-DCO

关于CCRC-DCO证书的颁发机构&#xff0c;它是由中国网络安全审查认证与市场监管大数据中心&#xff08;简称CCRC&#xff09;负责。 该中心在2006年得到中央机构编制委员会办公室的批准成立&#xff0c;隶属于国家市场监督管理总局&#xff0c;是其直辖的事业单位。 依据《网络…