← 返回写作← Back to writing

Isaac Lab 抓放Building a Four-Tool Pick-and-Place Task in Isaac Lab

2026-09-17

This essay is currently available in Chinese.

这次做的是一个 Isaac Lab 抓放任务:控制机械臂,把指定的工具从白箱搬到蓝箱。动作不复杂,但要让程序判断它有没有完成,就得把“放好了”说清楚。工具经过箱子上方,或是还被夹爪抓着,都不能算成功。录下成功的一次操作以后,还要检查同一串动作能不能再次完成任务。

场景里有一台 Franka Panda 机械臂、两个箱子、四种工具和三路相机。环境根据一句指令选择目标,接收键盘控制动作,再用明确的判据判断任务是否完成。这篇主要记录环境搭建和验证的过程。本次没有训练策略模型,也没有提供奖励函数。

实现、调试和自动化验证使用了 Codex 平台上的 GPT-6 Astra,推理强度为 low。下方四段正式录像由 AI 通过原生键盘控制接口操作,均保留 AI 标注。我后续完成了手动抓取,并检查了四种工具的动作回放;这些个人练习与正式录像分开记录。

这个项目做什么

这是一次机器人仿真工程技术题。需要交付的是一个能安装、操作、记录和回放的抓放环境:白箱里有螺丝刀、扳手、锤子和调色刀,程序指定其中一件,操作者控制 Franka Panda 把它搬到蓝箱,再由程序判断是否成功。

这里的 Franka Panda 是仿真里的机械臂模型。它和前几篇文章里实际连接相机、串口的 SO-101 真机是两个项目。这次也没有让 π0.5 自主决定动作:正式录像中的 AI 通过键盘接口操作,人工练习也使用这个接口。

一次完整运行可以这样理解:

重置场景并指定工具 → 操作者输入动作 → 仿真计算机械臂与工具的运动 → 相机和状态记录结果 → 程序检查是否放好。

交付内容除了四段录像,还包括环境代码、处理后的场景资产、结构化轨迹数据,以及安装、操作、回放和验证说明。录像用来直接看过程,轨迹和验证记录则用于检查过程能否恢复、判据是否可靠。

在什么平台上运行

平台或设备 在这次项目里负责什么
Isaac Sim NVIDIA 的机器人仿真平台,计算重力、碰撞、关节运动,并渲染相机画面;可以把它理解为机器人活动的虚拟实验室
Isaac Lab 建在 Isaac Sim 之上的机器人学习框架,组织动作、观测、重置和任务结束条件;本项目用它搭环境,没有训练策略
学校实验室的 Linux 工作站、RTX 3090 实际运行仿真、渲染、录制和回放;3090 是这台工作站里的 GPU
家里的 Mac 远程查看和操作 Linux 桌面,本次物理仿真不在 Mac 上运行
Codex 辅助编写、调试和验证代码的平台,与运行物理仿真的 Isaac Sim 分工不同

因此,Mac 上看到的是远程工作站传回来的画面。网络和触控板影响操作体验;机械臂会不会碰到箱壁、工具会不会滑落,则由工作站上的仿真计算决定。下面先放四段完整录像,再说明环境、控制和验证的实现。

四段完整录像

四段视频依次对应螺丝刀、扳手、锤子和调色刀。每段从重置开始,到环境实际触发成功结束;三路画面在同一帧内平铺,带有工具指令、操作者和判据状态。操作中的失误和调整都保留在原回合内。

视频采用 H.264 编码,播放帧率为 30 FPS。这里的时长是录像对应的仿真时间,不代表远程操作所花的真实时间。AI 操作使用分步键盘模式,输入之间暂停物理推进,再根据画面选择下一组按键。

螺丝刀 · 37.07 秒

螺丝刀这一段可用来查看完整流程:靠近目标、夹紧、搬运、松手,以及成功判据最后怎样变为成立。

螺丝刀:1112 帧,从重置到成功;AI 键盘操作。螺丝刀:1112 帧,从重置到成功;AI 键盘操作。

扳手 · 46.10 秒

扳手第一次抓取后滑回了白箱,随后在同一回合中调整并完成任务。这段保留了修正过程。

扳手:1383 帧,保留滑落和重新抓取;AI 键盘操作。扳手:1383 帧,保留滑落和重新抓取;AI 键盘操作。

