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

ROS2自定义接口Python实现机器人移动

1.创建机器人节点接口

cd chapt3_ws/

ros2 pkg create example_interfaces_rclpy --build-type ament_python --dependencies rclpy example_ros2_interfaces --destination-directory src --node-name example_interfaces_robot_02 --maintainer-name "Joe Chen" --maintainer-email "1027038527@qq.com"

touch src/example_interfaces_rclpy/example_interfaces_rclpy/example_interfaces_control_02.py

2.控制器节点代码

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_ros2_interfaces.msg import RobotStatus
from example_ros2_interfaces.srv import MoveRobot

class ExampleInterfacesControl02(Node):
    def __init__(self,name):
        super().__init__(name)
        self.get_logger().info("节点已启动:%s!" % name)
        self.client_ = self.create_client(MoveRobot,"move_robot") 
        self.robot_status_subscribe_ = self.create_subscription(RobotStatus,"robot_status",self.robot_status_callback,10)

    def robot_status_callback(self,msg):
        self.get_logger().info(f"收到状态数据位置:{msg.pose} 状态:{msg.status}")

    def move_result_callback_(self, result_future):
        response = result_future.result()
        self.get_logger().info(f"收到返回结果:{response.pose}")

    def move_robot(self, distance):
        while rclpy.ok() and self.client_.wait_for_service(1)==False:
            self.get_logger().info(f"等待服务端上线....")
        request = MoveRobot.Request()
        request.distance = distance
        self.get_logger().info(f"请求服务让机器人移动{distance}")
        self.client_.call_async(request).add_done_callback(self.move_result_callback_)


def main(args=None):
    rclpy.init(args=args) # 初始化rclpy
    node = ExampleInterfacesControl02("example_interfaces_control_02")  # 新建一个节点
    node.move_robot(5.0) #移动5米
    rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
    rclpy.shutdown() # 关闭rclpy

3.编写机器人节点

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_ros2_interfaces.msg import RobotStatus
import math
from time import sleep
from example_ros2_interfaces.srv import MoveRobot


class Robot():
    def __init__(self) -> None:
        self.current_pose_ = 0.0
        self.target_pose_ = 0.0
        self.status_ = RobotStatus.STATUS_STOP

    def get_status(self):
        return self.status_

    def get_current_pose(self):
        return self.current_pose_

    def move_distance(self,distance):
        self.status_ = RobotStatus.STATUS_MOVEING # 更新状态为移动、
        self.target_pose_ += distance # 更新目标位置

        while math.fabs(self.target_pose_ - self.current_pose_) > 0.01:
            step = distance / math.fabs(distance) * math.fabs(self.target_pose_ - self.current_pose_) * 0.1 # 计算一步移动距离
            self.current_pose_  += step # 移动一步
            print(f"移动了:{step}当前位置:{self.current_pose_}")
            sleep(0.5) #休息0.5s
        self.status_ = RobotStatus.STATUS_STOP # 更新状态为停止
        return self.current_pose_
     

class ExampleInterfacesRobot02(Node):
    def __init__(self,name):
        super().__init__(name)
        self.get_logger().info("节点已启动:%s!" % name)
        self.robot = Robot()
        self.move_robot_server_ = self.create_service(MoveRobot,"move_robot", self.handle_move_robot) 
        self.robot_status_publisher_ = self.create_publisher(RobotStatus,"robot_status", 10) 
        self.publisher_timer_ = self.create_timer(0.5, self.publisher_timer_callback)
    

    def publisher_timer_callback(self):
        """
        定时器回调发布数据函数
        """
        msg = RobotStatus() #构造消息
        msg.status = self.robot.get_status()
        msg.pose = self.robot.get_current_pose()
        self.robot_status_publisher_.publish(msg) # 发布消息
        self.get_logger().info(f'发布了当前的状态:{msg.status} 位置:{msg.pose}')

    def handle_move_robot(self,request, response):
        self.robot.move_distance(request.distance)
        response.pose = self.robot.get_current_pose()
        return response

        
def main(args=None):
    rclpy.init(args=args) # 初始化rclpy
    node = ExampleInterfacesRobot02("example_interfaces_robot_02")  # 新建一个节点
    rclpy.spin(node) # 保持节点运行,检测是否收到退出指令(Ctrl+C)
    rclpy.shutdown() # 关闭rclpy

4.链接、编译、运行节点

setup.py

from setuptools import find_packages, setup

package_name = 'example_interfaces_rclpy'

setup(
    name=package_name,
    version='0.0.0',
    packages=find_packages(exclude=['test']),
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='Joe Chen',
    maintainer_email='1027038527@qq.com',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'example_interfaces_control_02 = example_interfaces_rclpy.example_interfaces_control_02:main',
            'example_interfaces_robot_02 = example_interfaces_rclpy.example_interfaces_robot_02:main'

        ],
    },
)

source install/setup.bash
ros2 run example_interfaces_rclpy example_interfaces_robot_02

source install/setup.bash
ros2 run example_interfaces_rclpy example_interfaces_control_02

相关文章:

  • llama.cpp
  • CPP入门:日期类的构建
  • [AIGC] HashMap的扩容与缩容:动态调整容量以提高性能
  • 【JavaEE精炼宝库】多线程进阶(2)synchronized原理、JUC类——深度理解多线程编程
  • 【Qt+opencv】图片与视频的操作
  • 13018.CUDA工程配置GDB调试
  • 探索未来远程调试新纪元——《串口网口远程调试软件》:无缝连接,高效调试
  • 森林防火气象站:守护森林安全的科技利器
  • 【FFmpeg】avcodec_find_encoder和avcodec_find_decoder
  • 《mysql篇》--查询(进阶)
  • TCP: 传输控制协议
  • 双非本 985 硕,我马上要入职上海AI实验室大模型算法岗
  • 嵌入式实验---实验五 串口数据接收实验
  • Webpack: Loader开发 (1)
  • 基于正点原子FreeRTOS学习笔记——时间片调度实验
  • [译]前端离线指南(上)
  • Angular Elements 及其运作原理
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • IP路由与转发
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • oldjun 检测网站的经验
  • Redis 懒删除(lazy free)简史
  • spring + angular 实现导出excel
  • SQLServer之创建数据库快照
  • 给github项目添加CI badge
  • 悄悄地说一个bug
  • 深度解析利用ES6进行Promise封装总结
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 学习笔记:对象,原型和继承(1)
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 阿里云服务器如何修改远程端口?
  • ​如何防止网络攻击?
  • #include<初见C语言之指针(5)>
  • #vue3 实现前端下载excel文件模板功能
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (8)STL算法之替换
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (四)opengl函数加载和错误处理
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .NET delegate 委托 、 Event 事件
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • .net中生成excel后调整宽度
  • @RequestBody的使用
  • []我的函数库
  • [20171106]配置客户端连接注意.txt
  • [20190416]完善shared latch测试脚本2.txt
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下
  • [C#] 基于 yield 语句的迭代器逻辑懒执行
  • [C/C++] -- 二叉树