1024 特刊|机器人先想再动:把高层推理、坐标变换和闭环控制分开
“把杯子放进柜子”只是一句指令。机器人还需要知道杯子在哪个坐标系里、该抓哪里、柜门是否打开,以及接触后有没有滑脱。语言推理能提供子目标,却不能替代这些几何和反馈信息。
10 月 8 日提交的 ARC 机器人推理论文把推理轨迹与下一动作及其因果解释联系起来。另一条架构线索来自 Gemini Robotics ER 2 官方说明:高层规划与较低层 VLA 执行动作分工。这些材料描述各自系统,不意味着任意语言模型接一段机械臂代码就能复现其表现。
子目标必须落到可计算的坐标
用列向量约定,点从相机系 C 转到世界系 W:
$$p_W=R_{WC}p_C+t_{WC}.$$
R 表示方向旋转,t 表示相机原点在世界系中的位置。方向向量只乘 R,不加平移。多个变换组合时,写清下标比记忆“左乘还是右乘”的口号可靠:T_WC 与 T_CE 相乘,得到 T_WE。
图中的夹爪是概念示意。实际抓取还涉及物体几何、接触面、摩擦、力矩和控制器;图上的箭头不能代表这些已经验证。
手算和代码核对同一个变换
下面采用绕 z 轴旋转 90° 的矩阵。点 (1,0,0) 先转到 (0,1,0),再平移 (1,2,3),结果应为 (1,3,3)。
from math import isclose def matvec(matrix, vector): return [sum(a * b for a, b in zip(row, vector)) for row in matrix] def transpose(matrix): return [list(row) for row in zip(*matrix)] def transform(rotation, translation, point): return [a + b for a, b in zip(matvec(rotation, point), translation)] rotation = [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]] translation = [1.0, 2.0, 3.0] point = [1.0, 0.0, 0.0] world = transform(rotation, translation, point) recovered = matvec(transpose(rotation), [a - b for a, b in zip(world, translation)]) assert world == [1.0, 3.0, 3.0] assert all(isclose(a, b, abs_tol=1e-12) for a, b in zip(point, recovered)) print("world_point:", world) print("round_trip:", recovered)往返核对能抓出平移顺序和转置方向错误,却不能验证相机标定正确。即使公式算对,外参陈旧、时间戳错位、毫米与米混用,仍会把末端目标送错位置。
推理结果要经过反馈重新解释
高层模型输出“拿起杯子”,执行端应该转成有条件的子目标:目标位姿、允许速度、接触判定、超时以及失败后的恢复动作。传感器观察到未抓稳,就不应继续执行后续“移动到柜内”。
评估也要拆开。语言子目标是否正确、位姿估计误差、接触成功率和整任务完成率属于不同层。一次成功演示不能替代多次试验;仿真指标也不能直接写成实机装配精度。本文运行范围只有坐标算术,没有连接机械臂、训练 VLA、测量毫米误差或验证接触控制。把这些边界写清楚,才能知道下一次实验究竟该补哪块证据。