锤子 · 45.83 秒

锤子同样经历了滑回白箱和重新抓取。它在仿真中设定为 0.7 kg,接触负载下的末端漂移更明显,需要操作时补偿。这个质量是工程假设,没有做实物标定。

锤子:1375 帧,保留回合内调整;AI 键盘操作。锤子:1375 帧,保留回合内调整;AI 键盘操作。

调色刀 · 54.13 秒

调色刀这一段先误拿了螺丝刀,操作方将它放回白箱,再抓取指令指定的工具。任务判据始终检查调色刀,不会因为拿起了另一件工具就改变目标。

调色刀:1624 帧,保留误拿、放回和重新选择目标;AI 键盘操作。调色刀:1624 帧,保留误拿、放回和重新选择目标;AI 键盘操作。

四段录像合计 5494 帧,已有完整解码及逐步记录核验。这证明这四个录制回合完成了任务,不能据此估计一般场景下的抓取成功率。

环境结构

运行基线为 Isaac Lab 0.47.2、Isaac Sim 5.1.0 和 RTX 3090。Isaac Sim 提供物理仿真与渲染,Isaac Lab 负责把机器人、动作、观测和任务逻辑组织成可运行的环境。

工程采用独立外部项目,没有修改 Isaac Lab 核心代码,也没有把任务塞进其内置任务目录。这里的 Manager-based 可以理解为按职责拆开配置:动作管理器解释输入,观测管理器组织输出,事件管理器负责重置,终止管理器判断这一回合何时结束。主要文件如下:

palatial/
├── README.md、REPORT.md
├── scripts/                 # 启动、键盘操作、录制、回放、验证
├── assets/                  # 工具与箱体原始文件、处理后的资产
├── datasets/
│   ├── videos/              # 四段 MP4 与逐步 JSON 记录
│   └── hdf5/                # 四份结构化轨迹数据
├── evidence/                # 检查结果和运行记录
└── source/palatial/
    ├── setup.py、pyproject.toml、config/extension.toml
    └── palatial/tasks/bin_pick_place/
        ├── bin_pick_place_env_cfg.py
        ├── config/franka/env_cfg.py
        └── mdp/
            ├── events.py
            ├── observations.py
            └── terminations.py

安装后注册两个 Gym 环境 ID。Gym ID 就是启动时用于选择环境的名称:主环境在重置时选择目标;PLAY 版本固定一个环境、种子 42 和螺丝刀目标,便于重复检查同一个场景。

每回合的指令使用固定格式:

Pick the screwdriver from the white bin and place it in the blue bin.

指令中的工具名、观测中的目标编号和成功判据检查的物体,来自同一个目标配置。这样可以避免文字要求拿螺丝刀,程序却在检查锤子的错误。

箱体尺寸与碰撞

每次重置恢复机械臂、两个箱子和四件工具的位置,并清零线速度与角速度。蓝箱初始为空,四件工具分开放在白箱内;成功计数也从零开始。

资产接入时遇到了两个具体问题。

白箱原始水平尺寸约为 0.298 × 0.141 米,而锤子的占地宽度约为 0.145 米。为了给四件工具留下可抓取空间,白箱按 X、Y、Z 方向缩放为 2、3、1,工具保持原尺寸。这改变了白箱的真实比例,报告中保留了这个取舍。

蓝箱提供的是 OBJ/GLB 和凸碰撞网格,需要转换成 USD。USD 是这个工程里用于组织场景资产的文件格式。最初依照元数据坐标转换后,实际画面显示蓝箱部分陷入桌面;检查网格坐标后,对视觉网格和碰撞网格一起修正了变换。如果只修正外观,录像看着正常,工具仍可能碰到错误位置的“隐形箱壁”。

工具也需要统一刚体结构。刚体可以近似理解为仿真中不会自行变形的一个整体;一件工具不应因为源文件组织方式而散成多个独立运动的零件。处理后的工具各有一个根刚体,同时保留原来的视觉部件。

键盘控制

每个控制步输入七个数:

[dx, dy, dz, drx, dry, drz, gripper]

前三个表示末端平移,单位为米;接下来三个表示旋转增量,单位为弧度;最后一个控制夹爪开合。平移和旋转相对于机器人基座坐标系表达,不能直接把它们理解为屏幕上的上下左右。

