当前位置: 代码网 > it编程>编程语言>Java > 使用 RT 矩阵进行 3D 点云变换详解(基于 PCL 和 Eigen 库)

使用 RT 矩阵进行 3D 点云变换详解(基于 PCL 和 Eigen 库)

2024年08月02日 Java 我要评论
在 3D 点云处理中,RT 矩阵是一个常用的工具,用于对点云进行旋转和平移操作。本文将详细介绍 RT 矩阵的概念,并通过一个示例程序演示如何基于 PCL 和 Eigen 库将一帧点云进行矩阵变换再输出。

在 3d 点云处理中,rt 矩阵是一个常用的工具,用于对点云进行旋转和平移操作。本文将详细介绍 rt 矩阵的概念,并通过一个示例程序演示如何基于 pcl 和 eigen 库将一帧点云进行矩阵变换再输出。

什么是 rt 矩阵

rt 矩阵包含旋转矩阵(r)和平移向量(t),组合起来可以描述一个刚体变换。具体来说,rt 矩阵是一个 4x4 的同质坐标变换矩阵,包含两个部分:

  1. 旋转矩阵(r):这是一个 3x3 的矩阵,用于描述点云的旋转。旋转矩阵是一个正交矩阵,表示绕某个轴的旋转。
  2. 平移向量(t):这是一个 3x1 的向量,用于描述点云的平移。平移向量表示在各个方向上的移动距离。

组合起来,rt 矩阵可以表示为:

           |-------> this column is the translation
    | 1 0 0 x |  \
    | 0 1 0 y |   }-> the identity 3x3 matrix (no rotation) on the left
    | 0 0 1 z |  /
    | 0 0 0 1 |    -> we do not use this line (and it has to stay 0,0,0,1)

其中,r 是 3x3 的旋转矩阵,t 是 3x1 的平移向量,右下角的 1 是为了使矩阵成为同质坐标形式的 4x4 矩阵。

旋转矩阵(r)

旋转矩阵通常可以通过欧拉角、旋转向量或四元数来计算。

