三维旋转矩阵

前言

本文讲述三维旋转的矩阵推导,推导过程遵循下面的规则:

  • 本文的坐标系是基于右手坐标系的
  • 逆时针旋转为正向旋转

围绕坐标轴的旋转

x x x

在这里插入图片描述

我们假设旋转的点为 P P P
假设旋转之前 P P P的坐标为 ( x 0 , y 0 , z 0 ) (x_0,y_0,z_0) (x0,y0,z0)

当围绕 x x x轴做正向旋转,即逆时针旋转,我们取 x = x 0 x = x_0 x=x0的平面作为旋转的坐标系平面
此时,我们将旋转就转化为了二维旋转
因为是右手坐标系,所以此时 y y y轴向右, z z z轴向上,原点为平面与 x x x轴的交点 O O O

假设旋转之前 P P P到原点 O O O的线段与 y y y轴的夹角弧度为 α \alpha α
假设旋转的弧度为 β \beta β
假设点 P P P到原点 O O O的距离为 R R R
假设旋转之后 P P P的坐标为 ( x 1 , y 1 , z 1 ) , x 1 = x 0 (x_1,y_1,z_1), x_1 = x_0 (x1,y1,z1),x1=x0

那么,旋转前
y 0 = c o s ( α ) ∗ R z 0 = s i n ( α ) ∗ R (1) y_0 = cos(\alpha) \tag{1}*R\\ z_0 = sin(\alpha) *R y0=cos(α)Rz0=sin(α)R(1)

旋转后(注意,因为是逆时针旋转,所以旋转后的弧度 = 旋转前弧度 + 旋转弧度)
y 1 = c o s ( α + β ) ∗ R = c o s ( α ) c o s ( β ) ∗ R − s i n ( α ) s i n ( β ) ∗ R = y 0 ∗ c o s ( β ) − z 0 ∗ s i n ( β ) z 1 = s i n ( α + β ) ∗ R = s i n ( α ) c o s ( β ) ∗ R + c o s ( α ) s i n ( β ) ∗ R = y 0 ∗ s i n ( β ) + z 0 ∗ c o s ( β ) x 1 = x 0 (2) \begin{aligned} y_1 & = cos(\alpha + \beta)*R \\ & = cos(\alpha)cos( \beta)*R - sin(\alpha)sin( \beta)*R\\ & = y_0*cos( \beta) - z_0*sin( \beta)\\ \\ z_1 &= sin(\alpha + \beta)*R \\ & = sin(\alpha)cos( \beta) *R +cos(\alpha)sin( \beta)*R\\ & = y_0*sin( \beta) + z_0*cos( \beta)\\ \\ x_1 &= x_0 \end{aligned} \tag{2} y1z1x1=cos(α+β)R=cos(α)cos(β)Rsin(α)sin(β)R=y0cos(β)z0sin(β)=sin(α+β)R=sin(α)cos(β)R+cos(α)sin(β)R=y0sin(β)+z0cos(β)=x0(2)

我们可以得到绕 x x x轴旋转的矩阵:
M r x = ( 1 0 0 0 0 c o s ( β ) − s i n ( β ) 0 0 s i n ( β ) c o s ( β ) 0 0 0 0 1 ) M_{rx}= \begin{pmatrix} 1 & 0 & 0& 0\\ 0 & cos( \beta)& -sin( \beta)& 0\\ 0 & sin( \beta)& cos( \beta)& 0\\ 0 & 0& 0& 1\\ \end{pmatrix} Mrx= 10000cos(β)sin(β)00sin(β)cos(β)00001

下面是实现代码

static matrix4d rotationX(float angle)
{
	matrix4d m;
	T c = cos(angle);
	T s = sin(angle);
	m[5] = m[10] = c;
	m[9] = -s;
	m[6] = s;
	return m;
}

注意,代码中的矩阵数组是列主序的

y y y

围绕 y y y轴的旋转和 x x x轴类似
在这里插入图片描述

只不过此时向右变成了 z z z轴,向上变成了 x x x
所以,我们直接上公式
z 1 = z 0 ∗ c o s ( β ) − x 0 ∗ s i n ( β ) x 1 = z 0 ∗ s i n ( β ) + x 0 ∗ c o s ( β ) y 1 = y 0 \begin{aligned} z_1 & = z_0*cos( \beta) - x_0*sin( \beta)\\ \\ x_1 & = z_0*sin( \beta) + x_0*cos( \beta)\\ \\ y_1 &= y_0 \end{aligned} z1x1y1=z0cos(β)x0sin(β)=z0sin(β)+x0cos(β)=y0
M r y = ( c o s ( β ) 0 s i n ( β ) 0 0 1 0 0 − s i n ( β ) 0 c o s ( β ) 0 0 0 0 1 ) M_{ry}= \begin{pmatrix} cos( \beta) & 0 & sin( \beta)& 0\\ 0 & 1& 0& 0\\ -sin( \beta) & 0& cos( \beta)& 0\\ 0 & 0& 0& 1\\ \end{pmatrix} Mry= cos(β)0sin(β)00100sin(β)0cos(β)00001
下面是代码

