ROS python实现乌龟跟随

news2024/11/26 8:41:13

        产生两只乌龟,中间的乌龟(A) 和 左下乌龟(B), B 会自动运行至A的位置,并且键盘控制时,只是控制 A 的运动,但是 B 可以跟随 A 运行

        乌龟跟随实现的核心,是乌龟A和B都要发布相对世界坐标系的坐标信息,然后,订阅到该信息需要转换获取A相对于B坐标系的信息,最后,再生成速度信息,并控制B运动。

Python实现

1.创建功能包

创建项目功能包依赖于 tf2、tf2_ros、tf2_geometry_msgs、roscpp rospy std_msgs geometry_msgs、turtlesim

2.服务客户端(生成乌龟)
#! /usr/bin/env python
import rospy
from turtlesim.srv import Spawn,SpawnRequest,SpawnResponse
"""
    需求:向服务器发送请求生成一只乌龟
        话题:/spawn
        消息:turtlesim/Spawn

    1、导包
    2、初始化ROS节点
    3、创建服务的客户端对象
    4、组织数据并发送请求
    5、处理响应结果
"""

if __name__=="__main__":
    #2、初始化ROS节点
    rospy.init_node("service_call_p")
    #3、创建服务的客户端对象
    client=rospy.ServiceProxy("/spawn",Spawn)
    #4、组织数据并发送请求
    request = SpawnRequest()
    request.x=4.5
    request.y=2.0
    request.theta=-3
    request.name="turtle2"
    #4-2 判断服务器状态并发送
    client.wait_for_service()#客户端等待服务,若服务端没有启动则挂起
    try:
        response=client.call(request)
        #5、处理响应结果
        rospy.loginfo("生成乌龟的名字叫:%s",response.name)
    except Exception as e:
        rospy.logerr("请求处理异常")

3.发布方(发布两只乌龟的坐标信息)

#! /usr/bin/env python
import rospy
import tf.transformations
from turtlesim.msg import Pose
import tf2_ros
from geometry_msgs.msg import TransformStamped
import tf
import sys
"""
    发布方:订阅乌龟的位姿信息,转换处呢个坐标系的相对关系,再发布
    准备:
        话题:/turtle1/pose
        类型:/turtlesim/Pose

    流程:
        1、导包
        2、初始化ROS节点
        3、创建订阅对象
        4、回调函数处理订阅到的消息(核心)
        5、spin()
"""

#接受乌龟名称的变量
turtle_name = ""

def doPose(pose): #参数为订阅到的消息 pose
    #创建发布坐标系相对关系的对象
    pub=tf2_ros.TransformBroadcaster()
    #将pose转换成坐标系相对关系消息
    ts=TransformStamped()
    ts.header.frame_id="world"  #被参考的坐标系
    ts.header.stamp=rospy.Time.now()

    #修改2--------------------------------------------------------------
    ts.child_frame_id=turtle_name
    #子级坐标系相对于父级坐标系的偏移量
    ts.transform.translation.x=pose.x
    ts.transform.translation.y=pose.y
    ts.transform.translation.z=0

    #四元数
    #从欧拉角转换四元数
    """
        乌龟是2D的,不存在X上的翻滚Y上偏航,只有Z上的偏航
        0 0 pose.thera
    """
    qtn=tf.transformations.quaternion_from_euler(0,0,pose.theta)
    ts.transform.rotation.x=qtn[0]
    ts.transform.rotation.y=qtn[1]
    ts.transform.rotation.z=qtn[2]
    ts.transform.rotation.w=qtn[3]
    #发布
    pub.sendTransform(ts)

if __name__=="__main__":
    # 2、初始化ROS节点
    rospy.init_node("dynamic_pub_p")
    # 3、创建订阅对象

    #解析传入的参数(现在传入几个参数?文件全路径+传入的参数+自己定义的节点名称+日志文件路径)
    if len(sys.argv)!=4:
        rospy.loginfo("参数个数不对")
        sys.exit(1)
    else:
        turtle_name=sys.argv[1]
    #修改1
    sub=rospy.Subscriber(turtle_name+"/pose",Pose,doPose,queue_size=100)
    # 4、回调函数处理订阅到的消息(核心)
    # 5、spin()
    rospy.spin()

 4.订阅方(解析坐标信息并生成速度信息)

