旋转矩阵-变换矩阵-ROS-TF发布坐标变换

时间:2025-02-10 07:10:09

文章目录

  • 旋转矩阵
  • 平移
  • 变换矩阵与齐次坐标
  • TF中发布坐标变换

在空间中表示两个物体之间的位姿关系,通常可以分解为一个纯平移和一个纯旋转。也称为一个欧式变换。

旋转矩阵

这里介绍一种用旋转矩阵表示旋转的方式。旋转矩阵有一些特殊的性质,他是一个行列式为1的正交矩阵。因此它属于正交群。此外由于所有旋转矩阵都满足行列式为1,是一种特殊的正交矩阵,我们称旋转矩阵属于特殊正交群(Special Orthogonal Group)。表示三维旋转可以写成
S O ( 3 ) = { R ∈ R n × n ∣ R R T = I , det ⁡ ( R ) = 1 } SO(3) = \{R\in\mathbb R^{n\times n} | RR^T = I,\det (R) = 1\} SO(3)={RRn×nRRT=I,det(R)=1}
由于旋转矩阵是一个正交矩阵,它的逆矩阵(也就是它的转置)描述了一个相反的旋转,按照上面的定义
a ′ = R − 1 a = R T a a' = R^{-1}a = R^Ta a=R1a=RTa

平移

在欧式变换中,除了旋转还有平移。考虑世界坐标系下一个向量 a a a,经过一次旋转(用 R R R描述)和一次平移变换 t t t之后,得到了 a ′ a' a,那么把平移和旋转合到一起可以表示为:
a ′ = R a + t a' = Ra + t a=Ra+t
这样我们就完整的描述了一个欧式空间的坐标变换。我们通常定义坐标系1和坐标系2,用 R 12 R_{12} R12表示两个坐标系之间的旋转(通常不表示吧坐标系2中的向量旋转到坐标系1中),向量 a a a在两个坐标系下的坐标分别为 a 1 , a 2 a_1,a_2 a1,a2,那么他们之间的关系应该是
a 1 = R 12 a 2 + t 12 a_1 = R_{12}a_2 + t_{12} a1=R12a2+t12
关于平移 t 12 t_{12} t12,通常是知坐标系1原点指向坐标系2原点的向量。

变换矩阵与齐次坐标

假设我们进行了两次变换,分别为 R 1 , t 1 R_1,t_1 R1,t1 R 2 , t 2 R_2,t_2 R2,t2
b = R 1 a + t 1 , c = R 2 b + t 2 b = R_1a+t_1,c = R_2b + t_2 b=R1a+t1,c=R2b+t2
那么从 a a a c c c的变换可以表示为
c = R 2 ( R 1 a + t 1 ) + t 2 c = R_2(R_1a+t_1) + t_2 c=R2(R1a+t1)+t2
这样的形式会显得非常啰嗦,而且随着变换则增加,嵌套会显得非常冗长。因此我们映入齐次坐标和坐标变换矩阵
[ a ′ 1 ] = [ R t 0 T 1 ] [ a 1 ] = T [ a 1 ] \left[ \begin{matrix} a'\\1 \end{matrix}\right] = \left[ \begin{matrix} R & t\\ 0 ^T &1 \end{matrix}\right]\left[ \begin{matrix} a\\1 \end{matrix}\right] = T\left[ \begin{matrix} a\\1 \end{matrix}\right] [a1]=[R0Tt1][a1]=T[a1]
我们采用在向量末位补1的数学技巧,这样就可以表示为
b ~ = T 1 a ~ , c ~ = T 2 b ~    ⟹    c ~ = T 2 T 1 a ~ \tilde b = T_1 \tilde a,\tilde c = T_2\tilde b \implies \tilde c = T_2T_1\tilde a b~=T1a~,c~=T2b~c~=T2T1a~
称矩阵 T T T为变换矩阵,他具有比较特别的结构,左上三角为旋转矩阵,右侧为平移。这种矩阵又称特殊欧式群(Special Euclidean Group)。
S E ( 3 ) = { T = [ R t 0 T 1 ] ∈ R 4 × 4 ∣ R ∈ S O ( 3 ) , t ∈ R 3 } SE(3) = \{T = \left[ \begin{matrix} R&t\\0^T & 1 \end{matrix}\right]\in\mathbb R^{4\times 4} | R\in SO(3), t\in\mathbb R^3 \} SE(3)={T=[R0Tt1]R4×4RSO(3),tR3}
S O 3 SO3 SO3一样,求该矩阵的逆,可以得到一个反向的变换
T − 1 = [ R T − R T t 0 T 1 ] T^{-1} = \left[\begin{matrix} R^T & -R^Tt \\ 0^T&1 \end{matrix}\right] T1=[RT0TRTt1]

TF中发布坐标变换

我们常用的机器人描述中,通常有静态的变换(例如雷达相对于车的位置安装完成后就保持不变了),和动态的变换(例如小车在世界坐标系中移动,车声坐标系和世界坐标系的相对位置就是移动的)。前者可以通过TF的静态Transform命令实现,前者和后者都可以通过以下方式实现。
假设我的无人机机身坐标系为"uav",世界坐标系为"world",无人机上的雷达坐标系为"lidar",当我们获得无人机当前在世界坐标系下的位姿时,我们就可以通过以下代码发布坐标变换:

#include <tf/transform_broadcaster.h>
// 你也可以不用Eigen
#include <Eigen/Geometry>
#include <Eigen/Dense>

typedef Eigen::Matrix<double, 3, 3> Mat33;
typedef Eigen::Matrix<double, 3, 1> Vec3;

void publishTF(Mat33 rotation, Vec3 translation){
	// 创建一个坐标变换发布者
    static tf::TransformBroadcaster broadcaster;
    // 采用四元数和平移变换描述
    tf::Quaternion quad;
    tf::Transform trans;
	Vec3 eulerAngle = rotation.eulerAngles(0,1,2);

    // 发布机身到世界的动态变化
    trans.setOrigin(tf::Vector3(translation.x(), translation.y(), translation.z()));
    quad.setRPY(eulerAngle[0],eulerAngle[1],eulerAngle[2]);
    trans.setRotation(quad);
    broadcaster.sendTransform(tf::StampedTransform(trans, ros::Time::now(),"world","uav"));
	// 发布雷达到机身的静态变换
    trans.setOrigin(tf::Vector3(0,0,0.08));
    trans.setRotation( tf::Quaternion(-0.707107, 0, 0, 0.707107));
    broadcaster.sendTransform(tf::StampedTransform(trans, ros::Time::now(),"uav","laser"));
    }