tf坐标系问题记录
前言
在标定相机和雷达外参时,不可避免的会遇到tf坐标转换。
在分析标定结果时,用ros的tf工具进行坐标系平移旋转的转换,发现了一个有点意思的问题:
不同的yaw, roll, pitch 会得到相同的旋转坐标系,在此之前,我都是按照roll -> pitch -> yaw的旋转顺序进行旋转。查阅了一下相关资料,这与内部旋转(intrinsic rotations)、外部旋转(extrinsic rotations)有关。
在这篇文章中,我们不说数学证明,我们只说一些更加直观的、看得到的东西便于各位的运用与分析。
相机雷达坐标系初始化
- 相机、雷达坐标系的初始化
这里我们以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轴旋转
在这里,我们有如下的操作:
- 先绕Camera的X轴旋转 +90度, 也就是 +1.57弧度(rad)
Camera -> Camera1
- 再绕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轴旋转
在这里,我们有如下的操作:
- 先绕Camera的Z轴旋转 +90 度, 也就是 +1.57 弧度(rad)
Camera -> Camera1
- 再绕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中都很常见,这里就不赘述了。
希望阅读此文的你能对欧拉角的一些特性有一些认识与理解,感谢您的阅读与支持,文中有错误的地方还希望各位批评与指教。