#! /usr/bin/env python
import rospy
import tf2_ros
import tf2_geometry_msgs
# 不要使用 geometry_msgs,需要使用 tf2 内置的消息类型
from tf2_geometry_msgs import PointStamped
# from geometry_msgs.msg import PointStamped
from geometry_msgs.msg import TransformStamped,Twist   
import math                   

if __name__=="__main__":
    # 2、初始化
    rospy.init_node("static_sub_p")
    # 3、创建订阅对象
    #3-1 创建缓存对象
    buffer=tf2_ros.Buffer()
    #3-2 创建订阅对象(将缓存传入)
    sub=tf2_ros.TransformListener(buffer)
    # 创建速度消息发布对象
    pub=rospy.Publisher("/turtle2/cmd_vel",Twist,queue_size=100)
   
    # 5、转换逻辑实现,调用tf封装的算法
    rate=rospy.Rate(10)
    while not rospy.is_shutdown():
        try:
            #--------------------计算相son1相对于son2的坐标关系
            """
                参数1:目标坐标系
                参数2:源坐标系
                参数3:rospy.Time(0)----------取时间间隔最近的两个坐标系帧(son1相对world与son2相对world)来计算结果
                返回值:son1与son2的坐标关系
            """
            ts=buffer.lookup_transform("turtle2","turtle1",rospy.Time(0))
            rospy.loginfo("父级坐标系:%s,子级坐标系:%s,偏移量(%.2f,%.2f,%.2f)",ts.header.frame_id,ts.child_frame_id,
                          ts.transform.translation.x,ts.transform.translation.y,ts.transform.translation.z)
            
            #组织Twist消息
            twist=Twist()
            #线速度=系数*坐标系原点的间距=系数*(x^2 +y^2 )再开方
            #角速度=系数*夹角          =系数*atan2(y,x)
            twist.linear.x=0.5*math.sqrt(math.pow(ts.transform.translation.x,2) 
                                         + math.pow(ts.transform.translation.y,2))
            twist.angular.z=4*math.atan2(ts.transform.translation.y,ts.transform.translation.x)
            #发布消息
            pub.publish(twist)
        except Exception as e:
            rospy.logwarn("错误提示:%s",e)
    # 7、spain()  |spinOnce()
    rate.sleep()

 使用 launch 文件组织需要运行的节点

<launch>
<!--
    流程详解:
        1.准备工作:启动乌龟的GUI节点和键盘控制节点
        2、需要调用服务器生成一只新的乌龟
        3、发布两只乌龟的坐标信息
        4、订阅坐标信息,并转换成乌龟A相对于乌龟B 的坐标信息,最后再生成控制乌龟的速度信息
-->
    <!--1.准备工作:启动乌龟的GUI节点和键盘控制节点-->
    <!--乌龟GUI-->
    <node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen" />
    <!--键盘控制-->
    <node pkg="turtlesim" type="turtle_teleop_key" name="key" output="screen" />   
    <!--2、需要调用服务器生成一只新的乌龟-->
    <node pkg="tf04_test" type="test01_new_turtle_p.py" name="turtle2" output="screen" />
    <!--3、发布两只乌龟的坐标信息
        A、复用之前的乌龟坐标发布功能
        B、调用节点时,以参数的方式传递乌龟名称,解析参数置换:订阅的话题消息和子级坐标系的名称
    -->
    <node pkg="tf04_test" type="test02_pub_turtle_p.py" name="pub1" args="turtle1" output="screen" />
    <node pkg="tf04_test" type="test02_pub_turtle_p.py" name="pub2" args="turtle2" output="screen" />
    <!--4、订阅坐标信息,并转换成乌龟A相对于乌龟B 的坐标信息,最后再生成控制乌龟的速度信息-->
    <node pkg="tf04_test" type="test03_control_turtle2_p.py" name="control" output="screen" />



</launch>

 先修改py文件的权限并在CMakeList中加相应的配置

运行launch文件

参考链接:

[1]207坐标变换实操Python01_生成乌龟-ROS常用组件_哔哩哔哩_bilibili

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

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

