机器人系统ros2-开发实践05-将静态坐标系广播到 tf2(Python)-定义机器人底座与其传感器或非移动部件之间的关系

发布静态变换对于定义机器人底座与其传感器或非移动部件之间的关系非常有用。例如,最容易推断激光扫描仪中心框架中的激光扫描测量结果。

1. 创建包

首先,我们将创建一个用于本教程和后续教程的包。调用的包learning_tf2_py将依赖于geometry_msgs、python3-numpy、rclpy、tf2_ros_py和turtlesim

cd ros2_study/src
ros2 pkg create --build-type ament_python --license Apache-2.0 -- learning_tf2_py

learning_tf2_py您的终端将返回一条消息,验证您的包及其所有必需文件和文件夹的创建。

在这里插入图片描述

2 编写静态广播节点

我们首先创建源文件。在src/learning_tf2_py/learning_tf2_py目录中输入以下命令来下载示例静态广播器代码:

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

这个有点慢,可能要等一会才下好

下载后可查看:

在这里插入图片描述

static_turtle_tf2_broadcaster.py 代码内容如下:

import math
import sysfrom geometry_msgs.msg import TransformStampedimport numpy as npimport rclpy
from rclpy.node import Nodefrom tf2_ros.static_transform_broadcaster import StaticTransformBroadcasterdef 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 StaticFramePublisher(Node):"""Broadcast transforms that never change.This example publishes transforms from `world` to a static turtle frame.The transforms are only published once at startup, and are constant for alltime."""def __init__(self, transformation):super().__init__('static_turtle_tf2_broadcaster')self.tf_static_broadcaster = StaticTransformBroadcaster(self)# Publish static transforms once at startupself.make_transforms(transformation)def make_transforms(self, transformation):t = TransformStamped()t.header.stamp = self.get_clock().now().to_msg()t.header.frame_id = 'world't.child_frame_id = transformation[1]t.transform.translation.x = float(transformation[2])t.transform.translation.y = float(transformation[3])t.transform.translation.z = float(transformation[4])quat = quaternion_from_euler(float(transformation[5]), float(transformation[6]), float(transformation[7]))t.transform.rotation.x = quat[0]t.transform.rotation.y = quat[1]t.transform.rotation.z = quat[2]t.transform.rotation.w = quat[3]self.tf_static_broadcaster.sendTransform(t)def main():logger = rclpy.logging.get_logger('logger')# obtain parameters from command line argumentsif len(sys.argv) != 8:logger.info('Invalid number of parameters. Usage: \n''$ ros2 run learning_tf2_py static_turtle_tf2_broadcaster''child_frame_name x y z roll pitch yaw')sys.exit(1)if sys.argv[1] == 'world':logger.info('Your static turtle name cannot be "world"')sys.exit(2)# pass parameters and initialize noderclpy.init()node = StaticFramePublisher(sys.argv)try:rclpy.spin(node)except KeyboardInterrupt:passrclpy.shutdown()

2.1 代码解析:

第一行导入所需的包。首先,我们TransformStamped从导入geometry_msgs,它为我们将发布到转换树的消息提供了一个模板。

from geometry_msgs.msg import TransformStamped

然后rclpy导入,以便Node可以使用它的类。

import rclpy
from rclpy.node import Node

该tf2_ros包提供了一个StaticTransformBroadcaster使静态转换发布变得容易的方法。要使用StaticTransformBroadcaster,我们需要从tf2_ros模块导入它。

from tf2_ros.static_transform_broadcaster import StaticTransformBroadcaster

StaticFramePublisher构造函数用 name 初始化节点static_turtle_tf2_broadcaster。然后StaticTransformBroadcaster创建 ,它将在启动时发送一个静态转换。

    def __init__(self, transformation):super().__init__('static_turtle_tf2_broadcaster')self.tf_static_broadcaster = StaticTransformBroadcaster(self)# Publish static transforms once at startupself.make_transforms(transformation)