欧拉角:通过绕固定轴(如 x, y, z 轴)依次旋转相应的角度来构建旋转矩阵。例如:

  • 绕 x 轴旋转角度( α \alpha α
    r x ( α ) = [ 1 0 0 0 cos ⁡ α − sin ⁡ α 0 sin ⁡ α cos ⁡ α ] \mathbf{r_x}(\alpha) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\alpha & -\sin\alpha \\ 0 & \sin\alpha & \cos\alpha \end{bmatrix} rx(α)= 1000cosαsinα0sinαcosα

  • 绕 y 轴旋转角度( β \beta β
    r y ( β ) = [ cos ⁡ β 0 sin ⁡ β 0 1 0 − sin ⁡ β 0 cos ⁡ β ] \mathbf{r_y}(\beta) = \begin{bmatrix} \cos\beta & 0 & \sin\beta \\ 0 & 1 & 0 \\ -\sin\beta & 0 & \cos\beta \end{bmatrix} ry(β)= cosβ0sinβ010sinβ0cosβ

  • 绕 z 轴旋转角度( γ \gamma γ
    r z ( γ ) = [ cos ⁡ γ − sin ⁡ γ 0 sin ⁡ γ cos ⁡ γ 0 0 0 1 ] \mathbf{r_z}(\gamma) = \begin{bmatrix} \cos\gamma & -\sin\gamma & 0 \\ \sin\gamma & \cos\gamma & 0 \\ 0 & 0 & 1 \end{bmatrix} rz(γ)= cosγsinγ0sinγcosγ0001

通过将这些旋转矩阵按顺序相乘,可以得到最终的旋转矩阵 r \mathbf{r} r

旋转向量:通过旋转轴和旋转角度来构建旋转矩阵。旋转向量表示绕一个单位向量旋转一定角度,使用 rodrigues 公式可以将其转换为旋转矩阵。

四元数:四元数是一种表示旋转的方式,能够避免欧拉角的万向节锁问题。通过四元数转换公式可以得到旋转矩阵。

平移向量(t)

平移向量是一个简单的 3x1 向量,表示在 x, y, z 三个方向上的平移量:

t = [ t x t y t z ] \mathbf{t} = \begin{bmatrix} t_x \\ t_y \\ t_z \end{bmatrix} t= txtytz

应用 rt 矩阵

假设有一个 3d 点 p = [ x y z ] t \mathbf{p} = \begin{bmatrix} x & y & z \end{bmatrix}^t p=[xyz]t,其同质坐标表示为 p h = [ x y z 1 ] t \mathbf{p_h} = \begin{bmatrix} x & y & z & 1 \end{bmatrix}^t ph=[xyz1]t

应用 rt 矩阵进行变换可以表示为: p h ′ = r t ⋅ p h \mathbf{p'_h} = \mathbf{rt} \cdot \mathbf{p_h} ph=rtph

其中, p h ′ = [ x ′ y ′ z ′ 1 ] t \mathbf{p'_h} = \begin{bmatrix} x' & y' & z' & 1 \end{bmatrix}^t ph=[xyz1]t ,展开后为:

[ x ′ y ′ z ′ 1 ] = [ r 11 r 12 r 13 t x r 21 r 22 r 23 t y r 31 r 32 r 33 t z 0 0 0 1 ] ⋅ [ x y z 1 ] \begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_x \\ r_{21} & r_{22} & r_{23} & t_y \\ r_{31} & r_{32} & r_{33} & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix} xyz1 = r11r21r310r12r22r320r13r23r330txtytz1 xyz1

经过计算,变换后的点 p ′ \mathbf{p'} p 的坐标为:

p ′ = [ x ′ y ′ z ′ ] = r ⋅ [ x y z ] + t \mathbf{p'} = \begin{bmatrix} x' \\ y' \\ z' \end{bmatrix} = \mathbf{r} \cdot \begin{bmatrix} x \\ y \\ z \end{bmatrix} + \mathbf{t} p= xyz =r xyz +t

通过 rt 矩阵的应用,可以对一整帧点云的每一个点进行旋转和平移,从而实现点云的刚体变换。

示例程序

下面使用 pcl 库(point cloud library)来实现将一帧点云经过 rt 矩阵转换输出另一帧点云,并将两帧点云同时可视化进行对比的演示。完整示例代码如下所示。

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/common/transforms.h>
#include <eigen/dense>
#include <thread>
#include <chrono>

int main(int argc, char** argv)
{
    // 检查命令行参数
    if (argc != 2) {
        pcl_error("usage: %s <input.pcd>\n", argv[0]);
        return -1;
    }

    // 创建点云对象并读取pcd文件
    pcl::pointcloud<pcl::pointxyz>::ptr cloud(new pcl::pointcloud<pcl::pointxyz>);
    if (pcl::io::loadpcdfile<pcl::pointxyz>(argv[1], *cloud) == -1) {
        pcl_error("couldn't read the file %s\n", argv[1]);
        return -1;
    }

    // 创建rt矩阵,将矩阵初始化为单位矩阵
    eigen::matrix4f transform = eigen::matrix4f::identity();

    // 定义旋转矩阵 (绕z轴旋转45度)
    float theta = m_pi / 4; // 弧度制角度
    transform(0, 0) = cos(theta);
    transform(0, 1) = -sin(theta);
    transform(1, 0) = sin(theta);
    transform(1, 1) = cos(theta);

    // 定义平移向量 (平移 x 方向2.5米, y 方向0米, z 方向1米)
    transform(0, 3) = 2.5;
    transform(1, 3) = 0.0;
    transform(2, 3) = 1.0;

    // 创建变换后的点云
    pcl::pointcloud<pcl::pointxyz>::ptr transformed_cloud(new pcl::pointcloud<pcl::pointxyz>);
    pcl::transformpointcloud(*cloud, *transformed_cloud, transform);

    // 创建可视化对象
    pcl::visualization::pclvisualizer::ptr viewer(new pcl::visualization::pclvisualizer("3d viewer"));
    viewer->setbackgroundcolor(0, 0, 0);

    // 设置原始点云的颜色为白色
    pcl::visualization::pointcloudcolorhandlercustom<pcl::pointxyz> original_color(cloud, 255, 255, 255);
    viewer->addpointcloud<pcl::pointxyz>(cloud, original_color, "original cloud");

    // 设置变换后点云的颜色为红色
    pcl::visualization::pointcloudcolorhandlercustom<pcl::pointxyz> transformed_color(transformed_cloud, 255, 0, 0);
    viewer->addpointcloud<pcl::pointxyz>(transformed_cloud, transformed_color, "transformed cloud");

    // 设置点云大小
    viewer->setpointcloudrenderingproperties(pcl::visualization::pcl_visualizer_point_size, 1, "original cloud");
    viewer->setpointcloudrenderingproperties(pcl::visualization::pcl_visualizer_point_size, 1, "transformed cloud");

    // 添加坐标系
    viewer->addcoordinatesystem(1.0);
    viewer->initcameraparameters();

    // 开始可视化
    while (!viewer->wasstopped()) {
        viewer->spinonce(100);
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    return 0;
}

改程序依赖 pcl 库和 vtk 库,配套 cmakelists.txt 文件如下:

cmake_minimum_required(version 3.1)
project(transform_demo)

find_package(pcl required)
find_package(vtk required)

include_directories(${pcl_include_dirs})
link_directories(${pcl_library_dirs})
add_definitions(${pcl_definitions})

add_executable(${project_name} transform_demo.cpp)
target_link_libraries(${project_name} ${pcl_libraries} ${vtk_libraries})

依次执行以下命令编译源代码:

$ mkdir build && cd build
$ cmake ..
$ make

编译完成后,执行 transform_demo 演示程序,指定 pcd 文件:

$ ./transform_demo ../data/2024-04-09-22-06-07.pcd

输出结果如下:

可以看到,白色为原始点云,红色为经过旋转、平移后的点云。

小结

矩阵变换是点云处理中的一个重要的工具,本文介绍了 rt 矩阵的基本概念和计算方法,rt 矩阵可用于对 3d 点云进行旋转和平移操作。我们通过一个例子演示了如何通过 pcl 和 eigen 构建 rt 矩阵并实现 3d 点云的旋转平移,相信你已经掌握点云的矩阵变换操作。


(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com