同一个杯子,两个不同的答案
想象一只机械臂坐在厨房餐桌旁,面前放着一只咖啡杯。问机器人“杯子在哪里?”,它会说:“在我正前方 30 厘米处。”问房间同样的问题,它会说:“在窗边,餐桌的左半边。”这两个答案都完全正确,描述的是同一只杯子。可是数值却完全不同——而且没有哪一个比另一个更“真实”。
这正是机器人几何中最重要的一个观念:位置从来不只是悬在空中的三个数字。三个数字只有在你说清楚是从什么量起时才有意义。“前方 30 厘米”需要一个有“前方”的东西;“窗边”需要一个有墙的房间。换一个测量的参照物,数字就变了,尽管实物根本没有移动。
坐标系到底是什么:一个原点加三个箭头
那个“你测量的参照物”有个正式名字:坐标系(又称参考系)。坐标系不过是两样东西黏在一起。第一是原点——一个被选定、算作“零”的点,是你开始测量的起点。第二是三条坐标轴——从原点伸出的三个箭头,通常标记为 x、y、z,每一条都与另外两条互相垂直。它们合起来就像一套插在空间里的小尺子:一个箭头管“左右”,一个管“前后”,一个管“上下”。
坐标系一旦插好,描述任何一个点就成了一道简单的步骤:站在原点,沿 x 箭头走一段,沿 y 走一段,沿 z 走一段,就到达那个点。这三个“沿各箭头走多远”的距离,就是该点在这个坐标系里的坐标。一旦移动原点或旋转箭头,同一个实体点就会获得一组全新的三个数字。
房间不动,机器人随身带着自己的坐标系
机器人几乎总是同时拥有至少两个坐标系,而它们之间的对比正是后面一切的关键。第一个是世界坐标系:一个固定在房间本身上的坐标系。也许它的原点是地板的某个角落,x 箭头沿一面墙延伸,z 箭头朝天花板向上。它永远不动,是大家都能认同的共享地图。
第二个是机体坐标系:黏在机器人自身上的坐标系,机器人走到哪它就跟到哪。它的原点可能在机器人的胸口,或在机械臂的底座;它的 x 箭头指向“前方”,也就是机器人面朝的方向。机器人在房间里移动时,机体坐标系随之移动;机器人转身时,它的箭头也跟着转。正是这个坐标系,让机器人能说“杯子在我正前方 30 厘米”——“在我前方”只有在随机体移动的坐标系里才有意义。
真实的机器人不止两个坐标系。摄像头有自己的坐标系,机械臂的每个关节有一个,夹爪有一个,每个轮子也有一个。一台机器可以带着十几个坐标系,时时刻刻彼此相对移动。机器人软件把它们组织成一棵分叉的结构,叫做变换树——而整棵树的种子,正是这个“世界对机体”的区分。
一个点,多组数字——以及为何需要换算
我们用一个位置向量把这件事说具体——位置向量就是那串三个数字 (x, y, z) 的正式名称,它相对某个坐标系把一个点钉住。杯子在桌上从未移动,但在同一瞬间,从两个坐标系看,它的描述是这样的:
Same cup, same instant, two frames:
in BODY frame (origin = robot, x = forward):
cup = ( 0.30, 0.00, 0.00 ) # 30 cm straight ahead
in WORLD frame (origin = room corner, x = along wall):
cup = ( 1.85, 2.40, 0.75 ) # near window, table height
The cup did not move. Only the frame we asked in changed.于是实际的麻烦来了。机器人的摄像头看到杯子,并以摄像头坐标系报告它的位置。可机械臂的电机只听得懂以机械臂自身底座坐标系表述的指令。而人类监督者又用世界坐标系画了一个“禁入区”。三个坐标系,同一只杯子有三组不同的数字——在被换算到同一个共享坐标系之前,它们无法一起使用。
这种坐标系之间的换算——拿到杯子在一个坐标系里的数字,算出它在另一个坐标系里的数字——几乎是机器人所做一切的发动机:看见、伸手、抓取、导航。这条学习线后面的内容,其实就是对本篇提出的问题一个漫长而细致的回答:已知一个点在某坐标系里的数字,怎样求它在另一坐标系里的数字?要干净地完成这件事,还需要知道坐标系的扭转与倾斜,也就是它的姿态,而不只是原点的位置——这正是我们接下来要去的地方。