叉积
叉积把两个三维向量变成第三个向量:它垂直于两者,长度等于两者围成的平行四边形的面积,方向由右手定则决定。力矩、旋转物体上一点的速度、曲面的法向量,背后都是它。把它写成一个斜对称矩阵 \(\skew{\mathbf a}\),还能通向李群。
1为什么机器人需要它
机械臂手里拿着一块砖,肩关节要出多大的力来撑住它?这取决于砖有多重,也取决于砖离关节有多远、往哪个方向压。同样 10 牛的力,顺着手臂的方向推,关节纹丝不动;垂直于手臂推,关节被拧得最狠。"一个力对关节有多大的拧劲",就是叉积算出来的:\(\boldsymbol\tau = \mathbf r \times \mathbf F\)。
同一个运算在机器人里反复出现:
- 力矩:\(\boldsymbol\tau = \mathbf r\times\mathbf F\),一个力拧关节的力度。
- 旋转物体上一点的速度:转台、轮子、旋转的夹爪上,离轴心 \(\mathbf r\) 处的点速度为 \(\mathbf v = \boldsymbol\omega\times\mathbf r\)。
- 曲面的法向量:点云里取相邻三点,用叉积得到它们所在平面的法向,这就是抓取时的接近方向。
- 左转还是右转:二维路径规划里,判断拐角、求凸包、判断障碍物在直线哪一侧,用的都是叉积的符号。
更往后,叉积的矩阵形式 \(\skew{\boldsymbol\omega}\) 是旋转的"导数",5.5 和 5.6 节的李代数、指数映射都建立在它上面。
2直觉:一支垂直的箭头,长度是面积
在平面里,两个向量围出一个平行四边形,面积是一个数(1.5 节的行列式)。到了三维,这个平行四边形可以朝任何方向"躺着":只说面积还不够,还得说它躺在哪个平面里。叉积把两件事打包成一个向量:
- 长度是平行四边形的面积,\(\lVert\mathbf a\times\mathbf b\rVert = \lVert\mathbf a\rVert\lVert\mathbf b\rVert\sin\theta\);
- 方向垂直于这个平面,也就是同时垂直于 \(\mathbf a\) 和 \(\mathbf b\)。垂直方向有两个(朝上或朝下),由右手定则选:四指从 \(\mathbf a\) 弯向 \(\mathbf b\),拇指指向 \(\mathbf a\times\mathbf b\)。
如果 \(\mathbf a\)、\(\mathbf b\) 平行,平行四边形压成一条线,面积为零,叉积就是零向量。下面固定 a,让 b 在水平面里转一圈,看 a × b 怎么变。
叉积 = 面积 + 朝向,装进一个向量里。长度告诉你"围出了多少面积",方向告诉你"这块面积躺在哪个平面里、哪一面朝外"。
3动手玩:三维叉积实验室
用下面六个滑块摆放 a 和 b:每个向量由方位角(绕 z 轴转)、仰角(离开水平面)和长度决定。右边是实时读数,下方是逐分量的计算。也可以点一个预设,或者显示琥珀色虚线的 b × a。
- 只用滑块(不用预设),让 a × b 笔直朝上(+z)。提示:a、b 应该躺在哪个平面里?谁在谁的逆时针一侧?
- 让 a、b 都不是零向量,但 a × b = 0。这时平行四边形变成了什么?
- 让两个向量都不短于 1.2,并使 \(\lVert\mathbf a\times\mathbf b\rVert\) 达到上限 \(\lVert\mathbf a\rVert\lVert\mathbf b\rVert\)(读数两行相等)。夹角应该是多少?
- 点预设 x × y = z,然后只改 b(不碰 a 的滑块),让 a × b 翻成朝下。
4第二个视角:二维里的叉积是一个有符号的数
把 \(\mathbf a\)、\(\mathbf b\) 都放进 xy 平面(\(z=0\))。它们围出的平行四边形躺在这个平面里,叉积必然沿着 z 轴,只剩一个分量要算:
这正是 1.5 节的行列式:面积的正负号里藏着方向信息。结果为正,说明 \(\mathbf b\) 在 \(\mathbf a\) 的左边(从 \(\mathbf a\) 逆时针转不到 180° 就能到 \(\mathbf b\));为负,\(\mathbf b\) 在右边;为零,两者共线。拖动下图的两个箭头尖。
- 让 b 在 a 的左边,面积大于 1。
- 让 b 在 a 的右边,面积小于 −1。
- 让两个向量都不短于 1,并且共线(面积为 0)。
- 让叉积恰好等于 2(精度 0.05)。有很多种摆法,试试用最短的向量。
小游戏:左转还是右转
一台机器人沿着路径点走。在每个拐角处,设进来的方向是 \(\mathbf u = p_i - p_{i-1}\),出去的方向是 \(\mathbf v = p_{i+1}-p_i\),则 \(\mathbf u\times\mathbf v>0\) 是左转,\(<0\) 是右转。不用算角度,不用 \(\arctan\),一次乘减就够了。
"搭路径"模式下拖动路径点,实时看每个拐角;"抢答"模式下看一眼就判断。
- 在"搭路径"模式下,把路径改成恰好两个左转、一个右转(三个拐角,不能有"几乎直行"的)。
- 在"抢答"模式下连续答对 5 题。
同一个符号判断用在很多地方:凸包算法(Graham 扫描、Andrew 单调链)每加一个点都问"是不是左转";多边形顶点按逆时针还是顺时针排列,看各边叉积之和(鞋带公式)的正负;障碍物在规划线段的哪一侧,用 \((\mathbf b-\mathbf a)\times(\mathbf p-\mathbf a)\) 的符号;轨迹上的急转弯检测也是它。它只用乘法和减法,没有三角函数,快而且稳。
5第三个视角:叉积是一个矩阵
固定 \(\mathbf a\),看 \(\mathbf b\mapsto\mathbf a\times\mathbf b\)。这个映射对 \(\mathbf b\) 是线性的:\(\mathbf a\times(s\mathbf b+t\mathbf c) = s\,\mathbf a\times\mathbf b + t\,\mathbf a\times\mathbf c\)。1.3 节说过,线性映射都是矩阵。它的矩阵由 \(\mathbf a\) 的三个分量排成,叫做 \(\mathbf a\) 的叉积矩阵(hat 矩阵):
用下面的图验证:改 \(\mathbf a\) 和 \(\mathbf b\)(左右拖动数字,或直接输入),看矩阵乘出来的结果是不是琥珀色的 \(\mathbf a\times\mathbf b\)。淡琥珀色的圆盘是单位球经过 \(\skew{\mathbf a}\) 后的像:球被压扁成一个垂直于 \(\mathbf a\) 的圆盘,半径 \(\lVert\mathbf a\rVert\)。矩阵的秩是 2,沿 \(\mathbf a\) 的方向被完全抹掉。
- 把 a 设成 \((0,0,1)\)。矩阵的左上角 2×2 是哪个熟悉的矩阵?(见下面的提示框。)
- 选"归一化 â"和"3 次幂",确认 \(\skew{\hat{\mathbf a}}^3 = -\skew{\hat{\mathbf a}}\)(最大差值为 0)。
取 \(\mathbf a=\hat{\mathbf k}=(0,0,1)\):\(\skew{\hat{\mathbf k}} = \begin{bmatrix}0&-1&0\\1&0&0\\0&0&0\end{bmatrix}\)。左上角的 2×2 就是 1.3 节的"逆时针 90° 旋转",而 z 分量被抹掉。也就是说,\(\hat{\mathbf k}\times\mathbf b\) 把 \(\mathbf b\) 投到 xy 平面再逆时针转 90°。一般的 \(\mathbf a\) 做的是同样的事:把 \(\mathbf b\) 投到垂直于 \(\mathbf a\) 的平面,转 90°,再乘上 \(\lVert\mathbf a\rVert\)。
6再看数学
提示:把鼠标悬停在公式中带底色的符号上,FIG 2 中对应的元素会被高亮。
分量公式与记忆窍门
每个分量是"另外两个下标"的交叉相乘再相减,下标按 1→2→3→1 循环。更好记的是一个"形式上的行列式",第一行放的不是数而是基向量:
例:\(\mathbf a=(1,0,2)\),\(\mathbf b=(0,1,0)\),则 \(\mathbf a\times\mathbf b = (0\cdot0-2\cdot1,\; 2\cdot0-1\cdot0,\; 1\cdot1-0\cdot0) = (-2,0,1)\)。检验:与 \(\mathbf a\) 的点积是 \(-2+0+2=0\),与 \(\mathbf b\) 的点积是 0,确实同时垂直于两者。
几何意义:长度与方向
其中 \(\hl{theta}{\theta}\in[0,\pi]\) 是 \(\mathbf a\)、\(\mathbf b\) 的夹角。理由:以 \(\lVert\mathbf a\rVert\) 为底,平行四边形的高是 \(\lVert\mathbf b\rVert\sin\theta\),面积 = 底 × 高。把它和点积(1.7 节)放在一起看:
点积量"有多同向"(cos 部分),叉积量"有多垂直"(sin 部分)。最后一个等式叫拉格朗日恒等式,把分量展开就能验证;它对应 \(\cos^2\theta+\sin^2\theta=1\)。
代数性质
| 性质 | 公式 | 含义 |
|---|---|---|
| 反交换 | \(\mathbf b\times\mathbf a = -\,\mathbf a\times\mathbf b\) | 交换顺序,方向翻转,长度不变 |
| 自叉为零 | \(\mathbf a\times\mathbf a = \mathbf 0\) | 平行四边形没有面积 |
| 平行判据 | \(\mathbf a\times\mathbf b=\mathbf 0 \iff \mathbf a\parallel\mathbf b\) | (其中一个为零向量也算) |
| 双线性 | \(\mathbf a\times(s\mathbf b+t\mathbf c)=s\,\mathbf a\times\mathbf b+t\,\mathbf a\times\mathbf c\) | 对每个位置都线性,所以才有矩阵 \(\skew{\mathbf a}\) |
| 基向量循环 | \(\ihat\times\jhat=\khat,\ \jhat\times\khat=\ihat,\ \khat\times\ihat=\jhat\) | 右手系的定义性质 |
| 不满足结合律 | \((\mathbf a\times\mathbf b)\times\mathbf c\ne\mathbf a\times(\mathbf b\times\mathbf c)\) | 括号不能乱动,见下 |
非结合的反例:\(\ihat\times(\ihat\times\jhat) = \ihat\times\khat = -\jhat\),但 \((\ihat\times\ihat)\times\jhat = \mathbf 0\times\jhat=\mathbf 0\)。要化简嵌套的叉积,用 BAC-CAB 公式:\(\mathbf a\times(\mathbf b\times\mathbf c) = \mathbf b\,(\mathbf a\cdot\mathbf c) - \mathbf c\,(\mathbf a\cdot\mathbf b)\)。
三重积:体积
其中 \(V_{\mathbf a,\mathbf b,\mathbf c}\) 是 \(\mathbf a,\mathbf b,\mathbf c\) 张成的平行六面体的体积,三重积是带符号的体积。\(\mathbf b\times\mathbf c\) 的长度是底面积,方向垂直于底面;再和 \(\mathbf a\) 点积,就是 \(\mathbf a\) 在垂直方向的分量(高)乘底面积,即体积。正负号反映 \((\mathbf a,\mathbf b,\mathbf c)\) 是不是右手系,这就是 1.5 节说的三维行列式。例:\(\mathbf a=(1,0,0)\),\(\mathbf b=(1,2,0)\),\(\mathbf c=(1,1,3)\),则 \(\mathbf b\times\mathbf c=(6,-3,-1)\),\(\mathbf a\cdot(\mathbf b\times\mathbf c)=6\);矩阵是上三角的,行列式 \(1\cdot2\cdot3=6\),一致。
hat 矩阵的恒等式
第二条(斜对称)读矩阵就能看出:对角线是 0,关于对角线对称位置的两个数互为相反数。第三条是 \(\mathbf a\times\mathbf a=\mathbf 0\)。因为 \(\skew{\mathbf a}\) 把 \(\mathbf a\) 变成零,它不可逆,秩为 2,零空间是 \(\mathbf a\) 所在的直线(1.6 节)。第四条由 BAC-CAB 得到:\(\skew{\mathbf a}^2\mathbf b=\mathbf a\times(\mathbf a\times\mathbf b)=\mathbf a(\mathbf a\cdot\mathbf b)-\mathbf b\lVert\mathbf a\rVert^2\)。第五条再乘一次 \(\skew{\mathbf a}\),利用 \(\skew{\mathbf a}\mathbf a=\mathbf 0\):\(\skew{\mathbf a}^3=\skew{\mathbf a}\mathbf a\mathbf a\T-\lVert\mathbf a\rVert^2\skew{\mathbf a}=-\lVert\mathbf a\rVert^2\skew{\mathbf a}\)。
对单位向量 \(\hat{\mathbf u}\),\(K=\skew{\hat{\mathbf u}}\) 满足 \(K^3=-K\)。于是 \(K\) 的高次幂只在 \(K\) 和 \(K^2\) 之间来回,指数级数 \(e^{\theta K}\) 能合并成 \(I+\sin\theta\,K+(1-\cos\theta)K^2\):这就是 5.6 节的罗德里格斯公式。
右手定则依赖右手系
分量公式只是算术,在哪个坐标系里算数字都一样。"拇指方向"则是几何陈述,只有当 \((x,y,z)\) 构成右手系(\(\ihat\times\jhat=\khat\),本课程的约定)时才成立。在左手系里,同样的算术给出的箭头会按左手定则取向,也就是整体翻到另一边。
7机器人中的它:力矩、转动的速度、法向量
力矩:\(\boldsymbol\tau=\mathbf r\times\mathbf F\)
关节在原点,连杆伸到作用点 \(\mathbf r\),那里有一个力 \(\mathbf F\)。关节感受到的拧劲是 \(\boldsymbol\tau=\mathbf r\times\mathbf F\),它沿着关节轴。在平面里它退化成一个数 \(\tau=r_xF_y-r_yF_x\):正号表示逆时针拧。大小还可以写成 \(\tau=\lVert\mathbf F\rVert\cdot d\),\(d\) 是关节到力的作用线的垂直距离(力臂)。只有垂直于连杆的那部分力才拧关节。
拖动连杆末端(青色点)和力的箭头尖(紫色)。切换到"转动"模式,可以看同一个叉积的另一种用法。
- 在"力矩"模式下,用力推(不小于 3 N),却产生零力矩。力应该沿着什么方向?
- 在"转动"模式下,让所选点的速度笔直朝上。点应该在转轴的哪一侧?把 ω 改成负数,答案怎么变?
转台以 30 转/分钟转动,\(\omega=30\cdot2\pi/60=\pi\approx3.14\) rad/s,方向沿转轴。距轴心 0.2 m 的点速度大小 \(\lVert\boldsymbol\omega\rVert\lVert\mathbf r\rVert\sin 90^\circ\approx0.63\) m/s,方向垂直于半径,沿切线。轮子、旋转的夹爪、机械臂连杆上任一点的速度都是这样算的。如果 \(\boldsymbol\omega\) 和 \(\mathbf r\) 平行(点正好在转轴上),叉积为零,点不动。写成矩阵就是 \(\mathbf v=\skew{\boldsymbol\omega}\mathbf r\),这个 \(\skew{\boldsymbol\omega}\) 就是 5.5 节要讲的角速度的 hat。
三点求法向量
点云里取相邻三点 \(p_1,p_2,p_3\),两条边的叉积垂直于它们所在的平面:
未归一化的 \(\mathbf N\) 顺手给出三角形的面积 \(A_\triangle\)(平行四边形的一半)。下面给三个点加一点测量噪声,看噪声怎么影响法向量。深色的 琥珀色箭头 是无噪声的法向量,青色小点是 36 次加噪后的单位法向量的尖端。
- 把三角形压得足够扁,使法向量的平均误差超过 15°。
- 不动任何点,只点"交换 2 ↔ 3",让法向量朝下。
点云库一般取一个点的 20 个左右近邻,用 PCA(1.12 节)拟合平面,取最小奇异方向作法向量:它用了所有点,比三点叉积稳得多。叉积仍然用在网格里:给每个三角面算法向量,顶点法向量取周围面的加权平均(面积就是权重,未归一化的 \(\mathbf N\) 本来就带着)。法向量的符号需要统一:常见做法是和朝向传感器的向量点乘,为负就翻转。
8常见误区
\(\mathbf b\times\mathbf a=-\,\mathbf a\times\mathbf b\)。顺序写反,结果整个翻到另一侧。网格里三角形的顶点顺序(绕行方向)决定法向量朝外还是朝里:法向量指进物体内部,通常就是顶点顺序反了。力矩 \(\mathbf r\times\mathbf F\) 也一样,写成 \(\mathbf F\times\mathbf r\) 会得到相反的转向。
叉积的"垂直于平面的方向"只有在三维才唯一。二维里的"叉积" \(a_1b_2-a_2b_1\) 是一个数,是三维叉积 z 分量的简写。把它当向量去加、去归一化,是常见的类型错误。
\(\lVert\mathbf a\times\mathbf b\rVert=\lVert\mathbf a\rVert\lVert\mathbf b\rVert\sin\theta\),不是 1。要单位法向量,必须再除以长度,并且防止除以零。近乎共线的三点,\(\sin\theta\) 很小,长度被压缩,方向几乎由噪声决定(FIG 7)。这种三角形(细长的"针")不该拿来估计法向量。
本课程的所有坐标系都是右手系。但 Unity、DirectX 等引擎默认左手系:用同样的公式,叉积指向反过来。接数据时先确认两边的手性,不一致就要换算,否则法向量、旋转轴、力矩的符号会全部反号。
\((\mathbf a\times\mathbf b)\times\mathbf c\) 与 \(\mathbf a\times(\mathbf b\times\mathbf c)\) 一般不相等(见"再看数学"里的反例)。连续叉乘(例如 \(\boldsymbol\omega\times(\boldsymbol\omega\times\mathbf r)\) 向心加速度)要保留括号,化简用 BAC-CAB。
9小练习
10延伸阅读
- 3Blue1Brown, Essence of Linear Algebra — 第 10 章"叉积"与第 11 章"从线性变换看叉积"
- G. Strang, Introduction to Linear Algebra, §5.3 — 叉积、面积与体积
- K. Lynch & F. Park, Modern Robotics, §3.2.3 — 角速度与斜对称矩阵
- J. Solà, J. Deray & D. Atchuthan, "A micro Lie theory for state estimation in robotics", 2018 — hat 矩阵如何通向李代数