ROS2中的TF(Transform)系统:机器人坐标系的管理神器

ROS 2 TF 概述

TF(Transform) 是ROS中用于跟踪多个坐标系之间变换关系的库。在ROS 2中,TF系统被重构为 TF2,提供了更高效、更灵活的坐标变换管理。


核心概念

1. 坐标系(Frame)

  • 每个机器人部件、传感器或环境物体都有自己的坐标系
  • 例如:base_link(机器人基座)、laser(激光雷达)、camera(相机)

2. 变换(Transform)

  • 描述两个坐标系之间的平移(translation)和旋转(rotation)关系
  • 表示为:frame_B 相对于 frame_A 的位置和姿态

3. 变换树(Transform Tree)

  • 所有坐标系通过父子关系连接成一棵树
  • 必须有一个根坐标系(通常是mapodom

ROS 2 TF2 架构

┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ TF2 广播者 │ │ TF2 缓冲区 │ │ TF2 监听者 │ │ (Broadcaster) │────▶│ (Buffer) │◀────│ (Listener) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ │ 发布变换信息 │ │ 查询坐标变换 │ │ /tf 话题 │ │ lookupTransform │ └─────────────────┘ └─────────────────┘ 

核心组件

组件功能对应类/节点
Broadcaster广播坐标变换TransformBroadcaster
Static Broadcaster广播静态变换(固定关系)StaticTransformBroadcaster
Listener监听并查询变换Buffer + TransformListener
Buffer存储变换历史tf2_ros::Buffer

代码示例

1. 发布动态变换(Dynamic Transform)

import rclpy from rclpy.node import Node from geometry_msgs.msg import TransformStamped import tf2_ros import math classDynamicFramePublisher(Node):def__init__(self):super().__init__('dynamic_frame_publisher')# 创建TF广播者 self.br = tf2_ros.TransformBroadcaster(self)# 定时发布 self.timer = self.create_timer(0.1, self.publish_transform) self.t =0.0defpublish_transform(self): t = TransformStamped() t.header.stamp = self.get_clock().now().to_msg() t.header.frame_id ='base_link'# 父坐标系 t.child_frame_id ='rotating_laser'# 子坐标系# 旋转运动 self.t +=0.1 t.transform.translation.x =1.0 t.transform.translation.y =0.0 t.transform.translation.z =0.5# 四元数表示旋转 t.transform.rotation.x =0.0 t.transform.rotation.y =0.0 t.transform.rotation.z = math.sin(self.t /2) t.transform.rotation.w = math.cos(self.t /2) self.br.sendTransform(t)defmain(): rclpy.init() node = DynamicFramePublisher() rclpy.spin(node) rclpy.shutdown()

2. 发布静态变换(Static Transform)

from tf2_ros.static_transform_broadcaster import StaticTransformBroadcaster classStaticFramePublisher(Node):def__init__(self):super().__init__('static_frame_publisher') self.static_br = StaticTransformBroadcaster(self)# 只需要发布一次 static_transform = TransformStamped() static_transform.header.stamp = self.get_clock().now().to_msg() static_transform.header.frame_id ='base_link' static_transform.child_frame_id ='camera_link' static_transform.transform.translation.x =0.5 static_transform.transform.translation.y =0.0 static_transform.translation.z =0.3# 相机朝向(旋转90度) static_transform.transform.rotation.x =0.0 static_transform.transform.rotation.y =0.0 static_transform.transform.rotation.z =0.707 static_transform.transform.rotation.w =0.707 self.static_br.sendTransform(static_transform)

3. 监听变换(Transform Listener)

import tf2_ros from tf2_ros import LookupException, ConnectivityException, ExtrapolationException classFrameListener(Node):def__init__(self):super().__init__('frame_listener')# 创建Buffer和Listener self.tf_buffer = tf2_ros.Buffer() self.tf_listener = tf2_ros.TransformListener(self.tf_buffer, self) self.timer = self.create_timer(1.0, self.lookup_transform)deflookup_transform(self):try:# 查询从 'base_link' 到 'laser' 的变换 transform = self.tf_buffer.lookup_transform('base_link',# 目标坐标系'laser',# 源坐标系 rclpy.time.Time()# 最新时间) self.get_logger().info(f"Translation: [{transform.transform.translation.x:.2f}, "f"{transform.transform.translation.y:.2f}, "f"{transform.transform.translation.z:.2f}]")except(LookupException, ConnectivityException, ExtrapolationException)as e: self.get_logger().warn(f'Could not transform: {str(e)}')

常用工具

命令行工具

# 查看当前TF树 ros2 run tf2_tools view_frames # 查询特定变换 ros2 run tf2_ros tf2_echo base_link laser # 发布静态变换 ros2 run tf2_ros static_transform_publisher 001000 base_link camera 

RViz2 可视化

在RViz2中添加 TF 显示插件,可以实时可视化坐标系:

  • 红色 = X轴
  • 绿色 = Y轴
  • 蓝色 = Z轴

ROS 1 vs ROS 2 TF 对比

特性ROS 1 TFROS 2 TF2
默认库tftf2
时间处理较简单支持时间旅行(查询历史变换)
数据类型专用消息与ROS 2消息系统更好集成
静态变换混合处理独立话题 /tf_static
性能一般更高效,支持零拷贝
Python支持较弱原生支持,API更友好

最佳实践

  1. 区分静态/动态变换:固定关系用StaticTransformBroadcaster,减少网络负载
  2. 保持时间同步:确保所有节点使用相同的时间源(ROS时间 vs 系统时间)
  3. 异常处理:查询变换时总是捕获可能的异常
  4. 命名规范:使用REP 105标准坐标系命名(mapodombase_link
  5. 避免环形依赖:TF树必须是严格的树形结构,不能闭环

典型应用场景

  • 传感器数据融合:将激光雷达、相机数据转换到统一坐标系
  • 导航规划:将目标点从地图坐标系转换到机器人坐标系
  • 机械臂控制:计算末端执行器相对于基座的位姿
  • 多机器人协作:统一不同机器人的坐标参考系

Read more

Ψ0——人形全身VLA:先用800h人类自视角视频数据和30h的真实机器人交互数据预训练VLM,再后训练MM-DiT,最后用AMO做下肢RL跟踪

Ψ0——人形全身VLA:先用800h人类自视角视频数据和30h的真实机器人交互数据预训练VLM,再后训练MM-DiT,最后用AMO做下肢RL跟踪

前言 今26年3.11,一投资人微信上跟我说,“ 周老师好!最近在搞什么模型?今天USC大学发布的这个模型,请您评估看看?” 我当时回复她道,“这个我这个星期,抽时间解读一下,到时候再说一下我的看法哦” 对于本文要解读的Ψ0 1. 首先,作者在大规模第一视角人类视频(约800 小时的人类视频数据),和30 小时的真实世界机器人数据上对一个 VLM 主干进行自回归预训练,以获得具有良好泛化能力的视觉-动作表征 2. 随后,再在高质量的人形机器人数据上后训练一个基于流(flow-based)的动作专家,用于学习精确的机器人关节控制 个人认为,该工作在理念创新上 确实 挺不错的 1. 以规模不大的“人类第一视角数据和真实机器人交互数据”预训练vlm 再后训练、微调 避免一味 堆数据,毕竟 数据 很难是个头 2. 全身摇操系统 看起来 也组合的不错 更重要的是,虽然目前市面上loco-mani方向的工作已经不少了

树莓派4B连接大疆M300无人机全网最细教程

树莓派4B连接大疆M300无人机全网最细教程

注:本教程适用于树莓派4B连接大疆M300_RTK无人机,若是其余型号可以参考本文思路,但是具体细节请前往官方教程或大疆开发者论坛查找,第三方开发板连接大疆无人机,不同型号之间会有很多细节差异,请确认自己的型号然后针对性查找 官方教程网址:Payload SDK (官方的是树莓派4B连接M350!并非M300,实现细节完全不同,请慎重查看) 大疆开发者论坛网址:Payload SDK – 大疆创新SDK技术支持论坛 (优点:几乎能找到所有问题的解决方法;缺点:太零散了,找解决方法如同大海捞针) 1 硬件准备 1.1 硬件选型 * 无人机型号:M300_RTKM300顶部一共有三个接口,其中OSDK端口和云台口(Payload SDK Port)可以用来运行PSDK程序,TypeC调参口,则是用来与电脑连接,打开DJI Assistant2软件后,可以升级无人机固件,导出日志,使用模拟器,绑定负载等。 1.FPV摄像头13.左视和右视红外感知系统25.调参接口2.前视红外感知系统14.

【论文笔记】知识蒸馏的全面综述

【论文笔记】知识蒸馏的全面综述

目录 写在前面 一、知识从哪里来? 二、知识蒸馏的传授方案 三、知识蒸馏的核心算法 四、知识蒸馏的应用领域 写在前面         今天看一篇关于知识蒸馏(Knowledge Distillation, KD)的全面综述,知识蒸馏可以想象成一位“学霸”老师把自己的解题思路和秘诀传授给“学弟学妹”学生的过程,目的是让小巧高效的“学生”模型也能拥有接近庞大“老师”模型的强大能力。这在人工智能领域非常重要,能让我们在手机、摄像头等计算资源有限的设备上也能运行强大的AI模型。         这篇文章系统性地梳理了知识蒸馏这个领域,就像一本厚厚的“武功秘籍大全”,详细讲解了各种不同的“传授功力”的方法。下面我梳理一下最重要的内容。 论文地址:https://arxiv.org/pdf/2503.12067 一、知识从哪里来?         这就像是问,老师要教给学生什么?文章总结了三大类“知识宝库”: 1.

Mac平台Neo4j图数据库:从安装到核心操作详解

Mac平台Neo4j图数据库:从安装到核心操作详解 一、环境准备 * macOS 10.14+ * Java 11+(推荐AdoptOpenJDK) 安装Homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 系统要求 brew install adoptopenjdk11 二、Neo4j安装步骤 方式1:Homebrew安装(推荐) brew install neo4j brew services start neo4j # 启动服务 方式2:手动安装 1. 下载社区版: https://neo4j.