static matrix4d rotationY(float angle)
{
	matrix4d m;
	T c = cos(angle);
	T s = sin(angle);
	m[0] = m[10] = c;
	m[8] = s;
	m[2] = -s;
	return m;
}

注意,代码中的矩阵数组是列主序的

z z z

围绕 z z z轴的旋转和 x x x轴类似
在这里插入图片描述

只不过此时向右变成了 x x x轴,向上变成了 y y y
所以,我们直接上公式
x 1 = x 0 ∗ c o s ( β ) − y 0 ∗ s i n ( β ) y 1 = x 0 ∗ s i n ( β ) + y 0 ∗ c o s ( β ) z 1 = y 0 \begin{aligned} x_1 & = x_0*cos( \beta) - y_0*sin( \beta)\\ \\ y_1 & = x_0*sin( \beta) + y_0*cos( \beta)\\ \\ z_1 &= y_0 \end{aligned} x1y1z1=x0cos(β)y0sin(β)=x0sin(β)+y0cos(β)=y0
M r z = ( c o s ( β ) − s i n ( β ) 0 0 s i n ( β ) c o s ( β ) 0 0 0 0 1 0 0 0 0 1 ) M_{rz}= \begin{pmatrix} cos( \beta) & -sin( \beta) & 0& 0\\ sin( \beta) & cos( \beta)& 0& 0\\ 0& 0& 1& 0\\ 0 & 0& 0& 1\\ \end{pmatrix} Mrz= cos(β)sin(β)00sin(β)cos(β)0000100001
下面是代码

static matrix4d rotationY(float angle)
{
	matrix4d m;
	T c = cos(angle);
	T s = sin(angle);
	m[0] = m[5] = c;
	m[4] = -s;
	m[1] = s;
	return m;
}

注意,代码中的矩阵数组是列主序的

围绕任意轴的旋转

如果对象绕与每个坐标轴均不平行的轴旋转,则需要进行额外的变换。此时,还需要进行使旋转轴与某一选定坐标轴对齐的旋转,以后要将此轴变回到原始位置。若给定旋转轴和旋转角, 我们可以按照5个步骤来完成所需旋转:

  • 平移对象,使得旋转轴通过坐标原点
  • 旋转对象使得旋转轴与某一坐标轴重合
  • 绕该坐标轴完成指定的旋转
  • 利用逆旋转使旋转轴回到其原始方向
  • 利用逆平移使旋转轴回到其原始位置

从之前我们在坐标轴进行旋转时,发现其实绕 z z z轴的旋转是最符合我们平时的认知的,因为向右是 x x x轴,向上是 y y y轴,这就是我们使用的二维坐标系,下面讨论使用 z z z轴旋转矩阵的变换序列

我们假设旋转轴由两个点确定, P 1 P_1 P1 P 2 P_2 P2,方向是从 P 1 P_1 P1 P 2 P_2 P2,方向决定了旋转方向
P 1 = ( x 1 , y 1 , z 1 ) P 2 = ( x 2 , y 2 , z 2 ) P_1 = (x_1, y_1, z_1)\\ P_2 = (x_2, y_2, z_2) P1=(x1,y1,z1)P2=(x2,y2,z2)
V V V为旋转轴的方向向量,则:
V = P 2 − P 1 = ( x 2 − x 1 , y 2 − y 1 , z 2 − z 1 ) \begin{aligned} V & = P_2 - P_1\\ & = (x_2 - x_1,y_2 - y_1,z_2 - z_1) \end{aligned} V=P2P1=(x2x1,y2y1,z2z1)
u u u为旋转轴单位方向向量,则:
u = V ∣ V ∣ = ( a , b , c ) u = \frac{V}{|V|} = (a,b,c) u=VV=(a,b,c)
其中:
a = x 2 − x 1 ∣ V ∣ ,    b = y 2 − y 1 ∣ V ∣ ,    c = z 2 − z 1 ∣ V ∣ a = \frac{x_2 - x_1}{|V|}, \ \ b = \frac{y_2 - y_1}{|V|}, \ \ c = \frac{z_2 - z_1}{|V|} a=Vx2x1,  b=Vy2y1,  c=Vz2z1
下面给出初始位置图:
在这里插入图片描述

平移到原点

