| name | tf-visualization |
| description | RViz2 TF 可视化技能 - 坐标变换显示、帧调试、时间轴可视化 |
| argument-hint | rviz tf OR 坐标变换 OR tf调试 |
| user-invocable | true |
RViz2 TF Visualization Skill
用于在 RViz2 中可视化坐标变换关系
何时使用
当需要以下帮助时使用此技能:
- 可视化坐标变换树
- 调试 TF 关系
- 检查坐标系对齐
- 诊断坐标问题
快速参考
发布 TF
import rclpy
from rclpy.node import Node
from tf2_ros import TransformBroadcaster
from geometry_msgs.msg import TransformStamped
class TFBroadcaster(Node):
def __init__(self):
super().__init__('tf_broadcaster')
self.broadcaster = TransformBroadcaster(self)
def broadcast_tf(self, parent, child, x, y, z, qx, qy, qz, qw):
t = TransformStamped()
t.header.stamp = self.get_clock().now().to_msg()
t.header.frame_id = parent
t.child_frame_id = child
t.transform.translation.x = x
t.transform.translation.y = y
t.transform.translation.z = z
t.transform.rotation.x = qx
t.transform.rotation.y = qy
t.transform.rotation.z = qz
t.transform.rotation.w = qw
self.broadcaster.sendTransform(t)
TF 树结构
常见机器人 TF 树
map
└── odom (里程计)
└── base_link (机器人基座)
├── base_scan (激光雷达)
├── camera_link (相机)
├── imu_link (IMU)
├── wheel_left (左轮)
└── wheel_right (右轮)
TF 配置参数
TF:
Frame Timeout: 10
All Frames: True
Frames:
All Enabled: True
Show Names: True
Show Axes: True
Show Arrows: True
Tree:
map:
enabled: true
parent: ''
odom:
enabled: true
parent: map
base_link:
enabled: true
parent: odom
可视化选项
显示轴
Axes:
Frame: base_link
Length: 1.0
Radius: 0.1
显示设置
TF:
Show Axes: True
Show Names: True
Show Arrows: True
Axis Length: 1.0
Axis Radius: 0.05
Head Length: 0.2
Head Width: 0.1
Shaft Length: 0.8
Shaft Width: 0.05
TF 调试
检查 TF 关系
ros2 run tf2_ros view_frames
ros2 run tf2_ros tf2_echo source_frame target_frame
ros2 run tf2_ros tf2_echo base_link map
TF 缓冲区
from tf2_ros import TransformBroadcaster, Buffer, TransformListener
buffer = Buffer()
listener = TransformListener(buffer)
try:
transform = buffer.lookup_transform(
'target_frame',
'source_frame',
rclpy.time.Time()
)
print(f"Transform: {transform}")
except Exception as e:
print(f"Error: {e}")
时间同步
使用仿真时间
ros2 run my_node my_node --ros-args -p use_sim_time:=true
检查时间延迟
transform = buffer.lookup_transform('base_link', 'scan', rclpy.time.Time())
now = node.get_clock().now()
age = now - transform.header.stamp
print(f"TF age: {age.nanoseconds / 1e9} seconds")
坐标对齐问题
常见问题
修复建议
TF:
Frame Timeout: 30
批量 TF 操作
静态变换
from geometry_msgs.msg import TransformStamped
from tf2_ros import StaticTransformBroadcaster
static_broadcaster = StaticTransformBroadcaster(node)
transform = TransformStamped()
transform.header.frame_id = "base_link"
transform.child_frame_id = "laser"
transform.transform.translation.x = 0.2
transform.transform.translation.y = 0.0
transform.transform.translation.z = 0.1
static_broadcaster.sendTransform(transform)
动态变换
timer = node.create_timer(0.1, publish_transform)
def publish_transform(self):
t = TransformStamped()
t.header.stamp = self.get_clock().now().to_msg()
t.header.frame_id = "odom"
t.child_frame_id = "base_link"
t.transform.translation.x = current_x
t.transform.translation.y = current_y
t.transform.translation.z = 0.0
self.broadcaster.sendTransform(t)
坐标系颜色和标签
自定义颜色
TF:
Tree:
map:
Color: 255; 0; 0; 255
odom:
Color: 0; 255; 0; 255
base_link:
Color: 0; 0; 255; 255
标签设置
TF:
Labels:
Show: True
Color: 255; 255; 255; 255
Size: 12
常见问题
问题 1: 坐标系抖动
解决方案:检查传感器数据延迟,调整滤波器参数
问题 2: TF 坐标系偏移
解决方案:检查外参是否正确,确认父坐标系设置
另见