ROS python实现乌龟跟随

        产生两只乌龟,中间的乌龟(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.mfbz.cn/a/572192.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

按钮获取验证码倒计时60秒

把倒计时存在缓存里刷新页面依旧是接着倒计时 <el-buttonsize"large"class"btnStyle":class"btnStyleClass":style"buttonStyle":disabled"countdownActive"click"handleClick">{{ buttonText }}</el-b…

算法-KMP算法

时间复杂度&#xff1a; public int strStr(String haystack, String needle) {int[] next new int[needle.length()];//next数组的生成next[0] 0;int prefixLen 0;//共同前后缀长度int i 1, j 1;//i,j复用while (i < needle.length()) {if (needle.charAt(prefixLen)…

Shader实战(3):贴图像素化风格实现

话不多说&#xff0c;将以下shader赋给材质贴上贴图即可。 Shader "HQY/Shader2" //自己改名 {Properties{_Diffuse ("Diffuse", Color) (1,1,1,1)_MainTex ("MainTex", 2D) "white" {}_Specular("Specular", Color) (…

AI伙伴是什么

AI伙伴&#xff0c;或称为人工智能伙伴&#xff0c;是指能够执行特定任务、协助人类活动&#xff0c;甚至进行社交互动的智能系统。 编辑搜图 请点击输入图片描述&#xff08;最多18字&#xff09; AI伙伴通常是通过集成了先进的技术如语音识别、语义理解和图像识别等来实现与…

ubuntu扩展根目录磁盘空间

ubuntu扩展根目录磁盘空间 扩展虚拟机磁盘空间 查看现有磁盘状态 查询现有分区状态&#xff0c;/dev/sda是我们要扩展的磁盘 fdisk -l 开始进行磁盘空间的扩容 parted /dev/sda#扩展3号分区的空间 resizepart 3刷新分区空间 resize2fs /dev/sda3查询扩展结果&#xff0c;…

Golang GMP解读

概念梳理 1. 1 线程 通常语义中的线程&#xff0c;指的是内核级线程&#xff0c;核心点如下&#xff1a; 是操作系统最小调度单元&#xff1b;创建、销毁、调度交由内核完成&#xff0c;cpu 需完成用户态与内核态间的切换&#xff1b;可充分利用多核&#xff0c;实现并行. …

HTTP 网络协议请求的消息结构,具体详解(2024-04-25)

一、简介 HTTP 是基于客户端/服务端&#xff08;C/S&#xff09;的架构模型&#xff0c;通过一个可靠的链接来交换信息&#xff0c;是一个无状态的请求/响应协议。 HTTP 消息是客户端和服务器之间通信的基础&#xff0c;它们由一系列的文本行组成&#xff0c;遵循特定的格式和…

热门项目!知识付费小程序源码系统 带完整的安装代码包以及安装部署教程

近年来&#xff0c;随着在线教育、知识分享等领域的蓬勃发展&#xff0c;知识付费市场逐渐壮大。越来越多的用户愿意为高质量的知识内容付费&#xff0c;而企业和个人也看到了知识付费的巨大商机。然而&#xff0c;对于许多没有技术背景的用户来说&#xff0c;搭建一个稳定、易…

自定义数据 微调CLIP (结合paper)

CLIP 是 Contrastive Language-Image Pre-training 的缩写&#xff0c;是一个擅长理解文本和图像之间关系的模型&#xff0c;下面是一个简单的介绍&#xff1a; 优点&#xff1a; CLIP 在零样本学习方面特别强大&#xff0c;它可以&#xff08;用自然语言&#xff09;给出图像…

AI Agent新对决:LangGraph与AutoGen的技术角力

AI Agent变革未来&#xff0c;LangGraph对抗AutoGen ©作者|Blaze 来源|神州问学 引言 比尔.盖茨曾在他的博客上发表一篇文章&#xff1a;《AI is about to completely change how you use computers》。在文章中&#xff0c;比尔盖茨探讨AI Agent对我们未来生活的巨大影…

目标检测YOLO数据集的三种格式及转换

目标检测YOLO数据集的三种格式 在目标检测领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;算法是一个流行的选择。为了训练和测试YOLO模型&#xff0c;需要将数据集格式化为YOLO可以识别的格式。以下是三种常见的YOLO数据集格式及其特点和转换方法。 1. YOL…

RabbitMQ, DelayQueue, Redis的介绍以及IDEA的实现

RabbitMQ RabbitMQ是一个开源的消息队列中间件&#xff0c;它实现了高效、可靠的消息传递机制。它支持多种消息传递模式&#xff0c;如发布/订阅、点对点、请求/回应等。RabbitMQ以其可靠性、灵活性和易用性受到广泛的关注和应用。 RabbitMQ基于AMQP&#xff08;Advanced Mess…

【禅道客户案例】专访鸿泉物联研发副总监徐小倩,感受上市公司研发项目管理“知与行”

杭州鸿泉物联网技术股份有限公司&#xff08;以下简称“鸿泉物联”、“公司”&#xff09;成立于2009年6月11日&#xff0c;2019年11月6日登陆上海证券交易所科创板&#xff08;股票代码&#xff1a;688288&#xff09;&#xff0c;注册资本10034.392万元&#xff0c;目前员工6…

「案例分享」DevExpress XAF (WinForms UI)赋能医疗管理系统,让操作更自动化!

DevExpress XAF是一款强大的现代应用程序框架&#xff0c;它采用模块化设计&#xff0c;开发人员可以选择内建模块&#xff0c;也可以自行创建&#xff0c;从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。 获取DevExpress 新版正式版下载(Q技术交流&#xff1a…

CTFshow-PWN-栈溢出(pwn44)

64位的 system(); 但是好像没"/bin/sh" 上面的办法不行了&#xff0c;想想办法 检查&#xff1a; 是 64 位程序 ida 反编译 main 函数&#xff1a; 跟进 ctfshow 函数&#xff1a; 存在栈溢出 offset&#xff1a;0xAh8 在前面经验的基础上&#xff0c;这里我们直…

Redis第14讲——Redis实现分布式锁(Redission源码解析)

在多线程环境下&#xff0c;为了保证数据的线程安全&#xff0c;我们通常用加锁的方式&#xff0c;使同一时刻只有一个线程可以对这个共享资源进行操作&#xff0c;在单服务系统我们常用JVM锁——Synchronized、ReentrantLock等。然而在多台服务系统的情况下&#xff0c;JVM锁就…

数字科技助力垃圾分类展厅,增强内容交互新体验!

如今&#xff0c;许多行业都开始运用数字技术&#xff0c;探索其在展览展示领域中的应用&#xff0c;其中垃圾分类展厅作为现代城市文明建设的重要一环&#xff0c;也通过这些技术的运用&#xff0c;打造出了更加生动且富有科技感的展示空间&#xff0c;它不仅提升公众对垃圾分…

原生微信小程序中案例--仿boss区域树选择列多选功能

1. 需求描述&#xff1a; 区域三级列表&#xff0c; 有添加&#xff0c;编辑&#xff0c;删除功能。 选择父级分类&#xff0c;其下子类全部选中&#xff0c;当前分类后加标志显示全字样取消选中子类&#xff0c;其父类分类后标志显示选中数量若子类全部选中&#xff0c;除当…

神经网络鸢尾花分类

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

【超简单实用】Zotero 7 内置pdf背景颜色更改插推荐以及安装

Zotero beta7 pdf 内置颜色更换 zetore 6 很多成熟的插件在 zetore 7都不能用了。版本回退看起来内置文章的注释会被消除&#xff0c;所以又不想退回去。前几个月在找beta 7 的pdf 护眼色的插件一直没有&#xff0c;今天终于发现了&#xff01;&#xff01;&#xff01;&#…
最新文章