ROS第 13 课 TF 坐标系广播与监听的编程 实现

news2025/1/12 15:53:26

文章目录

  • 第 13 课 TF 坐标系广播与监听的编程 实现
    • 1.机器人的坐标变换
    • 2.创建功能包
    • 3.编程方法
      • 3.1 编写广播和监听程序
      • 3.2 运行程序

第 13 课 TF 坐标系广播与监听的编程 实现

1.机器人的坐标变换

在进行编程前,先需要了解机器人的坐标变换。这里以运行海龟案例来进行解说,步骤如下:

  1. 输入指令“sudo apt-get install ros-melodic-turtle-tf”,安装功能包。
    在这里插入图片描述
    其中“melodic”对应的是ROS版本。
  2. 输入指令“roslaunch turtle_tf turtle_tf_demo.launch”,启动launch文件。
    在这里插入图片描述
  3. 输入指令“rosrun turtlesim turtle_teleop_key”,运行海龟键盘控制节点。
    在这里插入图片描述
    在这里插入图片描述
  4. 输入指令“rosrun tf view_frames”,可视化框架。
    在这里插入图片描述
    在主目录下可以找到“frames.pdf”文件,如下图:
    在这里插入图片描述
    打开“frames.pdf”文件,可以看到当前系统TF坐标之间的位置关系,如下图:
    在这里插入图片描述

2.创建功能包

下面,就开始创建功能包,步骤如下:

  1. 输入指令“cd catkin_ws/src/”,回车,进入工作空间。
    在这里插入图片描述
  2. 输入指令“catkin_create_pkg tf_hiwonder rospy std_msgs”,回车,创建功能包。
    在这里插入图片描述

3.编程方法

3.1 编写广播和监听程序

  1. 打开Linux命令行终端。
  2. 输入进入功能包所在目录的指令“roscd tf_hiwonder”,并按下回车。
    在这里插入图片描述
  3. 输入指令“mkdir scripts”,并按下回车,新建用于存放Python脚本的文件夹“scripts”。
    在这里插入图片描述
  4. 输入指令“cd scripts/”,并按下回车,进入用于存放Python脚本的文件夹“scripts”。
    在这里插入图片描述
  5. 输入指令“vi turtle_tf_broadcaster.py”编辑程序,复制下面程序。如需修改,再按下“i”即可修改。修改完成,按下“Esc”,输入“:wq”保存并退出。
    在这里插入图片描述
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程监听turtlesim节点发布的乌龟位姿,并将其转换为tf转换消息广播出去

# 导入tf模块,这是ROS中用于处理转换的库
import tf
# 导入rospy,这是Python编写ROS节点的主要库
import rospy
# 导入turtlesim包的Pose消息类型
import turtlesim.msg

# 定义处理乌龟位姿消息的函数
def handle_turtle_pose(msg, turtlename):
    # 创建一个TransformBroadcaster对象,用于发送转换
    br = tf.TransformBroadcaster()
    # 发送转换,包括:
    # - 位置:根据乌龟的x、y坐标和固定的z坐标(0,因为turtlesim是2D的)
    # - 方向:将乌龟的角度转换成四元数,因为转换需要使用四元数来表示旋转
    # - 时间戳:当前的ROS时间
    # - 子坐标系:乌龟的名称
    # - 父坐标系:世界坐标系(通常称为"world")
    br.sendTransform((msg.x, msg.y, 0),
                     tf.transformations.quaternion_from_euler(0, 0, msg.theta),
                     rospy.Time.now(),
                     turtlename,
                     "world")

# 程序的主入口
if __name__ == '__main__':
    # 初始化ROS节点,名为'turtle_tf_broadcaster'
    rospy.init_node('turtle_tf_broadcaster')
    # 获取私有命名空间下的'turtle'参数,这将确定我们关注的是哪个乌龟
    turtlename = rospy.get_param('~turtle')
    # 订阅乌龟的位姿话题,这个话题名称是通过拼接乌龟的名字动态确定的
    rospy.Subscriber('/%s/pose' % turtlename,
        turtlesim.msg.Pose,
        handle_turtle_pose,
        turtlename)
    # ROS的spin循环,这将保持你的程序不会退出直到节点被明确关闭
    rospy.spin()

在这里插入图片描述
6) 输入指令“vi turtle_tf_listener.py”编辑程序,复制下面程序。如需修改,再按下“i”即可修改。修改完成,按下“Esc”,输入“:wq”保存并退出。
在这里插入图片描述

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 该例程监听turtle1的tf变换,并使turtle2向turtle1移动

# 导入所需要的模块
import roslib
import rospy
import math
import tf  # 用于处理ROS中的坐标变换
import geometry_msgs.msg  # 导入消息类型,用于发布速度
import turtlesim.srv  # 导入服务类型,用于创建新的乌龟

