机器人系统ros2-开发实践09-如何向 tf2 添加额外的坐标帧位置(Python)

在之前的教程中,我们通过编写tf2 广播器和tf2 监听器重新创建了乌龟演示。本教程将教您如何向转换树添加额外的固定和动态框架。事实上,在 tf2 中添加框架与创建 tf2 广播器非常相似,但此示例将向您展示 tf2 的一些附加功能。

对于许多与转换相关的任务,在局部框架内思考会更容易。例如,最容易推断激光扫描仪中心框架中的激光扫描测量结果。 tf2 允许您为系统中的每个传感器、链路或关节定义本地框架。从一帧转换到另一帧时,tf2 将处理引入的所有隐藏中间帧转换。

tf2树

tf2 建立了帧的树结构,因此不允许帧结构中出现闭环。这意味着一个框架只有一个父框架,但可以有多个子框架。目前,我们的 tf2 树包含三个帧:world、turtle1和turtle2。两个海龟框架是该world框架的子框架。如果我们想向 tf2 添加一个新框架,则现有的三个框架之一需要作为父框架,而新框架将成为其子框架。
在这里插入图片描述

比如在机械臂形态的机器人中,机器人安装的位置叫做基坐标系Base Frame,机器人安装位置在外部环境下的参考系叫做世界坐标系World Frame,机器人末端夹爪的位置叫做工具坐标系,外部被操作物体的位置叫做工件坐标系,在机械臂抓取外部物体的过程中,这些坐标系之间的关系也在跟随变化。

在这里插入图片描述
在移动机器人系统中,坐标系一样至关重要,比如一个移动机器人的中心点是基坐标系Base Link,雷达所在的位置叫做雷达坐标系laser link,机器人要移动,里程计会累积位置,这个位置的参考系叫做里程计坐标系odom,里程计又会有累积误差和漂移,绝对位置的参考系叫做地图坐标系map。
在这里插入图片描述

一层一层坐标系之间关系复杂,有一些是相对固定的,也有一些是不断变化的,看似简单的坐标系也在空间范围内变得复杂,良好的坐标系管理系统就显得格外重要。

在这里插入图片描述
关于坐标系变换关系的基本理论,在每一本机器人学的教材中都会有讲解,可以分解为平移和旋转两个部分,通过一个四乘四的矩阵进行描述,在空间中画出坐标系,那两者之间的变换关系,其实就是向量的数学描述。

1 编写固定帧广播器

在我们的海龟示例中,我们将添加一个新框架carrot1,它将成为turtle1.该框架将作为第二只乌龟的目标。

我们首先创建源文件。转到learning_tf2_py 我们在之前的教程中创建的包。在src/learning_tf2_py/learning_tf2_py目录中新建fixed_frame_tf2_broadcaster.py文件,然后用vccode 打开写入如下代码:

from geometry_msgs.msg import TransformStamped

import rclpy
from rclpy.node import Node

from tf2_ros import TransformBroadcaster


class FixedFrameBroadcaster(Node):

   def __init__(self):
       super().__init__('fixed_frame_tf2_broadcaster')
       self.tf_broadcaster = TransformBroadcaster(self)
       self.timer = self.create_timer(0.1, self.broadcast_timer_callback)

   def broadcast_timer_callback(self):
       t = TransformStamped()

       t.header.stamp = self.get_clock().now().to_msg()
       t.header.frame_id = 'turtle1'
       t.child_frame_id = 'carrot1'
       t.transform.translation.x = 0.0
       t.transform.translation.y = 2.0
       t.transform.translation.z = 0.0
       t.transform.rotation.x = 0.0
       t.transform.rotation.y = 0.0
       t.transform.rotation.z = 0.0
       t.transform.rotation.w = 1.0

       self.tf_broadcaster.sendTransform(t)


def main():
    rclpy.init()
    node = FixedFrameBroadcaster()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass

    rclpy.shutdown()

上面关键代码说明:

在这里,我们创建一个新的转换,从父级turtle1到新的子级carrot1。就框架而言,框架carrot1在 y 轴上偏移 2 米turtle1。

t = TransformStamped()

t.header.stamp = self.get_clock().now().to_msg()
t.header.frame_id = 'turtle1'
t.child_frame_id = 'carrot1'
t.transform.translation.x = 0.0
t.transform.translation.y = 2.0
t.transform.translation.z = 0.0

添加节点入口:

在src/learning_tf2_py,用vscode 打开setup.py

