机器人系统ros2-开发实践07-将机器人的状态广播到 tf2(Python)

上个教程将静态坐标系广播到 tf2,基于这个基础原理这个教程将演示机器人的点位状态发布到tf2

1. 写入广播节点

我们首先创建源文件。转到learning_tf2_py我们在上一教程中创建的包。在src/learning_tf2_py/learning_tf2_py目录中输入以下命令来下载示例广播示例代码:

wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/turtle_tf2_broadcaster.py

用vc code 打开源码文件

# Copyright 2021 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.import mathfrom geometry_msgs.msg import TransformStampedimport numpy as npimport rclpy
from rclpy.node import Nodefrom tf2_ros import TransformBroadcasterfrom turtlesim.msg import Pose# This function is a stripped down version of the code in
# https://github.com/matthew-brett/transforms3d/blob/f185e866ecccb66c545559bc9f2e19cb5025e0ab/transforms3d/euler.py
# Besides simplifying it, this version also inverts the order to return x,y,z,w, which is
# the way that ROS prefers it.
def quaternion_from_euler(ai, aj, ak):ai /= 2.0aj /= 2.0ak /= 2.0ci = math.cos(ai)si = math.sin(ai)cj = math.cos(aj)sj = math.sin(aj)ck = math.cos(ak)sk = math.sin(ak)cc = ci*ckcs = ci*sksc = si*ckss = si*skq = np.empty((4, ))q[0] = cj*sc - sj*csq[1] = cj*ss + sj*ccq[2] = cj*cs - sj*scq[3] = cj*cc + sj*ssreturn qclass FramePublisher(Node):def __init__(self):super().__init__('turtle_tf2_frame_publisher')# Declare and acquire `turtlename` parameterself.turtlename = self.declare_parameter('turtlename', 'turtle').get_parameter_value().string_value# Initialize the transform broadcasterself.tf_broadcaster = TransformBroadcaster(self)# Subscribe to a turtle{1}{2}/pose topic and call handle_turtle_pose# callback function on each messageself.subscription = self.create_subscription(Pose,f'/{self.turtlename}/pose',self.handle_turtle_pose,1)self.subscription  # prevent unused variable warningdef handle_turtle_pose(self, msg):t = TransformStamped()# Read message content and assign it to# corresponding tf variablest.header.stamp = self.get_clock().now().to_msg()t.header.frame_id = 'world't.child_frame_id = self.turtlename# Turtle only exists in 2D, thus we get x and y translation# coordinates from the message and set the z coordinate to 0t.transform.translation.x = msg.xt.transform.translation.y = msg.yt.transform.translation.z = 0.0# For the same reason, turtle can only rotate around one axis# and this why we set rotation in x and y to 0 and obtain# rotation in z axis from the messageq = quaternion_from_euler(0, 0, msg.theta)t.transform.rotation.x = q[0]t.transform.rotation.y = q[1]t.transform.rotation.z = q[2]t.transform.rotation.w = q[3]# Send the transformationself.tf_broadcaster.sendTransform(t)def main():rclpy.init()node = FramePublisher()try:rclpy.spin(node)except KeyboardInterrupt:passrclpy.shutdown()

代码解释:

def quaternion_from_euler(ai, aj, ak):ai /= 2.0aj /= 2.0ak /= 2.0ci = math.cos(ai)si = math.sin(ai)cj = math.cos(aj)sj = math.sin(aj)ck = math.cos(ak)sk = math.sin(ak)cc = ci*ckcs = ci*sksc = si*ckss = si*skq = np.empty((4, ))q[0] = cj*sc - sj*csq[1] = cj*ss + sj*ccq[2] = cj*cs - sj*scq[3] = cj*cc + sj*ssreturn q

这段 Python 代码的目的是将欧拉角转换为四元数表示。
欧拉角通常以滚转(roll)、俯仰(pitch)、偏航(yaw)的形式给出,也就是代码中的 (ai, aj, ak)。这个函数首先将这些角度除以2(假设输入的角度原本是以弧度为单位),然后使用三角函数计算四元数的组成部分。

这里逐步解释代码的每个部分:

  • 角度转换为弧度:
    假设输入的角度是以弧度为单位,首先将这些角度除以2。这一步是必要的,因为四元数的计算公式需要使用半角。
  • 计算半角的三角函数值:
    ci, si, cj, sj, ck, sk 分别是半角 ai, aj, ak 的余弦和正弦值。
  • 结合三角函数结果计算四元数分量:
    根据将欧拉角转换为四元数的特定公式进行组合,该公式考虑了旋转轴的顺序。结果是一个四元数 [q0, q1, q2, q3],其中 q0 是标量部分,[q1, q2, q3] 是向量部分。
  • 返回四元数:
    返回的四元数以 numpy 数组的形式,适用于 Python 中的数值计算。