在这里,我们创建一个TransformStamped对象,这将是我们在填充后发送的消息。在传递实际的转换值之前,我们需要为其提供适当的元数据。


  • 我们需要给正在发布的转换一个时间戳,我们只需用当前时间来标记它,self.get_clock().now()
t.header.stamp = self.get_clock().now().to_msg()
  • 然后我们需要设置我们正在创建的链接的父框架的名称
t.header.frame_id = 'world'
  • 最后,我们需要设置我们正在创建的链接的子框架的名称
t.child_frame_id = transformation[1]

在这里,我们填充海龟的 6D 姿势(平移和旋转)。

t.transform.translation.x = float(transformation[2])
t.transform.translation.y = float(transformation[3])
t.transform.translation.z = float(transformation[4])
quat = quaternion_from_euler(float(transformation[5]), float(transformation[6]), float(transformation[7]))t.transform.rotation.x = quat[0]
t.transform.rotation.y = quat[1]
t.transform.rotation.z = quat[2]
t.transform.rotation.w = quat[3]

最后,我们使用该sendTransform()函数广播静态变换。

self.tf_static_broadcaster.sendTransform(t)

2.2 更新package.xml

3.构建编译

最好rosdep在构建之前在工作区的根目录中运行以检查缺少的依赖项:

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

在这里插入图片描述

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

colcon build --packages-select learning_tf2_py

在这里插入图片描述
打开一个新终端,导航到工作区的根目录,然后获取安装文件:

. install/setup.bash

在这里插入图片描述

4. 运行

现在运行static_turtle_tf2_broadcaster节点:

ros2 run learning_tf2_py static_turtle_tf2_broadcaster mystaticturtle 0 0 1 0 0 0

这设置了海龟姿势广播,使其mystaticturtle漂浮在距地面 1 米的高度。

tf_static我们现在可以通过回显主题来检查静态转换是否已发布

ros2 topic echo /tf_static

如果一切顺利你应该看到一个静态转换

transforms:
- header:stamp:sec: 1622908754nanosec: 208515730frame_id: world
child_frame_id: mystaticturtle
transform:translation:x: 0.0y: 0.0z: 1.0rotation:x: 0.0y: 0.0z: 0.0w: 1.0

上面代码展示如何StaticTransformBroadcaster用于发布静态转换的原理。在实际的开发过程中,您不必自己编写此代码,而应该使用专用tf2_ros工具来执行此操作。 tf2_ros提供了一个名为 的可执行文件static_transform_publisher,可以用作命令行工具或可以添加到启动文件中的节点来使用

例如:

使用以米为单位的 x/y/z 偏移和以弧度为单位的横滚/俯仰/偏航将静态坐标变换发布到 tf2。在我们的例子中,横滚/俯仰/偏航分别指的是绕 x/y/z 轴的旋转。

ros2 run tf2_ros static_transform_publisher --x x --y y --z z --yaw yaw --pitch pitch --roll roll --frame-id frame_id --child-frame-id child_frame_id

使用以米和四元数为单位的 x/y/z 偏移量将静态坐标变换发布到 tf2。

ros2 run tf2_ros static_transform_publisher --x x --y y --z z --qx qx --qy qy --qz qz --qw qw --frame-id frame_id --child-frame-id child_frame_id

static_transform_publisher被设计为手动使用的命令行工具,以及在launch文件中使用以设置静态转换

例如:

from launch import LaunchDescription
from launch_ros.actions import Nodedef generate_launch_description():return LaunchDescription([Node(package='tf2_ros',executable='static_transform_publisher',arguments = ['--x', '0', '--y', '0', '--z', '1', '--yaw', '0', '--pitch', '0', '--roll', '0', '--frame-id', 'world', '--child-frame-id', 'mystaticturtle']),])

请注意,除了–frame-id和之外的所有参数–child-frame-id都是可选的

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蛋白质/聚合物防污的机器学习(材料基因组计划)

前言:对于采用机器学习去研究聚合物的防污性能,以及或者其他性质。目前根据我的了解我认为最困难的点有三条: 其一:数据,对于将要训练的数据必须要有三点要求,1.数据要多,也就是大数据&#xff…

