1 问题描述:
1.1 问题1
已知三维空间中的源向量
p
p
p和目标(参考)向量
q
q
q,计算旋转矩阵
R
R
R,最终能够使得源向量
p
p
p在旋转矩阵
R
R
R的作用下,与目标向量
q
q
q对齐(平行),如下图所示。
表示成公式的形式:
式中:
p = [ p x p y p z ] p=\begin{bmatrix} p_x\\ p_y\\ p_z \end{bmatrix} p=⎣⎡pxpypz⎦⎤, q = [ q x q y q z ] q=\begin{bmatrix} q_x\\ q_y\\ q_z \end{bmatrix} q=⎣⎡qxqyqz⎦⎤, R = [ r 11 r 12 r 13 r 21 r 22 r 23 r 31 r 32 r 33 ] R=\begin{bmatrix} r_{11} &r_{12} &r_{13}\\ r_{21} &r_{22} &r_{23}\\ r_{31} &r_{32} &r_{33} \end{bmatrix} R=⎣⎡r11r21r31r12r22r32r13r23r33⎦⎤。
1.2 问题2
已知三维空间中的源向量
p
p
p和目标(参考)向量
q
q
q,以及一锚点
a
a
a,计算刚体变换矩阵
T
T
T,最终能够使得源向量
p
p
p在矩阵
T
T
T的作用下,与目标向量
q
q
q对齐(平行),且矩阵
T
T
T的作用不会改变锚点
a
a
a的位置,如下图所示。
表示成公式的形式:
式中:
T = [ R t 0 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 ] T= \begin{bmatrix} R &t\\ 0 &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} T=[R0t1]=⎣⎢⎢⎡r11r21r310r12r22r320r13r23r330txtytz1⎦⎥⎥⎤。
注:齐次形式下,向量的“尾巴”是0,点的“尾巴”是1。
2 解决方案
2.1 问题1
问题可被简化成:源向量
p
p
p绕向量
n
n
n旋转
θ
\theta
θ角度,能够与目标向量
q
q
q对齐,即罗德里格斯旋转。
其中,向量
n
n
n是向量
p
p
p和
q
q
q所在平面的法向量,旋转角度
θ
\theta
θ是向量
p
p
p和
q
q
q之间的夹角,即:
参考文章:罗德里格斯旋转公式
可得:
式中,矩阵 N N N是向量 n n n的反对称矩阵形式,即:
最终的刚体变换矩阵 T T T如下:
2.2 问题2
问题2相对于问题1,增加了锚点,问题可被简化成:源向量
p
p
p以
a
a
a为旋转中心,并绕向量
n
n
n旋转
θ
\theta
θ角度,最终能够与目标向量
q
q
q对齐。
整个变换过程可以分为3个部分,如下:
- 构造坐标系 x ′ y ′ z ′ x'y'z' x′y′z′
由于是以
a
a
a为旋转中心进行变换,因此,以
a
a
a为原点,构建坐标系
x
′
y
′
z
′
x'y'z'
x′y′z′,各轴方向与坐标系
x
y
z
xyz
xyz的方向一样,因此,坐标系
x
y
z
xyz
xyz相对于坐标系
x
′
y
′
z
′
x'y'z'
x′y′z′的变化矩阵如下:
式(9)中的变换矩阵能够将坐标系 x y z xyz xyz中描述的点,转换至坐标系 x ′ y ′ z ′ x'y'z' x′y′z′空间。
- 在坐标系 x ′ y ′ z ′ x'y'z' x′y′z′下绕向量 n n n旋转 θ \theta θ角度
该过程的变换矩阵可利用罗德里格斯旋转公式获得,即式(8),如下:
- 变换回坐标系 x y z xyz xyz
由式(10)计算得到的点坐标都描述在坐标系
x
′
y
′
z
′
x'y'z'
x′y′z′空间,需要变换回原始坐标系
x
y
z
xyz
xyz中,变换矩阵如下:
合并上述3个过程,即联立式(9)-(11),如下:
上式完整展开如下:
式中,法向量 n = [ u , v , w ] T n=[u,v,w]^T n=[u,v,w]T,锚点 a = [ x , y , z ] T a=[x,y,z]^T a=[x,y,z]T。
3 代码实现
point_anchor = [10;20;30]; % 锚点
vec_src = [sqrt(3)/3;sqrt(3)/3;sqrt(3)/3]; % 源向量
vec_dst = [0;0;1]; % 目标向量
axis_rotation = cross(vec_src,vec_dst); % 叉积
axis_rotation = axis_rotation/norm(axis_rotation); % 单位法向量
angle = acos(dot(vec_src,vec_dst)); % 计算旋转角
axis_rotation_x = axis_rotation(1);
axis_rotation_y = axis_rotation(2);
axis_rotation_z = axis_rotation(3);
N = [0,-axis_rotation_z,axis_rotation_y; % 单位法向量对应的反对称矩阵形式
axis_rotation_z,0,-axis_rotation_x;
-axis_rotation_y,axis_rotation_x,0];
R=eye(3)+sin(angle)*N+(1-cos(angle))*N*N; % 根据罗德里格斯旋转公式求解得到的旋转矩阵
T = [R,-R*point_anchor+point_anchor; % 最终需要的刚体变换矩阵
0,0,0,1]