File size: 23,974 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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | # SceneSmith 完整技术文档
> 语言:中文
> 对应代码:[nepfaff/scenesmith](https://github.com/nepfaff/scenesmith)
> 论文:[arXiv 2602.09153](https://arxiv.org/abs/2602.09153)
> 本次运行环境:NVIDIA L40S GPU,SLURM 集群
---
## 目录
1. [系统总览](#1-系统总览)
2. [输入输出格式](#2-输入输出格式)
3. [核心流程详解](#3-核心流程详解)
4. [代码结构解析](#4-代码结构解析)
5. [Robot Eval 模块](#5-robot-eval-模块)
6. [SceneSmith 能做什么 / 不能做什么](#6-scenesmith-能做什么--不能做什么)
7. [本次运行结果](#7-本次运行结果)
8. [Demo采集说明](#8-demo采集说明)
9. [常见问题与局限性](#9-常见问题与局限性)
10. [复现指南](#10-复现指南)
---
## 1. 系统总览
SceneSmith 是一个**全自动、文本驱动的室内场景生成系统**,专为机器人仿真设计。
给一段自然语言描述(如"一个有书桌、床和衣柜的卧室"),SceneSmith 会输出一个**物理上可用的完整室内场景**,包含:
- 精确的 6D 物体位姿
- 每个物体的碰撞几何体(SDF 格式)
- 物理属性(质量、摩擦系数、惯性矩阵)
- 可以直接导入 Drake / MuJoCo / Isaac Sim 的格式
系统的核心是用**多个 LLM Agent 协作**代替人工设计:每个 Agent 负责场景生成的一个阶段,用视觉反馈迭代优化,直到满足质量标准。
```
文字描述
│
▼
┌─────────────────────────────────────────────────────────┐
│ SceneSmith Pipeline │
│ │
│ Floor Plan Agent → Furniture Agent → Wall Agent │
│ ↓ ↓ ↓ │
│ 生成平面图 摆放大件家具 墙面装饰 │
│ ↓ ↓ │
│ Ceiling Agent → Manipuland Agent │
│ ↓ ↓ │
│ 天花板灯具 小件可操作物体 │
│ │
│ 每个阶段:LLM 规划 → 3D资产生成 → 物理验证 → 视觉评分 │
└─────────────────────────────────────────────────────────┘
│
▼
house.blend (Blender 渲染) + house.dmd.yaml (Drake 仿真) + house_state.json
```
---
## 2. 输入输出格式
### 输入
| 输入项 | 格式 | 说明 |
|--------|------|------|
| 场景描述 | 自然语言字符串 | 例:`"A cozy bedroom with a queen bed..."` |
| CSV 提示文件(可选) | `prompts.csv` | 批量生成多个场景时使用 |
| 配置文件 | Hydra YAML | 控制使用的模型、后端、参数 |
**`prompts.csv` 格式**:
```csv
scene_index,prompt
0,"A modern kitchen with..."
1,"A cozy living room with..."
```
**关键配置参数**:
```yaml
openai:
model: "gpt-5.2" # LLM 模型名
experiment:
num_scenes: 5 # 生成场景数量
scene_prompt: "..." # 单场景描述
furniture_agent:
asset_manager:
backend: "hunyuan3d" # 3D资产生成后端: sam3d | hunyuan3d | hssd
```
### 输出
每次运行生成如下目录结构:
```
outputs/YYYY-MM-DD/HH-MM-SS/
└── scene_000/
├── combined_house/
│ ├── house.blend ← Blender 完整场景 (~200MB)
│ ├── house.dmd.yaml ← Drake Directives(仿真可用)
│ ├── house_furniture_welded.dmd.yaml ← 家具焊接版(稳定性更好)
│ ├── house_state.json ← 所有物体的位姿+元数据
│ └── sceneeval_state.json ← 场景评分数据
├── room_bedroom/
│ ├── generated_assets/ ← 每个物体的 SDF + 纹理
│ │ ├── desk_0/
│ │ │ ├── model.sdf
│ │ │ ├── model.obj
│ │ │ └── texture.png
│ │ └── ...
│ ├── scene_states/ ← 各阶段保存的中间状态
│ │ ├── scene_after_furniture/scene.blend
│ │ ├── scene_after_wall_objects/scene.blend
│ │ ├── scene_after_ceiling_objects/scene.blend
│ │ └── final_scene/
│ │ ├── scene.blend
│ │ └── scene_state.json
│ └── scene_renders/ ← 各阶段的渲染图像 (PNG)
└── floor_plans/
└── final_floor_plan/
├── floor_plan.blend
└── floor_plan.dmd.yaml
```
**`house_state.json` 结构**(关键字段):
```json
{
"rooms": {
"bedroom": {
"objects": {
"desk_0": {
"object_type": "furniture",
"name": "desk",
"description": "A modern wooden desk",
"sdf_path": "generated_assets/desk_0/model.sdf",
"transform": {
"translation": [0.79, 1.58, 0.0],
"rotation_wxyz": [1.0, 0.0, 0.0, 0.0]
},
"bbox_min": [-0.6, -0.3, 0.0],
"bbox_max": [0.6, 0.3, 0.75],
"mass": 15.0,
"mu_static": 0.6
}
}
}
}
}
```
**`house.dmd.yaml` 格式**(Drake Directives):
```yaml
directives:
- add_model:
name: bedroom_desk_0
file: package://scene/room_bedroom/generated_assets/desk_0/model.sdf
- add_weld:
parent: world
child: bedroom_desk_0::base_link
X_PC:
translation: [0.79, 1.58, 0.0]
rotation: !Rpy { deg: [0, 0, 0] }
```
---
## 3. 核心流程详解
### Stage 1:Floor Plan Agent(平面图规划)
**输入**:场景描述文字
**输出**:房间尺寸、门窗位置、墙体布局(`floor_plan.dmd.yaml`)
工作方式:
1. LLM 解析场景描述,确定所需房间类型(卧室、厨房等)
2. 生成候选平面图(房间长宽、门的位置)
3. 用 Blender 渲染俯视图,LLM 评分(0-1分)
4. 迭代优化,选择得分最高的方案
评分标准:空间合理性、比例、门窗位置是否符合常识。
---
### Stage 2:Furniture Agent(家具摆放)
**输入**:平面图、场景描述
**输出**:家具的精确 6D 位姿 + 每件家具的 SDF 模型
这是最复杂的阶段,分三个子步骤:
#### 2a. 家具规划
LLM 决定放什么家具、大概的位置,生成一个结构化的家具列表。
#### 2b. 3D 资产生成
对每件家具,走以下路由(Asset Router):
```
家具描述文字
│
▼
Asset Router (LLM决策)
├── "generated" → Hunyuan3D-2 / SAM3D
│ ├── 生成参考图 (GPT-Image-2)
│ └── 图片 → 3D mesh (扩散模型)
│ ↓
│ 纹理烘焙 + SDF生成
│
├── "artvip" → 从ArtVIP库检索关节物体(开门的衣柜等)
│
└── "hssd" → 从HSSD数据集检索(更快,质量稳定)
```
#### 2c. 迭代摆放
1. 放置家具到初始位置
2. Drake 物理仿真:检测碰撞、检查是否可站立
3. Blender 渲染多视角图
4. LLM 用视觉反馈打分(美观度、布局合理性、可达性)
5. 如果分数不满足阈值,调整位置重试(最多 N 轮)
---
### Stage 3:Wall Agent(墙面装饰)
**输入**:已摆好家具的场景
**输出**:墙面装饰物(画、镜子、时钟、架子等)的位姿
同样走 asset router → 3D 生成 → Drake 验证 → 视觉评分的流程,但专注于墙面的高度、朝向、装饰品间距。
---
### Stage 4:Ceiling Agent(天花板)
**输入**:已完成墙面的场景
**输出**:天花板灯具、风扇等物体
主要验证灯具位置是否在房间中央、是否与墙面冲突。
---
### Stage 5:Manipuland Agent(可操作小物件)
**输入**:已完成天花板的场景、每件家具的支撑面信息
**输出**:桌面上的书、杯子、水果等小物件
特点:
- 自动分析每件家具的"支撑面"(桌面、架子面)
- 在支撑面上随机采样放置位置,Drake 验证不碰撞
- 可生成组合(stack/pile/filled_container):叠起来的书、装苹果的碗等
---
### Stage 6:物理投影 + 最终导出
所有物体放好后:
1. Drake 运行物理仿真,让物体自然落下(消除浮空、轻微穿插)
2. 输出最终 `house.dmd.yaml`(固定位姿,weld 到 world)
3. Blender 渲染最终场景,保存 `house.blend`
---
## 4. 代码结构解析
```
scenesmith/
├── main.py ← 入口,Hydra 配置,调度各 Agent
│
├── scenesmith/
│ ├── experiments/
│ │ └── indoor_scene_generation.py ← 主实验类,串联所有 Agent
│ │
│ ├── floor_plan_agents/
│ │ ├── stateful_floor_plan_agent.py ← Floor Plan Agent 实现
│ │ └── tools/ ← 平面图相关工具
│ │
│ ├── furniture_agents/
│ │ ├── stateful_furniture_agent.py ← Furniture Agent 主类
│ │ └── tools/
│ │ ├── furniture_tools.py ← 家具放置、物理检查工具
│ │ ├── vision_tools.py ← Blender 渲染观察工具
│ │ └── scene_tools.py ← 场景状态查询
│ │
│ ├── wall_agents/ ← Wall Agent(同结构)
│ ├── ceiling_agents/ ← Ceiling Agent(同结构)
│ ├── manipuland_agents/ ← Manipuland Agent(同结构)
│ │
│ ├── agent_utils/
│ │ ├── asset_manager.py ← 资产获取总入口
│ │ ├── asset_router/ ← LLM决策走哪个资产后端
│ │ ├── geometry_generation_server/ ← 3D生成服务(Hunyuan3D工作进程)
│ │ │ ├── server_manager.py
│ │ │ ├── worker_pool.py ← GPU工作进程池
│ │ │ └── gpu_worker.py ← 单个GPU的3D生成进程
│ │ ├── drake_utils.py ← Drake 仿真工具
│ │ ├── rendering.py ← 场景渲染工具
│ │ ├── physics_validation.py ← 物理碰撞检测
│ │ ├── reachability.py ← 机器人可达性分析
│ │ ├── image_generation.py ← 参考图生成(GPT-Image-2)
│ │ ├── vlm_service.py ← VLM评分服务
│ │ └── blender/ ← Blender 进程通信
│ │ ├── server_manager.py ← Blender 服务器管理
│ │ └── renderer.py ← 渲染接口
│ │
│ └── robot_eval/
│ ├── dmd_scene.py ← Drake 场景加载
│ ├── policy_interface/
│ │ ├── policy_agent.py ← 任务 → 物体绑定 Agent
│ │ └── predicate_resolver.py ← 绑定 → 精确位姿
│ ├── success_validation/
│ │ └── validator_agent.py ← 任务成功验证 Agent
│ └── task_generation/
│ └── scene_prompt_generator.py ← 任务 → 场景描述
│
└── scripts/
├── robot_eval/
│ ├── generate_prompts.py ← Stage 1: task → prompts
│ ├── policy_interface.py ← Stage 3: scene + task → robot poses
│ └── validate.py ← Stage 4: 验证任务完成
├── collect_demo.py ← Demo采集与可视化(本次添加)
├── render_flythrough.py ← 生成场景飞行视频
└── export_scene_to_mujoco.py ← 导出到 MuJoCo
```
---
### 关键类说明
#### `StatefulFurnitureAgent`
继承自 `BaseStatefulAgent`,用 `openai-agents` SDK 运行 LLM agent loop。
Agent 的 tools 包括:
- `place_furniture(obj_id, x, y, yaw)` — 放置家具
- `observe_scene()` — 渲染当前场景,返回多视角图给 LLM 看
- `get_physics_check()` — 运行 Drake 碰撞检测
- `generate_furniture_assets(descriptions)` — 批量生成 3D 资产
- `score_scene()` — VLM 打分
每轮 LLM 调用 tools → 观察反馈 → 调整 → 直到评分达标或超过最大轮数。
#### `AssetManager`
统一的资产获取接口,内部调用 `AssetRouter` 决策:
```python
asset = await asset_manager.get_asset(
description="A wooden desk with drawers",
object_type="furniture",
strategy="generated" # or "hssd", "artvip"
)
# 返回 Asset(sdf_path, obj_path, texture_path, dimensions, ...)
```
#### `DMDScene` + `PredicateResolver`
用于 robot eval:
```python
scene = load_scene_for_validation(
scene_state_path=Path("house_state.json"),
dmd_path=Path("house.dmd.yaml"),
)
scene.finalize() # 建立 Drake plant,同步位姿
resolver = PredicateResolver(scene=scene, cfg=cfg)
result = resolver.resolve("Pick the apple and place it on the plate")
# result.poses[0].target_position → [x, y, z] 目标位姿
# result.poses[0].placement_bounds_min/max → 有效放置区域 AABB
```
---
## 5. Robot Eval 模块
这是 SceneSmith 的机器人评测框架,共 4 个阶段:
### 阶段 1:生成场景提示词
```bash
python scripts/robot_eval/generate_prompts.py \
--task "Pick a fruit from the bowl and place it on the plate" \
--output-dir outputs/eval_run \
--num-prompts 5
```
LLM 分析 task,提取:
- 必须存在的物体(水果、碗、盘子)
- 初始状态约束(水果不能已经在盘子上)
- 可变的风格维度(厨房风格、其他装饰物)
输出 `prompts.csv` 供 `main.py` 生成多个不同风格的场景。
### 阶段 2:生成场景
```bash
python main.py +name=eval experiment.csv_path=outputs/eval_run/prompts.csv
```
### 阶段 3:Policy Interface(任务 → 机器人位姿)
```bash
python scripts/robot_eval/policy_interface.py \
--scene-state outputs/.../house_state.json \
--dmd outputs/.../house.dmd.yaml \
--task "Pick a fruit from the bowl and place it on the plate" \
--output-json robot_commands.json
```
输出格式:
```json
{
"task": "Pick a fruit...",
"robot_start_xy": [1.2, -0.5],
"world_bounds": {"min": [-3, -3, 0], "max": [3, 3, 2.7]},
"commands": [{
"action": "pick_and_place",
"rank": 1,
"confidence": 0.92,
"drake_model_name": "bedroom_apple_0",
"target_position": [0.5, 0.3, 0.85],
"placement_bounds_min": [0.2, 0.1, 0.85],
"placement_bounds_max": [0.8, 0.5, 1.0],
"reasoning": "Apple found on nightstand (precondition met), plate on desk is valid goal"
}]
}
```
**注意**:SceneSmith 不包含 robot URDF 和 policy。`placement_bounds_min/max` 是给你的 policy 用的采样区域。
### 阶段 4:验证
Robot 执行完任务后,将修改过的 `house.dmd.yaml`(更新了物体位姿)传入验证器:
```bash
python scripts/robot_eval/validate.py \
--scene-state outputs/.../house_state.json \
--dmd outputs/.../modified_house.dmd.yaml \
--task "Pick a fruit from the bowl and place it on the plate"
```
验证器用 Drake 物理查询(签名距离、接触检测)+ VLM 视觉判断,输出每个子要求的得分。
---
## 6. SceneSmith 能做什么 / 不能做什么
### ✅ 能做的
| 场景类型 | 说明 |
|---------|------|
| 卧室 | 床、衣柜、书桌、台灯、挂画、小件(书、闹钟等) |
| 厨房 | 橱柜、餐桌、厨具、水果、杯子等 |
| 办公室 | 桌子、椅子、电脑、文具等 |
| 客厅 | 沙发、茶几、书架、摆件等 |
| 关节物体 | 可开关的柜子、抽屉(来自 ArtVIP 数据集) |
| 桌面操作场景 | 通过 manipuland agent 生成多个小物件,支持 pick-and-place |
| 组合物体 | 叠起来的书(stack)、装了东西的碗(filled_container)、散乱的一堆(pile) |
### ❌ 不能做的
| 类别 | 原因 |
|------|------|
| **柔性物体**(布料、毛绒玩具) | SceneSmith 只生成刚体 SDF。柔性物体需要 FEM/粒子仿真,Drake 支持有限,SceneSmith 不建模 |
| **流体**(倒水、液体) | 同上,流体需要 SPH/粒子系统,不在 SceneSmith 范围内。`house.dmd.yaml` 是刚体 Directives |
| **人体/角色动画** | 无 URDF/骨骼,无动画系统 |
| **室外场景** | 专为室内设计,无地形、植被等 |
| **Robot URDF** | SceneSmith 只生成环境,不包含机器人本体 |
| **Policy / Controller** | 不包含任何 policy,只提供场景 + eval harness |
### 关于柔性物体和流体的正确路径
如果需要:
- **布料**:用 MuJoCo 的 `composite` 元素或 Isaac Sim 的 FEM,把 SceneSmith 生成的刚体场景作为背景
- **流体**:FluidLab、Taichi,SceneSmith 生成杯子/瓶子的 SDF 作为容器几何体
- 可以用 `scripts/export_scene_to_mujoco.py` 先把 SceneSmith 场景转成 MuJoCo XML,再在 MuJoCo 里加入柔性/流体模拟
---
## 7. 本次运行结果
### 场景 1:卧室(Bedroom)
**提示词**:
> A cozy bedroom with a queen bed against the wall, two nightstands with lamps, a wardrobe in the corner, and a small desk with a chair near the window.
**运行时间**:约 1 小时 57 分钟(L40S GPU)
**生成物体**:
| 物体 | 类型 | 位置 (x, y, z) |
|------|------|---------------|
| desk_0 | furniture | (0.79, 1.58, 0.0) |
| nightstand_0 | furniture | (-0.55, -1.73, 0.0) |
| nightstand_1 | furniture | (0.62, -1.73, 0.0) |
| rug_0 | furniture | (-0.01, -0.39, 0.0) |
| wardrobe_0 | furniture | (2.06, -1.53, 0.0) |
**注意**:本次运行中 Hunyuan3D worker 因 CUDA fork 问题未能生成 manipuland(小件物体),house_state.json 只有家具级别的物体。
**输出文件**:
- `combined_house/house.blend` — 201MB Blender 场景
- `combined_house/flythrough.mp4` — 120帧 1280×720 飞行视频
- `combined_house/house.dmd.yaml` — Drake 仿真文件
---
## 8. Demo采集说明
### 什么是 Demo
在这里,"demo" 是指一个 **pick-and-place 任务的完整轨迹**,包含:
- 初始场景状态(物体位姿)
- 末端执行器的完整轨迹(6D位姿序列)
- 夹爪宽度序列
- 任务成功与否
### 本次 Demo 类型
由于 SceneSmith 不含真实 robot,我们采用 **scripted demo**(脚本化轨迹),按照标准 pick-and-place 轨迹规划:
```
Home → Approach(接近物体上方)→ Pre-grasp(下降)→ Grasp(夹爪闭合)
→ Lift(提升)→ Transport(平移)→ Place(放下)→ Release(张开夹爪)
```
### 与真实采集的区别
| 项目 | 本次(脚本化) | 真实采集 |
|------|--------------|---------|
| 轨迹来源 | 几何规划 | robot controller / teleop |
| 物理真实性 | 运动学插值 | 力矩控制 |
| 碰撞避免 | 简单直线轨迹 | 运动规划(RRT等) |
| 接触建模 | 无 | Drake/MuJoCo 物理仿真 |
| 用途 | 演示、可视化 | 训练 policy |
### Demo JSON 格式
```json
{
"task": "Pick an object from the nightstand and place it on the desk",
"scene_id": "bedroom_nightstand_to_desk",
"target_object": "bedroom_nightstand_0",
"initial_pos": [-0.55, -1.73, 0.5],
"goal_pos": [0.79, 1.58, 0.85],
"goal_reference": "bedroom_desk_0",
"success": true,
"total_duration_s": 7.5,
"num_steps": 150,
"trajectory": [
{
"step_id": 0,
"phase": "approach",
"end_effector_pos": [0.0, 0.0, 0.8],
"end_effector_quat_wxyz": [1, 0, 0, 0],
"gripper_width": 1.0,
"target_object_pos": [-0.55, -1.73, 0.5],
"timestamp": 0.0
},
...
]
}
```
### 可视化说明
`demo_*_trajectory.png` 包含 4 个子图:
1. **3D 轨迹图**:不同颜色表示不同阶段(接近/抓取/搬运/放置)
2. **俯视图**(XY平面):路径规划可视化
3. **高度-时间曲线**:末端执行器与物体的 Z 轴变化
4. **夹爪宽度-时间曲线**:抓取动作可视化
---
## 9. 常见问题与局限性
### Q: Hunyuan3D-2 生成质量很差怎么办?
**A**: 换 SAM3D 后端(需要 A100/H100,无 gated 访问限制)。Hunyuan3D 官方说明仅作 proof-of-concept,质量明显劣于 SAM3D。
### Q: manipuland 物体没有生成?
**A**: Hunyuan3D worker 在 fork 后 CUDA 重初始化失败。症状:`Worker shutting down. Stats: 279 total, 0 completed, 279 failed`。解决:换用 `strategy: "hssd"` 检索模式,不依赖 CUDA generation。
### Q: LLM 返回 `rs_*` 错误?
**A**: LiteLLM 代理是无状态的,不支持 server-side reasoning 续接。需要设置 `reasoning_effort: none` 并使用自定义 `NvidiaInferenceProvider`(已在本次配置中修复)。
### Q: 一次运行需要多久?
**A**: 单房间约 1-2 小时(L40S, Hunyuan3D)。SAM3D 质量更好但更慢。多 GPU 可以并行生成多个房间。
### Q: 能生成多房间场景吗?
**A**: 可以,在 `scene_prompt` 中描述多个房间,`experiment.num_scenes` 控制变体数量。
### Q: 如何接入自己的 robot?
**A**:
1. 加载 `house.dmd.yaml` 到 Drake/MuJoCo
2. 用 `policy_interface.py` 获取 task 的目标位姿
3. 用你自己的 robot controller 执行
4. 将结果写回修改后的 `.dmd.yaml`
5. 用 `validate.py` 验证成功率
---
## 10. 复现指南
### 环境要求
- Python 3.11
- CUDA 12.4(编译 custom_rasterizer)
- Blender 5.1(headless,EEVEE 渲染)
- SLURM 集群,L40S GPU(48GB)
### 安装步骤
```bash
# 1. 克隆仓库
git clone https://github.com/nepfaff/scenesmith.git
cd scenesmith
git submodule update --init --recursive
# 2. 创建虚拟环境
uv sync --no-dev
# 3. 安装 Hunyuan3D-2
bash scripts/install_hunyuan3d.sh
# 4. 下载 ArtVIP 数据
huggingface-cli download nepfaff/scenesmith-preprocessed-data \
artvip/artvip_vhacd.tar.gz --repo-type dataset --local-dir .
mkdir -p data/artvip_sdf
tar xzf artvip/artvip_vhacd.tar.gz -C data/artvip_sdf
# 5. 下载材质
python scripts/download_ambientcg.py --output data/materials
# 下载材质嵌入(从 HF)
# 6. 编译 CUDA 扩展(需要 CUDA toolkit)
# 见 cuda_home/ 目录的说明
```
### 运行
```bash
# 设置环境变量
export OPENAI_API_KEY=<your_key>
export OPENAI_BASE_URL=https://inference-api.nvidia.com/v1
export HF_TOKEN=<your_hf_token>
# 生成场景
python main.py \
"+name=my_scene" \
"experiment.scene_prompt=A cozy bedroom with a bed and desk" \
"openai.model=azure/openai/gpt-5.2" \
"furniture_agent.asset_manager.backend=hunyuan3d" \
"furniture_agent.reasoning_effort.generation=none"
# 渲染视频
python scripts/render_flythrough.py \
--blend outputs/.../combined_house/house.blend \
--output flythrough.mp4 \
--blender /path/to/blender
# 采集 Demo
python scripts/collect_demo.py \
--scene-state outputs/.../house_state.json \
--dmd outputs/.../house.dmd.yaml \
--task "Pick the book and place it on the desk" \
--output-dir demos/
```
### 本次运行的关键 Patch
本次在 NVIDIA 内部集群运行时,在原始代码基础上做了以下修改:
1. **`nvidia_inference_provider.py`**(新增):绕过 `openai-agents` SDK 对 `azure/openai/gpt-5.2` 的前缀解析,直接路由到 `inference-api.nvidia.com`
2. **`base_stateful_agent.py`**:注入自定义 Provider
3. **所有 YAML 配置**:`reasoning_effort: none`,防止 stateful reasoning items
4. **`worker_pool.py`**:限制 CUDA re-init 重试次数(max 3次)
5. **`render_flythrough.py`**(新增):适配 Blender 5.1 新 API(`action.layers[].strips[].channelbags[].fcurves`)
|