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

devtools/2024/10/18 17:39:51/

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

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.ppmy.cn/devtools/35849.html

相关文章

go语言并发实战——日志收集系统(十一)基于etcd来监视配置文件的变化

前言 在我们实际生产中,我们常常因为新的项目或者新的功能进而要对配置文件进行修改,但是在生产环境下我们不是每次配置文件发生变化都重启一次系统,这无疑是不切实际的,所以我们需要对配置文件进行实时监控,而今天我们所要展示的也就是如何…

2024年03月 Scratch 图形化(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、单选题(共10题,共30分) 第1题 圆点角色的程序如下图1所示(角色默认方向90),运行程序,输入“HLHLHLHL”后得到的结果如下图2所示,如果想得到下图3中的结果,应该输入的字符串是?( ) A:HLLLHLLL B:LLLLLLL…

测试环境搭建:JDK+Tomcat+Mysql+Redis

基础的测试环境搭建: LAMPLinux(CentOS、ubuntu、redhat)ApacheMysqlPHP LTMJLinux(CentOS、ubuntu、redhat)TomcatMysql(Oracle)RedisJava 真实的测试环境搭建:(企业真实的运维) 基于SpringBoot(SpringCloud分布式微…

git使用注意事项事项

以下操作均在gitee平台上实现 文章目录 1、本地仓库和远程仓库有冲突2、git提交自动忽略某些文件3、git无法push提交到远程仓库 1、本地仓库和远程仓库有冲突 在web端修改了文件内容或者删除了文件,本地仓库需要重新把远程仓库拉取到本地,或者强制提交到…

sqlalchemy 分表实现方案

1.需求及场景概述 现有系统中因历史数据量过大,产生了将历史数据进行按月存储的要求,系统和数据库交互使用的是sqlalchemy,假设系统的原来的历史记录表(record)如下: 为了将历史数据按月分表存储&#xff0…

社区养老服务|基于Springboot+vue的社区养老服务平台设计与实现(源码+数据库+文档)

社区养老服务平台 目录 基于Java的社区养老服务平台设计与实现 一、前言 二、系统设计 三、系统功能设计 1用户信息管理 2 服务信息管理 3服务申请管理 4公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#…

入侵检测与网络欺骗

目录 前言 1. 入侵检测系统(IDS)概述 1.1 定义 1.2 通用模型 传感器(Sensors) 分析引擎(Analysis Engine) 响应模块(Response Module) 1.3 分类 特征检测(Signature-…

<网络安全>《76 概念讲解<第十课 物联网常用协议-网络层协议>》

协议简称全称名称内容说明IPv4互联网通信协议第四版IPv4是互联网的核心IPv6互联网协议第6版TCPTransmission Control Protocol传输控制协议TCP旨在适应支持多网络应用的分层协议层次结构。连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务…