相关文章

用例整体执行及pytest.ini文件

在我们写代码的过程中&#xff0c;一般都是右键或者命令行去执行一个用例 但是当我们写完后&#xff0c;需要整体执行一遍。那应该怎么搞呢&#xff1f; 我们可以在根目录下新建一个main.py或者run.py之类的文件&#xff0c;文件内容如下&#xff1a; if __name__ "__ma…

报错:图片验证码接口对接vue+springboot(下一个笔记会记录整个验证码的代码)

问题&#xff1a;空指针异常ai: 根据错误堆栈信息中提供的方法调用位置&#xff0c;看起来空指针异常是在 AuthCodeServiceImpl 类的 authUserCoded 方法的第 41 行发生的。 为了解决这个问题&#xff0c;你可以检查 AuthCodeServiceImpl 类中 authUserCoded 方法的第 41 行&am…

发那科FANUC机器人R-2000iB平衡缸维修攻略

在发那科机器人中&#xff0c;平衡缸扮演着稳定机械臂运动的关键角色。它通过内部的压力调节来平衡负载&#xff0c;保证机器人的精准定位和平稳操作。一旦出现法兰克机械手平衡缸故障或损坏&#xff0c;机器人的性能可能会大打折扣&#xff0c;因此及时且正确的FANUC机械手平衡…

2024通信会|迈向智慧配电网建设新时代,锐捷网络发布双平面配电通信解决方案

近期,以“加快推进通信数智化,助力构建新型能源体系”为主题的2024年能源网络通信创新应用大会在四川成都圆满结束,会议围绕构建新型能源体系和新型电力系统建设需求,探讨能源网络通信创新应用的最新趋势与成果、“主、配、微”通信网一体化融合、配电通信网、通信数智化转型等…

Methoxy-PEG-PCL,Methoxy-PEG-Poly(ε-caprolactone)可以作为制备纳米颗粒的重要原料

【试剂详情】 英文名称 mPEG-PCL&#xff0c;MPEG-Poly(ε-caprolactone)&#xff0c;Methoxy-PEG-PCL&#xff0c;Methoxy-PEG-Poly(ε-caprolactone) 中文名称 聚乙二醇单甲醚聚己内酯两嵌段共聚物&#xff0c; 聚乙二醇单甲醚聚己内酯 外观性状 由分子量决定&#xff0…

C++实战演练---负载均衡在线oj项目预热

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 前言 学习准备了快一年时间&#xff0c;心心念念的实战演练终于可以开始了&#xff0c;话不多说&#xff0c;直接进入主题…

如何利用交易形态的失败进行现货黄金?

进行现货黄金理财&#xff0c;除了需要投资者对黄金投资有热情之外&#xff0c;有方法也是很重要的&#xff0c;光有热情而没有技术&#xff0c;我们的资金很可能会成为其他人的囊中之物。但如果有了现货黄金理财的技术&#xff0c;情况就可能扭转过来。下面我们就从买入的角度…

实战对抗DDoS攻击

引言 在当今数字化时代&#xff0c;网络安全威胁无处不在&#xff0c;其中分布式拒绝服务&#xff08;DDoS&#xff09;攻击因其强大的破坏性和难以防范性而备受关注。DDoS攻击通过控制多个僵尸节点向目标服务器发送海量请求&#xff0c;耗尽其网络带宽或计算资源&#xff0c;…

C语言面试题之相交链表

相交链表 实例要求 1、给定两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。2、如果两个链表不存在相交节点&#xff0c;返回 null 。示例&#xff1a; 实例分析 可以使用两种方法&#xff1a;哈希表方法和双指针方法。哈希表方法…

平抑风电波动的电-氢混合储能容量优化配置

