pcl使用矩阵变换点云

  • Post author:
  • Post category:其他


Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();

// Define a rotation matrix (see https://en.wikipedia.org/wiki/Rotation_matrix)
float theta = M_PI / 4; // The angle of rotation in radians
transform_1(0, 0) = cos(theta);
transform_1(0, 1) = -sin(theta);
transform_1(1, 0) = sin(theta);
transform_1(1, 1) = cos(theta);
//    (row, column)

// Define a translation of 2.5 meters on the x axis.
transform_1(0, 3) = 2.5;

这段代码使用 Eigen 库创建了一个 4×4 的变换矩阵

transform_1

,并对其进行了旋转和平移操作。

在此示例中,我们首先初始化

transform_1

为单位矩阵(Identity),然后定义了一个旋转角度

theta

,这里取 π/4 弧度(即 45°)。接下来,我们根据旋转角度填充了旋转矩阵的相关元素:

这些元素用于描述绕 Z 轴旋转

theta

弧度的旋转变换。

最后,我们在 X 轴上进行了一个平移操作,将点云沿 X 轴方向平移 2.5 米:

这里索引

(0, 3)

对应于平移向量的 X 分量。

生成的矩阵:

Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();

// Define a translation of 0.8 meters on the x axis.
transform_2.translation() << 0.8, 0.0, 0.0;

// The same rotation matrix as before; theta radians arround Z axis
transform_2.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()));

这段代码使用 Eigen 库创建了一个 Affine3f 变换矩阵 transform_2,并对其进行平移和旋转操作。

在此示例中,我们首先初始化 transform_2 为单位矩阵 (Identity)。接下来,我们使用 translation() 方法在 X 轴上进行了一个平移操作,将点云沿 X 轴方向平移 0.8 米:

在这里,translation() 方法返回一个 3D 向量,我们使用 << 运算符将平移向量设置为 (0.8, 0.0, 0.0),表示在 X 轴上的平移量。

然后,我们应用与之前相同的旋转变换到 transform_2 中,绕着 Z 轴旋转 theta 弧度:

rotate() 方法接受一个 AngleAxisf 对象作为参数,该对象定义了旋转轴和角度。在这里,使用 UnitZ() 定义了绕着 Z 轴的旋转轴,然后传入 theta 角度,以获得绕 Z 轴旋转 theta 弧度的旋转变换。

Affine3f 类是 Eigen 提供的一种特殊的 4×4 变换矩阵类型,它可以表示平移、旋转和缩放等变换。

viewer.addCoordinateSystem(0.5, "cloud", 0);


viewer.addCoordinateSystem(scale, id, viewport)

方法用于在点云可视化窗口中添加一个坐标系。它接受三个参数:


  1. scale

    是一个标量值,表示坐标系的大小。在这个例子中,传入的值为 0.5,表示坐标系的大小为原来的一半。


  2. id

    是一个字符串,表示坐标系的名称或标识符。在这个例子中,传入的值为 “cloud”,表示给添加的坐标系一个名称为 “cloud”。


  3. viewport

    是一个整数值,表示要将坐标系添加到哪个视口上。在这个例子中,传入的值为 0,表示将坐标系添加到默认的第一个视口上。

通过调用

viewer.addCoordinateSystem

方法,我们可以在点云可视化窗口中添加一个固定大小的坐标系,并使其与点云对齐,以便更好地理解点云的空间位置和方向。

viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud");


viewer.setPointCloudRenderingProperties(property, value, id)

方法用于设置点云可视化中的渲染属性。它接受三个参数:


  1. property

    是一个枚举类型,表示要设置的渲染属性。在这个例子中,使用了

    pcl::visualization::PCL_VISUALIZER_POINT_SIZE

    ,表示设置点的大小。


  2. value

    是一个数值,表示所设置渲染属性的值。在这个例子中,传入的值为 2,表示将点的大小设置为 2 个单位大小。


  3. id

    是一个字符串,表示要设置渲染属性的点云对象的标识符。在这个例子中,传入的值为 “transformed_cloud”,表示要对名称为 “transformed_cloud” 的点云对象进行设置。