在console_scripts 括号之间添加以下行’:

'fixed_frame_tf2_broadcaster = learning_tf2_py.fixed_frame_tf2_broadcaster:main',

在这里插入图片描述

编写启动文件

src/learning_tf2_py/launch目录中创建一个名为的新文件turtle_tf2_fixed_frame_demo.launch.py,代码内容如下:

import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource

from launch_ros.actions import Node


def generate_launch_description():
    demo_nodes = IncludeLaunchDescription(
        PythonLaunchDescriptionSource([os.path.join(
            get_package_share_directory('learning_tf2_py'), 'launch'),
            '/turtle_tf2_demo.launch.py']),
        )

    return LaunchDescription([
        demo_nodes,
        Node(
            package='learning_tf2_py',
            executable='fixed_frame_tf2_broadcaster',
            name='fixed_broadcaster',
        ),
    ])

此启动文件导入所需的包,然后创建一个demo_nodes变量来存储我们在上一教程的启动文件中创建的节点。

代码的最后一部分将carrot1使用我们的节点将我们的固定框架添加到turtlesim世界中fixed_frame_tf2_broadcaster。

Node(
    package='learning_tf2_py',
    executable='fixed_frame_tf2_broadcaster',
    name='fixed_broadcaster',
),

编译:

在工作区的根目录中运行rosdep以检查是否缺少依赖项。

rosdep install -i --from-path src --rosdistro humble -y

仍然在工作区的根目录中构建您的包:

colcon build --packages-select learning_tf2_py

打开一个新终端,导航到工作区的根目录,然后获取安装文件:

. install/setup.bash

运行

现在您可以启动海龟广播演示:

ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo.launch.py

这里跟上面教程一样,初始化两个乌龟,其中一个乌龟会向另外一个乌龟靠齐

在这里插入图片描述
新carrot1框架出现在转换树中

在这里插入图片描述
如果你驾驶第一只乌龟,你应该注意到,即使我们添加了一个新框架,其行为与之前的教程相比并没有改变。这是因为添加额外的帧不会影响其他帧,并且我们的侦听器仍在使用之前定义的帧。

因此,如果我们希望第二只乌龟而不是第一只乌龟跟随胡萝卜,我们需要更改 的值target_frame。这可以通过两种方式完成。一种方法是target_frame直接从控制台将参数传递给启动文件:

ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo.launch.py target_frame:=carrot1

在这里插入图片描述

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

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

相关文章

音频数字信号I2S一些知识理解

(1)I2S单向基本传输需要几根线传输音频信号? 3根线 LRCK SCLK(也叫BLK) DATA(单向) (2)如何理解I2S MASTER或者SLAVE的模式? codec的i2s作为slave mode,LRCK和SCLK来自于soc主控端,codec端自动检测MCLK和LRCK codec的i2s作为master mode,codec通过MCLK LRCLKDIV…

Java String转JSONObject时保持字段顺序不变

Java String转JSONObject时保持字段顺序不变 问题背景解决方案 问题背景 在业务接口开发过程中,有一个新增接口,需要支持批量新增数据,这时入参就需要用到 json 格式数据,且包含 list 集合,比如这样的数据格式&#x…

计算机视觉中的计算几何

计算几何领域出现于 20 世纪 70 年代,研究解决几何问题的数据结构和算法。这尤其包括确定图像内的拓扑结构,或者实际上是更高维的表示,例如点邻域,这可以帮助从数字图像数据等中导出几何意义[1]。 计算机视觉主要涉及静态或动态图…

Redis数据结构-Dict