我们把 P 1 P_1 P1平移到原点,下面是平移矩阵,平移后 P 2 P_2 P2也变成了 P 2 ′ P_2^{'} P2
( 1 0 0 − x 1 0 1 0 − y 1 0 0 1 − z 1 0 0 0 1 ) \begin{pmatrix} 1&0&0&-x_1\\ 0&1&0&-y_1\\ 0&0&1&-z_1\\ 0&0&0&1\\ \end{pmatrix} 100001000010x1y1z11
在这里插入图片描述

将旋轴转旋转到z轴

将旋轴转旋转到 z z z轴的思路是:

  • 先将旋转轴绕 x x x轴旋转到 x z xz xz平面
  • 然后绕 y y y轴旋转到与 z z z轴重合

在这里插入图片描述

x x x轴旋转到 x z xz xz平面

旋转角度为 α \alpha α
在这里插入图片描述

绕x轴的旋转矩阵我们上面已经介绍了,最重要的是要知道绕 x x x轴旋转到 x z xz xz平面的弧度的正弦余弦值

如果我们把 u u u投影到 y z yz yz平面 u ′ u^{'} u,则 u ′ u^{'} u z z z轴正向的夹角即为 α \alpha α
在这里插入图片描述

我们前面已经获取到了 u u u的坐标,所以
c o s ( α ) = c d ,    d = b 2 + c 2 s i n ( α ) = b d ,    d = b 2 + c 2 cos(\alpha) = \frac{c}{d},\ \ d = \sqrt{b^2 + c^2}\\ sin(\alpha) = \frac{b}{d},\ \ d = \sqrt{b^2 + c^2}\\ cos(α)=dc,  d=b2+c2 sin(α)=db,  d=b2+c2

此时我们可以获取到绕x轴旋转到 x z xz xz平面的旋转矩阵了
R x = ( 1 0 0 0 0 c d − b d 0 0 b d c d 0 0 0 0 1 ) R_x = \begin{pmatrix} 1&0&0&0\\ 0&\frac{c}{d}&-\frac{b}{d}&0\\ 0&\frac{b}{d}&\frac{c}{d}&0\\ 0&0&0&1\\ \end{pmatrix} Rx= 10000dcdb00dbdc00001
旋转后的 x z xz xz平面的向量记为 u ′ ′ u^{''} u′′

y y y轴旋转到 z z z

下一步需要确定变换矩阵,此矩阵将 x x x平面上的单位向量绕 y y y轴逆时针旋转到 z z z轴的正方向
x x x轴旋转后, x x x平面上单位向量的方向如下:
在这里插入图片描述

到目前为止,我们先理清 u ′ ′ u^{''} u′′的部分情况:

  • 因为绕 x x x轴的旋转保持 x x x分量不变,故其 x x x分量值仍为 a a a
  • 因为绕 x x x轴的旋转使 u ′ u^{'} u旋转到了 z z z轴上,所以 u ′ ′ u^{''} u′′ z z z分量为 d d d
  • u ′ ′ u^{''} u′′ y y y分量为0

根据上面的条件,我们可以得出 u ′ ′ u^{''} u′′旋转到 z z z轴正向的正弦余弦值
c o s ( β ) = d s i n ( β ) = − a cos(\beta) = d\\ sin(\beta) = -a cos(β)=dsin(β)=a

所以,旋转矩阵为
R y = ( d 0 − a 0 0 1 0 0 a 0 d 0 0 0 0 1 ) R_y = \begin{pmatrix} d&0&-a&0\\ 0&1&0&0\\ a&0&d&0\\ 0&0&0&1\\ \end{pmatrix} Ry= d0a00100a0d00001

z z z轴旋转

直接给出旋转矩阵了:
R z = ( c o s ( θ ) − s i n ( θ ) 0 0 s i n ( θ ) c o s ( θ ) 0 0 0 0 1 0 0 0 0 1 ) R_z= \begin{pmatrix} cos( \theta) & -sin( \theta) & 0& 0\\ sin( \theta) & cos( \theta)& 0& 0\\ 0& 0& 1& 0\\ 0 & 0& 0& 1\\ \end{pmatrix} Rz= cos(θ)sin(θ)00sin(θ)cos(θ)0000100001

最终的矩阵

到现在,很容易就能得出绕任意轴进行旋转的矩阵表示
R ( θ ) = T − 1 ∗ R x ( α ) ∗ R y − 1 ( β ) ∗ R z ( θ ) ∗ R y ( β ) ∗ R x ( α ) ∗ T R(\theta) = T^{-1}*R_x^{}(\alpha)*R_y^{-1}(\beta)*R_z(\theta)*R_y(\beta)*R_x(\alpha)*T R(θ)=T1Rx(α)Ry1(β)Rz(θ)Ry(β)Rx(α)T

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值