# 程序的主入口
if __name__ == '__main__':
    # 初始化ROS节点,名为'turtle_tf_listener'
    rospy.init_node('turtle_tf_listener')
    # 创建一个TransformListener对象,用于接收坐标变换
    listener = tf.TransformListener()
    # 等待spawn服务变得可用
    rospy.wait_for_service('spawn')
    # 创建一个服务客户端,用于调用spawn服务以生成新的乌龟
    spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
    # 调用spawn服务,在(4, 2)坐标处生成新的乌龟,角度为0,名为'turtle2'
    spawner(4, 2, 0, 'turtle2')
    
    # 创建一个发布者,用于发布turtle2的速度
    turtle_vel = rospy.Publisher('turtle2/cmd_vel', geometry_msgs.msg.Twist, queue_size=1)
    
    # 设置循环的频率为10Hz
    rate = rospy.Rate(10.0)
    while not rospy.is_shutdown():  # 当ROS没有关闭时循环执行
        try:
            # 查询turtle2到turtle1的最新变换,返回平移和旋转信息
            (trans, rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
        # 如果在查询变换时发生异常,则继续下一次循环
        except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
            continue
    
        # 根据turtle2和turtle1的相对位置计算出需要向turtle1移动的速度
        angular = 4 * math.atan2(trans[1], trans[0])  # 角速度
        linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)  # 线速度
        cmd = geometry_msgs.msg.Twist()  # 创建速度消息
        cmd.linear.x = linear  # 设置线速度
        cmd.angular.z = angular  # 设置角速度
        turtle_vel.publish(cmd)  # 发布速度消息,使turtle2向turtle1移动
    
        rate.sleep()  # 等待一段时间直到达到10Hz的循环频率

在这里插入图片描述
6) 输入指令“chmod +x turtle_tf_broadcaster.py”和“chmod +x turtle_tf_listener.py”,并按下回车,赋予文件可执行权限。
在这里插入图片描述
在这里插入图片描述
7) 输入指令“cd …”和“mkdir launch”,新建用于存放launch脚本的文件夹“launch”。
在这里插入图片描述
在这里插入图片描述
8) 输入指令“cd launch/”,并按下回车,进入用于存放Python脚本的文件夹“launch”。
在这里插入图片描述
9) 输入指令“vi start_tf_demo_py.launch”编辑程序,复制下面程序。如需修改,再按下“i”即可修改。修改完成,按下“Esc”,输入“:wq”保存并退出。
在这里插入图片描述

<launch>
	<!-- Turtlesim Node-->
	<node pkg="turtlesim" type="turtlesim_node" name="sim"/>
	<node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>
	
	<node name="turtle1_tf_broadcaster" pkg="tf_hiwonder" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
	 <param name="turtle" type="string" value="turtle1" />
	</node>
	<node name="turtle2_tf_broadcaster" pkg="tf_hiwonder" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
	 <param name="turtle" type="string" value="turtle2" /> 
	</node>
	
	 <node pkg="tf_hiwonder" type="turtle_tf_listener.py" name="listener" />
	 
</launch>

在这里插入图片描述

3.2 运行程序

  1. 输入指令“source ./devel/setup.bash”,并按下回车,设置工作环境。
    在这里插入图片描述
  2. 输入指令“roslaunch tf_hiwonder start_tf_demo_py.launch”,并按下回车,运行launch程序。
    在这里插入图片描述
    一只海龟自动行走到另一只海龟位置,显示如下图:
    在这里插入图片描述
  3. 如需终止程序,可按下快捷键“Ctrl+C”。

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

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

相关文章

洛谷-P1002-[NOIP2002 普及组]-过河卒

[NOIP2002 普及组] 过河卒 题目描述 棋盘上 A A A 点有一个过河卒&#xff0c;需要走到目标 B B B 点。卒行走的规则&#xff1a;可以向下、或者向右。同时在棋盘上 C C C 点有一个对方的马&#xff0c;该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为…

代码随想录第十八天 513 找树左下角的值 112 路径之和 106 从中序与后序遍历序列构造二叉树

LeetCode 513 找树左下角的值 题目描述 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出: 7 思路 1.确定递…

多级缓存

一、多级缓存 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;如图&#xff1a; 存在下面的问题&#xff1a; •请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈 •Redis缓存失效时&#xff…

打折:阿里云国外服务器价格购买优惠活动

阿里云国外服务器优惠活动「全球云服务器精选特惠」&#xff0c;国外服务器租用价格24元一个月起&#xff0c;免备案适合搭建网站&#xff0c;部署独立站等业务场景&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云国外服务器优惠活动&#xff1a; 全球云服务器精选特惠…

77. 组合 - 力扣(LeetCode)

题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 输入示例 n 4, k 2输出示例 [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ]解题思路 我们使用回溯、深度优先遍历的思想&#xff0c;我们使用一个栈 path…

