1 右手坐标系
右手坐标系如下图:
X
:拇指
指向X轴
Y
:食指
指向Y轴
Z
:中指
指向Z轴
可能很多人还是记不住,我个人总结两个小技巧,很容易牢记右手坐标系
:
X、Y、Z
的顺序刚好也是对应手指大拇指、食指、中指
也是顺序排列的
做一个右手坐标系
的姿势,然后让食指(Y轴)
指向别人的姿势,很容易就可以把右手坐标系画出来
如下,是我画的右手坐标系:
1.1 旋转90度是什么样的
例如X轴
顺时针旋转90度,为了验证这个旋转结果是否正确
,我们需要弄清楚这个90度是怎么旋转的:
可以从原点(0,0,0)向X轴看,此时就可以把三维坐标系
降维到二维坐标系YOZ
绕X轴旋转的过程中,自然X轴的坐标是不变的,只有Y和Z是变化的。
例如:(2, 0, 3)绕X轴顺时针旋转90度,旋转后的坐标为:(2, 3, 0)
2 XYZ空间内某点绕X、Y、Z轴旋转一次
首先假设:
旋转前
坐标为:$(x, y, z)$
旋转后
坐标为:$(x^{\prime}, y^{\prime}, z^{\prime})$
下面用一些内容的简单说明:
1、角度
和弧度
的相互转化(关于角度和弧度的更多介绍参考)
角度
转弧度
: $弧度 = 角度 \times \frac{\pi}{180}$
弧度
转角度
:$角度 = 弧度 \times \frac{180}{\pi}$
2、python的math
模块和numpy
模块计算正弦sin和余弦cos输入的参数值都是弧度制
的
如下,计算sin90度
:
>>> import numpy as np>>> import math>>> np.sin(90*(np.pi/180))1.0>>> math.sin(90*(math.pi/180))1.0>>>
2.1 XYZ空间内某点绕Z轴旋转γ角
1、绕Z轴
旋转:Z轴的坐标是不变化的
$$ \left[x^{\prime}, y^{\prime}, z^{\prime}, 1\right]=[x, y, z, 1]\left[\begin{array}{cccc} \cos \gamma & \sin \gamma & 0 & 0 \ -\sin \gamma & \cos \gamma & 0 & 0 \ 0 & 0 & 1 & 0 \ 0 & 0 & 0 & 1 \end{array}\right] $$
然后公式可以表示为:
$$ \begin{array}{l} x^{\prime}=\cos \gamma \cdot x-\sin \gamma \cdot y \ y^{\prime}=\sin \gamma \cdot x+\cos \gamma \cdot y \ z^{\prime}=z \end{array} $$
2、python
实现XYZ空间内某点绕Z轴旋转γ角
# 1、绕Z周旋转gamma角def rotate_Z(x, y, z, gamma): gamma = gamma * (np.pi / 180) x_r = np.cos(gamma)*x - np.sin(gamma)*y y_r = np.sin(gamma)*x + np.cos(gamma)*y z_r = z print(f"{(x, y, z)} rotate {gamma*(180/np.pi)} degrees around the Z-axis,result {(x_r, y_r, z_r)}") return x_r, y_r, z_r
3、C++
实现XYZ空间内某点绕Z轴旋转γ角
//将空间点绕Z轴旋转//输入参数 x y为空间点原始x y坐标//thetaz为空间点绕Z轴旋转多少度,角度制范围在-180到180//outx outy为旋转后的结果坐标void codeRotateByZ(double x, double y, double thetaz, double& outx, double& outy){ double x1 = x;//将变量拷贝一次,保证&x == &outx这种情况下也能计算正确 double y1 = y; double rz = thetaz * CV_PI / 180; outx = cos(rz) * x1 - sin(rz) * y1; outy = sin(rz) * x1 + cos(rz) * y1;}
2.2 XYZ空间内某点绕Y轴旋转β角
1、绕Z轴
旋转:Z轴的坐标是不变化的
$$ \left[x^{\prime}, y^{\prime}, z^{\prime}, 1\right]=[x, y, z, 1]\left[\begin{array}{cccc} \cos \beta & 0 & -\sin \beta & 0 \ 0 & 1 & 0 & 0 \ \sin \beta & 0 & \cos \beta & 0 \ 0 & 0 & 0 & 1 \end{array}\right] $$
然后公式可以表示为:
$$ \begin{array}{l} x^{\prime}=\cos \beta \cdot x+\sin \beta \cdot z \ y^{\prime}=y \ z^{\prime}=-\sin \beta \cdot x+\cos \beta \cdot z \end{array} $$
2、python
实现XYZ空间内某点绕Y轴旋转β角
# 2、绕Y轴旋转beta角def rotate_Y(x, y, z, beta): beta = beta * (np.pi / 180) x_r = np.cos(beta)*x + np.sin(beta)*z y_r = y z_r = -np.sin(beta)*x + np.cos(beta)*z print(f"{(x, y, z)} rotate {beta*(180/np.pi)} degrees around the Y-axis,result {(x_r, y_r, z_r)}") return x_r, y_r, z_r
3、C++
实现XYZ空间内某点绕Y轴旋转β角
//将空间点绕Y轴旋转//输入参数 x z为空间点原始x z坐标//thetay为空间点绕Y轴旋转多少度,角度制范围在-180到180//outx outz为旋转后的结果坐标void codeRotateByY(double x, double z, double thetay, double& outx, double& outz){ double x1 = x; double z1 = z; double ry = thetay * CV_PI / 180; outx = cos(ry) * x1 + sin(ry) * z1; outz = cos(ry) * z1 - sin(ry) * x1;}
2.3 XYZ空间内某点绕X轴旋转α角
1、绕Z轴
旋转:Z轴的坐标是不变化的
$$ \left[x^{\prime}, y^{\prime}, z^{\prime}, 1\right]=[x, y, z, 1]\left[\begin{array}{cccc} 1 & 0 & 0 & 0 \ 0 & \cos \alpha & \sin \alpha & 0 \ 0 & -\sin \alpha & \cos \alpha & 0 \ 0 & 0 & 0 & 1 \end{array}\right] $$
然后公式可以表示为:
$$ \begin{array}{l} x^{\prime}=x \ y^{\prime}=\cos \alpha \cdot y-\sin \alpha \cdot z \ z^{\prime}=\sin \alpha \cdot y+\cos \alpha \cdot z \end{array} $$
2、python
实现XYZ空间内某点绕X轴旋转α角
# 3、绕X轴旋转alpha角def rotate_X(x, y, z, alpha): alpha = alpha * (np.pi / 180) x_r = x y_r = np.cos(alpha)*y - np.sin(alpha)*z z_r = np.sin(alpha)*y + np.cos(alpha)*z print(f"{(x, y, z)} rotate {alpha*(180/np.pi)} degrees around the X-axis,result {(x_r, y_r, z_r)}") return x_r, y_r, z_r
3、C++
实现XYZ空间内某点绕X轴旋转α角
//将空间点绕X轴旋转//输入参数 y z为空间点原始y z坐标//thetax为空间点绕X轴旋转多少度,角度制范围在-180到180//outy outz为旋转后的结果坐标void codeRotateByX(double y, double z, double thetax, double& outy, double& outz){ double y1 = y;//将变量拷贝一次,保证&y == &y这种情况下也能计算正确 double z1 = z; double rx = thetax * CV_PI / 180; outy = cos(rx) * y1 - sin(rx) * z1; outz = cos(rx) * z1 + sin(rx) * y1;
完整代码:
import numpy as np# 1、绕Z周旋转gamma角def rotate_Z(x, y, z, gamma): gamma = gamma * (np.pi / 180) x_r = np.cos(gamma)*x - np.sin(gamma)*y y_r = np.sin(gamma)*x + np.cos(gamma)*y z_r = z print(f"{(x, y, z)} rotate {gamma*(180/np.pi)} degrees around the Z-axis,result {(x_r, y_r, z_r)}") return x_r, y_r, z_r# 2、绕Y轴旋转beta角def rotate_Y(x, y, z, beta): beta = beta * (np.pi / 180) x_r = np.cos(beta)*x + np.sin(beta)*z y_r = y z_r = -np.sin(beta)*x + np.cos(beta)*z print(f"{(x, y, z)} rotate {beta*(180/np.pi)} degrees around the Y-axis,result {(x_r, y_r, z_r)}") return x_r, y_r, z_r# 3、绕X轴旋转alpha角def rotate_X(x, y, z, alpha): alpha = alpha * (np.pi / 180) x_r = x y_r = np.cos(alpha)*y - np.sin(alpha)*z z_r = np.sin(alpha)*y + np.cos(alpha)*z print(f"{(x, y, z)} rotate {alpha*(180/np.pi)} degrees around the X-axis,result {(x_r, y_r, z_r)}") return x_r, y_r, z_r# https://zh.wikipedia.org/wiki/%E6%97%8B%E8%BD%AC%E7%9F%A9%E9%98%B5# 可能是坐标系的不同,维基百科上的斜对角的sin的负号,和我们使用的刚好是交换过来的if __name__ == '__main__': # 1、绕Z轴旋转,Z值不变 # 点(2, 0, 12)绕Z轴旋转90度,旋转后 (0, 2, 12) rotate_Z(2, 0, 12, 90) # 2、绕Y轴旋转,Y值不变 # 点(3, 4, 0)绕Y轴顺时针旋转90度,旋转后 (0, 4, -3) rotate_Y(3, 4, 0, 90) # 3、绕X轴旋转,X值不变 # 点(5, 0, 7)绕X轴顺时针旋转90度,旋转后 (5, -7, 0) rotate_X(5, 0, 7, 90) x, y, z = 1, 2, 3 x, y, z = rotate_X(x, y, z, 90) x, y, z = rotate_Y(x, y, z, -90) x, y, z = rotate_Z(x, y, z, -90) # 结果:(1,2,3) -> (-3, 2, 1) x, y, z = 1, 2, 3 x, y, z = rotate_Z(x, y, z, 90) x, y, z = rotate_Y(x, y, z, -90) x, y, z = rotate_X(x, y, z, -90) # 结果: (1,2,3) - > (-3, -2, -1) # 因此不同的旋转顺序会导致旋转的结果不一样
如果你看维基百科,会发现在维基百科上我们绕每个轴的旋转矩阵,斜对角的两个sin正弦值的正负号刚好是交换过来的,这个可能就可坐标系的选择有关了,我们这里选择的是右手坐标系
!
旋转变换参考 参考:https://www.cnblogs.com/singlex/p/3DPointRotate.html