JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

旋轉矩陣:把轉動寫下來

一個 3×3 的數字方陣如何精確地表示朝向,以及為什麼它的各列就是旋轉後的座標軸。

為什麼朝向需要的是數字,而不是文字

機器人必須對「自己的手指向哪邊」有一個前後一致的說法。「稍微往左偏一點」對人來說夠用了,但電腦需要一個能儲存、能比較、能做乘法的東西。這個東西就是旋轉矩陣:一小塊大小固定的數字,精確地釘住朝向,既不含糊,也不留下任何猜測的餘地。

回想前面幾級講過的設定:每一個測量都活在某個座標系裡,而機器人會同時操控好幾個座標系——一個釘在地面上的世界座標系,還有一個隨著運動部件移動的本體座標系。旋轉矩陣就是對「一個座標系相對於另一個座標系轉了多少」的精確表述。一旦有了它,你就能回答這樣的問題:「如果相機看到杯子在那邊,那麼對夾爪來說它在哪裡?」

訣竅:每一列就是一根轉過去的座標軸

整個思想用一句話就能講完。拿出本體座標系的三根單位箭頭——也就是畫在運動部件上的小小的 x、y、z 軸——問每一根在轉動之後指向哪裡,並用世界座標系的數字寫出來。把這三個答案並排擺成三列,你就建構出了旋轉矩陣。第一列是本體的 x 軸落到的地方,第二列是 y 軸落到的地方,第三列是 z 軸落到的地方。

這正是為什麼矩陣是 3×3 的,而不是比如說單單一個角度。在平面 2D 裡,一個數字(轉角)就夠了。在 3D 裡你可以繞三個互相獨立的方向轉動,於是你需要記下這三根軸最終都落到了哪裡——三列,每列三個數字。這個方陣並不是隨意的記帳;它實實在在就是轉過去的那幾根座標軸的一張快照。

做乘法:旋轉一個點,串接多次轉動

回報在於:這個矩陣透過普通的乘法就能幹真正的活。把任意一個點寫成位置向量,用矩陣去乘它,出來的就是這同一個點旋轉之後的樣子。你不必每次都搬出三角函數——那九個數字已經把轉動編碼好了,而「矩陣乘以向量」無非是按合適的比例把各列混合起來。電腦每秒能做幾百萬次這樣的運算,全程根本不用去想角度。

更妙的是,轉動可以透過矩陣相乘來串接。先轉 A,再轉 B,那麼合起來的轉動就是 B 乘以 A 得到的那一個矩陣。於是一條有許多關節、每個關節各添一份扭轉的長機械臂,就坍縮成一個只需算一次的乘積。這正是你將處處依賴的「變換串接」思想——不過要注意順序很重要:B 乘 A 一般不等於 A 乘 B,因為「先轉再傾」並不等於「先傾再轉」。

2D rotation by angle t (the simplest case):

    [ cos t   -sin t ]
    [ sin t    cos t ]

Column 1 = where the x-axis lands = (cos t, sin t)
Column 2 = where the y-axis lands = (-sin t, cos t)

Rotate a point p = (px, py):

    new_px = cos t * px  -  sin t * py
    new_py = sin t * px  +  cos t * py
由兩根轉過去的座標軸構成的 2D 旋轉矩陣;3D 是同一個思想,再加上第三列。

SO(3):所有「乾淨」旋轉構成的家族

並不是每一個 3×3 方陣都是合法的旋轉。真正的旋轉從不拉伸、壓扁或鏡像空間——它只把空間轉一轉。所有通過這道檢驗的矩陣,有一個名字:特殊正交群 SO(3)。可以把它想成「誠實旋轉」的會員俱樂部;前面那張「三列即三軸」的圖,正是會員資格的樣子。

兩條簡單的性質定義了這個俱樂部。第一,正交性:三列都是單位長度,且彼此互成直角——這無非是說「轉過去的幾根軸依然是一套乾淨、互相垂直的座標軸」。第二,行列式等於 +1,這就禁止了那種偷偷把右手變成左手的鏡像翻轉。兩者合在一起,保證這個矩陣是一次純粹的轉動,別無其他。

正交性還白送你一個好處:要撤銷一次旋轉,你只需把矩陣沿對角線翻折(取它的轉置),而不必去做昂貴的求逆運算。於是「杯子對夾爪在哪」和「夾爪對杯子在哪」之間,只隔著一步廉價的運算。這正是機器人程式即便要花九個數字、也願意用旋轉矩陣來儲存朝向的現實理由。