linux驱动(八):block,net

本文主要探讨210的block驱动和net驱动。 block 随机存取设备且读写是按块进行,缓冲区用于暂存数据,达条件后一次性写入设备或读到缓冲区 块设备与字符设备:同一设备支持块和字符访问策略,块设备驱动层支持缓冲区,字符设备驱动层没有缓冲 块设备单位:扇…

Leetcode的AC指南 —— 栈与队列:20. 有效的括号

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列&#xff1a;20. 有效的括号 **。题目介绍&#xff1a;给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字…

基于JavaWeb+SSM+Vue智能社区服务小程序系统的设计和实现

基于JavaWebSSMVue智能社区服务小程序系统的设计和实现 滑到文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 滑到文末获取源码 Lun文目录 目录 1系统概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系统设计思想 1 2相…

【计算机硬件】4、练习题

根据冯诺依曼原理&#xff0c;计算机硬件的基本组成是&#xff08;&#xff09; A.输入、输出设备、运算器、控制器、存储器 B.磁盘、软盘、内存、CPU、显示 C.打印机、触摸屏、键盘、软盘 D.鼠标、打印机、主机、显示器、存储器 CPU执行算术运算或者逻辑运算时&#xff0c;常…

class_14:继承

C继承有点类似于c语言 结构体套用 #include <iostream> #include <string> using namespace std;//基类,父类 class Vehicle{ public:string type;string contry;string color;double price;int numOfWheel;void run();void stop(); };//派生类&#xff0c…

Python基础第五篇(Python数据容器)

文章目录 一、数据容器入门二、数据容器 list 列表(1),list 列表定义(2),list列表的索引(3),list列表的常见操作(4),list列表的遍历 三、数据容器&#xff1a;tuple&#xff08;元组&#xff09;(1),tuple元组定义(2),tuple元组的索引(3),tuple元组的常见操作(4),tuple元组的遍…

力扣【四数之和】

一、题目描述 18. 四数之和 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#x…

PyQt5 快速入门(一)

第一节按钮控件,文本控件,输入框,app图标 文章目录 一.GUI按钮控件 二.文本控件 三.输入框 四.让窗口显示在屏幕中央 五.让窗口显示在屏幕中央 总结 一.GUI按钮控件 import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButtonif __name__ __main__:app …

python爬虫知识点:5种线程锁

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 线程安全 线程安全是多线程或多进程编程中的一个概念&#xff0c;在拥有共享数据的多条线程并行执行的程序中&#xff0c;线程安全的代码会通过同步机制保证各个…

Python使用graphviz绘制模块间数据流

graphviz官方参考链接&#xff1a; http://www.graphviz.org/documentation/ https://graphviz.readthedocs.io/en/stable/index.html 文章目录 需求描述环境配置实现思路代码实现 需求描述 根据各模块之间的传参关系绘制出数据流&#xff0c;如下图所示&#xff1a; 并且生成…

Redis(01)——常用指令

基础指令 select 数字&#xff1a;切换到其他数据库flushdb&#xff1a;清空当前数据库flushall&#xff1a;清空所有数据库dbsize&#xff1a;查看数据库大小exists key1[key2 …]&#xff1a;判断当前的key是否存在keys *&#xff1a;查看所有的keyexpire key 时间&#xff…

深入Matplotlib:画布分区与高级图形展示【第33篇—python:Matplotlib】

文章目录 Matplotlib画布分区技术详解引言方法一&#xff1a;plt.subplot()方法二&#xff1a;简略写法方法三&#xff1a;plt.subplots()实例展示添加更多元素 进一步探索Matplotlib画布分区自定义子图布局3D子图结语 Matplotlib画布分区技术详解 引言 Matplotlib是一个强大…

第13节-简历中的开放性问题

(点击即可收听) 不少公司的开放式题目每年不会有太大的变化&#xff0c;所以在答题前可先去相关求职论坛看看这些公司往年的问题&#xff0c;分析和思考自己应当怎么回答 开放式问题回答技巧 开放式问题主要考察的是求职者的求职动机、解决问题的能力、创造力等软实力&#xff…

C++入门之基础语法

目录 一.关键字 二.命名空间 2.1命名空间域 2.2展开命名空间域 using namespace bit 使用using将命名空间中的某个成员引入 2.3 头文件#include 2.3.1 头文件的展开和命名空间的展开区别 2.4 C的标准的库命名空间std 2.5 命名空间的套娃 三. C输入输出 3.1 流插入co…

线性代数:逆矩阵

目录 伴随阵 逆矩阵 证明&#xff1a;AA* A*A |A|E 证明&#xff1a;|A| 0 > |A*| 0 伴随阵 逆矩阵 证明&#xff1a;AA* A*A |A|E 证明&#xff1a;|A| 0 > |A*| 0