逆运动学(IK) 解决的是“希望手移动到哪里,关节应该怎样动”。这里使用相对位姿命令和微分 IK,每一步根据当前位置计算小幅关节调整,控制 Panda 的七个手臂关节。环境只接收动作,没有内置自动抓取或搬运状态机。

TCP(工具中心点) 是用来控制和测量末端位置的参考点。本项目将它设在 panda_hand 局部 +Z 方向 0.107 米处,靠近夹爪实际操作区域;控制器和末端传感器使用相同偏移。

正夹爪动作表示张开,每根手指的目标位置为 0.04 米;负动作表示闭合,目标为 0。正式录像使用 0.012 米的键盘平移步长,默认旋转步长为 0.025 弧度。

物理仿真以 120 Hz 推进,每四个物理步接收一次控制动作,因此控制与录像采样为 30 Hz。单回合上限是 120 秒仿真时间。一次场景检查中实际测得约 9.53 个控制步/真实秒,可见设置 30 Hz 并不保证画面实时运行。连续键盘模式下,即使不按键,物理时间也会继续走。

怎样算放好了

成功判据只检查指令指定的工具。它必须同时满足入箱、稳定和释放三个条件,并连续保持 10 个控制步。

条件 本项目的具体检查 主要排除什么
入箱 工具包围盒八个角点全部位于蓝箱局部 X ±0.20、Y ±0.13、Z 0.003~0.25 米内 中心入箱但一端伸出、停在箱沿
稳定 线速度小于 0.025 米/秒,角速度小于 0.25 弧度/秒 仍在运动、弹跳或快速转动
释放 双指总开度大于 0.065 米,TCP 到工具有向包围盒的距离大于 0.04 米 夹爪仍闭合抓持,或末端尚未撤离
持续成立 上述条件连续满足 10 个控制步,中断就重新计数 一帧恰好满足条件就提前结束

包围盒是包住工具的几何外框。检查八个角点比只检查中心保守,但也可能拒绝一些实际可接受的斜放姿态。计算前先把工具角点变换到蓝箱坐标系,箱子发生旋转时仍以它自己的内部边界为准。

这些阈值是工程选择,没有经过大规模统计调优。10 步对应约三分之一秒;若持续接近速度阈值,物体在这段时间里仍可能移动约 8.3 毫米、转动约 4.8 度,所以“稳定”并不等于绝对静止。夹爪完全张开的目标总开度是 0.080 米,0.065 米要求它接近张开状态,再结合末端距离降低误判。这个组合仍是释放状态的近似判断,没有直接测量接触力。

失败与超时也分开处理。目标原点越出 X 为 −0.35~1.2 米、Y 为 −0.85~0.85 米的范围,或低于 Z = −0.15 米,记为工作空间失败;用完时间预算则单独记为超时。否则下游分析会把“来不及完成”和“工具已经掉落”混成同一种结果。

反例检查

验证覆盖四种工具的成功状态,以及放错工具、目标仍运动、夹爪闭合、箱沿、掉落、超时、成功计数中断和同一步重复读取等情况。

其中多数反例通过设置受控状态来隔离某一个条件。例如要检查“释放”是否生效,就需要避免速度或入箱条件同时不成立,让结果难以解释。另有真实键盘抓持工具进入蓝箱但没有触发成功的物理记录;该快照没有独立证明工具当时已经静止,因此不能拿它替代所有释放条件测试。

这些区分很重要:一段成功录像能证明某次操作完成了任务,却不能单独证明判据不会误报。反例检查补充的正是后一个问题。

相机与观测

两个外部相机从不同方向观察机械臂、双箱和搬运路径,手腕相机跟随机械臂观察抓取区域。每路 RGB 分辨率为 640 × 480;录像拼接后为 1920 × 544,多出的高度用于文字标注。

相机的内参描述三维点怎样投影到图像,本项目三路相机的测量值均为 fx = fy = 480、cx = 320、cy = 240。外参描述相机的位置与朝向;外部相机固定,手腕相机的世界位姿需要由手掌位姿和安装偏移组合得到。

环境将观测保留为字典,包含关节位置与速度、末端位姿、夹爪状态、四件工具和两个箱子的姿态、目标编号、目标相对末端与蓝箱的位置、上一动作及三路 RGB。目标编号用四维 one-hot 表示,例如一个位置为 1、其余为 0,明确告诉后续策略当前要操作哪件工具。

