当前位置: 首页 > ops >正文

C++中的 Eigen库使用

简介

文章链接:(10 封私信 / 80 条消息) 快速入门矩阵运算——开源库Eigen - 知乎

向量

点积(点乘)

向量点积, 𝑎⋅𝑏=𝑐 ,符号为 ⋅ ,要求向量长度相同,是两个向量之间的点乘运算,结果是一个标量。又称:点乘、数量积、标量积、scalar product、projection product等

叉乘

与向量点乘不同,叉乘仅适用于三维向量,向量叉乘的运算结果是一个向量而不是一个标量。两个向量叉乘所得向量与这两个向量垂直,如下图所示。

矩阵

点积(点乘)

矩阵的点乘(也称为元素乘法)是两个相同大小矩阵之间的一种运算,其结果是一个与这两个矩阵大小相同的新矩阵,其中每个元素都是原矩阵对应位置元素的乘积。
 

叉乘

矩阵乘法

要求第一个矩阵(左矩阵)的列数与第二个矩阵(右矩阵)的行数相等。假设矩阵 A 是 \(m\times n\) 的矩阵,矩阵 B 是 \(n\times p\) 的矩阵,那么它们的乘积 \(C = AB\) 是一个 \(m\times p\) 的矩阵。其中,C 中第 i 行第 j 列的元素 \(c_{ij}\) 等于 A 的第 i 行元素与 B 的第 j 列对应元素乘积之和 。

矩阵乘法:结果矩阵的维度由参与运算的两个矩阵的行数和列数决定,一般情况下,AB 不一定等于 BA,即矩阵乘法不满足交换律。同时,矩阵乘法满足结合律和分配律,即 \((AB)C = A(BC)\) ,\(A(B + C)=AB + AC\) 。

矩阵乘法:在很多领域都有重要应用,比如在计算机图形学中,用于表示图形的变换(如旋转、平移、缩放等);在机器学习和深度学习中,用于计算神经网络的权重和激活值;在解线性方程组等问题中也起着关键作用。

使用

Eigen::Vector3d

    Eigen::Vector3d A(1, 2, 3); //(x1,y1,z1)Eigen::Vector3d B(4, 5, 6);//(x2,y2,z2)Eigen::Vector3d C = A.cross(B);   //叉乘 C = A*B = (x3,y3,z3) = (y1*z2 - z1*y2,z1*x2 -x1*z2,x1*y2 - y1*x2) = (2*6-3*5,3*4-1*6,1*5-2*4 ) = (-3 , 6, -3)cout <<"C = \n"<< C.transpose() <<endl; //transpose 转置将3*1 转为1*3Eigen::Vector3d D = B.cross(A);cout <<"D = \n"<< D<<endl;cout << A.dot(B) <<endl;//点乘(4+10+18)

Eigen::Matrix4d

    Eigen::Matrix4d eTw;// eTw.setZero(); //初始化全为0eTw.setIdentity(); //对角线为1其他为0 单位矩阵cout <<"eTw = \n"<< eTw<<endl;cout <<"isZero = "<< eTw.isZero(1e-9)<<endl; //不是判断全部为0,可以输入区间检测。cout <<"value ="<< (eTw(1,1) == 0) <<endl;
// 2. 定义A到B的变换矩阵T_B/A(旋转+平移)Eigen::Matrix4d T_BA;// 旋转部分:绕Z轴旋转90度(示例)double theta = M_PI / 2;  // 90度弧度cout<<"theta = "<< theta<<endl;T_BA << cos(theta), -sin(theta), 0, 5,  // 第一行:旋转+平移xsin(theta),  cos(theta), 0, 6,  // 第二行:旋转+平移y0,           0,          1, 7,  // 第三行:旋转+平移z0,           0,          0, 1;  // 齐次坐标行cout <<"T_BA = \n"<<T_BA<<endl;// 3. 计算B系中的点P_B = T_BA * P_AEigen::Vector4d P_B = T_BA * P_A;std::cout << "转换到B系后的坐标: " << P_B.transpose() << std::endl;// 4. 逆转换:从B系转回A系(验证)Eigen::Matrix4d T_AB = T_BA.inverse();  // 求逆矩阵cout <<"T_AB = \n"<<T_AB<<endl;Eigen::Vector4d P_A_back = T_AB * P_B;std::cout << "从B系转回A系的坐标: " << P_A_back.transpose() << std::endl;Eigen::Matrix4d  t;t = T_BA;cout << t<<endl;cout<<"===================="<<endl;cout << t.transpose()<<endl;//转置cout<<"===================="<<endl;cout << t.inverse()<<endl; //逆矩阵cout<<"T的转置*t =单位矩阵 \n"<< (t.inverse() *t)<<endl;return 0;

