tf坐标系旋转平移问题(欧拉角、内部旋转、外部旋转)

本文探讨了在ROS中相机和雷达坐标系初始化时的外部旋转(extrinsicrotations)与内部旋转(intrinsicrotations)的区别,通过实例和直观解释了欧拉角在不同旋转顺序下的效果,有助于理解和使用tf工具进行坐标转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

在标定相机和雷达外参时,不可避免的会遇到tf坐标转换。
在分析标定结果时,用ros的tf工具进行坐标系平移旋转的转换,发现了一个有点意思的问题:
不同的yaw, roll, pitch 会得到相同的旋转坐标系,在此之前,我都是按照roll -> pitch -> yaw的旋转顺序进行旋转。查阅了一下相关资料,这与内部旋转(intrinsic rotations)、外部旋转(extrinsic rotations)有关。
在这篇文章中,我们不说数学证明,我们只说一些更加直观的、看得到的东西便于各位的运用与分析。

想看数学证明的可以看一下这篇文章。

相机雷达坐标系初始化

  • 相机、雷达坐标系的初始化
    usb_cam -> velodyne
    这里我们以RVIZ的tf坐标系为图来说明。
    红色的坐标系是X轴,绕着X轴旋转称为roll;
    绿色的坐标系是Y轴,绕着Y轴旋转称为pitch;
    蓝色的坐标系是Z轴,绕着Z轴旋转称为yaw;
    三个轴都以右手坐标系方向为正

static_transform_publisher(tf2_ros )

发布一个tf2话题,让坐标轴(Axes)显示在rviz中

  • static_transform_publisher格式(launch文件)
<launch>
<node 
    pkg="tf2_ros" 
    type="static_transform_publisher" 
    name="your_tf_name" 
    args="x y z yaw pitch roll parent_frame_id child_frame_id"/>
</launch>

parent_frame_id是主坐标系
child_frame_id是从坐标系
也就是说,你应该发布(publish)一个从parent_frame_id到child_frame_id的坐标转换。
特别的,下面的例子将以相机(Camera)为主坐标系,以雷达(Lidar)为从坐标系进行说明。

外部旋转(extrinsic rotations)

  • extrinsic rotations
    这里的extrinsic指的是围绕绝对不动的坐标系轴旋转。
    TIPS:“绝对不动”并不准确,应该是说以初始的坐标系轴,比如下面的Camera轴进行旋转。
    这也是我刚开始认识到的旋转坐标轴:
  • 让我们先publish一下tf2转换
<launch>
<node 
    pkg="tf2_ros" 
    type="static_transform_publisher" 
    name="lidarLeftTransform" 
    args="1.0 0.0 0.0 0.0 -1.57 1.57 usb_cam velodyne1" />
</launch>

对于相机而言,他的坐标系是这样的:
在这里插入图片描述
问题来了,雷达的坐标如何用相机的坐标系表示呢?
平移我们就不用多说了:
translation = [1.0 0.0 0.0]
那么旋转呢?
对于extrinsic旋转来说,我们遵循 roll -> pitch -> yaw 的旋转方式
先绕X轴旋转,再绕Y轴旋转,最后绕Z轴旋转
在这里,我们有如下的操作:

  1. 先绕Camera的X轴旋转 +90度, 也就是 +1.57弧度(rad)
    Camera -> Camera1

在这里插入图片描述

  1. 再绕Camera的Y轴旋转 -90度(右手坐标系不要忘了), 也就是 -1.57弧度(rad)
    Camera1 -> Camera2
    在这里插入图片描述
  • 旋转总览
    在这里插入图片描述

  • 总结
    在这里,你会发现,坐标轴的变换均遵从于初始的那个Camera轴,
    x y z roll pitch yaw的正负都遵从初始坐标轴的右手坐标系的关系,这样的旋转,我们称之为外部旋转,也就是extrinsic rotation。

内部旋转(intrinsic rotations)

  • intrinsic rotations
    我们很容易想到,intrinsic和extrinsic那肯定是不相同了,extrinsic是根据不变的轴来旋转,那intrinsic就是根据变动的轴来旋转喽?
    答案是正确的。

  • 让我们先publish一下tf2转换

<launch>
<node 
    pkg="tf2_ros" 
    type="static_transform_publisher" 
    name="lidarLeftTransform" 
    args="1.0 0.0 0.0 1.57 -1.57 0 usb_cam velodyne1" />
</launch>

对于intrinsic旋转来说,我们遵循 yaw -> pitch -> roll 的旋转方式
先绕Z轴旋转,再绕Y轴旋转,最后绕X轴旋转
在这里,我们有如下的操作:

  1. 先绕Camera的Z轴旋转 +90 度, 也就是 +1.57 弧度(rad)
    Camera -> Camera1
    在这里插入图片描述
  2. 再绕Camera1(注意不是Camera)的Y轴旋转 -90 度, 也就是 -1.57 弧度(rad)
    Camera1 -> Camera2
    在这里插入图片描述
  • 旋转总览
    在这里插入图片描述
  • 总结
    在这里,你会发现,坐标轴的旋转变换均遵从于变化坐标轴,比如Camera->Camera1遵循的是Camera的右手坐标轴关系,Camera1->Camera2遵循的是Camera1的右手坐标轴关系。
    这样的旋转,我们称之为内部旋转,也就是intrinsic rotation。

总结

无论是内部旋转还是外部旋转,其最终得到的坐标轴是一样的。但不同的数得到相同的结果,这样合理么?

其实,欧拉角只是一个中间变量,最终其都需要转换成旋转矩阵(rotation_matrix)旋转向量(rotation_vector)四元数(quaternion) 来进行旋转平移的分析。

有时开玩笑的说,只有欧拉角是给人看的,其他的表示形式一出来,是个人都看不懂!🤡

欧拉角转换为以上三者的函数有很多,tf库、eigen库等等再C++和Python中都很常见,这里就不赘述了。

希望阅读此文的你能对欧拉角的一些特性有一些认识与理解,感谢您的阅读与支持,文中有错误的地方还希望各位批评与指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值