重置相机时也碰到过缓存问题。环境状态已经重置,首帧 RGB 却可能还是旧画面或黑帧。通过完整解码录像发现后,加入了只刷新渲染、不推进物理的步骤,并重新录制受影响回合。仅仅检查“生成了 MP4 文件”无法发现这种问题。

动作回放为什么只有 2/4 成功

HDF5 是一种能够在同一文件里保存多组数组和元数据的格式。本次用它记录动作、状态、观测、RGB、目标指令和判据结果,四份数据合计约 3.23 GB。

这些数据来自重新物理执行历史键盘动作日志,并非与原始四段 MP4 同时录制。工程接入了 Isaac Lab 的原生动作/状态 recorder,但使用自定义入口组织元数据、CPU 图像缓冲和终止观测,相关偏离在报告中说明。

这里有两种容易混淆的回放:

工具 状态回放 严格执行原动作序列 另一次允许末尾等待的测试
螺丝刀 保存字段精确恢复 成功 无需额外等待
扳手 保存字段精确恢复 未成功,最后 hold = 9/10 多等待 1 步后成功
锤子 保存字段精确恢复 成功 无需额外等待
调色刀 保存字段精确恢复 未成功,最后 hold = 4/10 多等待 6 步后成功

hold 是当前连续满足成功条件的步数。扳手差一步,依然不能记为严格成功;调色刀同理。两次额外等待发生在单独测试里,没有通过降低阈值把失败改写成成功。四种工具的动作回放轨迹都出现数值偏差,包括最终完成任务的两种。

因此,本次结果是:四段原始录像成功,四份状态回放通过,严格动作回放成功 2/4。这三个结果分别回答不同的问题,应该一起保留。

安装与回放

下面的命令面向已配置兼容 Isaac Lab / Isaac Sim 的 Linux 工作站,在项目根目录执行。它们依赖完整工程与资产,单独复制脚本无法运行。

# 安装外部项目
python -m pip install -e source/palatial

# 启动固定目标的 PLAY 环境
python scripts/zero_agent.py --task Palatial-Franka-BinPickPlace-PLAY-v0 --num_envs 1 --enable_cameras

# 真人键盘操作,使用新的输出文件名
python scripts/teleop.py --enable_cameras --target 0 --operator human --video datasets/user_runs/practice_01.mp4

# 查看螺丝刀状态回放
python scripts/replay_hdf5.py --enable_cameras --dataset datasets/hdf5/demo_0.hdf5 --mode states --realtime

# 严格动作回放,不追加末尾等待
python scripts/replay_hdf5.py --enable_cameras --dataset datasets/hdf5/demo_0.hdf5 --mode actions --realtime

运行键盘控制时,需要图形桌面、仿真窗口焦点和英文键盘输入。W/S、A/D、Q/E 控制平移,Z/X、T/G、C/V 控制旋转,K 切换夹爪。已有正式录像受防覆盖保护,新练习要使用新文件名。

工程内打包了工具与箱体资产,Seattle 实验桌仍来自 NVIDIA 的默认资产源或本地缓存。首次加载可能等待数分钟,网络超时也会导致启动失败。安装和回放验证是在同一台 3090 上通过新目录、新环境完成的,不能推广为所有机器、所有版本均兼容。

在 Mac 上远程操作

3090 放在学校实验室,我在家用 Mac 远程连接。这次操作下来,触控板调整视角和缩放都不太顺手,一些平常很简单的操作要绕好几步,期间也遇到过窗口无响应。按我目前的设备和使用习惯,在 Mac 本地用 MuJoCo 可能会方便一些。这只是这次操作的感受,没有做两个仿真器的性能对比。

后面还能做什么

这个项目目前适合拿来学习环境组织、检查任务判据,以及观察多视角动作数据。四个回合对于训练仍然太少。若继续做模仿学习,需要扩充示范、规范化数据、划分训练与验证集,并在独立回合上评估;更换工具、箱子或机器人,还要重新检查几何边界、初始摆放、控制器和 TCP。

回头看这次任务,我更关心的是录像之外的检查:成功由哪个判据触发,反例能不能被排除,保存的状态能不能恢复,同一组动作重跑会有什么偏差。这些结果都留在记录里,后面继续做策略学习时,才知道该拿什么作比较。