File size: 5,645 Bytes
42f5508 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | # SceneSmith 各类场景说明
> 本文档回答:SceneSmith 适合生成哪类场景,机器人能操作什么物体,以及哪些操作不支持。
---
## 1. 桌面场景(Tabletop Manipulation)
**最适合 SceneSmith 的场景类型**。
### 能生成什么
通过 `manipuland_agent` 可以在桌面上放置:
| 类别 | 具体物体 |
|------|---------|
| 食物/水果 | 苹果、橙子、香蕉、面包 |
| 餐具 | 盘子、碗、杯子、刀叉 |
| 文具 | 书本、笔记本、钢笔、尺子 |
| 电子产品 | 手机、遥控器、鼠标 |
| 装饰品 | 花瓶、小雕像、相框 |
| 组合体 | 装了水果的碗、叠放的书 |
### 怎么生成桌面场景
```
scene_prompt: "A kitchen counter with a wooden cutting board,
a ceramic bowl filled with apples and oranges, a glass of water,
a butter knife, and a small herb plant pot."
```
关键配置:`manipuland_agent` 会自动分析每件家具的支撑面,在支撑面上生成小物件。
### 抓取可行性
每个 manipuland 的 SDF 包含:
- 精确的碰撞几何体(VHACD 近似凸分解)
- 质量 + 摩擦系数
- 完整的 bounding box
可以用 `policy_interface.py` 获取抓取目标位姿:
```bash
python scripts/robot_eval/policy_interface.py \
--task "Pick the apple from the bowl and place it on the plate" \
--scene-state outputs/.../house_state.json \
--dmd outputs/.../house.dmd.yaml
```
---
## 2. 柔性物体(Deformable Objects)
**SceneSmith 不支持**。
### 原因
SceneSmith 的整个 pipeline 基于**刚体假设**:
- Drake 仿真:刚体多体动力学
- SDF 格式:刚体碰撞几何
- VHACD 分解:只适用于刚体
柔性物体(布料、毛绒玩具、橡皮泥)需要:
- FEM (Finite Element Method) 求解器
- 粒子系统
- 布料仿真(Position-Based Dynamics 等)
### 变通方案
1. 用 SceneSmith 生成**刚体背景场景**(桌子、椅子、柜子)
2. 用 `scripts/export_scene_to_mujoco.py` 转换为 MuJoCo XML
3. 在 MuJoCo 中用 `composite` 元素添加布料
4. 或在 Isaac Sim 中用 FEM solver 添加柔性物体
---
## 3. 流体(Fluid / Liquid)
**SceneSmith 不支持**。
### 原因
同上,Drake 不包含流体仿真。`house.dmd.yaml` 只有刚体 Directives。
"倒水"这类任务需要:
- SPH (Smoothed Particle Hydrodynamics)
- FLIP Fluid
- FluidLab、Taichi Physics 等
### 变通方案
1. 用 SceneSmith 生成**杯子、瓶子的几何体**(SDF包含容器形状)
2. 将容器几何体导入 FluidLab / Taichi
3. 在流体仿真器中加入液体粒子
注意:SceneSmith 生成的杯子是**视觉上的外壳**,不一定有精确的内部空腔几何体用于流体边界。
---
## 4. 常见场景类型
SceneSmith 论文中验证过的场景类型:
| 场景 | 典型任务 | 特点 |
|------|---------|------|
| 卧室 | 整理床头柜、拿取衣物 | 床、衣柜等大件家具 + 小件 |
| 厨房 | pick-and-place 食物 | 橱柜、水果、厨具,最适合操作 |
| 客厅 | 整理茶几 | 沙发、书架、遥控器、书本 |
| 办公室 | 文具整理、拿取文件 | 桌面小物件最丰富 |
| 社区中心 | 多人活动场景 | 乒乓球桌、椅子等 |
### 最适合操作的场景
**厨房** 和 **办公桌** 是操作任务密度最高的:
- 物体种类多(水果、餐具、文具)
- 桌面支撑面大
- 物体尺寸适合抓取(0.05m ~ 0.3m)
### 提示词技巧
- **明确指定物体**:"with a red apple, a ceramic plate, and a glass of water" 比 "with food" 更好
- **指定初始状态**:"apple is on the counter, not on the plate" 避免场景自动把任务solve了
- **避免过于复杂**:单个房间建议 5-10 个 manipuland,太多会让 agent 超时
---
## 5. Demo采集(Demonstration Collection)
### 当前能力(本次实现)
本次实现了基于 SceneSmith 输出的 **脚本化 demo 采集**:
```
SceneSmith 场景 → policy_interface → 目标位姿
↓
几何轨迹规划(home→approach→grasp→lift→transport→place)
↓
demo JSON + 轨迹可视化 PNG
```
**产出**:
- `demo_*.json`:完整轨迹(每步 50ms,包含 EE 位姿 + 夹爪宽度)
- `demo_*_trajectory.png`:4子图可视化
### 真实 Demo 采集的正确方案
SceneSmith 官方没有提供 demo 采集代码。正确路径是:
```
1. python scripts/robot_eval/policy_interface.py → 获取目标位姿
2. 加载场景到仿真器:
drake_sim = load_scene(house.dmd.yaml) # 或 MuJoCo/Isaac
3. 加入 robot URDF(如 Franka Panda):
drake_sim.add_robot("franka_panda.urdf", base_pose)
4. 运行 controller:
- scripted: 几何规划(本次实现的方式)
- teleop: 人工示教
- policy rollout: 用已有 policy 采样
5. 记录每步 (obs, action) → dataset
6. python scripts/robot_eval/validate.py → 验证 success
```
### Demo 数据格式(与主流兼容)
本次采集的 JSON 格式可以直接转换为:
- **RLDS (tensorflow_datasets)**:`(observation, action, reward, discount)` 格式
- **LeRobot**:`lerobot` 库的 episode 格式
- **HDF5**:标准 robot learning 数据格式
转换示例:
```python
import json
import numpy as np
with open("demo_bedroom_nightstand_to_desk.json") as f:
demo = json.load(f)
# 转换为 numpy arrays
ee_traj = np.array([s["end_effector_pos"] for s in demo["trajectory"]])
gripper = np.array([s["gripper_width"] for s in demo["trajectory"]])
# shape: (150, 3) and (150,)
```
|