Eigen::norm

在 Eigen 库中,Matrix::norm() 函数默认返回的是弗罗贝尼乌斯范数(Frobenius Norm),也叫欧几里得范数(Euclidean Norm) 的矩阵版本。简单说,就是矩阵所有元素的绝对值的平方和的平方根。

应用场景

    Eigen::Vector3d O(177.330, 19.736, 32.725); //原点Eigen::Vector3d X(177.330, 41.935, 13.790);//X坐标点Eigen::Vector3d Y(177.330, 44.744, 17.329);//Y坐标点//计算X轴方向向量Eigen::Vector3d u_x =X -O;cout<< "u_x transpose = "<< u_x.transpose() <<endl;//计算初始 Y 轴方向向量Eigen::Vector3d u_y = Y-O;cout<< "init u_y transpose = "<< u_y.transpose() <<endl;//计算Z轴方向向量 使用叉乘计算Eigen::Vector3d u_z =u_x.cross(u_y);cout<< "u_z transpose = "<< u_z.transpose() <<endl;// 检查是否共线cout <<"u_z.norm = "<< u_z.norm() <<endl;if (u_z.norm() < 1e-6){std::cout << "向量共线,无法创建有效的坐标系。" << std::endl;}//u_y = u_z.cross(u_x); // Y轴方向向量 修正 Y 轴方向// u_x = u_y.cross(u_z);// 通过 Z 轴和 X 轴的叉乘重新计算 Y 轴,确保 X、Y、Z 轴两两垂直(正交化处理),这是关键的修正步骤,正确。cout<< "u_x transpose = "<< u_x.transpose() <<endl;cout<< "u_y transpose = "<< u_y.transpose() <<endl;cout<< "u_z transpose = "<< u_z.transpose() <<endl;// 初始化一个4x4单位矩阵Eigen::Matrix4d UserMatrix;UserMatrix.setIdentity();// 归一化向量u_x.normalize();u_y.normalize();u_z.normalize();UserMatrix <<u_x.x(), u_y.x(), u_z.x(), O.x(),u_x.y(), u_y.y(), u_z.y(), O.y(),u_x.z(), u_y.z(), u_z.z(), O.z(),0, 0, 0, 1;cout <<"UserMatrix = \n "<< UserMatrix<<endl;

为什么需要修正?

在构建三维坐标系时,X、Y、Z 轴必须两两垂直(正交),否则坐标系会 “歪扭”,无法正确描述空间变换(如旋转、平移)。因此:

  • 原始u_y可能不满足垂直要求,必须通过u_z.cross(u_x)重新计算(利用叉乘 “垂直于两个输入向量” 的特性 ),确保Y轴与XZ轴都垂直。

共线 = 三个点 A、B、O 落在 同一条直线上

http://www.xdnf.cn/news/18261.html

相关文章:

  • 数据库DML语言(增、删、改)
  • oracle服务器导入dmp文件
  • Causal-Copilot: An Autonomous Causal Analysis Agent 论文解读
  • 栈的概念(韦东山学习笔记)
  • C#APP.Config配置文件解析
  • Java内功修炼(2)——线程安全三剑客:synchronized、volatile与wait/notify
  • 5.4 4pnpm 使用介绍
  • kotlin 协程笔记
  • AI 创业公司分析报告:RealRoots
  • 0基础安卓逆向原理与实践:第2章:编程基础与工具链
  • 使用PCL读取PCD点云文件
  • Pandas 数据处理核心操作:合并、替换、统计与分组
  • 分贝单位全指南:从 dB 到 dBm、dBc
  • 深入解析EventPoller:Disruptor的轮询式事件处理机制
  • k8s笔记01
  • 服务器硬盘进行分区和挂载
  • SLAM文献之-Globally Consistent and Tightly Coupled 3D LiDAR Inertial Mapping
  • AI +金融 = 七大核心维度+ 落地典型困难
  • 【Golang实战】Go Module 双段 require 配置深度解析
  • Lecture 5 GPUs课程笔记
  • C语言---编译的最小单位---令牌(Token)
  • 认识Node.js及其与 Nginx 前端项目区别
  • KubeBlocks AI:AI时代的云原生数据库运维探索
  • Notepad++批量转UTF-8脚本
  • Flink Stream API - 顶层Operator接口StreamOperator源码超详细讲解
  • 结合SAT-3D,运动+饮食双重养腰新方式
  • Java:将视频上传到腾讯云并通过腾讯云点播播放
  • STM32F407VGT6从零建立一个标准库工程模板+VSCode或Keil5
  • 详解MySQL中的多表查询:多表查询分类讲解、七种JOIN操作的实现
  • 《Linux运维总结:Shell脚本位置参数的具体使用》