什么是 TF2
在 ROS 2(Robot Operating System 2)中,TF2(Transform 2)是一个非常重要的工具,用于处理机器人中不同坐标系之间的变换关系。它允许开发者轻松地管理、查询和广播坐标系之间的相对位置和姿态。
-
坐标系(Frames)
- 坐标系是 TF2 的核心概念之一。每个坐标系都有一个唯一的名称,例如“base_link”(机器人位置)、“camera_link”(相机位置)、“odom”(里程计坐标系)等。这些名称用于标识机器人或环境中的不同部分。
-
变换(Transforms)
- 变换是两个坐标系之间的相对位置和姿态关系。变换通常用一个 的齐次变换矩阵表示,也可以用四元数和平移向量表示。TF2 使用这些变换来计算不同坐标系之间的相对位置和姿态。
-
广播(Broadcasting)
- 广播是指将一个坐标系相对于另一个坐标系的变换关系发送到 TF2 系统中。通常,一个节点会定期广播它所知道的变换关系。例如,一个 IMU(惯性测量单元)节点可能会广播从“base_link”到“imu_link”的变换。
- 内容:
- 位置:xyz
- 姿态:欧拉角 zyx / 四元数
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import TransformStamped
from tf2_ros import TransformBroadcaster
class FramePublisher(Node):
def __init__(self):
super().__init__('frame_publisher')
self.tf_broadcaster = TransformBroadcaster(self)
self.timer = self.create_timer(0.1, self.broadcast_transform)
def broadcast_transform(self):
t = TransformStamped() # 详见5.时间戳
t.header.stamp = self.get_clock().now().to_msg()
t.header.frame_id = 'base_link' # 参考坐标系
t.child_frame_id = 'camera_link' # 目标坐标系
t.transform.translation.x = 0.1
t.transform.translation.y = 0.2
t.transform.translation.z = 0.3
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(args=None):
rclpy.init(args=args)
frame_publisher = FramePublisher()
rclpy.spin(frame_publisher)
frame_publisher.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()- 查询(Querying)
- 查询是指从 TF2 系统中获取两个坐标系之间的变换关系。一个节点可以通过查询来获取它需要的变换关系,从而将数据从一个坐标系转换到另一个坐标系。例如,一个视觉处理节点可能需要将相机数据从“camera_link”转换到“base_link”。
TransformListener的职责是监听TF2系统中的变换信息,并将这些信息存储到Buffer中;TransformListener在定义时自动启动。
import rclpy
from rclpy.node import Node
from tf2_ros import Buffer, TransformListener
class FrameListener(Node):
def __init__(self):
super().__init__('frame_listener')
self.tf_buffer = Buffer()
self.tf_listener = TransformListener(self.tf_buffer)
self.timer = self.create_timer(1.0, self.lookup_transform)
def lookup_transform(self):
try:
trans = self.tf_buffer.lookup_transform(
'base_link', 'camera_link', rclpy.time.Time())
self.get_logger().info(
f'Transform from base_link to camera_link: {trans}')
except Exception as e:
self.get_logger().info(f'Lookup failed: {e}')
def main(args=None):
rclpy.init(args=args)
frame_listener = FrameListener()
rclpy.spin(frame_listener)
frame_listener.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()-
时间戳(Timestamps)
- TF2 中的变换是时间戳化的,这意味着每个变换都有一个时间戳,表示该变换在特定时间点的有效性。这使得 TF2 能够处理动态变换,例如机器人在移动时的坐标系变换。
- 内容:
- 父坐标系名称
- 子坐标系名称
- 父坐标系和子坐标系之间的关系
-
缓冲区(Buffer)
- TF2 维护一个缓冲区,用于存储最近的变换关系。这个缓冲区允许节点查询过去某个时间点的变换关系,而不仅仅是当前的变换关系。这对于处理延迟和时间同步问题非常有用。
-
工具和库
tf2_ros:提供了 ROS2 的 TF2 接口,包括广播和查询功能。tf2_monitor:查看所有的发布者和频率。tf2_geometry_msgs:提供了将 ROS2 的几何消息(如geometry_msgs/Pose)与 TF2 的变换关系进行转换的工具。tf2_eigen:提供了将 Eigen 库的矩阵与 TF2 的变换关系进行转换的工具。
rqt_tf_tree:可视化 tf 更新信息sudo apt install ros-humble-rqt-tf-tree