绕任一向量旋转矩阵计算思考与实现
欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
问题提出
如图所示,在空间中有一向量A,问点O绕A方向逆时针旋转角度α的矩阵如何表示。
问题分析
问题化规
直接去构造一个矩阵是比较困难的。
我们知道绕X,Y,Z三个方向的旋转矩阵是可以直接给出的。分别如下。
角度根据右手定则绕各轴逆时针旋转θ
绕 X 轴表示为: X ( θ ) = [ 1 0 0 0 c o s θ − s i n θ 0 s i n θ c o s θ ] 绕X轴表示为:X(\theta)=\begin{bmatrix}1&0&0\\0&cos\theta&-sin\theta\\0&sin\theta&cos\theta\end{bmatrix} 绕X轴表示为:X(θ)= 1000cosθsinθ0−sinθcosθ
绕 Y 轴表示为: Y ( θ ) = [ c o s θ 0 s i n θ 0 1 0 - s i n θ 0 c o s θ ] 绕Y轴表示为:Y(\theta)=\begin{bmatrix}cos\theta&0&sin\theta\\0&1&0\\-sin\theta&0&cos\theta\end{bmatrix} 绕Y轴表示为:Y(θ)= cosθ0-sinθ010sinθ0cosθ
绕 Z 轴表示为: Z ( θ ) = [ c o s θ − s i n θ 0 s i n θ c o s θ 0 0 0 1 ] 绕Z轴表示为:Z(\theta)=\begin{bmatrix}cos\theta&-sin\theta&0\\sin\theta&cos\theta&0\\0&0&1\end{bmatrix} 绕Z轴表示为:Z(θ)= cosθsinθ0−sinθcosθ0001
一个直观的想法就是先把向量A转到与X轴相同的方向。
也就是沿着A与X叉乘方向旋转β,如图所示。
图中向量M分别与向量A,向量X垂直,可知向量M处于平面YOZ中。
设上述旋转为RM
那么O点最终结果可以表示如下
O ′ = R M − 1 ⋅ X ( α ) ⋅ R M ⋅ O O'=RM^{-1}\cdot X(\alpha) \cdot RM\cdot O O′=RM−1⋅X(α)⋅RM⋅O
由于向量M并不与X,Y,Z轴中任意一轴平行,所以还是不好直接给出RM表达式。
但是向量M处于平面YOZ,可以行将向量M旋转到与Y轴平行,再按照上述同理操作。设旋转到Y轴矩阵为RY。
R M = R Y − 1 ⋅ Y ( − β ) ⋅ R Y RM=RY^{-1}\cdot Y(-\beta)\cdot RY RM=RY−1⋅Y(−β)⋅RY
= X ( − γ ) − 1 ⋅ Y ( − β ) ⋅ X ( − γ ) =X(- \gamma)^{-1}\cdot Y(-\beta)\cdot X(- \gamma) =X(−γ)−1⋅Y(−β)⋅X(−γ)
致此,所有旋转都转化成和X轴,Y轴相关的旋转。
求解过程
RY计算。
RY的作用是把M转到与Y轴相同位置。
M可以由A与X叉乘得到
设 M = ( 0 , M y , M z ) , 由于 M 处于 Y O Z 平面,可知 M x = 0 设M=(0, My, Mz), 由于M处于YOZ平面,可知Mx=0 设M=(0,My,Mz),由于M处于YOZ平面,可知Mx=0
由上图可以知
R Y = X ( − γ ) = X ( γ ) T RY=X(-\gamma)=X(\gamma)^T RY=X(−γ)=X(γ)T
= [ 1 0 0 0 c o s γ − s i n γ 0 s i n γ c o s γ ] T =\begin{bmatrix}1&0&0\\0&cos\gamma&-sin\gamma\\0&sin\gamma&cos\gamma\end{bmatrix}^T = 1000cosγsinγ0−sinγcosγ T
= [ 1 0 0 0 c o s γ s i n γ 0 - s i n γ c o s γ ] =\begin{bmatrix}1&0&0\\0&cos\gamma&sin\gamma\\0&-sin\gamma&cos\gamma\end{bmatrix} = 1000cosγ-sinγ0sinγcosγ
= [ 1 0 0 0 M y M z 0 - M z M y ] =\begin{bmatrix}1&0&0\\0&My&Mz\\0&-Mz&My\end{bmatrix} = 1000My-Mz0MzMy
R Y − 1 = R Y T RY^{-1}=RY^T RY−1=RYT
有了RY后,可以先将A乘上RY。这样A就会被旋转到平面ZOX上来。
A ′ = R Y ⋅ A = ( A x ′ , 0 , A z ′ ) A' = RY\cdot A = (Ax',0, Az') A′=RY⋅A=(Ax′,0,Az′)
同理,
R X = Y ( − β ) = Y ( β ) T RX=Y(-\beta) = Y(\beta)^T RX=Y(−β)=Y(β)T
= [ c o s β 0 − s i n β 0 1 0 s i n β 0 c o s β ] = \begin{bmatrix}cos\beta&0&-sin\beta\\0&1&0\\sin\beta&0&cos\beta\end{bmatrix} = cosβ0sinβ010−sinβ0cosβ
= [ A x ′ 0 A z ′ 0 1 0 - A z ′ 0 A x ′ ] = \begin{bmatrix}Ax'&0&Az'\\0&1&0\\-Az'&0&Ax'\end{bmatrix} = Ax′0-Az′010Az′0Ax′
旋转后的P’
P ′ = R Y − 1 ⋅ R X − 1 ⋅ X ( α ) ⋅ R X ⋅ R Y ⋅ P P'=RY^{-1}\cdot RX^{-1}\cdot X(\alpha)\cdot RX\cdot RY\cdot P P′=RY−1⋅RX−1⋅X(α)⋅RX⋅RY⋅P
代码实现
- 代码链接点击前往
- 代码链接点击前往
- 代码链接点击前往
namespace acamcad {const double pi = acos(-1);using Point = Eigen::Vector3d;class RigidRTMatrix {private:Eigen::Matrix3d mat;Eigen::Vector3d trans;public:RigidRTMatrix(Point start, Point end, double theta) {cout << "generate RigidRTMatrix 2" << endl;Eigen::Vector3d v = end - start;cout << "v:" << v << endl;cout << "angle:" << theta << endl;assert(!v.isZero());// Point::Zero();v.normalize();Eigen::Vector3d X(1,0,0);Eigen::Vector3d m = v.cross(X);// todo m=0时特殊处理if (m.isZero()) {if (v.dot(X) > 0) m = { 0,1,0 }; // 直接等于Y轴else m = { 0,-1,0 }; // 等于Y轴的反轴}auto RY = GetRY(m);// 将v 旋转至ZOX 平面。auto vZOX = RY * v;auto RX = GetRX(vZOX);auto Xrotate = GetXRotate(theta);mat = RY.transpose() * RX.transpose() * Xrotate * RX * RY;cout << "mat create :" << mat << endl;}RigidRTMatrix() {}// 给定YOX平面上的单位M向量,将其旋转到Y轴上。Eigen::Matrix3d GetRY(Eigen::Vector3d m) {assert(!m.isZero());m.normalize();Eigen::Matrix3d RY;RY.setIdentity();RY(1, 1) = m.y();RY(1, 2) = m.z();RY(2, 1) = -m.z();RY(2, 2) = m.y();return RY;}// 给定ZOX平面上的单位M向量,将其旋转到X轴上。Eigen::Matrix3d GetRX(Eigen::Vector3d m) {assert(!m.isZero());m.normalize();Eigen::Matrix3d RX;RX.setIdentity();RX(0, 0) = m.x();RX(0, 2) = m.z();RX(2, 0) = -m.z();RX(2, 2) = m.x();return RX;}// 给定ZOX平面上的单位M向量,将其旋转到X轴上。Eigen::Matrix3d GetXRotate(double theta) {double rad = theta / 180 * pi;Eigen::Matrix3d X;X.setIdentity();X(1, 1) = cos(rad);X(1, 2) = -sin(rad);X(2, 1) = sin(rad);X(2, 2) = cos(rad);return X;}double angleMod(double theta) {while (theta < -180)theta += 360;while (theta > 180)theta -= 360;return theta;}Point Trans(Point &a) {return mat * a;}friend static RigidRTMatrix operator*(RigidRTMatrix& a, RigidRTMatrix& b) {RigidRTMatrix multi;multi.mat = a.mat * b.mat;return multi;}};
}
数据测试
测试代码链接点击前往
测试代码链接点击前往
测试代码链接点击前往
效果展示
往外的三条线分别是X,Y,Z中间那么是向量(1,1,1),红点是(0.5,0,0.5)
绿点是红点沿(1,1,1)逆时针转90度结果。
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。
欢迎添加我的公众号,进群交流。
绕任一向量旋转矩阵计算思考与实现相关推荐
- 空间向量绕任一向量旋转计算
假定向量P绕单位向量A旋转角度θ,得到新的向量P',则: P'=P * cosθ + (A×P)sinθ +A(A·P)(1 - cosθ) 其中A为单位向量,旋转角度θ为逆时针方向旋转的角度. 假定 ...
- 从某一点出发沿任意一方向旋转矩阵计算思考与实现
欢迎关注更多精彩 关注我,学习常用算法与数据结构,一题多解,降维打击. 上期讲到 绕任一向量旋转矩阵计算思考与实现 点击前往 点击前往 问题提出 之前讲到绕任一向量旋转矩阵实现,原来的向量都是从原点出 ...
- 绕任意向量旋转分解到坐标系旋转
如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 一.原理解析 假设向量为(a,b,c),旋转角度为θ. 绕任意向量旋转的过程分解如下: ...
- coding随笔 | 点绕向量旋转
之所以会写这个东西,是因为我在半个月前coding的时候遇到了我难以解决的问题,直接要我复习了高中的数学知识,也记录下这难忘的一刻. 1 点绕向量旋转的分类 看来点绕向量旋转一般分为两类,第一是点在坐 ...
- 二维空间下的向量旋转
向量运算是计算机图形学的数学基础,而向量的旋转是向量的一种常见操作,本文将详细讲解向量在二维空间下的旋转原理. 在前端项目中,旋转一个元素我们会使用CSS的 rotate 函数,本文会让你对 rota ...
- 游戏开发的数学知识(一)三维向量绕某一向量旋转
最近在b站看到的某up主搬运了youtube大佬的游戏开发数学知识所以这里总结一下每一节讲的游戏开发中的数学问题 原视频链接 https://www.bilibili.com/video/BV1Yt4 ...
- 物体绕任意向量的旋转——四元数法、旋转矩阵法、欧拉角法的比较
3D空间中的旋转可用旋转矩阵.欧拉角或四元数等形式来表示,他们不过都是数学工具,其中在绕任意向量的旋转方面,旋转矩阵和四元数两种工具用的较多,欧拉角由于存在万向节死锁等问题,使用存在限制. (本文假设 ...
- 18.外部相机校准——旋转(Rotation),R是什么样子的,绕Z轴旋转的例子,齐次坐标旋转_2
目录 旋转(rotation) R是什么样子的 绕Z轴旋转的例子 齐次坐标旋转 旋转(rotation) 现在生活变得更加丑陋,旋转(rotation).我这里有一个图,或者我想这也是来自四边复合幻灯 ...
- 详解坐标变换矩阵 - 绕 x 轴旋转的旋转矩阵
在高级驾驶辅助系统(ADAS)领域,存在多种常用的坐标系:LiDAR 坐标系.车辆坐标系.相机坐标系.图像坐标系等. 在高级驾驶辅助系统(ADAS)领域,存在多种常用的坐标系:LiDAR 坐标系.车辆 ...
最新文章
- python 16进制转10进制, 8进制转10进制, 2进制转10进制的方法
- 归并排序(代码注释超详细)
- 如何判断Android手机当前是否联网?
- 什么?欧洲也有个恩智浦杯?
- ML之SVM:基于Js代码利用SVM算法的实现根据Kaggle数据集预测泰坦尼克号生存人员
- 使用python自己搭建一个简单的BP神经网络
- 使用T-SQL管理数据中的Unicode字符
- php模拟post方法
- GitHub Actions 部署 VuePress 文档
- TortoiseSVN中Branching和Merging实践
- DELPHI 编程(一) __快速认识Delphi
- linux系统下的打印机驱动下载,用于UNIXLinux系统的打印机驱动程序-Lexmark.PDF
- css各种角度的三角形
- js 主动触发 a 标签 href 链接写法,
- html中this的作用,JavaScript 中的 this :工作原理和陷阱
- 流量不清零跑得快风波,运营商到底在掩盖什么
- Swift学习笔记 ——(一)
- Bzoj3687简单题(bitset)
- matlab怎么加采样开关,开关量采集模块怎么使用?
- mysql数据库应用经典案例_MySQL数据库“十宗罪”(十大经典错误案例)