self.turtlename = self.declare_parameter('turtlename', 'turtle').get_parameter_value().string_value

定义并获取一个参数turtlename,它指定一个海龟名称,例如turtle1或turtle2。就是定义一个机器人对象


之后,节点订阅主题并对每条传入消息turtleX/pose运行函数。handle_turtle_pose

self .subscription = self.create_subscription(Pose,f'/{self.turtlename}/pose',self.handle_turtle_pose,1)

现在,我们创建一个TransformStamped对象并为其提供适当的元数据。

  1. 我们需要为正在发布的转换提供一个时间戳,并且我们只需通过调用 来用当前时间来标记它self.get_clock().now()。这将返回 所使用的当前时间Node。

  2. 然后我们需要设置我们正在创建的链接的父框架的名称,在本例中为world。

  3. 最后,我们需要设置我们正在创建的链接的子节点的名称,在本例中这是海龟本身的名称。

海龟姿势消息的处理程序函数广播该海龟的平移和旋转,并将其作为帧world到帧的变换发布turtleX。

t = TransformStamped()# Read message content and assign it to
# corresponding tf variables
t.header.stamp = self.get_clock().now().to_msg()
t.header.frame_id = 'world'
t.child_frame_id = self.turtlename

这段代码是在处理与图形界面中的“乌龟”,它使用了欧拉角到四元数的转换来处理乌龟的旋转,同时也设置了乌龟在2D空间中的位置。以下是详细解释:

设置位置坐标:
t.transform.translation.x = msg.x 和 t.transform.translation.y = msg.y:这两行代码从消息中获取乌龟在x和y轴上的位置坐标,并将其赋给变换的位置属性。
t.transform.translation.z = 0.0:由于乌龟仅存在于2D平面中,z轴的坐标设置为0。
设置旋转:
因为乌龟只能在2D空间中绕z轴旋转(即仅围绕一个轴旋转),因此旋转在x轴和y轴的分量需要设置为0。
q = quaternion_from_euler(0, 0, msg.theta):这行代码调用之前提到的函数,将欧拉角转换为四元数。由于乌龟只在一个平面上旋转,所以x和y的旋转角度为0,而z轴的旋转角度从消息中获取。
t.transform.rotation.x = q[0]、t.transform.rotation.y = q[1]、t.transform.rotation.z = q[2] 和 t.transform.rotation.w = q[3]:这些行将计算出的四元数分量赋值给旋转的相应属性。

# Turtle only exists in 2D, thus we get x and y translation
# coordinates from the message and set the z coordinate to 0
t.transform.translation.x = msg.x
t.transform.translation.y = msg.y
t.transform.translation.z = 0.0# For the same reason, turtle can only rotate around one axis
# and this why we set rotation in x and y to 0 and obtain
# rotation in z axis from the message
q = quaternion_from_euler(0, 0, msg.theta)
t.transform.rotation.x = q[0]
t.transform.rotation.y = q[1]
t.transform.rotation.z = q[2]
t.transform.rotation.w = q[3]

最后,我们将构建的转换传递给负责广播sendTransform

# Send the transformation
self.tf_broadcaster.sendTransform(t)

1.2 添加入口点

要允许命令运行您的节点,您必须将入口点添加到(位于目录中)。
更改
/home/yhg/ros2_study/src/learning_tf2_py/setup.py

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

'turtle_tf2_broadcaster = learning_tf2_py.turtle_tf2_broadcaster:main',

在这里插入图片描述


2. 编写启动文件

现在为此演示创建一个启动文件。在 learning_tf2_py下新增launch 文件夹,在launch 文件夹创建 turtle_tf2_demo.launch.py 文件

代码如下:

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='turtlesim',executable='turtlesim_node',name='sim'),Node(package='learning_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename': 'turtle1'}]),])

首先我们从和包中导入所需的模块launch_ros。应该注意的是,这launch是一个通用的启动框架(不是 ROS 2 特定的),并且launch_ros具有 ROS 2 特定的东西,比如我们在这里导入的节点。


现在我们运行节点来启动turtlesim 模拟并使用我们的节点将turtle1状态广播到tf2 。turtle_tf2_broadcaster

定义启动节点对象

