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

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

本教程的示例代码和点云数据可在 GitHub 下载。

什么是 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 点云的旋转平移,相信你已经掌握点云的矩阵变换操作。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/656756.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

100个 Unity小游戏系列六 -Unity 抽奖游戏专题四 翻卡游戏

一、演示效果 二、知识点讲解 2.1 布局 void CreateItems(){reward_data_list reward_data_list ?? new List<RewardData>();reward_data_list.Clear();for (int i 0; i < ItemCount; i){GameObject item;if (i 1 < itemParent.childCount){item itemParent…

垂类短视频:四川鑫悦里文化传媒有限公司

垂类短视频&#xff1a;内容细分下的新媒体力量 随着移动互联网的迅猛发展和智能手机的普及&#xff0c;短视频已成为当下最受欢迎的媒介形式之一。四川鑫悦里文化传媒有限公司而在短视频领域&#xff0c;一个新兴的概念——“垂类短视频”正逐渐崭露头角&#xff0c;以其独特…

⌈ 传知代码 ⌋ 高速公路车辆速度检测软件

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…

WMS仓库管理系统是怎么操作的?WMS操作流程详解

WMS 是仓库管理系统(Warehouse Management System) 的缩写。通过标准化的来料管理、拣配管理、仓库管理&#xff0c;打造实时化、透明化、可视化的仓储管理体系。一款合格的wms系统具有以下优势 提供实时可视性和自动化仓储流程&#xff0c;帮助企业更好地应对复杂的供应链网络…

python fstring教程(f-string教程)(python3.6+格式化字符串方法)

文章目录 Python F-String 教程&#xff1a;深度探究与实用指南引言基础用法什么是F-String?表达式嵌入 格式化选项小数点精度宽度与对齐数字格式化 高级用法复杂表达式调用函数多行F-String嵌套格式化 总结 Python F-String 教程&#xff1a;深度探究与实用指南 引言 在Pyt…

AI赋能:人工智能技术驱动下的品牌海外市场精准分析与营销策略

随着全球化的加速和科技的飞速发展&#xff0c;品牌在海外市场的竞争愈发激烈。为了在竞争激烈的国际市场中脱颖而出&#xff0c;品牌需要更深入地了解海外消费者的行为、趋势和偏好。在这个过程中&#xff0c;人工智能&#xff08;AI&#xff09;技术以其强大的数据处理和分析…

闲话 .NET(6):.NET Core 各个版本的特性

前言 之前我们聊了一下 .NET Core 有哪些优势&#xff0c;.NET Core 发展非常迅速&#xff0c;不过短短几年&#xff0c;.NET Core 已经发布 .NET 8 了&#xff0c;基本上保持了一年一个版本的速度&#xff0c;每个版本都有自己的独有特性&#xff0c;下面我们来简单的盘点一下…

Enable Full Line suggestions 启用全行建议

开启后效果如下&#xff1a; 直接提示可能要输入的参数

医卫兰大药学试题及答案,分享几个实用搜题和学习工具 #媒体#微信

这些软件以其强大的搜索引擎和智能化的算法&#xff0c;为广大大学生提供了便捷、高效的解题方式。下面&#xff0c;让我们一起来了解几款备受大学生欢迎的搜题软件吧&#xff01; 1.彩虹搜题 这个是公众号 题库内容丰富全面&#xff0c;细致分类整理。找题再也不费力&#…

嵌入式学习记录5.23(超时检测、抓包分析)

目录 一.自带超时参数的函数 1.1 select函数 1.2 poll函数的自带超时检测参数 二、不带超时检测参数的函数 三、通过信号完成时间的设置 四、更新下载源 五、wireshark使用 5.1. 安装 5.2. wireshark 抓包 5.2.1 wireshark与对应的OSI七层模型 ​编辑5.2.2 包头分析 …

旺店通与金蝶云星空 就应该这样集成打通

在当今数字化商业环境中&#xff0c;企业需要高效、灵活的系统来支持其业务运营。旺店通和金蝶云星空作为两个领先的企业管理解决方案&#xff0c;它们的集成能够为企业带来无缝的业务流程和数据一致性。本文将详细介绍旺店通与金蝶云星空的全场景集成方案&#xff0c;包括主数…

netcat一键开始瑞士军刀模式(KALI工具系列六)

目录 1、KALI LINUX简介 2、netcat工具简介 3、在KALI中使用netcat 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、命令示例 4.1 测试某IP的端口是否打开 4.2 TCP扫描 4.3 UDP扫描 4.4 端口刺探 4.5 直接扫描 5、即时通信 5.1 单击对话互联 5.2 传…

idea的project structure下project [lauguage ]()level 没有java的sdk17选项如何导入

idea的project structure下project lauguage level 没有java的sdk17选项如何导入 别导入了&#xff0c;需要升级idea版本。idea中没有project language level没有17如何添加 - CSDN文库 别听这文章瞎扯淡 2021版本就是没有&#xff0c;直接卸载升级到最新版本就可以了。没办法…

离大模型落地应用最近的工程化技术(RAG)

虽然大规模语言模型&#xff08;LLM&#xff09;在自然语言处理&#xff08;NLP&#xff09;方面表现出了其强大的文本生成和理解能力&#xff0c;但是它们在实际应用中仍然面临一些挑战&#xff0c;如处理大规模知识库和实时获取最新信息的能力&#xff0c;并且会产生幻觉。为…

线性回归计算举例

使用正规方程计算&#xff08;一元线性回归&#xff09; import numpy as np import matplotlib.pyplot as plt # 转化成矩阵 X np.linspace(0, 10, num 30).reshape(-1, 1) # 斜率和截距&#xff0c;随机生成 w np.random.randint(1, 5, size 1) b np.random.randint(1,…

c-lodop 打印面单 内容串页

场景&#xff1a;使用c-lodop程序调取打印机连续打印多张快递单时&#xff0c;上页内容&#xff0c;打到了下一页了 问题原因&#xff1a; 由于是将所有面单内容放到了一个页面&#xff0c;c-lodop 在打印时&#xff0c;发现一页放不下&#xff0c;会自动分割成多页 页面元素…

【InternLM实战营第二期笔记】03:“茴香豆“,搭建你的 RAG 智能助理(未完成)

文章目录 笔记-RAG课程结构为什么要用 RAG&#xff1f;定义工作原理向量数据库RAG 工作流程发展历程常见优化RAG vs 微调LLM 优化方法比较RAG的评价总结 笔记-茴香豆什么是茴香豆茴香豆实战 笔记-RAG 课程结构 为什么要用 RAG&#xff1f; 新增知识&#xff0c;尤其是高频变动…

Clickhouse字典关联外部 MySQL 表联合查询实践

前言 clickhouse 可以将源数据加载进 clickhouse 作为字典表使用&#xff0c;字典表可以理解为 clickhouse 中的一张特殊表&#xff0c;我们在查询 clickhouse 表中的数据的时候不需要 JOIN 就可以直接查询字典表中的数据&#xff0c;非常方便&#xff0c;快速。我刚好在工作场…

MySQL8报错Public Key Retrieval is not allowedz 怎么解决?

问题描述 当我们使用数据库管理工具连接mysql8的时候&#xff0c;可能遇到报错&#xff1a; Public Key Retrieval is not allowed 解决办法 1、在连接属性中配置allowPublicKeyRetrieval设置为true 2、在连接URL中加上配置allowPublicKeyRetrieval为true

如何彻底卸载sql sever2022

目录 背景过程1、关闭sql sever服务2、打开控制面板&#xff0c;卸载SQL Sever3、手动删除 SQL Server 遗留文件4、清空注册表5、重启计算机以确保所有更改生效。 总结 背景 重装了电脑&#xff0c;安装sqlServer&#xff0c;一直报错&#xff0c;不成功&#xff0c;所以每次安…