一个看似简单的问题
把手机随手拍在一块倾斜的桌面、岩层面或者墙面上,不管手机是横着放、竖着放、还是斜着扭一个角度贴上去,只要它紧贴着那个平面,手机总能算出这个平面「朝哪个方向倾、倾多少度」。地质上把这两个量叫产状:倾向(dip direction)和倾角(dip)。手机里的「产状测量」「电子罗盘」App 干的就是这件事。
关键的直觉是:手机贴在平面上时,它自己的朝向是任意的(你可以随便转),但它背面(屏幕法线)永远垂直于那个平面。所以平面的产状只跟法线有关,跟手机怎么摆无关。这篇文章把这套逻辑从头推一遍,给出可复现的计算案例和可视化。
三个姿态角的英文说法
描述一个刚体在空间里的朝向,最常用的是三个欧拉角。中英文对照如下:
- 俯仰角 —— Pitch,绕横轴(x 轴,机体的左右方向)旋转,抬头/低头。
- 横滚角 —— Roll,绕纵轴(y 轴,机体的前后方向)旋转,左右翻滚。
- 偏航角 —— Yaw,绕竖轴(z 轴,垂直机体平面)旋转,也就是航向(Heading)。
在航空航天里这三个词几乎是固定搭配。另外你还会见到几个近义词:航向角常写作 Heading 或 Azimuth(方位角);整体姿态叫 Attitude 或 Orientation;三个角合起来常缩写为 RPY(Roll-Pitch-Yaw)。手机传感器文档里则叫 Pitch / Roll / Azimuth。

坐标系与旋转约定
要把话说清楚,先固定两个坐标系。
世界系(导航系)用 ENU:x 轴指向正东(East),y 轴指向正北(North),z 轴指向天顶(Up)。这是本地水平坐标系的标准约定之一。
机体系(手机系):x 轴指向手机右侧,y 轴指向手机顶部,z 轴垂直屏幕向外——这正是手机加速度计/陀螺仪的常见轴向。
姿态就是一个旋转矩阵 $R$,它把机体系的坐标变换到世界系。$R$ 的三个列向量,恰好就是机体三个轴在世界系(ENU)里的方向。我们采用 Z-X-Y 的旋转次序(先偏航、再俯仰、后横滚):
$$R = R_z(\text{yaw})\, R_x(\text{pitch})\, R_y(\text{roll})$$
其中各基本旋转为:
$$R_x(\alpha)=\begin{bmatrix}1&0&0\0&\cos\alpha&-\sin\alpha\0&\sin\alpha&\cos\alpha\end{bmatrix},\quad R_y(\beta)=\begin{bmatrix}\cos\beta&0&\sin\beta\0&1&0\-\sin\beta&0&\cos\beta\end{bmatrix},\quad R_z(\gamma)=\begin{bmatrix}\cos\gamma&-\sin\gamma&0\\sin\gamma&\cos\gamma&0\0&0&1\end{bmatrix}$$
手机的姿态怎么来的?静止时,加速度计测得的是重力反方向(近似天顶方向),由此可解出 pitch 和 roll;磁力计测得地磁水平分量,配合前两个角度可解出 yaw(航向)。这三个角就是我们的输入。
核心一步:屏幕法线的方向
手机贴在平面上,手机的 z 轴(屏幕法线)就等于平面的法线。而机体 z 轴在世界系里的方向,正是旋转矩阵的第三列:
$$\mathbf{n} = R \begin{bmatrix}0\0\1\end{bmatrix} = R_{:,3}$$
把 $R = R_z R_x R_y$ 展开,第三列只跟 pitch、yaw 有关(roll 是绕 y 轴自身,不改变 y 轴、也就不改变第三列的方向):
$$\mathbf{n} = \begin{bmatrix} n_E \ n_N \ n_U \end{bmatrix} = \begin{bmatrix} \sin(\text{yaw})\cos(\text{pitch}) \ \cos(\text{yaw})\cos(\text{pitch}) \ \cos(\text{pitch}) \end{bmatrix}$$
这就是「怎么摆都一样」的数学原因:roll 不出现在法线公式里。你绕着屏幕法线随便自转(改变的是 roll 和一部分 yaw 的组合),只要 z 轴指向不变,法线就不变,产状自然不变。
从法线到产状(倾向与倾角)
有了单位法线 $\mathbf{n}=(n_E, n_N, n_U)$(约定朝上,若 $n_U<0$ 就整体取反),产状就是简单的几何:
倾角 是平面与水平面的夹角,等于法线与竖直方向的夹角:
$$\text{dip} = \arccos\left(n_U\right)$$
倾向 是平面「最陡下坡」方向的水平方位角,从正北起顺时针度量。最陡下坡方向是法线在水平面的投影的反方向,因此:
$$\text{dip direction} = \operatorname{atan2}\left(-n_E,\; -n_N\right) \bmod 360^\circ$$
反过来,已知产状也能重建法线,用于校验:设上倾方位角 $\phi = (\text{dip direction} + 180^\circ)$,则
$$\mathbf{n} = \big(\sin(\text{dip})\sin\phi,\; \sin(\text{dip})\cos\phi,\; \cos(\text{dip})\big)$$
关键演示:同一平面,两种任意摆法
下面这个 GIF 是全文的核心。同一个倾斜平面,手机绕着屏幕法线不停自转(模拟你「随便怎么贴」)。注意看:上面一行的 yaw / pitch / roll 一直在剧烈变化,而下面一行的 倾角、倾向纹丝不动。