Node(package='turtlesim',executable='turtlesim_node',name='sim'
),
Node(package='learning_tf2_py',executable='turtle_tf2_broadcaster',name='broadcaster1',parameters=[{'turtlename': 'turtle1'}]
),

2.2 添加依赖

导航回到learning_tf2_py目录 ,新增

package.xml使用文本编辑器打开。添加与启动文件的导入语句相对应的以下依赖项

<exec_depend>launch</exec_depend>
<exec_depend>launch_ros</exec_depend>

在这里插入图片描述

这在执行其代码时声明了额外的必需launch和launch_ros依赖项

2.3 更新setup.py

  1. 在文件顶部添加依赖
import os
from glob import glob
  1. 在data_files 中加入
 (os.path.join('share', package_name, 'launch'), glob(os.path.join('launch', '*launch.[pxy][yma]*'))),

在这里插入图片描述

3.构建

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

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

运行结果如下:在这里插入图片描述

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

colcon build --packages-select learning_tf2_py

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

. install/setup.bash

4 运行

现在运行启动文件,将启动turtlesim模拟节点和turtle_tf2_broadcaster节点:

ros2 launch learning_tf2_py turtle_tf2_demo.launch.py

在第二个终端窗口中键入以下命令:

ros2 run turtlesim turtle_teleop_key

在这里插入图片描述

现在,使用该tf2_echo工具检查海龟姿势是否确实广播到 tf2:

在这里插入图片描述
控制小乌龟移动可观察到上面数字的变动

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

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

相关文章

EXCEL数据快速上传至SAP透明表

文章目录 前言一、案例介绍/笔者需求二、备份数据三、数据处理转化 a.EXCEL转为TXT注意事项 b.EXCEL转为TXT 四、ABAP结合内表更新数据至透明表 a.代码实现 b.断点TXT上传至内表 c.查看上传结果 五、总结 前言 这篇文章…

OpenSPG docker 安装教程

文章目录 前言自述 一、OpenSPG1.介绍 二、安装步骤1.安装服务端2.客户端部署 前言 自述 我最近是想结合chatglm3-6b和知识图谱做一个垂直领域的技术规范的问答系统&#xff0c;过程中也遇到了很多困难&#xff0c;在模型微调上&#xff0c;在数据集收集整理上&#xff0c;在知…

【Qt 学习笔记】Qt常用控件 | 输入类控件 | Dial的使用及说明

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 输入类控件 | Dial的使用及说明 文章编号&#xff1a;Qt…

【intro】GraphSAGE

论文 https://arxiv.org/pdf/1706.02216 abstract 大图中节点的低维embedding已经被证明在各种预测任务中非常有用&#xff0c;然而&#xff0c;大多数现有的方法要求在embedding训练期间图中的所有节点都存在;这些先前的方法属于直推式&#xff08;transductive&#xff09…

女性名字有孤寡数,易离婚

丁老师&#xff1a;您好&#xff01;我孩子&#xff08;女孩&#xff09;准备取名&#xff1a;周小程&#xff0c;宝宝出生于阳历2016年8月13号16时30分左右&#xff0c;准备给孩子取个名字&#xff0c;在网上查询了哈&#xff0c;这个名字的分数还蛮高的&#xff0c;99分&…

Mitmproxy 抓包工具安装使用

简介 Mitmproxy是一个使用python编写的中间人代理工具&#xff0c;跟Fiddle、Charles等等的抓包工具是差不多的&#xff0c;同样可以用于拦截、修改、保存http/https请求。比起Fiddle、Charles&#xff0c;mitmproxy有一个最大的特点是支持python自定义脚本。 安装 Win 官网…

【重塑世界的火种】制造业:从匠人之心到智能未来之旅

在人类文明的宏伟乐章中&#xff0c;有一段旋律始终激昂&#xff0c;它既古老又现代&#xff0c;既是力量的象征&#xff0c;也是智慧的结晶——这就是制造业&#xff0c;一个将梦想变为现实&#xff0c;将创意铸就为生活的神奇领域。今天&#xff0c;让我们一起走进这个塑造世…

【ITK配准】第七期 尺度(Metric)- 均方Metric

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享ITK中的均方Metric,即itk::MeanSquaresImageToImageMetricv4,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力…

携手并进:OpenCSG与博云科技共同探索DevOps的AI化之路

01 DevOps AI化迫在眉睫 数字化转型的浪潮席卷全球&#xff0c;企业对于提升研发效能和软件交付质量的需求日益迫切。在这一背景下&#xff0c;AIGC的发展为DevOps带来了革命性的变化。近日&#xff0c;OpenCSG与云计算解决方案服务商博云宣布建立战略合作伙伴关系&#xff0c…