通过调用

viewer.setPointCloudRenderingProperties

方法,我们可以设置已变换点云的渲染属性,例如点的大小、颜色等。在这个例子中,将已变换点云的点大小设置为 2 单位大小。



完整代码:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_cloud.h>
#include <pcl/console/parse.h>
#include <pcl/common/transforms.h>
#include <pcl/visualization/pcl_visualizer.h>


int main(int argc, char** argv) {
    // Load file | Works with PCD and PLY files
    pcl::PointCloud<pcl::PointXYZ>::Ptr source_cloud(new pcl::PointCloud<pcl::PointXYZ>());

    if (pcl::io::loadPCDFile("../data/bunny.pcd", *source_cloud) < 0) {
        std::cout << "Error loading point cloud " << "bunny.pcd" << std::endl << std::endl;
        return -1;
    }

    /* Reminder: how transformation matrices work :

             |-------> 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)

      METHOD #1: Using a Matrix4f
      This is the "manual" method, perfect to understand but error prone !
    */
    Eigen::Matrix4f transform_1 = Eigen::Matrix4f::Identity();

    // Define a rotation matrix (see https://en.wikipedia.org/wiki/Rotation_matrix)
    float theta = M_PI / 4; // The angle of rotation in radians
    transform_1(0, 0) = cos(theta);
    transform_1(0, 1) = -sin(theta);
    transform_1(1, 0) = sin(theta);
    transform_1(1, 1) = cos(theta);
    //    (row, column)

    // Define a translation of 2.5 meters on the x axis.
    transform_1(0, 3) = 2.5;

    // Print the transformation
    printf("Method #1: using a Matrix4f\n");
    std::cout << transform_1 << std::endl;

    /*  METHOD #2: Using a Affine3f
      This method is easier and less error prone
    */
    Eigen::Affine3f transform_2 = Eigen::Affine3f::Identity();

    // Define a translation of 0.8 meters on the x axis.
    transform_2.translation() << 0.8, 0.0, 0.0;

    // The same rotation matrix as before; theta radians arround Z axis
    transform_2.rotate(Eigen::AngleAxisf(theta, Eigen::Vector3f::UnitZ()));

    // Print the transformation
    printf("\nMethod #2: using an Affine3f\n");
    std::cout << transform_2.matrix() << std::endl;

    // Executing the transformation
    pcl::PointCloud<pcl::PointXYZ>::Ptr transformed_cloud(new pcl::PointCloud<pcl::PointXYZ>());
    // You can either apply transform_1 or transform_2; they are the same
    pcl::transformPointCloud(*source_cloud, *transformed_cloud, transform_2);

    // Visualization
    printf("\nPoint cloud colors :  white  = original point cloud\n"
        "                        red  = transformed point cloud\n");
    pcl::visualization::PCLVisualizer viewer("Matrix transformation example");

    // Define R,G,B colors for the point cloud
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> source_cloud_color_handler(source_cloud, 192, 127, 220);
    // We add the point cloud to the viewer and pass the color handler
    viewer.addPointCloud(source_cloud, source_cloud_color_handler, "original_cloud");

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> transformed_cloud_color_handler(transformed_cloud, 230, 20, 20); // Red
    viewer.addPointCloud(transformed_cloud, transformed_cloud_color_handler, "transformed_cloud");

    // 设置坐标系系统
    viewer.addCoordinateSystem(0.5, "cloud", 0);
    // 设置背景色
    viewer.setBackgroundColor(0.9647, 0.9412, 0.8392, 0); // Setting background to a dark grey
    // 设置渲染属性(点大小)
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud");
    // 设置渲染属性(点大小)
    viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "transformed_cloud");
    //viewer.setPosition(800, 400); // Setting visualiser window position

    while (!viewer.wasStopped()) { // Display the visualiser until 'q' key is pressed
        viewer.spinOnce();
    }

    return 0;
}

效果图



版权声明:本文为Scarlett2025原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。