我们用一个具体的平面来跑数值——真实产状定为倾角 35°、倾向 120°,对应法线(ENU)为 $(-0.4967,\ 0.2868,\ 0.8192)$。然后用两种完全不同的摆法把手机贴上去:
| 摆法 | yaw | pitch | roll | 反算法线 (E,N,U) | 倾角 | 倾向 |
|---|---|---|---|---|---|---|
| 摆法一(spin=0°) | 60.00° | −35.00° | 0.00° | (−0.4967, 0.2868, 0.8192) | 35.00° | 120.00° |
| 摆法二(spin=137°) | −168.70° | 24.80° | 25.53° | (−0.4967, 0.2868, 0.8192) | 35.00° | 120.00° |
两种摆法的三个欧拉角天差地别,但反算出来的法线一模一样,产状都精确回到 35°/120°。这正是手机「怎么放都能测」的底气。

完整可复现代码
下面是从三个姿态角到产状的核心函数,以及上面案例的验证。可直接运行。
import numpy as np
r2d, d2r = np.rad2deg, np.deg2rad
def Rx(a): c,s=np.cos(a),np.sin(a); return np.array([[1,0,0],[0,c,-s],[0,s,c]])
def Ry(a): c,s=np.cos(a),np.sin(a); return np.array([[c,0,s],[0,1,0],[-s,0,c]])
def Rz(a): c,s=np.cos(a),np.sin(a); return np.array([[c,-s,0],[s,c,0],[0,0,1]])
def R_from_ypr(yaw, pitch, roll):
return Rz(yaw) @ Rx(pitch) @ Ry(roll) # 列 = 机体轴在 ENU 中的方向
def attitude_from_normal(n):
n = n/np.linalg.norm(n)
if n[2] < 0: n = -n # 法线取朝上
dip = r2d(np.arccos(np.clip(n[2], -1, 1)))
dip_dir = r2d(np.arctan2(-n[0], -n[1])) % 360
return dip, dip_dir
def normal_from_attitude(dip, dip_dir):
up = d2r((dip_dir + 180) % 360)
return np.array([np.sin(d2r(dip))*np.sin(up),
np.sin(d2r(dip))*np.cos(up),
np.cos(d2r(dip))])
# 真实平面:倾角35°,倾向120°
n_true = normal_from_attitude(35, 120)
# 摆法一:yaw=60, pitch=-35, roll=0
R1 = R_from_ypr(d2r(60), d2r(-35), d2r(0))
print(attitude_from_normal(R1 @ [0,0,1.0])) # -> (35.0, 120.0)
# 摆法二:yaw=-168.7, pitch=24.8, roll=25.53
R2 = R_from_ypr(d2r(-168.70), d2r(24.80), d2r(25.53))
print(attitude_from_normal(R2 @ [0,0,1.0])) # -> (35.0, 120.0)
别忘了磁偏角与经纬度
上面算出来的倾向是相对手机航向的,而手机航向来自磁力计,指的是磁北。地质记录和地图用的是真北。两者之差就是磁偏角(magnetic declination),它随经纬度和年份变化,可由 WMM/IGRF 地磁模型按位置查得。校正很简单:
$$\text{倾向}{\text{真北}} = \big(\text{倾向}\big) \bmod 360^\circ$$}} + \text{磁偏角
以重庆(纬度 29.563°、经度 106.551°)为例,磁偏角约 −1.9°(西偏),则磁北倾向 120° 对应真北倾向 118.10°。
如果还想把这个法线放到全球统一的地心地固坐标系(ECEF)里——比如做跨区域的构造统计——就要用经纬度做一次 ENU→ECEF 旋转:
$$\begin{bmatrix}X\Y\Z\end{bmatrix}= \begin{bmatrix}-\sin\lambda & -\sin\varphi\cos\lambda & \cos\varphi\cos\lambda\ \cos\lambda & -\sin\varphi\sin\lambda & \cos\varphi\sin\lambda\ 0 & \cos\varphi & \sin\varphi\end{bmatrix} \begin{bmatrix}n_E\n_N\n_U\end{bmatrix}$$
其中 $\varphi$ 是纬度、$\lambda$ 是经度。同一块岩层面在重庆测得的法线,换算到 ECEF 就是 $(0.3135, 0.6889, 0.6536)$。这样,无论你在地球上哪个位置,任意时刻、任意摆法测到的产状,都能落到同一套全局坐标里比较。
小结
整条链路其实非常干净:
- 手机静止时用加速度计+磁力计解出 yaw / pitch / roll 三个姿态角;
- 组成旋转矩阵 $R$,取第三列得到屏幕法线 $\mathbf{n}$——这一步天然把 roll 消掉,所以怎么摆都行;
- 由法线用 $\arccos$ 和 $\operatorname{atan2}$ 直接读出倾角和倾向;
- 用磁偏角把磁北换成真北,必要时用经纬度把法线搬进 ECEF 全局坐标。
一部手机、几行三角函数,就复刻了地质罗盘的核心功能。而它「随便怎么放都准」的秘密,不过是一句话:产状只认那根垂直于平面的法线,不认手机自己转了多少。
CycleUser