Part I · 第 1 章 线性代数 · 1.4Part I · Ch. 1 Linear Algebra · 1.4

矩阵乘法即复合Matrix Multiplication as Composition

机器人是一串坐标系:世界、底盘、云台、相机。从一个坐标系走到下一个,是一次变换;走完整条链,是把这些变换一个接一个做下去。矩阵乘法 \(AB\) 的本意正是这个:先做 B,再做 A,合成一个新的变换。"行乘列"只是算它的记账法。顺序一换,结果就变。 A robot is a chain of frames: world, base, pan-tilt head, camera. Going from one frame to the next is one transformation; going down the whole chain is doing them one after another. That is what the matrix product \(AB\) means: do B first, then A, as one new transformation. "Row times column" is only the bookkeeping for computing it. Swap the order and the answer changes.

约 25 分钟~25 min 前置:1.3 矩阵即变换Prereqs: 1.3 Matrices as Transformations 7 个交互7 interactives

    1为什么机器人需要它Why robots need this

    想象一台移动机器人,底盘上立着一个云台,云台上装着相机。相机看到一个杯子,报告:"杯子在我正前方 2.4 米、偏左 0.8 米。"可机械臂要的是杯子在世界坐标系里的位置。怎么换算?

    先用云台相对相机的姿态,把读数换到云台坐标系;再用云台相对底盘的姿态,换到底盘坐标系;最后用底盘相对世界的姿态,换到世界坐标系。每一步是一个矩阵,一共三步。三步不必每次分开做,把它们连乘成一个矩阵,一次就够:

    Picture a mobile robot with a pan-tilt head on its base and a camera on the head. The camera spots a cup and reports: "the cup is 2.4 m straight ahead and 0.8 m to my left." The arm, however, needs the cup in the world frame. How do you convert?

    First use the camera's orientation relative to the head to move the reading into the head frame; then the head's orientation relative to the base to reach the base frame; finally the base's orientation relative to the world. Each step is one matrix, three steps in all. You do not have to apply them separately every time: multiply them into one matrix and a single step does it all:

    $$ {}^{W}R_{C} \;=\; {}^{W}R_{B}\;\;{}^{B}R_{H}\;\;{}^{H}R_{C} $$

    注意下标像多米诺骨牌一样"接龙":相邻的 B 对 B、H 对 H 约掉,剩下最外面的 W 和 C。机械臂也是同一个套路:底座 → 肩 → 肘 → 腕 → 夹爪,一路连乘。

    这条链里最容易出事的是顺序。写反了,程序不会崩溃,只会给出一个看起来合理、其实错了的位置,机器人则会伸手去抓空气。本节只讲旋转,平移要到 5.3 节才加进来。

    Notice how the subscripts chain like dominoes: the neighbouring B's and H's cancel, leaving the outermost W and C. A robot arm follows the same pattern: base → shoulder → elbow → wrist → gripper, multiplied all the way down.

    The treacherous part of this chain is the order. Write it backwards and nothing crashes; you just get a plausible-looking wrong position, and the robot reaches for thin air. This lesson covers rotations only; translations join in Lesson 5.3.

    2直觉:先 B,再 A,合成一个变换Intuition: first B, then A, as one transformation

    上一节学到:矩阵是一个动作,它由 î 和 ĵ 的落点决定。现在做两个动作:先用 \(B\) 把空间变形,再用 \(A\) 把变形后的空间再变形一次。两步合起来仍然是一个线性变换(直线仍是直线,原点不动),所以它也有一个矩阵。这个矩阵怎么找?跟上一节一样:追踪 î 和 ĵ 的去向。

    下图中,\(B\) 是逆时针转 90°,\(A\) 是水平剪切。用下面的切换键一步步看。拖动黄色向量,也可以看它被先后推到哪里。

    Last lesson: a matrix is an action, fixed by where î and ĵ land. Now do two actions: first deform space with \(B\), then deform the deformed space again with \(A\). The two steps together are still a linear transformation (lines stay lines, the origin stays put), so they have a matrix too. How do we find it? Exactly as before: track where î and ĵ go.

    In the figure, \(B\) is a 90° counter-clockwise rotation and \(A\) is a horizontal shear. Step through it with the switch. Drag the amber vector to see where it is pushed at each stage.

    FIG 1两步合成一步Two steps, one matrix
    基向量的旅程The journey of the basis vectors
    黄色向量The amber vector
    淡色网格是原始网格,亮色网格是做完当前步骤后的样子。红、绿箭头是 î、ĵ 当前的位置;虚线箭头是黄色向量在前几步的位置。到最后一步,两个箭头的坐标并排写下来,就是 \(AB\)。 The faint grid is the original; the bright grid is the result after the current step. The red and green arrows are where î and ĵ are right now; dashed arrows show the amber vector at earlier stages. At the last step, the coordinates of the two arrows written side by side are \(AB\).

    看右边的记录。î 先被 \(B\) 送到 \(B\hat\imath\)(就是 \(B\) 的第 1 列),再被 \(A\) 送到 \(A(B\hat\imath)\)。ĵ 同理。所以:

    Read the record on the right. î is first sent by \(B\) to \(B\hat\imath\) (which is just column 1 of \(B\)), then by \(A\) to \(A(B\hat\imath)\). Same story for ĵ. Hence:

    核心洞见Key insight

    \(AB\) 是"先做 B,再做 A"的矩阵。它的第 \(j\) 列,是 \(A\) 作用在 \(B\) 的第 \(j\) 列上的结果。从右往左读:和函数复合 \(f(g(x))\) 一样,离向量最近的那个最先作用。

    \(AB\) is the matrix of "do B, then A". Its column \(j\) is \(A\) applied to column \(j\) of \(B\). Read right to left: just like function composition \(f(g(x))\), the matrix nearest the vector acts first.

    3动手玩:复合实验室Play: the composition lab

    现在你来选 \(A\) 和 \(B\)。改矩阵里的数(左右拖动数字可以连续调节),或点下面的预设。"先 B 后 A" 给出 \(AB\),"先 A 后 B" 给出 \(BA\)。点 ▶ 播放:网格先从单位网格变成第一步的样子,再变成最终的样子。

    Now you choose \(A\) and \(B\). Edit the entries (drag a number sideways to scrub it) or click a preset below. "B then A" gives \(AB\); "A then B" gives \(BA\). Press ▶ to play: the grid first turns from the plain grid into the result of step one, then into the final result.

    FIG 2复合实验室Composition lab
    矩阵 AMatrix A
    矩阵 BMatrix B
    A 预设A presets
    B 预设B presets
    淡色网格是原始网格;青色亮网格是做完当前步骤后的网格,红、绿箭头是 î、ĵ 此刻的位置。进度条拖到最右端时,紫色虚线是另一种顺序的结果。把鼠标悬停在"再看数学"一节的符号 A、B、AB 上,这里会单独画出对应的网格。 The faint grid is the original; the bright cyan grid is the result after the steps so far, and the red and green arrows are where î and ĵ are right now. With the progress bar at the far right, the dashed purple grid is the result of the other order. Hover the symbols A, B, AB in "The math" section and the matching grid is drawn alone here.
    试一试Try this
    • 改动至少一个矩阵,让 \(AB \ne BA\)(很容易),然后切换"先 B 后 A / 先 A 后 B",看两个最终网格不一样。Change at least one matrix so that \(AB \ne BA\) (easy), then flip between "B then A" and "A then B" and watch the two final grids differ.
    • 找两个可交换的矩阵(\(AB = BA\)):两个都不是单位矩阵,且 \(A \ne B\)。提示:两个旋转?两个只沿坐标轴拉伸的矩阵?Find two matrices that commute (\(AB = BA\)): neither is the identity, and \(A \ne B\). Hint: two rotations? Two matrices that only stretch along the axes?
    • 让 \(AB = I\),而 A、B 都不是单位矩阵。这时 B 恰好把 A 撤销了(1.6 节的主题)。提示:拉伸用反向拉伸撤销,旋转用转回去撤销。Make \(AB = I\) with neither A nor B the identity. Now B exactly undoes A (the topic of Lesson 1.6). Hint: undo a stretch by stretching back; undo a rotation by rotating back.
    • 让 \(AB = 0\)(四个数全为 0),而 A、B 都不是零矩阵。提示:先把平面压成一条线,再把剩下的那条线压成一个点。Make \(AB = 0\) (all four entries zero) although neither A nor B is the zero matrix. Hint: squash the plane onto a line, then squash what is left of that line to a point.

    小游戏:这是 AB 还是 BA?Mini-game: is this AB or BA?

    给你两个矩阵 \(A\) 和 \(B\),以及其中一种顺序的最终网格(紫色虚线)。判断它是 \(AB\) 还是 \(BA\)。诀窍:只看 î 去了哪里,也就是乘积的第 1 列。连续答对 4 题。

    You get two matrices \(A\) and \(B\), and the final grid of one of the two orders (dashed purple). Decide whether it is \(AB\) or \(BA\). The trick: look only at where î lands, i.e. the first column of the product. Get 4 in a row.

    FIG 3AB 还是 BA?AB or BA?
    • 连续答对 4 题。Get 4 right in a row.

    4第二种视角:"行乘列"从哪里来A second view: where "row times column" comes from

    课本上的乘法口诀是"第 \(i\) 行乘第 \(j\) 列,对应相乘再相加"。有了上面的图景,这条口诀不再神秘:它只是把"\(A\) 作用在 \(B\) 的第 \(j\) 列上"这件事,一个数一个数地算出来。

    在下面的表里,把鼠标移到(或点击)乘积 \(AB\) 的任意一格。左边会高亮 \(A\) 的那一行,上边高亮 \(B\) 的那一列,右边列出它们的"对应相乘再相加"。同一格也可以按列视角读:乘积的整个第 \(j\) 列,是 \(A\) 的各列按 \(B\) 的第 \(j\) 列的数配比后的组合。两种读法,同一个数。

    Textbooks teach "multiply row \(i\) by column \(j\), matching entries, then add." With the picture above this rule stops being mysterious: it is just the number-by-number way of computing "\(A\) applied to column \(j\) of \(B\)."

    In the table below, hover (or tap) any cell of the product \(AB\). The matching row of \(A\) lights up on the left, the matching column of \(B\) on top, and the side panel lists "multiply matching entries and add." The same cell can also be read in the column view: the whole column \(j\) of the product is a combination of the columns of \(A\), mixed in the proportions given by column \(j\) of \(B\). Two readings, one number.

    FIG 4乘积表The product table
    行乘列:对应相乘再相加Row times column: multiply matching entries and add
    列视角:A 作用在 B 的这一列上Column view: A applied to this column of B
    A
    B
    和 FIG 2 共用同一对矩阵,这里改了那里也变。These are the same A and B as in FIG 2: edit here and the lab changes too.
    青色是 \(A\) 的第 \(i\) 行,紫色是 \(B\) 的第 \(j\) 列,黄色是它们算出的那一格。表的摆法让每个乘积格的"行"在它左边,"列"在它上边,一眼就能对上。 Cyan is row \(i\) of \(A\), purple is column \(j\) of \(B\), amber is the cell they produce. The table is laid out so each product cell has its row to the left and its column above, so the match is easy to see.
    • 把乘积 \(AB\) 的四个格子都看一遍。Visit all four cells of the product \(AB\).
    实际计算时怎么选Which reading to use in practice

    手算或写循环时,用"行乘列"最顺手:每个数独立,互不依赖。想弄明白一个乘积做了什么时,用"列视角":每一列是一个基向量的落点。机器人里要排查坐标系链的时候,也是追着一个向量一步步看它落在哪个坐标系。

    When computing by hand or writing loops, "row times column" is the handiest: every entry is independent. When you want to understand what a product does, use the column view: each column is where a basis vector lands. When debugging a chain of frames you do the same thing: follow one vector and see which frame it lands in at each step.

    5第三种视角:到了三维,顺序更要紧A third view: in 3D, order matters even more

    拿一本书放在桌上。先绕 x 轴转 90°,再绕 z 轴转 90°,书最后朝哪边?反过来,先绕 z 再绕 x,会一样吗?下图把两种顺序并排放在一起。书的六个面按"垂直于哪根轴"着色:红色垂直于 x 轴(短的两端),绿色垂直于 y 轴(长边),蓝色垂直于 z 轴(封面和封底)。琥珀色边框是封面。

    两次旋转都是绕固定的世界坐标轴转的,所以每做一步,就把新矩阵乘在左边:先绕 x 再绕 z,矩阵是 \(R_z R_x\)。

    Put a book on a table. Rotate it 90° about the x-axis, then 90° about the z-axis. Which way does it end up facing? Now do z first, then x. Is it the same? The figure shows both orders side by side. The six faces are coloured by which axis they are perpendicular to: red for x (the two short ends), green for y (the long edges), blue for z (front and back cover). The amber frame marks the front cover.

    Both rotations are about the fixed world axes, so each new step multiplies on the left: x first, then z, gives \(R_z R_x\).

    FIG 5同样两次转动,不同顺序The same two turns, in different orders
    先绕 x,再绕 z:RzRxx first, then z: RzRx
    先绕 z,再绕 x:RxRzz first, then x: RxRz
    拖动画面可以转动视角(两张图同步)。进度条 0 到 1 是第一次转动,1 到 2 是第二次。两个角度默认都是 90°,也可以改。数学上两张图的最终姿态由下方两个矩阵给出。 Drag a canvas to orbit the view (both stay in sync). Progress 0 to 1 is the first turn, 1 to 2 the second. Both angles default to 90° but can be changed. The two final orientations are given by the matrices below the canvases.
    • 找一对角度(两个都至少 20°),让两种顺序的最终姿态完全一样。有且只有一种选法,想想为什么。Find a pair of angles (both at least 20°) for which the two orders end in exactly the same orientation. There is just one choice; think about why.
    核心洞见Key insight

    平面里的旋转可交换:转 30° 再转 40°,和转 40° 再转 30°,都是转 70°。三维里的旋转一般不可交换:转轴不同,顺序就是内容的一部分。角度很小的时候两种顺序几乎一样(把两个角都拖到 5° 试试),角度大了差别才明显。机器人姿态的所有 bug,几乎都来自把这条忘了。

    Rotations in the plane commute: 30° then 40° is the same as 40° then 30°, namely 70°. Rotations in 3D generally do not: with different axes, the order is part of the information. For tiny angles the two orders nearly agree (drag both to 5°), and the gap only shows up as angles grow. Nearly every robot-orientation bug comes from forgetting this.

    6再看数学The math

    提示:把鼠标悬停在公式中带底色的 A、B、AB 上,FIG 2 会单独画出对应的网格。Tip: hover the highlighted A, B and AB in the formulas; FIG 2 draws that grid alone.

    定义:先 B,后 ADefinition: first B, then A

    乘积 \(AB\) 是这样一个矩阵:对每个向量 \(\mathbf v\),

    The product \(AB\) is the matrix for which, for every vector \(\mathbf v\),

    $$ \hl{AB}{(AB)}\,\mathbf v \;=\; \hl{A}{A}\,\bigl(\hl{B}{B}\,\mathbf v\bigr). $$

    它存在而且唯一:两个线性变换复合后仍是线性变换,而线性变换由 \(\hat\imath,\hat\jmath\) 的落点唯一决定。

    It exists and is unique: composing two linear maps gives a linear map, and a linear map is determined by where \(\hat\imath,\hat\jmath\) land.

    一列一列算,以及单个数的公式Column by column, and the entry formula

    把 \(\hat\imath\) 代入定义:\((AB)\hat\imath = A(B\hat\imath) = A\mathbf b_1\),其中 \(\mathbf b_1\) 是 \(B\) 的第 1 列。对 \(\hat\jmath\) 同理。所以

    Plug \(\hat\imath\) into the definition: \((AB)\hat\imath = A(B\hat\imath) = A\mathbf b_1\), where \(\mathbf b_1\) is column 1 of \(B\). Likewise for \(\hat\jmath\). So

    $$ AB = A\,[\,\ci{\mathbf b_1}\;\;\cj{\mathbf b_2}\,] = [\,\ci{A\mathbf b_1}\;\;\cj{A\mathbf b_2}\,]. $$

    再把 \(A\mathbf b_j\) 按"行视角"展开(1.3 节),第 \(i\) 个分量是 \(A\) 的第 \(i\) 行与 \(\mathbf b_j\) 对应相乘再相加:

    Now expand \(A\mathbf b_j\) with the row view (Lesson 1.3): its \(i\)-th entry is row \(i\) of \(A\) times \(\mathbf b_j\), matching entries multiplied and added:

    $$ (AB)_{ij} \;=\; \sum_{k=1}^{n} a_{ik}\,b_{kj} \;=\; a_{i1}b_{1j} + a_{i2}b_{2j} + \dots + a_{in}b_{nj}. $$

    形状:内维必须相同Shapes: the inner dimensions must match

    $$ \underbrace{A}_{m\times n}\;\underbrace{B}_{n\times p} \;=\; \underbrace{AB}_{m\times p}. $$

    \(B\) 把 \(\R^p\) 里的向量送到 \(\R^n\),\(A\) 再把 \(\R^n\) 里的向量送到 \(\R^m\)。能接起来的前提是:\(B\) 的输出空间必须正好是 \(A\) 的输入空间,也就是两个 \(n\) 要相等。例如相机投影 \(A\)(\(2\times 3\):三维点到二维像素)乘一个 \(3\times 3\) 的旋转 \(B\),得到 \(2\times 3\) 的"先转再投影";反过来 \(BA\) 没有意义,因为投影的输出是二维,而旋转要吃三维。

    \(B\) sends vectors of \(\R^p\) to \(\R^n\); \(A\) then sends vectors of \(\R^n\) to \(\R^m\). The two can only be chained if the output space of \(B\) is exactly the input space of \(A\), i.e. the two \(n\)'s agree. For example a camera projection \(A\) (\(2\times 3\): 3D point to 2D pixel) times a \(3\times 3\) rotation \(B\) gives a \(2\times 3\) "rotate, then project"; \(BA\) makes no sense, because the projection outputs 2D while the rotation expects 3D.

    结合律:怎么加括号都一样Associativity: grouping does not matter

    $$ A(BC) = (AB)C. $$

    两边都表示"先 C,再 B,最后 A"。不需要逐项验算,只需看懂两边在做同一件事。机器人里它很有用:可以提前把不变的那段链连乘好存起来,比如相机装在云台上,\({}^{H}R_{C}\) 是固定的,每帧只需要更新变化的部分。

    Both sides mean "C first, then B, then A". No term-by-term check is needed; just see that both do the same thing. In robotics it is handy: you can pre-multiply the unchanging stretch of a chain and cache it. A camera bolted to a head has a fixed \({}^{H}R_{C}\), so each frame only the changing parts need updating.

    不可交换,以及单位矩阵Non-commutativity and the identity

    $$ AB \ne BA \;\text{(in general)}, \qquad AI = IA = A. $$

    "先穿袜子再穿鞋"和"先穿鞋再穿袜子"不是一回事,这就是 \(AB \ne BA\)。少数情况下可以交换:\(A\) 或 \(B\) 是单位矩阵("什么也不做",对角线全是 1),或其中一个是单位矩阵的倍数,或两个都是对角矩阵,或两个都是同一平面内的旋转。

    "Socks then shoes" is not the same as "shoes then socks"; that is \(AB \ne BA\). A few cases do commute: when one is the identity (the "do nothing" map, ones on the diagonal), or a multiple of it, or when both are diagonal, or both are rotations in the same plane.

    转置:穿袜子与穿鞋The transpose: socks and shoes

    $$ (AB)^{\T} = B^{\T}A^{\T}. $$

    验证只要一行:\(\big((AB)^{\T}\big)_{ij} = (AB)_{ji} = \sum_k a_{jk}b_{ki} = \sum_k (B^{\T})_{ik}(A^{\T})_{kj}\)。直觉是"撤销":穿的时候先袜后鞋,脱的时候先鞋后袜,顺序必须反过来。同一条规则也管逆矩阵:\((AB)^{-1} = B^{-1}A^{-1}\)(1.6 节)。对旋转矩阵 \(R^{-1} = R^{\T}\)(1.10 节),所以反过来换算坐标系时,整条链的顺序也会反过来。

    The check is one line: \(\big((AB)^{\T}\big)_{ij} = (AB)_{ji} = \sum_k a_{jk}b_{ki} = \sum_k (B^{\T})_{ik}(A^{\T})_{kj}\). The intuition is "undoing": you put on socks then shoes, but you take off shoes then socks, so the order must reverse. The same rule governs inverses: \((AB)^{-1} = B^{-1}A^{-1}\) (Lesson 1.6). For rotations \(R^{-1} = R^{\T}\) (Lesson 1.10), so going the other way through a frame chain reverses the order of the whole chain.

    二维旋转:角度加法白送2D rotations: angle addition for free

    旋转 \(R(\theta)\) 的两列是转过 \(\theta\) 后的 \(\hat\imath,\hat\jmath\)。先转 \(\beta\) 再转 \(\alpha\),就是转 \(\alpha+\beta\)。把乘积算出来:

    The rotation \(R(\theta)\) has as columns the turned \(\hat\imath,\hat\jmath\). Turning by \(\beta\) then \(\alpha\) is turning by \(\alpha+\beta\). Compute the product:

    $$ R(\alpha)R(\beta) = \begin{bmatrix} \cos\alpha & -\sin\alpha \\ \sin\alpha & \cos\alpha \end{bmatrix}\begin{bmatrix} \cos\beta & -\sin\beta \\ \sin\beta & \cos\beta \end{bmatrix} = \begin{bmatrix} \ci{\cos\alpha\cos\beta - \sin\alpha\sin\beta} & \cdots \\ \ci{\sin\alpha\cos\beta + \cos\alpha\sin\beta} & \cdots \end{bmatrix}. $$

    它必须等于 \(R(\alpha+\beta)\),其第 1 列是 \((\cos(\alpha+\beta),\,\sin(\alpha+\beta))\)。比较第 1 列,两角和公式就出来了:

    It must equal \(R(\alpha+\beta)\), whose first column is \((\cos(\alpha+\beta),\,\sin(\alpha+\beta))\). Compare first columns and the angle-addition formulas drop out:

    $$ \cos(\alpha+\beta) = \cos\alpha\cos\beta - \sin\alpha\sin\beta, \qquad \sin(\alpha+\beta) = \sin\alpha\cos\beta + \cos\alpha\sin\beta. $$

    因为 \(\alpha+\beta = \beta+\alpha\),所以 \(R(\alpha)R(\beta) = R(\beta)R(\alpha)\):平面旋转可交换。下面的图让你亲手拨一拨。

    Since \(\alpha+\beta = \beta+\alpha\), we get \(R(\alpha)R(\beta) = R(\beta)R(\alpha)\): planar rotations commute. Play with it below.

    FIG 6转两次,角度相加Two turns, angles add
    紫色是先转 \(\beta\) 的位置,黄色是再转 \(\alpha\) 后的位置;灰色虚线是反过来先转 \(\alpha\) 的路线。两条路终点相同。可以拖动紫色或黄色箭头尖,也可以用滑块。 Purple is the position after turning by \(\beta\), amber the position after then turning by \(\alpha\); the dashed grey route turns by \(\alpha\) first. Both routes end at the same place. Drag the purple or amber tip, or use the sliders.
    • 让乘积正好是 90° 旋转 \(\begin{bmatrix}0&-1\\1&0\end{bmatrix}\),且两个角都不是 0。Make the product exactly the 90° rotation \(\begin{bmatrix}0&-1\\1&0\end{bmatrix}\), with neither angle zero.

    7机器人中的它:云台相机的坐标系链In robotics: the frame chain of a pan-tilt camera

    云台由两个关节组成:下面一个关节绕竖直的 z 轴水平转(pan,偏航 \(\psi\)),上面一个关节让相机俯仰(tilt,\(\theta\)),它绕的是云台自己的 y 轴,这根轴会随着水平转动而转走。相机坐标系在世界里的姿态是

    A pan-tilt head has two joints: the lower one pans about the vertical z-axis (yaw \(\psi\)), the upper one tilts the camera (\(\theta\)) about the head's own y-axis, which swings away as the head pans. The camera frame's orientation in the world is

    $$ {}^{W}R_{C} = R_z(\psi)\,R_y(\theta), \qquad R_y(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix}, \qquad \mathbf p_W = {}^{W}R_{C}\,\mathbf p_C. $$

    \(R_y(\theta)\) 在 \(\theta>0\) 时把相机的前方(x 轴)向下压,所以正的 \(\theta\) 是"向下看"。杯子在相机坐标里固定为 \(\mathbf p_C = (2.4,\,0.8,\,0)\)(正前方 2.4 米,偏左 0.8 米)。调整 \(\psi\) 和 \(\theta\),看它在世界里的位置如何变化。再切到"错误顺序":\(R_y(\theta)R_z(\psi)\) 把两个矩阵的次序对调了。(为了专注旋转,所有坐标系都放在同一个原点。)

    For \(\theta>0\), \(R_y(\theta)\) pushes the camera's forward axis (x) downward, so positive \(\theta\) means "looking down". The cup is fixed in camera coordinates at \(\mathbf p_C = (2.4,\,0.8,\,0)\) (2.4 m ahead, 0.8 m to the left). Change \(\psi\) and \(\theta\) and watch where it lands in the world. Then switch to "swapped order": \(R_y(\theta)R_z(\psi)\) swaps the two matrices. (To focus on rotation, all frames share one origin.)

    FIG 7云台相机看到的杯子The cup seen by a pan-tilt camera
    淡色的 x、y、z 箭头是世界坐标系;虚线箭头是只做了水平转动之后的云台坐标系(注意它的 y 轴,就是俯仰轴);粗箭头是相机坐标系。黄点是正确算出的杯子位置,虚线折线是从相机原点出发沿 \(x_c\)、\(y_c\) 走到杯子的路。在"错误顺序"下,紫色的相机轴和紫点显示把矩阵乘反后的结果。 The faint x, y, z arrows are the world frame; the dashed arrows are the head frame after the pan alone (note its y-axis: the tilt axis); the bold arrows are the camera frame. The amber dot is the correctly computed cup position, and the dashed path goes from the camera origin along \(x_c\), \(y_c\) to the cup. In "swapped order", the purple camera axes and purple dot show what you get from multiplying the matrices the wrong way round.
    • 切到"错误顺序",找一组 \(\psi\)、\(\theta\),让错算的位置偏离真实位置超过 1.5 米。Switch to "swapped order" and find \(\psi,\theta\) that put the wrong position more than 1.5 m from the true one.
    • 切到"错误顺序",让两种顺序给出相同的位置,同时俯仰角 \(|\theta|\ge 15°\)。什么时候这种错误不会被发现?In "swapped order", make both orders give the same position while \(|\theta|\ge 15°\). When would this bug go unnoticed?
    同一个乘积的两种读法:固定轴与移动轴One product, two readings: fixed axes and moving axes

    \(R_z(\psi)R_y(\theta)\) 可以这样读:从右往左,先绕世界 y 轴转 \(\theta\),再绕世界 z 轴转 \(\psi\),每一步都绕固定的世界轴;也可以从左往右,先转 \(\psi\),再绕云台"现在的" y 轴转 \(\theta\),每一步都绕当前的轴。口诀:右乘(把新旋转写在右边)是绕自身的移动轴转,左乘(写在左边)是绕固定的世界轴转。FIG 5 的书每步都是左乘;云台的俯仰是右乘。这两种说法的完整关系在 5.2 节讲。

    \(R_z(\psi)R_y(\theta)\) can be read right to left: first turn by \(\theta\) about the world y-axis, then by \(\psi\) about the world z-axis, every step about a fixed world axis. It can also be read left to right: first turn by \(\psi\), then turn by \(\theta\) about the head's current y-axis, every step about the current axes. Rule of thumb: post-multiplying (new rotation on the right) rotates about the current, moving axes; pre-multiplying (on the left) rotates about the fixed world axes. The books in FIG 5 use pre-multiplication at every step; the tilt of the pan-tilt head is post-multiplication. The full story is in Lesson 5.2.

    真实系统里In real systems

    ROS 的 tf2 把整个机器人表示成一棵坐标系树,查询"相机在地图里的位姿",就是沿树把一串变换连乘(并在需要反向走时取逆)。机械臂的正运动学也是同一件事:每个关节一个矩阵,从底座乘到末端(5.3 节、5.10 节)。把关节角写进变量名,再把链写成 R_world_cam = R_world_base @ R_base_head @ R_head_cam,下标能接龙就基本不会错。

    ROS's tf2 models the whole robot as a tree of frames; asking for "the camera's pose in the map" multiplies a chain of transforms along the tree (inverting when it must walk backwards). Forward kinematics of an arm is the same thing: one matrix per joint, multiplied from base to tip (Lessons 5.3 and 5.10). Name the matrices by their frames and write the chain as R_world_cam = R_world_base @ R_base_head @ R_head_cam: if the subscripts chain up, you are almost certainly right.

    8常见误区Common pitfalls

    误区 1:顺序写反(AB 当成 BA)Pitfall 1: getting the order backwards (AB for BA)

    \(AB\) 是先做 B 再做 A:最后一个作用的矩阵写在最左边。很多人按"时间顺序"从左往右写,于是整条链反了。检查办法:看下标能不能接龙,\({}^{W}R_{B}\,{}^{B}R_{H}\) 对,\({}^{B}R_{H}\,{}^{W}R_{B}\) 错。

    \(AB\) means do B, then A: the matrix applied last sits on the far left. Many people write the chain left to right in time order, which reverses everything. Check by the subscripts: \({}^{W}R_{B}\,{}^{B}R_{H}\) chains, \({}^{B}R_{H}\,{}^{W}R_{B}\) does not.

    误区 2:NumPy 里用 * 做矩阵乘法Pitfall 2: using * for matrix products in NumPy

    在 NumPy 里,对数组 A * B 是逐元素相乘,矩阵乘法要写 A @ B(或 np.matmul)。对小测验第 1 题的两个矩阵,A * B 给出 \(\begin{bmatrix}2&0\\0&1\end{bmatrix}\),A @ B 才是 \(\begin{bmatrix}2&6\\1&4\end{bmatrix}\)。两个都是 2×2,程序不会报错,只会悄悄算错。(C++ 的 Eigen 里 * 才是矩阵乘法,换语言时要留神。)

    In NumPy, A * B on arrays is element-wise; the matrix product is A @ B (or np.matmul). For the two matrices of quiz question 1, A * B gives \(\begin{bmatrix}2&0\\0&1\end{bmatrix}\) and only A @ B gives \(\begin{bmatrix}2&6\\1&4\end{bmatrix}\). Both are 2×2, so nothing complains; the result is just silently wrong. (In C++ Eigen, * is the matrix product, so mind the language.)

    误区 3:把形状不匹配的报错当成小问题Pitfall 3: treating a shape-mismatch error as a nuisance

    看到 matmul: Input operand 1 has a mismatch in its core dimension,别急着 .T 或 reshape 把它压下去。内维对不上,往往说明你把坐标系接错了:这个矩阵的输出空间,并不是下一个矩阵的输入空间。先搞清每个矩阵"从哪来到哪去",再动手。

    When you see matmul: Input operand 1 has a mismatch in its core dimension, do not silence it with .T or reshape. A mismatched inner dimension often means you have wired the frames wrong: the output space of one matrix is not the input space of the next. Work out what each matrix maps from and to before touching the code.

    误区 4:混淆绕移动轴转和绕固定轴转Pitfall 4: mixing up rotating about moving axes and fixed axes

    "先绕 z 转 30°,再绕 y 转 20°"有两种合理的意思:y 轴是世界的 y 轴,还是转完之后云台自己的 y 轴?前者是 \(R_y(20°)R_z(30°)\),后者是 \(R_z(30°)R_y(20°)\),结果不同。写代码前先说清每个关节转的是哪根轴。

    "Turn 30° about z, then 20° about y" has two sensible meanings: is that y the world's y, or the head's own y after the first turn? The former is \(R_y(20°)R_z(30°)\), the latter \(R_z(30°)R_y(20°)\), and they differ. Before coding, say exactly which axis each joint turns about.

    误区 5:\((AB)^{\T} = A^{\T}B^{\T}\)Pitfall 5: \((AB)^{\T} = A^{\T}B^{\T}\)

    转置和求逆都会把顺序反过来:\((AB)^{\T} = B^{\T}A^{\T}\)。如果 \(A\) 是 \(2\times 3\)、\(B\) 是 \(3\times 4\),错误写法 \(A^{\T}B^{\T}\) 连形状都对不上(\(3\times 2\) 乘 \(4\times 3\)),这也是形状检查能救你的一个例子。

    Transposing and inverting both reverse the order: \((AB)^{\T} = B^{\T}A^{\T}\). If \(A\) is \(2\times 3\) and \(B\) is \(3\times 4\), the wrong form \(A^{\T}B^{\T}\) does not even have matching shapes (\(3\times 2\) times \(4\times 3\)), one more case where the shape check saves you.

    9小练习Check yourself

    1. 设 \(A = \begin{bmatrix}2&0\\1&1\end{bmatrix}\),\(B = \begin{bmatrix}1&3\\0&1\end{bmatrix}\)。\(AB\) 是?1. Let \(A = \begin{bmatrix}2&0\\1&1\end{bmatrix}\) and \(B = \begin{bmatrix}1&3\\0&1\end{bmatrix}\). What is \(AB\)?
    按列算:第 1 列是 \(A\) 乘 \(B\) 的第 1 列 \((1,0)\),得 \((2,1)\);第 2 列是 \(A\) 乘 \((3,1)\),即 \(3\,(2,1) + 1\,(0,1) = (6,4)\)。所以 \(AB = \begin{bmatrix}2&6\\1&4\end{bmatrix}\)。选项 A 是 \(BA\),选项 B 是 \(A+B\),选项 D 是逐元素相乘(NumPy 的 *)。By columns: column 1 is \(A\) times column 1 of \(B\), \((1,0)\), giving \((2,1)\); column 2 is \(A\) times \((3,1)\), i.e. \(3\,(2,1) + 1\,(0,1) = (6,4)\). So \(AB = \begin{bmatrix}2&6\\1&4\end{bmatrix}\). Option A is \(BA\), option B is \(A+B\), option D is the element-wise product (NumPy's *).
    2. \(B\) 是"沿 x 方向拉伸 2 倍"(\(B=\begin{bmatrix}2&0\\0&1\end{bmatrix}\)),\(A\) 是"逆时针转 90°"。在 \(AB\)(先 B 后 A)下,î 和 ĵ 各落在哪里?2. \(B\) stretches along x by 2 (\(B=\begin{bmatrix}2&0\\0&1\end{bmatrix}\)) and \(A\) rotates 90° counter-clockwise. Under \(AB\) (B first, then A), where do î and ĵ land?
    追踪:î 先被拉成 \((2,0)\),再转 90° 成 \((0,2)\);ĵ 先保持 \((0,1)\),再转成 \((-1,0)\)。所以 \(AB = \begin{bmatrix}0&-1\\2&0\end{bmatrix}\)。选项 B 是反过来的 \(BA\)(先转再拉:\((0,1)\) 被拉后不变,\((-1,0)\) 被拉成 \((-2,0)\))。Track them: î is first stretched to \((2,0)\), then rotated to \((0,2)\); ĵ stays \((0,1)\) under the stretch, then rotates to \((-1,0)\). So \(AB = \begin{bmatrix}0&-1\\2&0\end{bmatrix}\). Option B is the reverse order \(BA\) (rotate then stretch: \((0,1)\) is unchanged by the stretch, \((-1,0)\) becomes \((-2,0)\)).
    3. 已知 \({}^{W}R_{B}\)、\({}^{B}R_{H}\)、\({}^{H}R_{C}\),要把相机坐标换算到世界坐标,应该用哪个乘积?3. Given \({}^{W}R_{B}\), \({}^{B}R_{H}\) and \({}^{H}R_{C}\), which product converts camera coordinates to world coordinates?
    相邻下标要能约掉:\({}^{W}R_{B}\,{}^{B}R_{H}\,{}^{H}R_{C} = {}^{W}R_{C}\),把 C 坐标送到 W 坐标。选项 B 是从世界到相机的方向(\({}^{C}R_{W}\),即上式的逆),选项 A、C的下标接不上。Neighbouring subscripts must cancel: \({}^{W}R_{B}\,{}^{B}R_{H}\,{}^{H}R_{C} = {}^{W}R_{C}\), taking C coordinates to W coordinates. Option B goes the other way (\({}^{C}R_{W}\), the inverse of this one); options A and C do not chain.
    4. 相机投影矩阵 \(A\) 是 \(2\times 3\)(三维点到二维像素),\(B\) 是 \(3\times 3\) 的旋转矩阵。下面哪个说法对?4. A camera projection matrix \(A\) is \(2\times 3\) (3D point to 2D pixel) and \(B\) is a \(3\times 3\) rotation. Which statement is right?
    \(AB\):\((2\times 3)(3\times 3)\),内维都是 3,结果 \(2\times 3\),含义是"先旋转三维点,再投影到图像"。\(BA\):\((3\times 3)(2\times 3)\),内维是 3 和 2,对不上:投影输出的是二维,旋转却要吃三维。\(AB\): \((2\times 3)(3\times 3)\), inner dimensions both 3, result \(2\times 3\), meaning "rotate the 3D point, then project to the image". \(BA\): \((3\times 3)(2\times 3)\), inner dimensions 3 and 2 do not match: the projection outputs 2D, but the rotation expects 3D.
    5. 云台先水平转 \(\psi\)(绕竖直 z 轴),再让相机绕云台自己的 y 轴俯仰 \(\theta\)。相机在世界中的姿态是?5. A pan-tilt head first pans by \(\psi\) (about the vertical z-axis), then the camera tilts by \(\theta\) about the head's own y-axis. The camera's orientation in the world is?
    绕"自身当前轴"转,新旋转写在右边:\(R_z(\psi)R_y(\theta)\)。两个顺序一般不同(FIG 7 里切到"错误顺序"可以看到),只有 \(\psi = 0\) 或 \(\theta = 0\) 这类特殊情形才一样。矩阵相加没有"先后"的含义。Rotating about the "current own axis" puts the new rotation on the right: \(R_z(\psi)R_y(\theta)\). The two orders generally differ (switch FIG 7 to "swapped order" to see), agreeing only in special cases such as \(\psi = 0\) or \(\theta = 0\). Adding matrices has no "first, then" meaning.

    10延伸阅读Further reading

    • 3Blue1Brown, Essence of Linear Algebra — 第 4 章(矩阵乘法即复合)与第 5 章(三维线性变换)Ch. 4 (matrix multiplication as composition) and Ch. 5 (three-dimensional linear transformations)
    • G. Strang, Introduction to Linear Algebra, Ch. 2 — 矩阵乘法的几种读法(2.4 节 矩阵运算规则)The several ways to read a matrix product (Section 2.4, rules for matrix operations)
    • K. Lynch & F. Park, Modern Robotics, Sec. 3.2 — 旋转矩阵,以及绕固定轴与绕自身轴的复合Rotation matrices, and composing rotations about fixed versus body axes
    • J. Ström et al., Immersive Linear Algebra — 矩阵乘法一章,带可拖动的交互插图The matrix-multiplication chapter, with draggable interactive figures