坐标系基础:世界坐标系、机器人坐标系、传感器坐标系的定义与变换

做机器人运动控制,说白了就是回答三个问题:我在哪?我要去哪?我怎么去? 而这三个问题的答案,全都绕不开坐标系。

我记得刚入行那会儿,带我的老工程师丢给我一台AGV小车,让我写一段直线运动程序。我吭哧吭哧写完,小车一跑,直接撞墙。后来一查,我把传感器坐标系当成了机器人坐标系来用。嗯,那次教训挺深刻的。

今天我们就来把这三个坐标系彻底捋清楚。

1. 世界坐标系:绝对参考系

世界坐标系,也叫全局坐标系。它是整个运动空间的绝对基准

你可以把它想象成房间里的一个固定墙角。无论机器人怎么动,这个墙角的位置永远不变。所有其他坐标系,最终都要跟它对齐。

关键特征:

  • 原点固定,通常选在场地角落或某个标志物上
  • 坐标轴方向固定(比如X轴指向东,Y轴指向北)
  • 所有运动指令最终都要换算到世界坐标系下执行

我个人的习惯是,在部署机器人之前,先用激光测距仪把世界坐标系的原点和方向标定好。这一步省了,后面全是坑。

2. 机器人坐标系:本体参考系

机器人坐标系是固定在机器人身上的。它的原点通常在机器人的几何中心或驱动轮轴中心。

你想想看,机器人自己可不知道「东」和「北」是什么。它只知道「我左边轮子转快点,右边轮子转慢点,我就转弯了」。这就是机器人坐标系的意义——描述机器人相对于自身的运动。

举个例子,差速驱动小车的运动控制,本质上就是在机器人坐标系下算的:

// 机器人坐标系下的速度指令
v_x = (v_right + v_left) / 2;   // 前进速度
v_y = 0;                        // 侧向速度(差速小车为0)
omega = (v_right - v_left) / L; // 角速度,L为轮距

我在项目中遇到过一个问题:机器人坐标系的原点到底放在哪?放在几何中心还是驱动轮轴中心?

我的建议是:放在驱动轮轴中心。因为运动学方程在那里最简洁,后续做轨迹跟踪也最方便。

3. 传感器坐标系:感知参考系

传感器坐标系,顾名思义,是每个传感器自己的小天地。

激光雷达有激光雷达的原点,摄像头有摄像头的焦点,IMU有IMU的安装位置。它们各自测量到的数据,都是相对于自己坐标系的。

这里有个很容易踩的坑:传感器测到的障碍物位置,不等于机器人坐标系下的位置

我曾经犯过的错:

有一次做避障,激光雷达装在车头右侧,测到一个障碍物距离0.5米。我直接把这个距离当成机器人到障碍物的距离,结果机器人左转时撞上了左侧的墙。

原因很简单:激光雷达看到的障碍物,是在传感器坐标系下的坐标。必须经过变换,才能变成机器人坐标系下的坐标。

4. 坐标系变换:把一切对齐

三个坐标系之间怎么转换?核心就是齐次变换矩阵

一个变换矩阵包含两部分:

  • 旋转矩阵 R:描述两个坐标系之间的姿态差异
  • 平移向量 t:描述两个坐标系原点之间的位置差异

写成矩阵形式就是:

T = [ R  t ]
    [ 0  1 ]

假设传感器坐标系下有一个点 P_s,要转换到机器人坐标系 P_r:

P_r = T_sr * P_s

其中 T_sr 是传感器坐标系到机器人坐标系的变换矩阵。

再进一步,从机器人坐标系到世界坐标系:

P_w = T_rw * P_r

所以,传感器数据最终到世界坐标系的完整变换是:

P_w = T_rw * T_sr * P_s

小技巧:

我习惯把变换矩阵的命名规则写成「从哪来到哪去」。比如 T_sr 表示「从传感器坐标系到机器人坐标系」。这样写代码时不容易搞混。

5. 知识体系总览

下面这张图把三个坐标系的关系画清楚了:

世界坐标系 X_w Y_w 原点O_w 机器人坐标系 X_r Y_r 原点O_r 传感器坐标系 X_s Y_s 原点O_s T_rw T_sr T_sw = T_rw * T_sr 图例: 坐标系变换 复合变换

从图上可以看得很清楚:传感器数据要想到达世界坐标系,必须经过两次变换。任何一步出错,机器人的「世界观」就是歪的。

6. 实际项目中的坐标系标定流程

最后,我分享一下我在实际项目中做坐标系标定的流程:

  1. 固定世界坐标系:在场地选两个固定点,确定原点和X轴方向
  2. 标定机器人位姿:用全站仪或激光跟踪仪,测量机器人坐标系原点在世界坐标系下的位置和姿态
  3. 标定传感器安装位置:测量传感器坐标系原点相对于机器人坐标系原点的偏移和旋转
  4. 写入变换参数:把 T_rw 和 T_sr 写到机器人的配置文件中
  5. 验证:让机器人走到一个已知点,用传感器测量,看数据是否对齐

一句话总结:

世界坐标系是「上帝视角」,机器人坐标系是「自我认知」,传感器坐标系是「感知器官」。三者通过变换矩阵串联,缺一不可。

嗯,坐标系这块内容就讲到这里。下次你写运动控制代码时,记得先问问自己:我现在用的是哪个坐标系?


专注资料整理