1.3 Redis数据结构-Dict 我们知道Redis是一个键值型(Key-Value Pair)的数据库,我们可以根据键实现快速的增删改查。而键与值的映射关系正是通过Dict来实现的。 Dict由三部分组成,分别是:哈希表(DictHashTa…

[muduo网络库]——muduo库三大核心组件之 Poller/EpollPoller类(剖析muduo网络库核心部分、设计思想)

接着上文,[muduo网络库]——muduo库三大核心组件之Channel类(剖析muduo网络库核心部分、设计思想),本章我们来学习muduo网络库中第二大核心组件Poller/EpollPoller类。 先回顾一下三大核心组件之间的关系。 接着我们进入正题。 P…

什么是Meme币?——区块链技术的加密货币

Meme代币是一种基于区块链技术的加密货币,旨在为用户提供一种简单、有趣且易于传播的方式来进行数字资产交易和投资。Meme代币通常与特定的主题或故事相关联,通过社交媒体等渠道进行传播和推广,吸引更多的用户参与并增加其价值。 Meme代币的…

提升SEO排名!SSL证书对SEO效果的积极影响

搜索引擎优化(SEO)作为提升网站可见度和吸引有机流量的关键策略,其规则与标准也在不断进化以适应这些变化。其中,安装SSL证书对SEO效果产生的正面影响尤为显著。以下是关于安装SSL证书如何促进SEO效果的详细分析。 一、搜索引擎的…

【Ajax零基础教程】-----第四课 简单实现

一、XMLHttpRequest对象 通过XMLHttpRequest对象来向服务器发送异步请求,从服务器获取数据。然后用JavaScript来操作DOM而更新页面。XMLHttpRequest是ajax的核心机制,它是IE5中首先引入的,是一种支持异步请求的技术。 简单的说,也…

【python量化交易】qteasy使用教程05——创建第一个自定义交易策略

创建第一个自定义交易策略 使用qteasy创建自定义交易策略开始前的准备工作本节的目标自定义策略的实现方法使用 qteasy 的 Strategy 策略类三种不同的自定义策略基类定义一个双均线择时交易策略定义策略运行时机定义策略需要的数据自定义交易策略的实现:realize()获…

SwiftUI 调整视图内容周围间隙(Content Margins)的“时髦”方法

概述 在 SwiftUI 开发的应用中,往往在小屏设备(比如 iPhone)上布局良好的 App 放到大屏(iPad)上后就会“一塌糊涂”。因为它们一味的只想着“占据”却不知道“舍弃”。 从 iOS 17.0(iPad 17.0)开始苹果提供了原生的视图修改器方法专注于处理此事。 在本篇博文中,您将…

pyqt 工具栏QToolBar控件

pyqt 工具栏QToolBar控件 QToolBar控件介绍效果代码 QToolBar控件介绍 QToolBar 是 PyQt(中的一个控件,它提供了一个工具栏,通常包含一系列的工具按钮或下拉菜单,用于提供对应用程序功能的快速访问。 QToolBar 通常与 QMainWind…

霍金《时间简史 A Brief History of Time》书后索引(E--H)

A–D部分见:霍金《时间简史 A Brief History of Time》书后索引(A–D) 图源:Wikipedia INDEX E Earth: circumference, motion, shape Eclipses Eddington, Arthur Einstein, Albert: biography, see also Relativity; Special…

hadoop大数据的一些知识点--Map reduce编程

实验4 MapReduce编程(2) 本实验的知识地图如图4-1所示( 表示重点 表示难点)。 图4-1 实验4MapReduce编程(2)知识地图 一、实验目的 1. 理解YARN体系架构。 2. 熟练掌握YARN Web UI界面的使用。 3. 掌握YARN Shell常用命令的使用。 4. 了解YARN编程之…

Linux 第二十七章

🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…

前端本地调试云效上Vue项目的构建产物

一、问题背景 前两天前端小伙伴,在云效上构建了一个前端项目,构建结果显示成功,访问后发现Console控制台报错:ReferenceError: defineComponent is not defined 在此之前的版本,构建和访问并没有此异常,而…

HNU操作系统小班讨论-Windows、Linux文件系统

【题目描述】 叙述Windows、Linux文件系统的演化,比较他们的优劣 【PPT展示】

(Java)心得:LeetCode——15.三数之和

一、原题 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组。…

【网络安全】一次sql注入问题的处理

目录 问题 10.60.100.194,修改之前 修改方案 问题解决 测试过程 问题思考与总结 问题 一次sql注入问题的筛查报告,主要是sql注入的问题资源-CSDN文库 doc-new\20-设计文档\34-Mesh设备管理\100-网络安全 10.60.100.194,修改之前 修改…

springboot如何查看版本号之间的相互依赖

第一种: 查看本地项目maven的依赖: ctrl鼠标左键:按下去可以进入maven的下一层: ctrl鼠标左键:按下去可以进入maven的再下一层: 就可以查看springboot的一些依赖版本号了; 第二种: 还…

ssrf学习2——内网ip绕过

环回地址绕过 尝试访问内网 也就是127.0.0.1里面的flag.php 但是如果真的去访问127.0.0.1/flag.php 还是不行 也就是说127.0.0.1被过滤了 进制转换 127.0.0.1是点分十进制 可以用二进制八进制十六进制来绕过过滤 0x7F000001/flag.php 017700000001/flag.php(八进制前面是…