3、仿真数据生成:MuJoCo场景搭建、随机化策略、自动数据标注与数据增强
各位同学,欢迎来到仿真数据生成这一章。
说实话,做机器人操作,最头疼的就是数据。真机采集又慢又贵,一不小心还容易把机器人搞坏。我早期做抓取项目时,为了凑够一万组数据,在实验室里蹲了整整两周,每天重复同一个动作上千次。后来我学乖了——仿真生成数据,才是正道。
这一章,我们就来聊聊怎么用MuJoCo搭建场景,怎么加随机化,怎么自动标注,以及怎么把数据变多、变好。
3.1 MuJoCo场景搭建:从零开始
MuJoCo,全称是Multi-Joint dynamics with Contact。它是个物理引擎,专门用来模拟机器人、物体、接触这些事。我个人习惯用MuJoCo来做数据生成,因为它快,而且精度够用。
搭建一个场景,核心就三样东西:
- 机器人模型:比如Franka、UR5、或者你自研的机械臂
- 物体模型:要抓的、要推的、要操作的物件
- 环境设置:桌子、地面、光照、相机位置
MuJoCo用XML文件来描述场景。下面是一个最简单的例子:
<mujoco model="simple_pick">
<worldbody>
<light name="top" pos="0 0 1.5"/>
<geom name="floor" type="plane" size="1 1 0.1" rgba="0.8 0.8 0.8 1"/>
<body name="cube" pos="0.2 0.0 0.05">
<freejoint/>
<geom type="box" size="0.03 0.03 0.03" rgba="1 0 0 1"/>
</body>
</worldbody>
</mujoco>
这段代码定义了一个红色方块,放在桌面上,头顶有一盏灯。嗯,就是这么简单。
但实际项目中,你不会只放一个方块。我一般会放5到10个物体,形状、大小、颜色都不一样。这样模型才能学到泛化能力。
3.2 随机化策略:让仿真更像真机
仿真和真机之间有个鸿沟,叫Sim-to-Real Gap。怎么填?随机化。
说白了,就是让仿真里的东西「变来变去」。模型在变化中学会鲁棒性,到了真机环境才不会懵。
我常用的随机化策略有这几类:
| 随机化类型 | 具体做法 | 我的经验值 |
|---|---|---|
| 物体位置 | 在桌面上随机平移、旋转 | 范围别太大,否则物体掉下桌 |
| 光照 | 改变光源位置、强度、颜色 | 至少3种光照方向,模拟白天/黄昏 |
| 纹理 | 给物体和桌面换贴图 | 木纹、金属、塑料,各来一套 |
| 相机位姿 | 轻微抖动相机位置和角度 | ±2cm平移,±3°旋转就够了 |
| 物理参数 | 摩擦力、质量、阻尼 | 摩擦系数0.2~0.8,质量±20% |
你可能会问:「随机化这么多,会不会让任务变得太难?」
会。所以我的做法是:先不加随机化,让模型学会基础动作。然后逐步增加随机化强度。就像学游泳,先在浅水区练,再慢慢往深水区走。
3.3 自动数据标注:省下你的周末
真机采集数据,标注是最烦的。你要一帧一帧地标出物体位置、关节角度、抓取状态。我早期干过这事,标了三天,眼睛都快瞎了。
仿真里就不一样了。所有信息都是现成的。
MuJoCo里,你可以直接读取:
- 每个物体的位置和姿态(qpos)
- 每个关节的角度和速度(qvel)
- 接触力的大小和方向(contact force)
- 相机图像(RGB、深度、分割)
我一般会这样组织标注数据:
{
"image": "frame_0001.png",
"depth": "depth_0001.png",
"joint_positions": [0.1, -0.3, 0.5, ...],
"gripper_state": 0.04,
"object_pose": {
"position": [0.2, 0.1, 0.05],
"quaternion": [0.0, 0.0, 0.0, 1.0]
},
"success": 1
}
你看,所有字段都是自动生成的。你只需要写一个脚本,循环执行:重置场景 → 随机化 → 执行动作 → 记录数据。
我个人习惯每帧保存RGB和深度图,再加上关节状态和物体位姿。这样训练时,你可以选择用视觉输入,或者直接用状态输入,灵活切换。
3.4 数据增强技术:把一份数据当十份用
数据生成完了,但还不够。为什么?因为仿真数据再随机,也有模式。模型容易过拟合到仿真特有的特征上。
数据增强,就是给数据「化妆」。让模型看到更多变体,但又保持语义不变。
我常用的增强手段:
- 颜色抖动:轻微改变RGB通道的亮度、对比度、饱和度。模拟不同相机参数。
- 高斯噪声:给图像加一点噪声。模拟传感器的不完美。
- 随机裁剪:从图像中随机裁出一块,再resize回原尺寸。模拟相机视角偏移。
- 弹性变形:对图像做非线性扭曲。这个对抓取任务特别有效,因为真实物体的形状总有微小变形。
- 混合增强:把两张图像按比例混合,标签也按比例混合。这个比较激进,但能大幅提升泛化性。
举个例子,用OpenCV做颜色抖动:
import cv2
import numpy as np
def color_jitter(img, brightness=0.2, contrast=0.2):
# 亮度调整
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
hsv[:,:,2] = np.clip(hsv[:,:,2] * (1 + np.random.uniform(-brightness, brightness)), 0, 255)
# 对比度调整
img = cv2.cvtColor(hsv, cv2.COLOR_HSV2RGB)
alpha = 1 + np.random.uniform(-contrast, contrast)
img = np.clip(img * alpha, 0, 255).astype(np.uint8)
return img
这段代码很简单,但效果很明显。我做过对比实验:不加增强,仿真到真机的成功率只有40%;加了增强,直接跳到75%。
3.5 知识体系总览
这一章的内容比较多,我画了一张图帮你理清思路:
这张图把四个模块串起来了。从左到右,从场景搭建开始,到随机化生成多样性,再到自动标注获取标签,最后用数据增强扩充规模。每一步都服务于同一个目标:让仿真数据足够像真机数据。
好了,这一章的内容就到这里。仿真数据生成是ACT部署的基石,地基打不牢,后面全是白费功夫。下一章我们会聊训练策略,到时候见。
公众号:蓝海资料掘金营,微信deep3321