设置定位坐标+请按任意键继续

设置定位坐标 目的 在编程和游戏开发中,设置定位坐标的目的是为了确定对象在屏幕或游戏世界中的具体位置。坐标通常由一对数值表示,例如 (x, y),其中 x 表示水平位置,y 表示垂直位置。设置定位坐标的目的包括: 1. **精…

jquery项目 html使用export import方式调用模块

jquery的老项目,引入vue3, 需要方便使用export, import方式引用一些常用的方法与常量 导出模块 export js/numberUtil.js /*** Description:* Author Lani* date 2024/1/10*//* * 【金额】 保留2位小数,不四舍五入 * 5.992550 >5.99 , 2 > 2.…

Vue3 动态引入图片: require is not defined报错

问题&#xff1a;在 Vue3 项目中&#xff0c;使用 require 引入图片&#xff0c;报错 require is not defined 原因&#xff1a; Vue3 使用的是 vite&#xff0c;而 require 是 Webpack 的方法。 官网说明&#xff1a; 解决代码&#xff1a; <template><div v-fo…

ElasticSearch知识点汇总

1、ES中的​​​​​​​倒排索引是什么。 倒排索引&#xff0c;是通过分词策略&#xff0c;形成了词和文章的映射关系表&#xff0c;这种词典映射表即为倒排索引 2、ES是如何实现master选举的。 选举过程主要包括以下几个步骤&#xff1a; 心跳检测&#xff1a; 每个节点…

websevere服务器从零搭建到上线(四)|muduo网络库的基本原理和使用

文章目录 muduo源码编译安装muduo框架讲解muduo库编写服务器代码示例代码解析用户连接的创建和断开回调函数用户读写事件回调 使用vscode编译程序配置c_cpp_properties.json配置tasks.json配置launch.json编译 总结 muduo源码编译安装 muduo依赖Boost库&#xff0c;所以我们应…

webstorm 常用插件

安装插件步骤&#xff1a; 打开软件&#xff0c;文件 -- 设置-- 插件 -- 输入插件名称 -- 安装 代码截图: code screenShots 先选中代码&#xff0c;按 ctrl shift alt a&#xff0c;就可截取选中的代码颜色注释: comments highlighter 对注释的文字改变颜色高亮成对符号: h…

Redis开源社区持续壮大,华为云为Valkey项目注入新的活力

背景 今年3月21日&#xff0c;Redis Labs宣布从Redis 7.4版本开始&#xff0c;将原先比较宽松的BSD源码使用协议修改为RSAv2和SSPLv1协议&#xff0c;意味着 Redis在OSI&#xff08;开放源代码促进会&#xff09;定义下不再是严格的开源产品。Redis官方表示&#xff0c;开发者…

[Docker]容器的网络类型以及云计算

目录 知识梗概 1、常用命令2 2、容器的网络类型 3、云计算 4、云计算服务的几种主要模式 知识梗概 1、常用命令2 上一篇已经学了一些常用的命令&#xff0c;这里补充两个&#xff1a; 导出镜像文件&#xff1a;[rootdocker ~]# docker save -o nginx.tar nginx:laster 导…

Codeforces Round 943 (Div. 3) C-G

C. Assembly via Remainders 思路&#xff1a; 我们可以注意到&#xff0c;数组的长度只有 500 500 500 &#xff0c;并且每个数的大小都在 500 500 500 以内&#xff0c;再看向这题&#xff0c;容易知道&#xff0c;当第一个数确定之后&#xff0c;之后所有的数字都会确定下…

力扣:63. 不同路径 II

63. 不同路径 II 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物。那么…

延时任务通知服务的设计及实现(五)-- Netty时间轮HashedWheelTimer

一、背景 前文我们讲述了如何使用redisson的RDelayedQueue以及JDK的DelayQueue实现延迟队列&#xff0c;本文将补充一种实现延迟队列的方式–Netty的时间轮HashedWheelTimer。 它和JDK的DelayQueue一样&#xff0c;都存在着以下问题&#xff1a; 占jvm内存&#xff0c;数据量…