这篇论文中的EMD分解法在非线性扰动信号分解上优于小波分解法,EMD分解出来的imf各频次信号,继而利用C2F实现信号重构,根据最大波动量限值剔除出需要储能平抑的波动量,继而用超级电容实现平抑(论文中用的碱水电解槽+燃料电池我认为有很多个点可以佐证不合适,但是电制氢是热…

惠州工厂降温、惠州惠城惠阳大亚湾仲恺高新惠城博罗车间降温通风

惠州工厂降温、惠州惠城惠阳大亚湾仲恺高新惠城博罗车间降温通风&#xff0c;惠州博罗车间降温、 惠州博罗的车间降温是一个涉及提高工作环境舒适度与生产效率的重要问题。以下是一些建议的降温方法&#xff1a; 通风换气&#xff1a;对于车间来说&#xff0c;良好的通风是降…

什么是独立服务器?独立服务器最全面介绍

独立服务器是单个客户端具有独占访问权的服务器类型&#xff0c;在服务器开发过程中&#xff0c;以前使用虚拟主机和虚拟独立服务器&#xff08;VPS&#xff09;的公司几乎不可避免地转向独立服务器。 什么是独立服务器&#xff1f; 独立服务器是单个客户端具有独占访问权的服…

4.28|重量级嘉宾携卓翼飞思RflySim平台亮相国际盛会,内容抢先看!

一. 大会背景 2024国际无人机应用及防控大会暨无人机产业博览会即将拉开帷幕&#xff0c;一场高规格、高水平的无人机产业应用国际盛会将再次点亮科技界的星空。 该大会由中国无人机产业创新联盟联合各方有影响力的单位&#xff0c;于4月27-29日在北京举办。组委会致力于将会…

亿道三防onerugged|三防车载电脑在港口货柜车上的应用

作为一个专业人员&#xff0c;我深知在港口货柜车运输中&#xff0c;三防车载电脑的应用对于提高工作效率和解决实际问题的重要性。亿道三防onerugged系列产品的三防车载电脑以其卓越的功能特点和可靠性&#xff0c;为港口货柜车运输带来了深远的影响。 首先&#xff0c;三防车…

Vue3 + Element-Plus 对接高德地图实现搜索提示选址、点击地图选址、自我定位功能(最新)

Vue3 Element-Plus 对接高德地图实现搜索提示选址、点击地图选址、自我定位功能&#xff08;最新&#xff09; 1、效果展示2、实现代码2.1 GaoDeMap.vue2.2 SystemDialog.vue2.3 UnusedList.vue.vue 1、效果展示 2、实现代码 2.1 GaoDeMap.vue <template><div style…

关于C++如何导出dll用于C++和C#的研究(内含有YOLOV5调用接口的制作完整代码)

文章目录 一、VS2019复现视频的易错点。二、[补充一个C接口的知识](https://www.bilibili.com/video/BV1tA411N7HB/?spm_id_from333.337.search-card.all.click&vd_sourcef99e21db912f182fe051b1b6b156e0e3)三、回归正题如何调用dll&#xff1f;前面第一个视频教会我们导出…

07 流量回放实现自动化回归测试

在本模块的前四讲里&#xff0c;我向你介绍了可以直接落地的、能够支撑百万并发的读服务的系统架构&#xff0c;包含懒加载缓存、全量缓存&#xff0c;以及数据同步等方案的技术细节。 基于上述方案及细节&#xff0c;你可以直接对你所负责的读服务进行架构升级&#xff0c;将…

SpringBoot引入Layui样式总是出现404

一般出现Layui样式文件如css&#xff0c;js404的错误 解决方案 &#xff08;1&#xff09;首先将其中的静态资源下载resources/static中 &#xff08;2&#xff09;在启动类中重写方法 package com.gq.booksystem;import org.mybatis.spring.annotation.MapperScan; import …

Java本地缓存技术选型(Guava Cache、Caffeine、EhCache)

前言 对一个java开发者而言&#xff0c;提到缓存&#xff0c;第一反应就是Redis。利用这类缓存足以解决大多数的性能问题了&#xff0c;我们也要知道&#xff0c;这种属于remote cache&#xff08;分布式缓存&#xff09;&#xff0c;应用的进程和缓存的进程通常分布在不同的服…

nvm下载的node没有npm

nvm下载的node没有npm 相信大家最近可能发现自己使用的nvm下载nodejs没有npm了。 会出现这种情况&#xff1a; C:\Users\89121>nvm install 15 Downloading node.js version 15.14.0 (64-bit)... Complete Downloading npm version 7.7.6... Download failed. Rolling Bac…