FebHost:为什么注册法国.FR域名?

注册 .FR 域名&#xff0c;意味着您的网站将主要面向法国市场。法国不仅是欧盟内购买力第二强的经济体&#xff0c;也是全球第七大经济体。值得注意的是&#xff0c;法语是29个国家的官方语言&#xff0c;使用人数约达2.7亿。一旦您拥有了 .FR 域名&#xff0c;就能向这个具有强…

C++算法题 - 二叉树层次遍历

目录 199. 二叉树的右视图637. 二叉树的层平均值102. 二叉树的层序遍历103. 二叉树的锯齿形层序遍历 199. 二叉树的右视图 LeetCode_link 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节…

Web前端三大主流框架是什么?

Web前端开发领域的三大主流框架分别是Angular、React和Vue.js。它们在Web开发领域中占据着重要的地位&#xff0c;各自拥有独特的特点和优势。 Angular Angular是一个由Google开发的前端框架&#xff0c;最初版本称为AngularJS&#xff0c;后来升级为Angular。它是一个完整的…

全面升级企业网络安全 迈入SASE新时代

随着数字化业务、云计算、物联网和人工智能等技术的飞速发展&#xff0c;企业的业务部署环境日渐多样化&#xff0c;企业数据的存储由传统的数据中心向云端和SaaS迁移。远程移动设备办公模式的普及&#xff0c;企业多分支机构的加速设立&#xff0c;也使得企业业务系统的用户范…

Redis如何保证数据一致性?

Redis如何保证数据一致性&#xff1f; Redis通常作为持久层数据库&#xff08;例如MySQL&#xff09;的缓存层&#xff0c;如果缓存或者数据库数据发生改变&#xff0c;如何保证双方的数据是一致的&#xff1f; 这其实是要分情况讨论滴&#xff0c;对数据一致性不同的要求有不…

Transformer详解:从放弃到入门(完结)

前几篇文章中&#xff0c;我们已经拆开并讲解了Transformer中的各个组件。现在我们尝试使用这些方法实现Transformer的编码器。   如图所示&#xff0c;编码器(Encoder)由N个编码器块(Encoder Block)堆叠而成&#xff0c;我们依次实现。 class EncoderBlock(nn.Module):def …

【求助】鸿蒙DevEco Studio 4.1 Release-模拟器启动方式错误

软件版本&#xff1a;DevEco Studio 4.1 Release 报错提示&#xff1a; 没有权限查看处理指导 Size on Disk 显示1.0MB 尝试方案&#xff08;统统无效&#xff09;&#xff1a; 1、“windows虚拟机监控程序平台”、"虚拟机平台"已开启 启用CPU虚拟化 2、CPU虚…

微服务项目实战-黑马头条(十三):持续集成

文章目录 项目部署_持续集成1 今日内容介绍1.1 什么是持续集成1.2 持续集成的好处1.3 今日内容 2 软件开发模式2.1 软件开发生命周期2.2 软件开发瀑布模型2.3 软件的敏捷开发 3 Jenkins安装配置3.1 Jenkins介绍3.2 Jenkins环境搭建3.2.1 Jenkins安装配置3.2.2 Jenkins插件安装3…

pymysql用法整理--python实现mysql数据库操作

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文着重整理pymsql的常用方法 不专门讲解MySQL数据库的相关知识 常用基本语法汇总 import pymysql#连接数据库 connpymysql.connect(host127.0.0.1,port3306,userroot,password123456,charsetutf8,db"expe…

【python数据分析基础】—pandas透视表和交叉表

目录 前言一、pivot_table 透视表二、crosstab 交叉表三、实际应用 前言 透视表是excel和其他数据分析软件中一种常见的数据汇总工具。它是根据一个或多个键对数据进行聚合&#xff0c;并根据行和列上的分组键将数据分配到各个矩形区域中。 一、pivot_table 透视表 pivot_tabl…

git commit后发现git pull 拉取代码失败的解决方案(致命错误:需要指定如何调和偏离的分支。)

文章目录 前言一、情况复现1.以前多人开发同一分支提交代码逻辑(下拉取后提交)2.报错 二、解决方案1. 撤销最近一次提交2.提交代码3.注意点&#xff1a;常用的 git stash 命令&#xff1a; 前言 人员张三和人员李四在同一分支&#xff08;dev&#xff09;上开发 一、情况复现 …