SimGenProbe Stage 1 与 Harness 规划

2026-11-04 ET · 来源:branch step_1_hidden_reference_scene_generation @ e5dcd30(Viet Luong),kitchen_drawer_pull_handoff.tar.gz,github-code main @ 1f64265,midpoint report。文稿与校验记录在 .note/others/stage1_study_1104/。

隐藏目录 stage1/<scene>/(含 θ(s)) agent 可见(无 θ) Tabletop held_out_00(seed 848) sample scene.json ground_truth.json scene_physics.usda build_scene + V1–V9 robot/panda.usd scene.usda validation.json isaac_render renders/<view>.png instance masks verify_views size, exposure, noise cube within 8 px finalize held_out/<scene>/ scene.json, manifest, views/ observe (simgenprobe) base text + views θ removed, leak scan Kitchen kitchen_drawer_pull_00(seed 2611) simready 0.8 GB SimReady hash-verified sample scene_spec.json ground_truth.json scene_physics.usda build + K1–K17 robot/, scene.usda validation.json, demo/ render benchmark/, demo/ reference_match, workspace verify_views provenance, hashes visibility, camera finalize bundle/<scene>/ observation/<scene>/ CPU 步骤 GPU 步骤(Isaac Sim 6.2, PhysX / RTX path tracing)
Stage 1 的两条流水线。每一格写的是该步写出的文件;虚线左边的目录带 θ(s),永远不给 agent;右边是 finalize 之后 agent 可见的 bundle 或 observation。

TAB 1. Stage 1 hidden reference scene generation, explained

写给 Yi Ge:在把 LLM generation harness 架到 Viet 的 stage1_reference 上之前,先把它的每一步、每个文件、每个物理量看清楚。所有数字都带来源;代码里没有的东西标 "not in the code"。

路径缩写:S1 = code/private/stage1_reference(= 分支 step_1_hidden_reference_scene_generation @ e5dcd30,S1/ARCHIVED_FROM.txt);KD = S1/kitchen_drawer_pull;PKG = code/github-code/src/simgenprobe(main);HO = code/private/_asset/kitchen_drawer_pull_handoff_extracted/kitchen_drawer_pull_handoff;USDA = HO/scene/scene.usda(Viet 交付的已 build 好的 kitchen 场景,2627 行);template = code/github-code/data/development_scenes/development_00/scene.json;RUNS = code/runs/stage1(我们的集群 上的 Stage 1 输出);ENV62 = $ENVS/simgenprobe(Isaac Sim 6.2.0.0)。seed 848 的值来自本机用 conda-envs/848x 跑 S1/sample.py 两次得到的 ground_truth.json(两次字节相同:scene.json sha256 d6d0586b…,scene_physics.usda b7499786…);seed 2611 的值用 KD/truth.py 重算并与 USDA 逐行核对;我们的集群 实测来自 smoke job 3506650(RUNS/logs/stage1-smoke-3506650.log,<node>,L40S,driver 615.71.09,2026-11-04 18:56:42 到 19:10:09 ET,COMPLETED)。

19:3x ET 更新(主会话):第 9 节的 WebRTC 插件问题已修并复查通过;第 6、10 节 OptiX 的原因查明、verify_views 已 PASS;交互 viewer 的 我们的集群 版 job 脚本已写好(code/private/tools/jobs/stage1_live_viewer.sbatch)。

1. 一句话 + 总 pipeline 图

Stage 1 把一个 seed 变成一个 θ(s) 完全已知、在 Isaac Sim 6.2 里 build 过、validate 过、render 过的 hidden reference scene,然后只把 public 的那一层(几何、颜色、材料名、两张 view、相机内参)交给 agent;θ(s)、ground_truth.json、所有 USD 永远留在 hidden 目录(S1/README.md:20-39,KD/README.md:63-69)。

两个 family 的流程并排如下。每个 node 有 id、短 label、sublabel(输入/输出)、lane(CPU 或 GPU)、zone(hidden / bundle / agent);optional: true 的 node 画成浅色;edge 带动词;zone 变化处就是 hidden/public 边界(画成虚线)。

{
  "lanes": ["CPU", "GPU"],
  "zones": {
    "hidden": "Stage 1 only: ground truth, theta, USD, validation, renders",
    "bundle": "evaluation only, contains theta (not agent-safe)",
    "agent": "agent-safe observation package"
  },
  "rows": [
    {"family": "tabletop held_out_00 (seed 848)", "nodes": [
      {"id": "t_in", "label": "config + seed", "sublabel": "S1/config.yaml (seed 848), template development_00/scene.json, PKG/data/materials/materials.json", "lane": "CPU", "zone": "hidden"},
      {"id": "t_sample", "label": "sample", "sublabel": "out: scene.json, scene_physics.usda, ground_truth.json", "lane": "CPU", "zone": "hidden"},
      {"id": "t_build", "label": "build_scene V1-V9", "sublabel": "URDF import, compose scene.usda, reload, validate | out: robot/panda.usd, scene.usda, validation.json, ground_truth.json(+robot, isaac)", "lane": "GPU", "zone": "hidden"},
      {"id": "t_tools", "label": "validate_existing / inspect_stage", "sublabel": "optional: V1-V9 again on a copy; read-only inventory of a saved scene.usda | for comparing Isaac versions", "lane": "GPU", "zone": "hidden", "optional": true},
      {"id": "t_render", "label": "isaac_render", "sublabel": "PathTracing 64 spp x 8 subframes, warmup 64 (CLI defaults) | out: renders/front_right.png, top_down.png, *_instances.npz, render.json", "lane": "GPU", "zone": "hidden"},
      {"id": "t_verify", "label": "verify_views", "sublabel": "exposure, noise, cube/table/robot/room masks | out: renders/verify.json", "lane": "CPU", "zone": "hidden"},
      {"id": "t_finalize", "label": "finalize", "sublabel": "stage_checks (62 items), theta read-back, Isaac validation passed, verified views, ReferenceStore contract, separation, MuJoCo settle | out: finalize.json", "lane": "CPU", "zone": "hidden"},
      {"id": "t_bundle", "label": "held_out/held_out_00/", "sublabel": "scene.json (theta inside), manifest.json, views/front_right.png, views/top_down.png", "lane": "CPU", "zone": "bundle"},
      {"id": "t_observe", "label": "simgenprobe observe", "sublabel": "S1/observe_held_out.yaml: verify_lock, ReferenceStore load, public_projection, write_base_text, disclose, leak_scan | out (harness only, outside package/): <out_dir>/record.json", "lane": "CPU", "zone": "bundle"},
      {"id": "t_obs", "label": "observation package/", "sublabel": "base_text.md, disclosed_parameters.json, cameras.json, manifest.json, views/", "lane": "CPU", "zone": "agent"}
    ]},
    {"family": "kitchen kitchen_drawer_pull_00 (seed 2611)", "nodes": [
      {"id": "k_simready", "label": "simready", "sublabel": "download 4 SimReady packages, sha256 vs BOM | out: simready_cache/, simready_assets.json", "lane": "CPU", "zone": "hidden"},
      {"id": "k_in", "label": "config + seed + screenshot", "sublabel": "KD/config.yaml (seed 2611), references/target_scene.png, landmarks.json", "lane": "CPU", "zone": "hidden"},
      {"id": "k_camera", "label": "camera", "sublabel": "optional: fit eye, angles, focal, cabinet size, tile from landmarks.json (72 starts) | stdout only, must equal config.yaml", "lane": "CPU", "zone": "hidden", "optional": true},
      {"id": "k_sample", "label": "sample", "sublabel": "theta, layout, pull plan | out: scene_spec.json, ground_truth.json, scene_physics.usda", "lane": "CPU", "zone": "hidden"},
      {"id": "k_build", "label": "build K1-K17", "sublabel": "URDF import, compose, home pose, validate, rollout | out: robot/panda.usd, scene.usda, validation.json, demo/pull_rollout.npz, demo/states.json", "lane": "GPU", "zone": "hidden"},
      {"id": "k_render", "label": "render", "sublabel": "states A, B x views reference_match, workspace | out: renders/{benchmark,demo}/*.png, *_instances.npz, render.json", "lane": "GPU", "zone": "hidden"},
      {"id": "k_compare", "label": "compare", "sublabel": "optional: state B render vs target_scene.png, chamfer | out: comparison/iter_NN/ (record only)", "lane": "CPU", "zone": "hidden", "optional": true},
      {"id": "k_verify", "label": "verify_views", "sublabel": "provenance, staleness, exposure, noise, visibility, landmarks | out: renders/verify.json", "lane": "CPU", "zone": "hidden"},
      {"id": "k_finalize", "label": "finalize", "sublabel": "gates validation, renders, files, stage; leak_scan | out: finalize.json", "lane": "CPU", "zone": "hidden"},
      {"id": "k_bundle", "label": "bundle/kitchen_drawer_pull_00/", "sublabel": "scene_spec.json (theta inside), manifest.json, views/ (state A), demo/reference_match.png (state B), ATTRIBUTION.md", "lane": "CPU", "zone": "bundle"},
      {"id": "k_obs", "label": "observation/kitchen_drawer_pull_00/", "sublabel": "base_text.md, cameras.json, views/", "lane": "CPU", "zone": "agent"}
    ]}
  ],
  "edges": [
    {"from": "t_in", "to": "t_sample", "label": "seeds PCG64(848), fills the template"},
    {"from": "t_sample", "to": "t_build", "label": "reads ground_truth.json + scene_physics.usda"},
    {"from": "t_build", "to": "t_tools", "label": "optional: re-validate a copy, inventory the stage", "optional": true},
    {"from": "t_build", "to": "t_render", "label": "opens scene.usda, poses the settled cube in the session layer"},
    {"from": "t_render", "to": "t_verify", "label": "checks renders against ground_truth.json"},
    {"from": "t_verify", "to": "t_finalize", "label": "verify.json must pass, hashes pinned"},
    {"from": "t_finalize", "to": "t_bundle", "label": "copies scene.json, re-encodes verified views, writes manifest.json"},
    {"from": "t_bundle", "to": "t_observe", "label": "ReferenceStore(held_out_root) loads, contract G-B1 to G-B10"},
    {"from": "t_observe", "to": "t_obs", "label": "writes package/, leak scan fails closed"},
    {"from": "k_simready", "to": "k_sample", "label": "cache required even to sample"},
    {"from": "k_in", "to": "k_camera", "label": "optional: landmarks.json -> camera fit", "optional": true},
    {"from": "k_in", "to": "k_sample", "label": "seeds PCG64(2611); screenshot sha256 must match"},
    {"from": "k_sample", "to": "k_build", "label": "reads ground_truth.json + scene_physics.usda"},
    {"from": "k_build", "to": "k_render", "label": "link poses of states A and B into the session layer"},
    {"from": "k_render", "to": "k_compare", "label": "optional: state B render vs screenshot", "optional": true},
    {"from": "k_render", "to": "k_verify", "label": "4 input hashes pinned in render.json"},
    {"from": "k_verify", "to": "k_finalize", "label": "verify.json must pass and not be stale"},
    {"from": "k_finalize", "to": "k_bundle", "label": "atomic swap after all gates"},
    {"from": "k_finalize", "to": "k_obs", "label": "handwritten base_text + cameras.json, leak_scan"},
    {"from": "k_simready", "to": "k_build", "label": "scene_physics.usda references ../simready_cache/... (written at sample time); scene.usda is its Export copy, so the cache must stay beside the scene"}
  ],
  "boundary": {"between_zones": ["hidden", "bundle", "agent"], "note": "the only files an agent may ever receive are the agent-zone nodes; record.json stays with the harness"}
}

2. 输入与输出

Tabletop(held_out_00):hidden 文件在 <output_root>/stage1/held_out_00/,bundle 在 <output_root>/held_out/held_out_00/,output_root = ../runs/stage1(S1/config.yaml:4,S1/config.py:106-118,相对 stage1_reference/ 的父目录)。

步骤 设备 / 时间 读 写(格式) zone
python -m stage1_reference.sample (S1/sample.py:270-298) CPU, 秒级 (README.md:50) config.yaml,template scene.json,materials.json (version "0.1") scene.json(SceneSpecification schema 0.1,canonical,6 位有效数字);scene_physics.usda(ASCII USD,PKG 的 write_usd,无 robot,usd_file.py:548 robot_included: False);ground_truth.json(sorted keys,S1/ground_truth.py:281-288) hidden
isaac/build_scene.py GPU 节点,Kit isaaclab.python.headless.kit,CPU PhysX,约 2 min (README.md:52);我们的集群 实测 job 3506650 V1 到 V9 全 PASS,STAGE1_BUILD passed=True steps=2761(log :100-109) ground_truth.json,scene_physics.usda,Isaac exts 里的 URDF (config.yaml:43) robot/panda.usd(usda 文本);scene.usda;validation.json(V1 到 V9);ground_truth.json 补上 robot.links/joints、isaac record、文件 hash (build_scene.py:104-146) hidden
render/isaac_render.py GPU RTX,约 3 min (README.md:54);我们的集群 实测 render exit 0,render.json passed: true(log :1557),但 OptiX denoiser 没起来(第 6 节) scene.usda,validation.json 的 settled cube pose renders/<view>.png,renders/<view>_instances.npz(instance id 到 prim path),renders/render.json hidden
render/verify_views.py CPU renders,ground_truth.json,validation.json renders/verify.json(记录 render.json 与每张 png 的 sha256) hidden
finalize.py CPU,需要 MuJoCo (README.md:59 MUJOCO_GL=egl) 以上全部 bundle:scene.json(含 θ)、manifest.json、views/front_right.png、views/top_down.png(write_png 重编码);finalize.json bundle
simgenprobe observe --config S1/observe_held_out.yaml CPU;view 缺失时需要 engine (PKG/input_conditions/build.py:143-148) bundle(经 ReferenceStore,held_out_root) package/:base_text.md、disclosed_parameters.json、cameras.json、manifest.json(scene_id、input_combination、lock_hash、renderer、files 的 sha256、labels、described_objects、fixtures、units、observation_sha256,build.py:217-230)、views/;package/ 之外的 <out_dir>/record.json(Disclosure、label 到 reference name 的映射,harness 侧,build.py:252;文件名 observation.py:41-47) agent(package/);harness(record.json)

Kitchen(kitchen_drawer_pull_00):output_root = ../runs/stage1/kitchen_drawer_pull(KD/config.yaml:5);hidden 在 <root>/kitchen_drawer_pull_00/,bundle 在 <root>/bundle/<scene>/,observation 在 <root>/observation/<scene>/,cache 在 <root>/simready_cache/(KD/config.py:254-272)。

步骤 设备 / 时间 读 写 zone
kitchen_drawer_pull.simready (KD/simready.py) CPU + 网络 config.yaml:120-126 的 4 个 package simready_cache/<path>/…(跳过 .thumbs/、.simready/(package.json 单独取)、除 .mdl 外的 source_assets/,以及不在 BOM 里的已发布文件(LICENSE.txt 除外),simready.py:39-47, 99-106, 121-124),simready_assets.json;每个文件 sha256 对 BOM,不符即 raise (:133-136);约 0.8 GB (README.md:36) hidden
kitchen_drawer_pull.camera(可选) CPU references/landmarks.json stdout(fit 结果;test 保证与 config.yaml 一致,tests/test_kitchen_drawer_pull.py:56-69) 无
kitchen_drawer_pull.sample (KD/sample.py:209-247) CPU, 秒级 config.yaml,target_scene.png(sha256 必须等于 config.yaml:7,sample.py:216-218),SimReady cache scene_spec.json(family schema kitchen_drawer_pull/0.1,sample.py:39),ground_truth.json(θ、fixed、parameter table、mass properties、plan、camera fit、SimReady provenance、软件版本、hash),scene_physics.usda hidden
isaac/build.py GPU,约 2 min (README.md:45),CPU PhysX (session.py:69) ground_truth.json,scene_physics.usda,URDF robot/panda.usd,scene.usda,validation.json(K1 到 K17),demo/pull_rollout.npz(每步 time、phase、q、targets、slide、slide_speed、tcp,加 robot_dofs,KD/isaac/validate.py:91-99, 773),demo/states.json(state A、B 的 link poses);ground_truth.json 补 robot、isaac、hash hidden
isaac/render.py GPU RTX,约 1.5 min (README.md:47) scene.usda,demo/states.json renders/benchmark/{reference_match,workspace}.png(state A),renders/demo/…(state B),*_instances.npz,render.json(pin 4 个输入文件的 sha256,render.py:36,43-45) hidden
kitchen_drawer_pull.verify_views CPU renders,ground_truth.json renders/verify.json hidden
kitchen_drawer_pull.compare(可选) CPU state B 的 render,screenshot comparison/iter_NN/,只记录 hidden
kitchen_drawer_pull.finalize CPU 以上全部 bundle/<scene>/(scene_spec.json、manifest.json、views/、demo/reference_match.png、ATTRIBUTION.md),observation/<scene>/(base_text.md、cameras.json、views/),finalize.json;先在临时目录建好再原子换入 (finalize.py:295-302, 413-414) bundle + agent

三点提醒:(1) HO/scene/scene.usda 自己就带全部物理值(HANDOFF.md:102-104),所以 HO/scene 算 hidden。(2) archive 不能原地跑,REPOSITORY_ROOT 是 stage1_reference/ 的父目录(S1/config.py:13);code/private/data 现在是 symlink → ../github-code/data(2026-11-04 18:53 ET 建),所以 S1/config.yaml:5 的 data/development_scenes/development_00/scene.json 直接能解析,不用再覆盖 template_scene。(3) 我们的集群 上的 Isaac 步骤走 S1/isaac_python_cluster.sh(本地文件,不在 e5dcd30 里;:11 指向 ENV62,:21 把 github-code/src 和 code/private 放进 PYTHONPATH),提交入口 code/private/tools/jobs/stage1_smoke.sbatch(scavenger,gpu:nvidia_l40s:1,:8-10)。

3. 两个场景族

Tabletop:table、一个 cube、桌下 drawer、Panda、visual-only 的房间;几何全部来自 template,只有 cube 和 θ 是抽的。

物体 几何(m) 物理角色 来源
table top 0.8 x 0.6 x 0.04,中心 (0, 0, 0.38),上表面 z = 0.40;4 条腿 0.05 x 0.05 x 0.36,inset 0.04 static collider,table material (friction = θ,restitution 0.0) template:17-43
drawer box 0.3 x 0.25 x 0.08,closed center (0.25, 0, 0.315);prismatic 沿 +x,range [0, 0.25];handle 0.02 x 0.1 x 0.015 在前脸中央(link 中心 +x 0.16 处,usd_file.py:443) articulation:base 1 kg / inertia 0.01 FixedJoint 到 world,link mass = θ;handle 没有 CollisionAPI(usd_file.py:438-445,只有传了 material 才加 collider,:300-302) template:45-91;PKG/constants.py:238-239
cube item_0 a x a x a,a ∈ [0.045, 0.07];中心 x ∈ [-0.20, 0.25],y ∈ [-0.10, 0.10];yaw ∈ [-30, 30] deg;放在 z = 0.40 + a/2 + 0.001(spawn gap constants.py:71) rigid body,mass/friction/restitution = θ S1/config.yaml:8-13
robot Panda,base (0.40, -0.45, 0.2),yaw 90 deg,站在 0.20 x 0.20 x 0.2 的 pedestal 上;fingers 闭合(finger_opening_m: 0.0,用指外侧推) 11 rigid links(asset 质量,共 18.00 kg),pedestal 只是 collider template:94-110;constants.py:78-80;S1/config.yaml:48
ground 20 x 20 x 0.1 slab,上表面 z = 0 friction 0.5,restitution 0.0 constants.py:61-62, 82-83
room 两面墙 x = -2.225 和 y = -2.225(5.4 x 0.05 x 2.6);5 个 prop:cabinet、bin、plant_pot、2 个 box_stack,落在离原点 0.9 到 2.0 m 的环上 纯 visual:无 collision、无 rigid body、无 mass(stage_checks.py:291-308 断言) S1/environment.py:117-141;config.yaml:22-40
cameras front_right eye (0.976765, 0.926765, 1.16772) 看 (0.05, 0, 0.25);top_down eye (0, 0, 1.45) 看 (0, 0, 0.4);1280 x 720,fovy 40 deg,fx = fy = 989.09 px,cx = 640,cy = 360 另两台 front_left、side 也写进 USD 但不 render template:189-254;seed 848 ground_truth.json cameras

Kitchen:一个 procedural 的白色 island、一个带 bar handle 的 drawer、站在地上的 Panda、4 件 SimReady 背景家具。世界系:island 前脸是 x = 0,柜体占 x ∈ [-0.669, 0],y 居中,地面 z = 0(KD/layout.py:3-6)。

物体 几何(m) 物理角色 来源
island carcass 宽 0.930(y)x 深 0.669(x)x 高 0.86,板厚 0.018;countertop 0.04 厚,上表面 z = 0.90,x ∈ [-0.669, +0.025](前脸 overhang 0.025,后面没有),y 两侧各 overhang 0.025 10 个 static collider:side_left/right、back、bottom、divider、top_rail、mid_rail、countertop、door_left/right;无 rigid body KD/config.yaml:12-31;layout.py:149-192(countertop :170-180);finalize.py:186 "overhangs the front and the sides";USDA island colliders
drawer opening z ∈ [0.66, 0.85](高 0.19),top rail 0.010,mid rail 0.06;门板 z ∈ [0.012, 0.597](plinth 0.012;z_doors_top 0.60 减 door_gap 0.003) layout.py:146-148, 183-184(算出);config.yaml:23-24
drawer link link 原点 = 前脸外表面中心,闭合时 (0, 0, 0.755);front 0.019 x 0.888 x 0.184;box 深 0.50、宽 0.870、高 0.12、壁 0.012;box 后壁在 x = -0.519 rigid body,8 个 box collider(front、box_bottom/left/right/back 用 drawer material;handle_bar、两个 post 用 handle material) layout.py:232-301;usd_scene.py:191-213
handle bar 0.014 x 0.16 x 0.014,中心离前脸 0.035;两个 post 0.028 x 0.012 x 0.012 在 y = ±0.068;闭合时 bar 中心 world (0.035, 0, 0.755) collider(handle friction = θ) config.yaml:42-47
drawer_slide prismatic +x,limits [0, 0.40];闭合时最小间隙 3 mm(front 对 side_left),全开 6 mm(box_bottom 对 divider);全开时 box 还有 0.119 留在柜内 force drive,stiffness 0,damping = θ;joint-axis friction effort = θ config.yaml:41;layout.py:331, 341;USDA:1258-1277
robot base (0.655, -0.026, 0),yaw 180 deg,直接站在地上;home q [0, -0.6, 0, -2.6, 0, 2.0, 0.7854] rad,TCP 在 (0.2938, -0.026, 0.3452);fingers 开 0.04 同 tabletop 的 asset 与 gains config.yaml:65-75;USDA:2450-2456
floor 12 x 12 x 0.1 slab,上表面 z = 0;tile 0.576 pitch,grout 0.024,42 条 grout 条 floor material 0.8 / 0 usd_scene.py:327-339;config.yaml:85-91
cameras reference_match eye (1.93489, -1.63035, 1.52610),forward (-0.658076, 0.616647, -0.432068),roll 4.0697 deg,fovy 29.2663,1424 x 1124,fx = fy = 2152.4 px(focal 31.6745 mm);workspace eye (1.45, 1.35, 1.55) 看 (-0.119, 0.006, 0.169),fovy 38.4,1280 x 960,fx = fy = 1378.4 px config.yaml:93-107;USDA:1284-1309
lights dome 220;distant key 1600,angle 12 deg,方向 (-0.35, 0.45, -0.82);rect fill 3000,1.6 x 1.2 在 (0.4, -0.2, 2.6) config.yaml:109-117;USDA:1317-1335
background back_counter Counter_A01 在 (-1.20, 0.20, 0);right_cabinet Cabinet_B01 (-0.357, 2.165, 0) yaw -76;wall_cabinet Cabinet_D01 (-0.44, 2.495, 1.30) yaw -76;dishwasher Dishwasher_A01 (0.31, 2.33, 0) yaw -76 物理全关(见第 6 节) config.yaml:120-126;USDA:1345-2448

4. 物理属性 θ(s)

Tabletop 的 θ(s) 就是我们 PKG/scene_specification/physical_parameters.py:47-60 定义的那 7 项,一项不多一项不少;评分方式 log(mass、damping、friction)或 absolute(contact_friction、restitution)(:24-29)。

参数 θ key (owner, quantity) 单位 分布 seed 848 值 抽样代码 区间出处 我们的 θ 覆盖
桌面摩擦 (table, contact_friction) 1 U[0.2, 0.6] 0.419825 S1/sampler.py:198-199 materials.json:214-220 是 (:58)
抽屉质量 (drawer, mass) kg U[0.4, 1.2] 0.671937 :201 :221-227 是 (:59)
滑轨阻尼 (drawer_slide, joint_damping) N s/m U[2.0, 8.0] 2.22435 :202-204 :228-234 是 (:56)
滑轨摩擦 (drawer_slide, joint_friction) N U[0.3, 1.2] 0.421894 :205-207 :235-241 是 (:57)
cube 质量 (item_0, mass) kg density x a^3,density U[class range] 0.253765 = 1023.23 x 0.0628279^3 :213, 228 class row 是 (:51)
cube 摩擦 (item_0, contact_friction) 1 U[class range](abs_plastic [0.2, 0.5]) 0.339249 :229-231 materials.json:12-17 是 (:52)
cube 弹性 (item_0, restitution) 1 U[class low, min(class high, 0.8)](abs_plastic [0.4, 0.7]) 0.64654 :232-234;cap constants.py:69 :18-23 是 (:53)

五个 cube 材料类(config.yaml:13;glass、rubber、steel 在材料表里但不在 cube 类里);质量范围是 a ∈ [0.045, 0.07] 推出的(我的算术)。0.8 的 restitution cap 永远不起作用(最高上界 0.7)。

class (materials.json 行) density kg/m^3 contact friction restitution 隐含 mass kg
wood (186-211) 400 到 900 0.25 到 0.6 0.3 到 0.6 0.0365 到 0.309
abs_plastic (4-29) 1020 到 1080 0.2 到 0.5 0.4 到 0.7 0.0929 到 0.370
cardboard (56-81) 100 到 700 0.3 到 0.6 0.1 到 0.3 0.00911 到 0.240
aluminum (30-55) 2640 到 2810 0.25 到 0.6 0.4 到 0.7 0.241 到 0.964
foam (82-107) 30 到 120 0.5 到 1.0 0.1 到 0.4 0.00273 到 0.0412

Tabletop 里不进 θ 的其它量:

类别 量 seed 848 值 agent 可见 来源
抽样 material class abs_plastic(5 类等概率) public sampler.py:210
抽样 edge a 0.0628279 public config.yaml:9;sampler.py:212
抽样 中心 xy,yaw (-0.0469382, -0.0764218),-26.7965 deg public config.yaml:10-12;sampler.py:220-224
抽样 density 1023.23 kg/m^3(canonicalize 重算为 mass/volume,canonical.py:33-41) hidden sampler.py:213
固定 table restitution 0.0 hidden template:43
固定 drawer contact_friction / restitution 0.5 / 0.0 hidden template:63-64
固定 ground friction / restitution 0.5 / 0.0 hidden constants.py:61-62
固定 robot 接触材料 friction 0.5,restitution 0.0 hidden S1/isaac/compose.py:32-35
固定 arm drive;finger drive;gravity 400 N m/rad,80 N m s/rad;2000 N/m,100 N s/m;disable_gravity: true hidden S1/config.yaml:44-49
asset 自带 Panda link 质量 link0 2.8142028、link1 2.3599997、link2 2.3795187、link3 2.6498823、link4 2.6948018、link5 2.9812818、link6 1.1285807、link7 0.40529126、hand 0.5583305、每指 0.014055223 kg,合计 18.00 kg hidden HO/scene/robot/panda.usd:782, 1102, 1138, 1174, 1297, 1420, 1518, 1966, 2196, 2344, 2444(同一 URDF 导出;USDA 本身只有 drawer base 的 1 kg :1095 和 drawer 的 2.1217 :1120)
asset 自带 drive maxForce;maxJointVelocity joint1 到 4 为 87,joint5 到 7 为 12,fingers 20;124.61832 deg/s(joint1 到 4)、149.54198 deg/s(joint5 到 7)、0.2 m/s(fingers) hidden panda.usd:2801-2975(87、12)、:3016, 3041(20);:2815、:2931、:3030
派生 cube inertia diagonal m a^2/6 = 1.66950e-4 kg m^2 hidden uniform_solid_inertia;ground_truth.json
派生 drawer inertia;articulation base box 公式;1 kg、0.01 kg m^2 hidden usd_file.py:423;constants.py:238-239
派生 V8 slip force μmg = 1.0451 N,μ = max(0.339249, 0.419825) validate.py:516-519

Kitchen 的 θ(s) 有 5 项(KD/truth.py:20-47 THETA_ORDER),每项 rng.uniform 后取 6 位有效数字(:50-61);USD 里写的就是取整后的值,PhysX 必须按这个值读回来(:3-4)。

参数 θ key 单位 区间 (KD/config.yaml) seed 2611 值 USD 属性 (USDA 行) 我们的 θ kind (truth.py)
抽屉质量 drawer.mass kg [0.8, 2.5] (:52) 2.1217 /World/Kitchen/Drawer/drawer physics:mass (:1120) mass (:21);但在我们的 fixture range [0.4, 1.2] 之外(materials.json:221-227;contract.py:504-514 G-B3 会拒)
滑轨阻尼 drawer_slide.joint_damping N s/m [2.0, 10.0] (:53) 2.80644 drawer_slide drive:linear:physics:damping (:1262) joint_damping (:28);区间比我们的 [2.0, 8.0] 宽(materials.json:228-234),这个值在内
滑轨摩擦 drawer_slide.joint_friction N [0.5, 3.0] (:54) 2.13293 physxJointAxis:linear:{static,dynamic}FrictionEffort (:1276-1277) joint_friction (:35);在我们的 [0.3, 1.2] 之外(materials.json:235-241)
抽屉接触摩擦 drawer.contact_friction 1 [0.3, 0.7] (:55) 0.660176 /World/PhysicsMaterials/drawer static = dynamic (:58, 60) contact_friction (:43);我们的 schema 有这个 field 但不进 θ(contract.py:238-240 从 public projection 排除)
把手接触摩擦 handle.contact_friction 1 [0.5, 1.0] (:56) 0.931859 /World/PhysicsMaterials/handle (:69, 71) None(:46):我们的 handle 只有 size 和 color(schema.py:256-260)

Kitchen 不进 θ 的其它量:

类别 量 值 来源
固定 restitution(drawer、handle、cabinet、floor) 全 0 config.yaml:58-63
固定 cabinet friction;floor friction 0.5;0.8 config.yaml:60, 62;USDA:47, 49;:36, 38
固定 travel [0, 0.40] m config.yaml:41;USDA:1274-1275
固定 drive stiffness / type 0 N/m / "force" truth.py:241-248;USDA:1263, 1266
固定 robot 接触材料 0.5 / 0 compose.py:32-35;USDA:80-82
固定 combine mode(4 个 kitchen 材料) "max"(robot 材料没写) usd_file.py:248-251;USDA 每个 material
固定 robot gains 400 / 80 / 2000 / 100(USD angular 写成每度 6.981317 / 1.396263) config.yaml:67-70;S1/isaac/robot.py:166-171
派生 COM(link frame) (-0.217877, 0, -0.0453954) m truth.py:69-98;USDA:1118
派生 principal inertia (0.0812338, 0.169798, 0.241747) kg m^2 USDA:1119
派生 principal axes (w, x, y, z) (0.70646, -0.03030, -0.03030, 0.70646) USDA:1121
派生 density;分件质量 197.252 kg/m^3;front 0.612359、box_bottom 1.02966、box_left/right 各 0.127819、box_back 0.21627、handle_bar 0.00618582、post 各 0.00079532 kg truth.py:94-97
asset 自带 Panda link 质量、maxForce、速度上限 同上表 HO/scene/robot/panda.usd

一个物理含义(我的推断,不在代码里):drawer 不碰柜体(间隙 3 到 6 mm),K13/K14 又禁止机器人碰 handle 以外的东西,所以 drawer.contact_friction 在这个 task 里不作用于任何接触;手指对 bar 的摩擦按 "max" 规则等于 handle 值。

5. 怎么生成的

Tabletop 用一个 PCG64 流(S1/sample.py:277),消耗顺序固定:先 4 个 fixture 抽样(sampler.py:198-207),然后每次 cube attempt 8 次抽样(class、edge、density、x、y、yaw、friction、restitution,:210-234),最后房间(sample.py:286-288)。改 cube 的区间或 attempt 次数会把整个房间换掉;改房间配置不影响 cube。每个 cube attempt 要过三道门,500 次不过就 RuntimeError(config.yaml:6;sampler.py:245-247):

  1. canonicalize:6 位有效数字,density = mass/volume(canonical.py:33-41)。
  2. contract 零 finding,通过一个无 view 的临时 bundle 跑 verify_reference_scene(sampler.py:130-151, 238-240)。会卡的规则:G-B10 mass ∈ [0.005, 2.0] kg(contract.py:71, 534-542,小 foam 会撞);G-B6 slip/topple margin:box 的 ratio = (w/2)/(h/2) = 1,min over μ ∈ {own, max(own, table)} 的 |μ/ratio − 1| 必须 ≥ 0.15(constants.py:127;contract.py:610-634),所以 foam 的 μ ∈ (0.85, 1.0] 被拒;G-B8 density = mass/volume 必须在 class range 内(contract.py:543-554),理论上 6 位取整能把贴边的 density 推出区间,200 seed 实测 0 次;G-B5 edge margin 0.04 m(x reach ≤ 0.36,最大只有 0.298)和中心间距 0.16 m(单物体)永远不卡。
  3. push plan 存在(:241-243):沿 +y(config.yaml:16);start = center − dir·(yaw-aware half extent + 0.03);end = start + 0.10·dir;expected cube xy = center + 0.07·dir(sampler.py:76-84);expected 必须还在桌面内,每轴 |expected − top_center| ≤ top_size/2 − 该轴 half extent,否则 plan_push 直接返回 None(:85-92);推的高度 z = 0.40 + a/2(:78-80);waypoints:approach 在 push 高度上方 0.12 m,然后 6 个等距点 pre_push、push_1 到 push_4、post_push(:94-99;config.yaml:19-20);tool pose z 朝下、x 沿推向(kinematics.py:92-99);IK 用 Franka modified DH 链 + damped least squares,300 次迭代、damping 0.05、数值 Jacobian 步长 1e-6、裁到关节限位、上一个 waypoint 的 q 做 warm start(kinematics.py:130-155);通过条件:限位内、位置误差 < 1e-3 m、姿态误差 < 1e-2 rad(:122-127),相邻 waypoint 的 max |Δq| ≤ 0.5 rad(sampler.py:40, 106-107)。出桌面和 IK 失败都计为 "push plan 不存在",没有分开统计。seed 848 第 1 次 attempt 就通过,IK 残差 2e-6 到 8e-6 m。

本机实测(seeds 0 到 199,不在代码里):200 个场景共 216 次 attempt,被拒 11 次 G-B6(foam)、1 次 G-B10 mass(foam)、4 次 push plan、0 次 G-B8;接受的 class 分布 cardboard 50、aluminum 45、wood 42、abs_plastic 38、foam 25。

房间抽样(environment.py:109-215):两面墙各取 4 色之一、地板 4 色之一;每个 prop 尺寸逐轴均匀(cylinder 令 y = x),环半径 U[0.9, 2.0],角度 U[0, 2π],box 的 yaw U[0, 90](硬编码,:156-158);每个 prop 最多 400 次(config.yaml:40);灯光 dome U[150, 400],key U[400, 800],方位 U[20, 160] deg、仰角 U[40, 70] deg(config.yaml:36-39)。seed 848 用了 21 次 attempt。房间不进 scene.json,agent 的文本里没有它(README.md:258-259)。

prop 被拒条件 阈值 environment.py
离桌面 footprint 太近 < 0.30 m 164-165
离 robot base(减 half footprint)太近 < 0.45 m 166-170
穿墙 footprint 的最小角越过墙:center − half < −2.2(x 或 y 任一轴) 171-172
离已放 prop 太近 < 0.05 m(硬编码) 173-176
在某个 view 里可能挡桌面 image box 重叠且比桌子最远角近 63-73, 177-178
两个 view 都出画 76-86, 179-180

Kitchen 没有 accept/reject 循环:θ 一次抽 5 个(sample.py:93-94),layout 由 config 确定性算出(layout.py:138-343),pull plan 用同一套 IK 从 home 解 pregrasp、approach、close、pull_1 到 pull_8、release、retreat、return_home(plan.py:131-205);通过条件是 IK 全部 ok、接触段相邻 waypoint 的 max |Δq| ≤ 0.25 rad、arm(球模型半径 0.06 m)离所有 collider 和 drawer ≥ 0.02 m(plan.py:37-45, 196-200),不满足就 RuntimeError(sample.py:97-102)。seed 2611:最大关节步 0.0928 rad,最小间隙 0.0730 m(retreat 到 return_home 段对 drawer front)。抓取姿态 GRASP_ROTATION(plan.py:36):TCP 沿 world −x 接近,手指开合方向竖直,闭合后上下夹住 bar,拉力靠指垫摩擦,没有任何 attach joint(PROGRESS.md:171)。

Validation 的 rollout 从 settle 后直接走 pregrasp(KD/isaac/validate.py:171-177),没有 home 相位;viewer 的 scripted pull 多一段 home(时长 seconds.move,drawer_panel.py:97-98)。下表是 validation 的相位,合计 12.6 s = 3024 步:

phase TCP(world, m) fingers(m) 时长 + dwell(s,config.yaml:83)
pregrasp (0.158, 0, 0.755) = grasp + 0.12 0.04 1.5 + 0.4
approach (0.038, 0, 0.755) = bar 中心 0.035 + grasp_depth 0.003 0.04 1.0 + 0.4
close 同上 0.0 0.8 + 0.4
pull_1 到 pull_8 x 每步 +0.025,到 0.238 0.0 8 x 0.375 + 0.4
release (0.238, 0, 0.755) 0.04 0.6 + 0.4
retreat (0.358, 0, 0.755) 0.04 1.0 + 0.4
return_home home (0.2938, -0.026, 0.3452) 0.04 1.5 + 0.8

Kitchen 的相机不是抽的,是从截图拟合的(KD/camera.py:214-307):

项 内容 来源
观测 5 个手选柜体角点 + 8 段 RANSAC grout 线,图 712 x 562 references/landmarks.json
未知量(12) eye 3、yaw/pitch/roll 3、焦距 1、柜宽、柜深、tile pitch、tile offset 2 camera.py:228-234
假设 carcass 高 0.86(定尺度)、countertop 0.04、overhang 0.025、主点在图心 camera.py:313;PROGRESS.md:97-99
求解 72 个起点的 least_squares,取最小 cost camera.py:260-284
结果 eye (1.935, -1.630, 1.526),fovy 29.27 deg,roll 4.07 deg,柜体 0.930 x 0.669,tile 0.576;角点 RMS 3.6 px,线 RMS 3.3 px;robot base 由像素 (468, 505) 反投影到地面得 (0.655, -0.026) PROGRESS.md:99-101
看不见、靠假设 rails、抽屉深度、travel、handle PROGRESS.md:103-105, 230-231
render 对截图 chamfer 7.44 px(iter 1)、9.67 px(iter 2,加 MDL 后背景多了边),之后停 PROGRESS.md:186-193

可复现性:tabletop 的 sample 不写时间戳,同 seed 字节相同(tests/test_stage1_reference.py:114-125,本机复现);但 ground_truth.json 记录 python/numpy/usd-core 版本(sample.py:181-190),换环境字节会变;manifest.json 带 created_utc(sampler.py:177)。numpy 跨版本是否保持同一随机流:not in the code。Kitchen 同理(sample.py:11, 45-50)。

6. Isaac 技术要点

要点 做法 代码
URDF import(6.x) URDFImporter(merge_fixed_joints=False, fix_base=True, allow_self_collision=False, run_asset_transformer=False) 导到临时目录,Flatten,把 Flattened_Prototype_N 按首次引用顺序重编号后导出为 usda 文本,使同一 robot 给出相同字节 S1/isaac/robot.py:74-134
drives revolute 用 angular DriveAPI,type "force",stiffness 400·π/180、damping 80·π/180(USD 角量按度),target 与 JointStateAPI 写 home(度)、速度 0;prismatic 指 2000 / 100;newton:velocityLimit 复制到 physxJoint:maxJointVelocity;每个 rigid link disableGravity = True;articulation enabledSelfCollisions = False robot.py:143-211
compose scene.usda Sdf.Layer.Export 把 scene_physics.usda 复制成 scene.usda(拷贝,不是 sublayer);/World/Robot reference ./robot/panda.usd 并 translate + orient 到 base pose;没有 body0 的 root joint 的 localPos0/localRot0 设成 base pose(6.x 里 body0 已指向 root Xform,这步跳过);robot 材料 0.5 / 0 以 weakerThanDescendants 绑到每个 robot collider;pedestal 是 CollisionAPI 的 Cube;房间和 lights 写入;layer customData robot_included: True S1/isaac/compose.py:107-215;kitchen 复用 KD/isaac/build.py:41-62
PhysX scene up Z,metersPerUnit 1,kilogramsPerUnit 1;gravity 9.81;240 steps/s;solver TGS;broadphase MBP;enableGPUDynamics False;bounceThreshold 0.1 m/s;材料 combine mode "max";body damping 0、sleep threshold 0 usd_file.py:325-349, 239-252, 305-322;constants.py:77, 229-234;USDA:17-27
reload + read-back(Session) open_stage,5 次 app.update(),关掉 4 个 USD write-back 设置,dt = 1/timeStepsPerSecond,给 robot 的每个 rigid body 加 PhysxContactReportAPI(threshold 0),tabletop 再加 cube(S1/isaac/validate.py:133-135),kitchen 再加 drawer link(KD/isaac/session.py:63-66);overwrite_gpu_setting(0)(CPU PhysX),attach_stage,start_simulation,每步手动 simulate + fetch_results 并收集 contact report;再建 numpy tensor view(create_simulation_view("numpy"),subspace root "/"),用 get_masses、get_material_properties、get_dof_dampings、get_dof_friction_properties、get_dof_stiffnesses、get_link_transforms 读 PhysX 实际值 S1/isaac/validate.py:104-173;KD/isaac/session.py:22-133
home 姿态写进文件 用 PhysX 给出的 link 世界位姿写回每个 link 的 translate/orient,再把内存里的 ContactReportAPI 去掉后保存,文件打开就是摆好姿势的 validate.py:275-314;session.py:205-234
path tracing,不用 DLSS SimulationApp({"headless": True, "renderer": "PathTracing", "samples_per_pixel_per_frame": 64, "denoiser": True});/rtx/pathtracing/totalSpp = clampSpp = 64 x 8 = 512;warmup 64 次 update;Replicator render_product + rgb + instance_id_segmentation(colorize False),rep.orchestrator.step(rt_subframes=8);OptiX denoiser(:103,没有关闭开关);real-time 模式靠 DLSS,image 里没 NGX 所以不用(README.md:152-153)。64 spp、8 subframes、warmup 64 都是 isaac_render.py:64-70 的 CLI 默认值;S1/config.yaml:53-54 的 warmup_updates: 32、rt_subframes: 64 只有旧的 isaac/render_views.py:81-83 读,isaac_render.py 不读,改 config 不改 render S1/render/isaac_render.py:64-70, 96-161;KD/isaac/render.py:89-187;KD/config.yaml:131-134
OptiX denoiser 在 我们的集群 上 <node> 实测 optixDenoiserCreate 失败:Unable to load denoiser weights: Could not open optix denoiser weights file /usr/share/nvidia/nvoptix.bin(节点上没有这个文件;tabletop render 段 353 次,viewer robot 测试完整 log 6170 次);render 仍 exit 0、render.json passed: true,两张 view 是没去噪的 512 spp path tracing;verify_views 19:1x ET 跑过:噪声门 PASS,全部检查 PASS,verified=True。同名文件在我们的 driver user-space 拷贝里有:conda-envs/848x-isaac/nvidia-userspace/615.71.09/share/nvidia/nvoptix.bin,但 OptiX 只认 /usr/share/nvidia/nvoptix.bin,没有环境变量可改(NVIDIA 论坛的办法只有 root 放文件或容器 bind)。verify_views 19:1x ET 在这两张图上跑过:噪声门 PASS,verified=True RUNS/logs/stage1-smoke-3506650.log:1545-1557;RUNS/kitchen_drawer_pull/view-test-3506650/test-robot.log;RUNS/stage1/held_out_00/renders/render.json
session layer 摆姿势 render 时把 settled cube pose(tabletop)或 state A/B 的 link poses(kitchen)写进 stage.GetSessionLayer(),scene.usda 不动;每换一个 state 就 session_layer.Clear() isaac_render.py:32-42;render.py:131-139
先写失败记录 render.json 在 Kit 启动前先写 passed: False 和 "Kit ended before a frame was rendered",RTX 把进程带崩也有记录 isaac_render.py:86-94;render.py:78-87
确定性测试 tabletop V7:snapshot/restore 后重跑 480 步,cube pose 差 < 1e-6;kitchen K17:两次重新 load 文件再 settle + rollout,q/slide/tcp 差 < 1e-6,因为 snapshot/restore 不重置 PhysX contact cache(第一次 build 差 6.1e-6 失败) validate.py:500-514;KD/isaac/validate.py:730-769;PROGRESS.md:171-174
SimReady 背景去物理 三个 variant set PhysX/MuJoCo/Newton 置 "Disabled" 还不够;再把 instance 解开,rigid body、collider 全 disable,joint SetActive(False),ArticulationRootAPI 移除。四件合计 24 个 rigidBodyEnabled = 0、24 个 collisionEnabled = 0、20 个 joint active = false、4 处 delete apiSchemas = ["PhysicsArticulationRootAPI"];分件 back_counter 9/9/8、right_cabinet 3/3/2、wall_cabinet 6/6/5、dishwasher 6/6/5;finalize 要求背景 live physics 为 0 KD/usd_scene.py:244-307;PROGRESS.md:78-79;USDA:1346, 1760, 1898, 2123;KD/finalize.py:124-140
退出码 6.x 的 app.close() 默认以 0 退出,close_app(app, status) 传 exit_code S1/isaac/launch.py:48-53
两个 experience build/validate 用 isaaclab.python.headless.kit(不启 RTX),rendering 用 isaaclab.python.headless.rendering.kit(5.1 路径);launch.py 在 isaacsim/apps 和 isaaclab/apps 找,找不到就 FileNotFoundError。ENV62(isaacsim 6.2.0.0 + isaaclab 3.0.0 --no-deps)里两份 kit 都在 isaaclab/apps/,build_scene 在它上面跑通;848x-isaac(6.0.0.1)没装 isaaclab,apps/ 只有 isaacsim.exp.*.kit,所以 build_scene / validate_existing 在它上面起不来;isaac_render.py 不用这些 experience launch.py:19-38;README.md:122-124

7. 校验

Tabletop V1 到 V9(S1/isaac/validate.py:340-652),settle 480 步 = 2 s(config.yaml:55),robot 一直 hold home。我们的集群 实测(job 3506650,ENV62,<node>):九项全 PASS,STAGE1_BUILD passed=True steps=2761(log :100-109;RUNS/stage1/held_out_00/validation.json)。

V 通过条件 行
V1 stage 打开、PhysX attach;settle 后 cube pose 与 robot q 全有限 351-371
V2 cube:|z − (0.40 + a/2)| < 2e-3 m,xy 漂移 < 1e-3 m,倾斜 < 0.5 deg,速度 < 1e-3 m/s 372-390
V3 max 关节误差 < 0.01 rad;panda_link0 位置误差 < 1e-3 m;panda_hand 对 DH 链 < 5e-3 m 且 < 1.0 deg 391-423
V4 settle 期间 robot 与非 robot collider 零接触(pedestal 碰 link0 除外) 253-268, 424-433
V5 cube mass / static / dynamic friction / restitution、drawer mass、damping、joint friction、7 个 arm stiffness(对 400 每 rad)、link 质量,相对误差 ≤ 1e-5;注意 table friction 读的是 USD binding 不是 PhysX(_table_material,317-327) 435-488
V6 |slide| < 1e-3 m 489-498
V7 restore 初始 snapshot 重跑 480 步,max |cube pose 差| < 1e-6 500-514
V8 F* = μmg,μ = max(cube, table),0.5 s:0.5F* 下位移 < 1e-3 m;1.5F* 下位移对 ½(1.5F*/m − μg)t² 相对误差 < 0.15 516-550
V9 按 waypoints 关节空间插值(approach 1.5 s,pre_push 1.0 s,push 2.0 s,dwell 0.75 s,hold 0.5 s);TCP 误差 < 0.01 m(approach、pre_push、post_push);cube 沿推向位移 ∈ [0.035, 0.105] m(计划 0.07);横向 < 0.03 m;倾斜 < 10 deg;z > 桌面;碰到了 cube;没碰别的 38, 552-636

Kitchen K1 到 K17(KD/isaac/validate.py:236-795),settle 480 步,K11 到 K17 从重新 load 的文件开始,rollout 12.6 s = 3024 步。括号里是 Viet 的实测(PROGRESS.md:151-169,job 8138527,Isaac Sim 6.2.0.0,Kit 110.4)。

K 通过条件(实测) 行
K1 2 个 articulation root,状态有限(dt 1/240) 252-263, 289-291
K2 robot 9 DOF 名字对、drawer 1 个 prismatic drawer_slide 266-284
K3 island 下无 rigid body;drawer base 位姿变化 < 1e-6(0) 298-306
K4 settle 后 |slide| 和 |v| < 1e-4(4.8e-13 m) 308-316
K5 (f + 5 N) 推 0.5 s:沿 x > 0.005、横向 < 1e-4、转动 < 0.01 deg;反向推后 > −1e-3(0.241 m,1.2e-10 m,0 deg) 319-354
K6 ±40 N 各 3 s:到达上下限误差 < 2e-3,过冲 < 3e-3(0.40000 m) 357-388
K7 mass 相对误差 ≤ 1e-5,COM < 1e-5 m,principal inertia 相对 < 1e-4(2.3e-8,6.8e-10 m,1.8e-7) 391-429
K8 damping、static/dynamic friction 读回 ≤ 1e-5;0.5f 推 1 s |x| < 5e-4;F = f + 0.05c 推 4 s 稳态速度与 0.05 m/s 相对误差 < 0.10 432-483
K9 base 位置 < 1e-3 m,yaw < 0.1 deg(2.7e-5 m,0.002 deg) 486-513
K10 关节 < 0.01,hand 对 DH 链 < 5e-3 m、< 1 deg(4.6e-5,2.5e-5 m) 514-540
K11 plan reachable;pregrasp、approach 的 TCP 误差 < 5e-3(4.5 / 2.4 mm) 561-582
K12 闭指前 robot 零接触(link0 碰地除外) 583-592
K13 两指都碰 bar,每指位置在 0.007 ± 0.003 m,无其它接触(6.88 mm) 593-630
K14 final slide ∈ [0.9 x 0.20, 0.40],slip < 0.01,TCP tracking < 0.01,无其它接触(0.1980 m,slip 4.8 μm,2.0 mm) 631-671
K15 最小 separation > −0.005 m,off-axis < 1e-4,slide 在 limits ± 1e-3(−0.05 mm) 672-701
K16 retreat 后零接触,slide 变化 < 2e-3,arm 离 home < 0.01 rad(0.1986 m,2.6e-3 rad) 702-729
K17 两次 fresh load 的 rollout 差 < 1e-6(0.0,3024 samples) 730-769

Render 之后和 finalize 的检查:

检查 tabletop (S1/render/verify_views.py:45-53, 139-321) kitchen (KD/verify_views.py:35-42, 151-224)
来源 / 新鲜度 render.json passed;verify 记录 render.json 和 png 的 sha256 另要求 engine 为 Isaac Sim 6.2.0.0,4 个输入 hash 未变
尺寸、曝光 相机尺寸;mean ∈ [40, 220],clipped < 0.05 mean ∈ [30, 225],clipped ≤ 0.05
噪声 桌面 mask(腐蚀 6 px)高频 std ≤ 6.0 柜体平面 mask(腐蚀 3 px)MAD ≤ 6.0
几何 cube mask 质心离 settled 中心投影 ≤ 8 px;桌面 ≥ 1000 px 且质心在投影轮廓 ± 5 px 内 robot base 投影落在 robot 上;3 个柜体 landmark(front_left、front_right、countertop_front)每个都要落在 cabinet mask 上或被 robot mask 整窗遮住,且至少 2 个落在 cabinet 上(:186-197)
可见性 robot ≥ 1000 px;每个投影面积 ≥ 5000 px² 的墙/prop ≥ 200 px;至少一个 view 有房间 robot ≥ 2000 px,drawer_front ≥ 1500,handle ≥ 60(demo/reference_match 免)
两 view 不同 平均绝对差 ≥ 10 同
finalize 静态比对 S1/stage_checks.py(usd-core,无 GPU):units、gravity、cube pose/size/mass/material、table material 和 top_z、drawer mass/damping/friction、robot base/anchor/articulation/joint limits/home targets/link masses、房间无物理、相机 fovy 和位置、灯光;容差 1e-6 x max(1, |expected|)(:18-24),6.x robot 共 62 项(README.md:102-103);另加 θ read-back ≤ 1e-6、"Isaac Sim validation of the reloaded scene passed"、"views: verified renders of scene.usda, room included"、ReferenceStore contract、separation、MuJoCo settle(finalize.py:139-276,其中 :156-176) KD/finalize.py:51-162:θ 和 fixed 对 USD、joint 类型/轴/limits、articulation roots = 2、背景 live physics = 0、decor/floor 无物理、相机 focal 和 eye;gates validation / renders / files / stage 全过才发布

8. agent 看到什么,看不到什么

Tabletop 走我们自己的 observe(S1/observe_held_out.yaml,与 configs/sample.yaml 只差四处:visual_condition: text with two complementary static views、held_out_root: ../runs/stage1/held_out、split: held-out scenes、scene_ids: [held_out_00];仍是 engines: [MuJoCo],:8-20)。ReferenceStore.load 跑全部 contract;build_observation 从 bundle 拷贝已 ship 的 view 并记录 manifest 的 renderer,只 render 没 ship 的 view(build.py:141-160, 192-210)。

文件 内容 来源
base_text.md public projection 的文字化:table、drawer(几何、关节轴和行程、handle 尺寸、"closed")、robot(pedestal 高、base 位置、yaw)、objects(label、形状、尺寸、颜色词、材料名、位置、yaw) PKG/input_conditions/base_text.py:175;contract.py:234-278
disclosed_parameters.json NONE 为空;PARTIAL 按 one_value_per_relationship:每个 object 三选一、每个 joint 二选一,table friction 和 drawer mass 永远 withheld,3 位有效数字;ALL 给全部 7 个 partial_information.py:173-242;constants.py:225-226
views/front_right.png、views/top_down.png Isaac Sim RTX 的 render(房间在图里但不在文字里) finalize.py:122-136
cameras.json 两台相机的 fx、fy、cx、cy 和 OpenCV camera_to_world views.py:86-96
manifest.json scene_id、input_combination、lock_hash、renderer、每个文件的 sha256、labels、described_objects、fixtures block、units、observation_sha256 build.py:217-230

seed 848 的 base_text.md(用 write_base_text 对 sampled scene.json 生成;object label 由 object_labels 的 seeded permutation 给出,单物体时 permutation 长度 1,任何 seed 都得到 object_1,base_text.py:41-45):

A tan wood table that does not move. Its top is a slab of 80.0 x 60.0 x 4.0 cm (x, y, z) centered on the origin with its upper face at z = 0.0 cm. … A purple wood drawer, a closed box of 30.0 x 25.0 x 8.0 cm (x, y, z), hangs under the table top and moves along +x on a prismatic joint. Closed, its center is at x = 25.0 cm, y = 0.0 cm, z = -8.5 cm; it can move by up to 25.0 cm from the closed position. A dark gray handle of 2.0 x 10.0 x 1.5 cm sits in the middle of its front face. The drawer is closed. … A robot arm (franka emika panda) with a panda hand is mounted on a pedestal 20.0 cm tall; its base stands at x = 40.0 cm, y = -45.0 cm, rotated by 90.0 degrees about the vertical axis. … object_1: a red ABS plastic box of 6.3 x 6.3 x 6.3 cm (x, y, z). Its center is at x = -4.7 cm, y = -7.6 cm; its top is at z = 6.3 cm. It is rotated by -26.8 degrees about the vertical axis.

Kitchen 的 observation 是 finalize 手写的(KD/finalize.py:176-236),只有一个 level "no supplied physical parameter values"(:257-259),没有 disclosed_parameters.json 和 PackageManifest,所以我们的 load_observation 读不了它,9 个 input condition 一个都没产出。base_text.md 原文:

A kitchen. In the middle stands a white island cabinet on a dark tiled floor with pale grout lines. The island is 93 cm wide, 67 cm deep and 90 cm tall to the top of its thick white countertop, which overhangs the front and the sides slightly. Under the countertop is one drawer across the full width of the island, with a metal bar handle in the middle of its front; the drawer slides straight out of the front of the island. Below the drawer are two panelled doors with round knobs next to the gap between them. A Franka Emika Panda arm with its two-finger hand stands on the floor in front of the island, facing the drawer, its base about 66 cm in front of the island's front face, centred on it. Further white kitchen furniture stands in the background. Frame: z up, the island's front face is the plane x = 0, the drawer opens towards +x, the island is centred on y = 0 and stands on the floor at z = 0. The views show the initial state: the drawer closed, the arm at its home pose with the hand open. The robot's task in this scene is to grasp the drawer handle and pull the drawer open. Background furniture: NVIDIA SimReady assets, CC-BY-4.0.

cameras.json 给 reference_match(1424 x 1124,fovy 29.2663,fx = fy = 2152.445,cx 712,cy 562)和 workspace(1280 x 960,fovy 38.4,fx = fy = 1378.372,cx 640,cy 480)的内参和 OpenCV camera_to_world(:207-236)。

看不到的 tabletop kitchen
θ(s) 7 个值(hidden_values() = 0.253765, 0.339249, 0.64654, 2.22435, 0.421894, 0.419825, 0.671937) 5 个值
其它物理量 density、table/drawer restitution、drawer contact friction、robot gains、PhysX 设置 固定值、派生值、combine mode、robot gains、PhysX 设置
几何 房间的任何描述(只在图里) travel 0.40、box 深 0.50、高 0.12、rails、opening 0.19;handle 0.16 bar、14 mm、35 mm standoff
robot 无(base pose、pedestal 在文本里) 精确 base pose 和 home q(只能看图)
其它 seed、ground truth、USD、record.json plan、state B 图、截图、SimReady 选件和位置、seed、ground truth、USD
防泄漏 规则 代码
finalize 文本/文件名 不得含 seed、ground_truth、.usd、validation S1/finalize.py:47, 210-235
finalize 数值 %.6g 格式的任何 θ 值不得出现在 public projection :222-224
test regex (?<![0-9a-f])848(?![0-9a-f]):禁的是不与 hex 字符相邻的独立 848(0.848 也禁,因为 . 不是 hex);1848、8480、sha256 里的 848 都允许 tests/test_stage1_reference.py:163-165
observe leak_scan 扫 package 里的 withheld 值和派生值(density 用 4 种 scale,e² 用 3 种),3 位有效数字;marker 词 seed、secret、private、held_out、hidden、scene.json partial_information.py:265-299;leak_scan.py:120-128
kitchen leak_scan needles:θ、非零固定值、principal inertia、0.4、400/80/2000/100;有 finding 就不把临时目录换入 observation/<scene>/,finalize 失败;已发布的旧 observation 不会被删 KD/finalize.py:239-274, 399-414

9. 交互查看

S1/isaac/stream_scene.py 用 isaacsim.exp.full.streaming.kit 把整个 Isaac Sim UI headless 渲染后经 WebRTC 推流(signalling TCP 49100,media UDP 47998,:3-6, 81-82),客户端是同版本(6.2)的 Isaac Sim WebRTC Streaming Client(README.md:181-183)。--public-ip 是客户端发 media 的目标:直连填节点地址,ssh 转发填 127.0.0.1(:7-8)。ssh -L 不转 UDP、socat 会合并 datagram 导致黑屏,所以 udp_tcp_relay.py 给每个 datagram 加 (channel, length) 头走一条 TCP(udp_tcp_relay.py:2-14, 26)。启动约 1 min,打印 STAGE1_STREAM ready(README.md:192;stream_scene.py:174-180);关掉客户端 session 就结束。渲染模式 RENDER_MODES = ("default", "RealTimePathTracing", "PathTracing")(:40):default 是 RTX Real-Time(靠 DLSS,无 NGX 会 grainy),PathTracing 是 OptiX(代码设 4 spp/帧,静止时累积到 256,:59-67, 86-95);--capture-dir + --capture-every 把 viewport 存成 PNG(:99-102, 223-230)。

面板 控件 作用 代码
Panda Control Play、Pause、Reset robot、Reset simulation 只改 live PhysX 状态;状态行显示 PhysX 步数计的 sim time robot_panel.py:404-415, 265-291
Panda Control Camera:orbit(步长 5 到 45 deg)、pan 0.1、zoom 0.8、Focus selected、Reset view 只动 viewport 相机 :294-365, 416-441
Panda Control 7 个 arm joint 滑条(度) 裁到 PhysX 限位后下发 drive target :226-232, 442-452
Panda Control Gripper Open(0.04 m/指)、Close、0 到 40 mm 滑条 finger drive target :234-239, 453-466
Panda Control End effector x/y/z/roll/pitch/yaw,Go (IK),Use current pose 只在 IK 收敛且在限位内才下发,否则 "nothing commanded" :241-263, 467-479
Panda Control Feedback(约 10 Hz) actual/target q、tracking error、PhysX TCP、DH 链与 PhysX 的差(mm) :537-571
Kitchen Drawer(--drawer-panel) Scripted pull 按 plan_pull 的 waypoints 和 config.pull.seconds 在 sim time 里插值(比 validation 多一段 home);成功判据 0.9 x 0.20 ≤ final ≤ upper + 1e-3;plan 来自 config.yaml,不来自 stage,UI 里改 θ 不影响它 drawer_panel.py:89-152
Kitchen Drawer Reset drawer slide 和速度归 0 :80-86
Kitchen Drawer Travel limits session layer 里两块半透明板标闭合和全开位置 :177-203
Kitchen Drawer 标签 slide、速度、limits、phase、status :205-223
headless 自检 --robot-test、--drawer-test Viet 实测 33/33,pull 到 0.1988 m 成功 PROGRESS.md:235-249

我们的集群 实测(job 3506650,code/private/tools/jobs/stage1_smoke.sbatch,<node> L40S,ENV62,--render-mode PathTracing --drawer-panel,对 HO 场景的副本):--robot-test summary passed=True 33/33(RUNS/kitchen_drawer_pull/view-test-3506650/test-robot.log:63745);--drawer-test pull PASS final 0.1988 m planned 0.200 m, best 0.1988 m, 1539 frames, sim 17.14 s,summary passed=True(test-drawer.log:13206, 13424);启动 254.2 s(第一次)和 88.2 s(第二次)(job log :7;test-drawer.log:1811);副本没被改写、hidden 文件 hash 不变(job log :91-92)。两个问题:(1) WebRTC 插件没加载:[Plugin: libomni.kit.livestream.webrtc.plugin.so] Could not load the dynamic library ... Error: libatomic.so.1: cannot open shared object file(job log :5,两次测试各一次),headless 自检不需要它,但 Mac 客户端连不上。已修(19:13 ET):env 的 conda libgcc 自带 lib/libatomic.so.1,加了 lib/extra/libatomic.so.1 符号链接并写进 hook 的 LD_LIBRARY_PATH(simgenprobe.sh:29, 35);复查 job 3507469(<node>,2 min,default 渲染模式)插件错误 0 条,omni.kit.livestream.webrtc-10.7.3 startup,STAGE1_STREAM ready ... startup=70.6s,DRAWER_TEST summary passed=True;(2) PathTracing 模式下 ready 行报 /rtx/pathtracing/spp=64 /rtx/pathtracing/totalSpp=64(job log :6),不是代码设的 4 / 256,设置没生效,原因 not in the code;OptiX denoiser 同样缺 weights(第 6 节)。

永远打开一个 copy:UI 里 File > Save 写的是打开的那个文件(README.md:187-189);kitchen 的 copy 必须和 simready_cache 平级(scene.usda 用 ../simready_cache/... 引用,USDA:1347, 1761, 1899, 2124),robot 文件夹放旁边(KD/README.md:77-82)。Viet 的 sbatch 假设 队友的集群:account/partition/qos 都是 scavenger(HO/jobs/kitchen_webrtc.sbatch:6-8)、--gres=gpu:<their-gpu>:1(:9)、Apptainer 镜像 STAGE1_ISAAC_SIF(:14)、NGX bind(:23)、.<their-domain> 主机名(:34);我们的集群 上这些都要换(smoke sbatch 已经换成 scavenger + gpu:nvidia_l40s:1,无 Apptainer)。

10. 需要你拍板的几处

  1. Isaac 版本:Stage 1 已定在 6.2,harness 还没定。 ENV62(conda-envs/simgenprobe,23 GB,code/private/tools/create_simgenprobe_env.sh 建,log 末行 "2026-11-04 18:39:39 EST done";isaacsim 6.2.0.0 + isaaclab 3.0.0 --no-deps,isaaclab/apps/isaaclab.python.headless*.kit 都在)已经存在,S1/isaac_python_cluster.sh:11 指向它,smoke job 3506650 把 viewer 自检、build V1 到 V9、render 全跑通(第 7、9 节)。没定的是我们的 package:PKG/constants.py:228 写死 ISAAC_SIM_VERSION = "6.0.0.1",Isaac engine 的 worker handshake 版本不等就 EngineUnavailable(scene_compilation/isaac_sim/isaac_sim_engine.py:251-256),version() 也回这个常量(:868-870);constants_sha256() 把 constants 模块里每个大写常量 hash 进 lock(evaluation_protocol/lock.py:124-127,data/protocol/protocol.lock.json:44),verify_lock 在 observe / evaluate / cli 开头重算,不等就 ProtocolLockMismatch(lock.py:257-271;steps/observe.py:57,steps/evaluate.py:88,cli.py:141)。所以 ENV62 能跑 Stage 1,但不能当 observe / generate / evaluate 的 engines.isaac_sim 用。(a) 把 constants.py:228 改成 6.2.0.0 并重新生成 lock:一套 Isaac 跑 Stage 1 和 harness,代价是 lock_hash 变,已有的 observation / record 带旧 hash;(b) harness 留 6.0.0.1(848x-isaac),Stage 1 用 6.2:两套 Isaac,跨版本一致性只能靠 validate_existing.py / inspect_stage.py 比(README.md:109-112),没验证过。推荐 (a),"一律用 Isaac" 应当是一个版本,Stage 1 的 V1 到 V9 和 K1 到 K17 都只在 6.2 上验证过。附带一个矛盾:建 env 的 log 18:39:34 EST 列出 usd-core 26.8(create_simgenprobe_env.log:394, 414),19:1x EST 在 ENV62 里 pip list 没有它,顶层 pxr 来自 usd-exchange 3.0.1(usd_exchange-3.0.1.dist-info/RECORD),是主会话 18:52 ET 用 uv pip uninstall usd-core 特意拿掉的:Isaac 自带 pxr,site-packages 里的 usd-core 会被先 import 到(Viet 分两个 venv 就是为了这个);smoke 的 build 和 render 都过了。
  2. finalize 里的 MuJoCo。 tabletop finalize.py:237-262 用 MuJoCo settle 做交叉检查,observe_held_out.yaml:19-20 的 evaluation engine 也是 MuJoCo;kitchen 不碰 MuJoCo。(a) 保留为独立检查;(b) 删掉或换成 Isaac settle。推荐 (b),与"一律用 Isaac"一致,代价是少一道独立 cross-check。
  3. demo 用哪个 family。 (a) kitchen:pull 已验证(K11 到 K17),但不在我们的 SceneSpecification 里(14 个 schema error,PROGRESS.md:214),没有 9 个 condition;θ 对我们的协议:2 个值超出 fixture 区间(drawer.mass 2.1217 vs [0.4, 1.2],materials.json:221-227;joint_friction 2.13293 vs [0.3, 1.2],:235-241),1 个区间更宽但值在内(damping [2, 10] vs [2, 8],:228-234),1 项 schema 有但不进 θ(drawer.contact_friction),1 项无对应(handle.contact_friction,truth.py:46);(b) tabletop held_out_00:完全在协议里,但 task 只有 push(ground_truth.py:188),handle 没 collider。推荐先 (a) 做 policy demo、(b) 跑 harness 的 9 个 condition,两条线分开;要合并就得做 schema 0.2(cabinet fixture、floor-standing robot、带 friction 的 handle),周级工作。
  4. viewer 连接。 (a) ssh 隧道到计算节点 loopback(PUBLIC_IP=127.0.0.1 + relay);(b) VPN 直连(需要节点的 49100/tcp 和 47998/udp 可达,firewalld 未验证)。插件加载问题已修(第 9 节,复查 job 3507469)。推荐先 (a),Mac 已能直接 ssh 到计算节点;节点侧的 job 脚本已备好:code/private/tools/jobs/stage1_live_viewer.sbatch(提交后 log 里打印 Mac 端要敲的两条命令)。
  5. 渲染去噪(已有结论)。 <node> 没有 /usr/share/nvidia/nvoptix.bin,OptiX denoiser 建不起来;这个路径是写死的,没有环境变量能改,只能 root 放文件或容器 bind(我们的拷贝在 nvidia-userspace/615.71.09/share/nvidia/,指不过去)。实测影响:tabletop 两张 view 是未去噪的 512 spp path tracing,verify_views 19:1x ET 跑过,噪声门和全部检查 PASS,verified=True。结论:reference 渲染不动;交互 viewer 走 default 模式(RTX Real-Time + DLSS,dlss/supported=True,复查 job 3507469 就是这个模式)。
Stage 1 bundle scene.json / observation views/, cameras.json observe 3 visual × 3 physical none / partial / all LLM agent loop edit_specification + tools budget 40 calls, 1 submit compile → USD scene.usda + robot/ Engine Agreement Isaac Sim worker settle, checks, probes render, compare generated scene ŝ scene.usda, task, cameras → policy teammate tool reports: compile / simulate / render / check 的结果回到 agent 评测:ŝ 与隐藏的 s 比 geometry、θ、probe 响应;policy 在 ŝ 和 s 里各训一次,都在 s 里测成功率。
Harness 在 Stage 1 之上的一条路:observe 决定 agent 看到多少 θ,agent 用工具改规格,每次 compile / simulate / render / check 都在 Isaac Sim 里跑,submit 之后的 ŝ 才进入评测和 policy 训练。

TAB 2 · 我们的 harness 怎么一步步设计(Isaac-only)

写于 2026-11-04 18:42 ET,19:1x ET 按审查结果修订(21 条)并更新现状。路径缩写:PKG/ = code/github-code/src/simgenprobe/(main 1f64265,v0.1.3);CFG/ = code/github-code/configs/;S1/ = code/private/stage1_reference/(e5dcd30 归档);KD/ = S1/kitchen_drawer_pull/;HO/ = code/private/_asset/kitchen_drawer_pull_handoff_extracted/kitchen_drawer_pull_handoff/;ENVS/ = $ENVS/;GT848 = 今天用 seed 848 重跑 sample 得到的 ground_truth.json(完整路径见文末)。每个数字后面带 file:line;代码里没有的写"不在代码里"。

19:3x ET 更新(主会话):§6 的两件事有了结论(libatomic 已修并复查通过;OptiX 是权重文件路径写死,verify_views 已 PASS);T13 的节点侧脚本已写好(code/private/tools/jobs/stage1_live_viewer.sbatch)。

1. 目标与 demo

你定的 demo:一个隐藏的 reference scene s,任务是"把抽屉拉开",同一个 policy 分别在 s 和 LLM 生成的 ŝ 里训练,训练前后都在 s 里测成功率。midpoint 的写法与此一致:train in ŝ and s, evaluate both in s, 报 success-rate gap G_t(body/evaluation.tex:4)。所以 demo 最少要出这张表:

行 policy 在哪训 在哪测 含义
0 不训 s 起点成功率
1 s s 上界:直接在 reference 里训
2 ŝ(LLM 生成) s 核心数字:ŝ 里学到的东西能不能搬回 s
3 ŝ ŝ 可选:证明 policy 在 ŝ 里确实学会了

G_t = 行 1 减 行 2。

分工:

谁 负责 交出去的东西
你(Yi Ge) LLM 生成 harness:observe → generate → evaluate,全部 Isaac;ŝ 的交付包 §3.6 的包
teammate A(Viet,Stage 1) 隐藏 reference:held_out_00(seed 848)和 kitchen_drawer_pull_00(seed 2611);bundle、observation、scene.usda、task、demo 状态 §3.1 的两个目录
teammate B(policy) LearningSetting(算法、预算、repeats,现在三项全空,PKG/policy_level/trainer.py:20-27),trainer 注册到 entry point group simgenprobe.trainers(:55),上表四行 成功率表、G_t

先说清一件事:package 里的 policy 全是"力"接口。Action 只有 body_forces 和 joint_forces(PKG/scene_compilation/engine.py:255-260),scripted policy 第一行就写 "never through the robot"(PKG/evaluation_protocol/policy_agreement/scripted_policy.py:1)。你的 demo 是 Panda 去抓把手,所以 policy 必须能给机器人下关节目标。Stage 1 已经有这条路:tabletop 的 Session.step 每步 set_dof_position_targets(S1/isaac/validate.py:198-207,调用在 :201),kitchen 的 KitchenSession 加 Rollout 跑完整的 grasp-and-pull(KD/isaac/session.py:22,KD/isaac/validate.py:79-233)。DESIGN 把它列为 seam S6(.note/code_planning_1024/DESIGN_v0.1.md:1245);本文把它当必做项(§4 第 9 行,§6 的 T9)。

2. 设计原则:继承什么,Isaac-only 改什么

继承的八条,每条 main 上都在跑:

原则 代码里的样子 file:line
隐藏 reference agent 只拿 observation package:base_text.md、disclosed_parameters.json、cameras.json、views/、manifest.json;bundle 经 ReferenceStore.load 过合同 G-B1 到 G-B10 PKG/input_conditions/observation.py:41-47;PKG/reference_scenes/store.py:89-91;PKG/reference_scenes/contract.py:1
九种输入条件 三种 VisualCondition × 三级 PhysicalInformationLevel,INPUT_COMBINATIONS 是笛卡尔积;views 为 ()、("front_right",)、("front_right", "top_down") PKG/input_conditions/conditions.py:26-39, 58-62;views.py:79-84
渐进披露 OneValuePerRelationship:每个 object 三选一,每个 joint 二选一,table friction 和 drawer mass 永远不给;同一 relationship 组里不许给两个 partial_information.py:173-198, 230-239;四个 relationship :56-77;候选量 PKG/constants.py:225-226
工具循环 + 预算 11 个工具,6 个计费(compile, simulate, render, compare_images, look_up_materials, check),预算 40,submit 一次 PKG/scene_generation/tools.py:55-70;CFG/budget.yaml:2;prompts/instructions.md:11-13
内建检查 Execution, Plausibility, Engine Agreement, Text Consistency:既是评测第一层,也是 check 工具 constants.py:9;PKG/built_in_checks/__init__.py:1;harness.py:511-525
泄漏扫描 每个 agent 可见字节扫 L1 到 L5,工具结果扫 L6 PKG/input_conditions/leak_scan.py:1
lock development set、prompts、materials、cameras、views、constants、tool names、score scales、task weights、reference readings 全部进 lock;lock 不同分数不互通;evaluation engine 不同拒绝评分 PKG/evaluation_protocol/lock.py:193-209;steps/generate.py:183-184;steps/evaluate.py:113-123
评测三层 checks → Parameters + Physical Probes(tilt, push, drop, pull)→ Policy Agreement(pushing, drawer pulling) constants.py:11-12;PKG/evaluation_protocol/protocol.py:1-40

Isaac-only 改动清单(本 tab 的核心表):

# 现状 Isaac-only 之后 代价
1 engines.names: [MuJoCo],evaluation_engine: MuJoCo,isaac_sim.python: "" [Isaac Sim] / Isaac Sim / 一个 6.2 worker wrapper 的绝对路径(先 source ENVS/simgenprobe/etc/conda/activate.d/simgenprobe.sh,再 exec ENVS/simgenprobe/bin/python;样板是 6.0 的 code/private/isaac/isaac_gpu/isaac_worker_python.sh:10-13)。三个不能:不能写裸解释器,worker 直接 exec 这个路径(isaac_sim_engine.py:239),不经 activation hook,没有 hook 设的 LD_LIBRARY_PATH / VK_DRIVER_FILES 时,在没有系统 nvidia-driver-libs 的节点上(<node> 实测没有)Kit 挂不上 hydra engine,render 一律拒绝(worker.py:823-825);不能写相对路径,Path(python).is_file() 按 cwd 判(:830);不能把集群绝对路径写进公开仓的 yaml(§4 末的 pre-commit) 改 yaml(CFG/sample.yaml:17-20;S1/observe_held_out.yaml:18-21);真正的配置放 code/private/configs/,公开仓的 CFG/isaac.yaml 留 python: ""
2 load_config 构造并关闭一次 EngineSet(PKG/config.py:172-173),而 IsaacSimEngine.from_config 立刻 worker.start()(isaac_sim_engine.py:834-838) observe / generate / evaluate / calibrate 每条命令都要在 GPU 节点跑,并付一次 Kit 启动:worker 的 physics experience 冷 78.9 s、热 27 s(H200,.note/code_planning_1024/reports/isaac_env_fix_1026.md:181);Stage 1 的 streaming experience 在 L40S <node> 上冷 254.2 s、同节点第二次 88.2 s(smoke job 3506650 的 log) 全部走 scavenger L40S job
3 ISAAC_SIM_VERSION = "6.0.0.1"(constants.py:228),worker 握手版本不符即 EngineUnavailable(isaac_sim_engine.py:251-256) 改成 "6.2.0.0":Stage 1 两个 config 都钉 6.2(S1/config.yaml:52;KD/config.yaml:129),build 拒绝别的版本(S1/isaac/build_scene.py:63-67;KD/isaac/build.py:98-102),ENVS/simgenprobe 已建好(18:39:39 EST,code/private/tools/logs/create_simgenprobe_env.log 末行),version('isaacsim') 打印 6.2.0.0 改 constants 即改 constants_sha256(lock.py:124-127, 205):新 lock
4 λ 和 w 在 MuJoCo 3.12.0 里拟合:拟合引擎记在 data/protocol/score_scales.json:25-26 和 task_weights.json:33-34 的 engine / engine_version,EvaluationProtocol 比的就是这两个字段(protocol.py:110-114);lock 的 engine_pins(protocol.lock.json:7-10)只是 version(distribution) 读到的安装版本(engine.py:388-396) 在 Isaac 里重跑 simgenprobe calibrate(steps/calibrate.py:35-53:六个 development scene 的 reference readings、λ、w、新 lock) GPU 时间;corrupted copies 48 份(CHANGELOG.md:85-87)
5 development bundle 的 views 是 MuJoCo 渲的;observe 有 view 就起引擎(steps/observe.py:66-68),已 ship 的 view 只复制(input_conditions/build.py:141-160, 203-210) 代码不强制,但 agent 的 compare_images 会拿 Isaac 渲染去比 MuJoCo 图:六个 development bundle 用 Isaac 重渲,views_sha256 进 lock(lock.py:136-152, 204) 再跑一次 observe
6 write_usd 不写机器人(usd_file.py:536-537, 548:robot_included: False) reference views 里有 Panda(Stage 1 compose.py:200-212 引用 ./robot/panda.usd),agent 的 render 里没有:把机器人引用搬进 write_usd §4 第 3 行
7 engine_pins() 在 core venv 里读 version("isaacsim")(engine.py:388-396),Isaac-only 时 lock 还是记 null 改成读 worker 握手的版本 15 行
8 MuJoCo 是核心依赖(pyproject.toml:14);generate.py:32, 369 记 gl_backend;Stage 1 finalize 有 MuJoCo 交叉验证(S1/finalize.py:237-262) 见决策 (b)

3. 在 Stage 1 之上的流水线

 teammate A: Stage 1(隐藏侧)               |  我们: harness(Isaac-only)                                |  teammate B
                                              |                                                             |
 tabletop  sample -> build_scene(V1-V9)       |  [1] observe   lock verify -> ReferenceStore.load            |
           -> isaac_render -> verify_views    |                -> build_observation(3 visual x 3 physical) |
           -> finalize -> held_out/held_out_00|                package/: base_text, disclosed_parameters,     |
              {scene.json, manifest, views/}  |                          cameras, views/, manifest           |
                                        ------+--->                      |                                   |
 kitchen   simready -> sample -> build(K1-K17)|  [2] generate  agent loop: edit_specification(免费)         |
           -> render -> verify -> finalize    |                compile / simulate / render / compare_images   |
              bundle/<scene>, observation/    |                / check / look_up_materials(计费,共 40)      |
                                              |                      ^              |  Isaac worker(GPU 节点,|
                                              |                      | reports      v  CPU PhysX,RTX 渲染)  |
                                              |  [3] submit    submission/specification.json -> compile       |
                                              |                -> scene.usda(+ robot/panda.usd)              |
                                              |  [4] evaluate  checks -> Parameters -> Probes ->               |
                                              |                Policy Agreement(scripted,Isaac)             |
                                              |  [5] handoff   s 和 ŝ 各一包:scene.usda, robot/, task.json,   |--> 在 ŝ 和 s 里各训一次
                                              |                cameras.json, 初始状态, 成功判据                |    都在 s 里测:四个成功率

3.1 观测从哪里来

来源 Stage 1 写出什么 能直接走我们的 observe 吗 要改什么
tabletop held_out_00 held_out/held_out_00/:scene.json(含 θ)、manifest.json、views/front_right.png、views/top_down.png(S1/finalize.py;目录含义见 S1/config.yaml:4) 能。S1/observe_held_out.yaml 已把 held_out_root 指到 ../runs/stage1/held_out(:13),split 为 held-out(:14),scene_ids: [held_out_00](:15),两视角(:8),NONE(:9)。lock 只 hash development set(lock.py:170-184),加 held-out 不换 lock。产物在 code/runs/observations/held_out_00/<combination slug>/package/,旁边一个 record.json(observation.py:46-47;build.py:175) engines 块改 Isaac(:18-21);三个 physical level 各跑一次 observe(:9 换值;S1 只读,所以复制三份到 code/private/configs/)
kitchen kitchen_drawer_pull_00 observation/<scene>/:base_text.md(手写模板,KD/finalize.py:176-204)、cameras.json(手拼,:207-236)、views/;只有 NONE 一级(:253-259) 不能。没有 disclosed_parameters.json 和 PackageManifest,load_observation 读不了(observation.py:205-251);scene_spec.json 的 schema 是 kitchen_drawer_pull/0.1(KD/sample.py:39),对我们的 SceneSpecification 有 14 个错(KD/PROGRESS.md:214) 一个转换器把它写成 package 格式,并对 kitchen θ 跑 disclose(§4 第 6 行)

3.2 渐进披露:每一级到底给什么

规则(partial_information.py:184-198):按 θ 顺序,每个 object 从 mass / contact_friction / restitution 三选一,每个 joint 从 joint_damping / joint_friction 二选一(候选量 constants.py:225-226),随机数来自 lock 派生的 seed:lock.observation_seed(scene_id, PARTIAL_PURPOSE)(build.py:169;PARTIAL_PURPOSE 在 :63);owner 是 table 或 drawer 的 key(FIXTURE_MEMBERS,:42)被 member() 归为 fixture(:85-93),kind not in choices 直接跳过(:189-191)。给出的值取 3 位有效数字(build.py:101-106)。ALL 给 θ 的全部值,NONE 一个不给(partial_information.py:211-214)。θ 之外的东西(几何、材料类别、颜色、机器人、相机)三级都给;θ 的值三级都不进 base text。

tabletop held_out_00(θ 共 7 项,值来自 GT848):

θ key seed 848 的值(GT848 行) NONE PARTIAL ALL
item_0.mass 0.253765 kg(:674-677) 不给 item_0 三选一 给
item_0.contact_friction 0.339249(:668-671) 不给 同上,同一次抽 给
item_0.restitution 0.64654(:680-683) 不给 同上 给
drawer_slide.joint_damping 2.22435 N s/m(:656-659) 不给 joint 二选一 给
drawer_slide.joint_friction 0.421894 N(:662-665) 不给 同上,同一次抽 给
drawer.mass 0.671937 kg(:650-653) 不给 永远不给 给
table.contact_friction 0.419825(:686-689) 不给 永远不给 给

所以 PARTIAL 下 agent 拿到 2 个数,ALL 拿到 7 个。cube 的类别 abs_plastic、边长 0.0628279 m、yaw -26.7965 度三级都可见;density 1023.23 kg/m³ 三级都不给(public projection 剔掉 mass / contact_friction / restitution,contract.py:234-264,density 不在公开字段里)。

kitchen kitchen_drawer_pull_00(θ 共 5 项,KD/truth.py:20-47;值读自 HO/scene/scene.usda):

θ key 值(scene.usda 行) 区间(KD/config.yaml) 套现有 OneValuePerRelationship 会怎样 NONE PARTIAL ALL
drawer.mass 2.1217 kg(:1120) [0.8, 2.5](:52) owner drawer 是 fixture,跳过 不给 不给 给
drawer_slide.joint_damping 2.80644 N s/m(:1262) [2.0, 10.0](:53) joint 二选一 不给 二选一 给
drawer_slide.joint_friction 2.13293 N(:1276-1277) [0.5, 3.0](:54) joint 二选一 不给 二选一 给
drawer.contact_friction 0.660176(:58, 60) [0.3, 0.7](:55) package 的 θ 没有这一项(KD/truth.py:38-45 把它标成 contact_friction);owner drawer 是 fixture,和 drawer.mass 一样被跳过:现有规则下永远不给,这就是它的规则 不给 不给(现有规则) 给
handle.contact_friction 0.931859(:69, 71) [0.5, 1.0](:56) 没有字段:Handle 只有 size 和 color(schema.py:256-260);THETA_ORDER 最后一列是 None(KD/truth.py:46);owner handle 不是 fixture、quantity 不是 joint,member() 归为 object(:85-93),于是 mass / contact_friction / restitution 三选一(:185, 194):抽到 contact_friction(1/3)正常披露,抽到 mass 或 restitution(2/3)抛 "theta has no handle.mass to disclose" 或同样的 handle.restitution(:195-196) 不给 1/3 给、2/3 抛错:要定规则的只有这一项 给

两点要你知道。第一,kitchen 的 ALL 也只给这 5 个数。leak scan 的 needle 是 θ 的 5 个值、fixed 的非零值、抽屉的三个 principal inertia、travel_m[1] 和四个机器人增益(KD/finalize.py:239-250,零值剔掉 :250);抽屉行程 0.40 m(KD/config.yaml:41)在 needle 里,箱深 0.50、箱高 0.12(:36, 38)、把手 0.16 m 杆、14 mm 截面、35 mm 外伸(:43-45)和 base 位姿(:72-73)不是 needle,只是 base_text 没写它们;base 的 x 其实写了:"its base about 66 cm in front"(KD/finalize.py:191-192,abs(base[0]) * 100 取整,base x = 0.655)。第二,抽屉前板和面框之间的 reveal 是 0.003 m(KD/config.yaml:34),K15 测得 min separation -0.05 mm(KD/PROGRESS.md:167)但没说是哪一对,所以"抽屉与柜体零接触"是推断,不在代码里;K13、K14 禁止机器人碰把手以外的东西,所以 drawer.contact_friction 在任务里几乎没有接触可作用,披露了也测不出来;handle.contact_friction 才是拉抽屉真正用到的接触量。给 kitchen 定规则时我建议:PARTIAL = joint 二选一,外加 handle.contact_friction 和 joint 项配成一组二选一;drawer.contact_friction 保持现有规则(不给)。

3.3 agent 循环:每个工具在 Isaac 里做什么

工具 计费 Isaac-only 下做什么 file:line
get_observation 否 base text、described objects、图和相机、disclosed values、fixtures block、单位 prompts/tool_descriptions.yaml:2
get_specification / edit_specification 否 整份 JSON 或 JSON Patch,整体校验;拒绝则原文不动 harness.py:322-370
compile 是 IsaacSimEngine.compile_scene:canonicalize → write_usd → 从盘上重读 → topology 对比。纯 CPU usd-core,不碰 GPU isaac_sim_engine.py:872-891
simulate 是 worker settle op,0.1 到 5.0 s,默认 2.0;报 drift / tilt / speed / penetration / drawer travel。penetration 和 in_contact_with_support 是 CPU 几何算的(最低点对 support,PHYSX_CONTACT_DISTANCE_M = 1e-3),不是 PhysX contact harness.py:417-439;constants.py:219-221, 237;isaac_sim_engine.py:1067, 1132-1133
render 是 worker render op:Kit 默认渲染器,warmup 32 帧,64 subframes,最多 3 次,超时 120 s;Kit 没挂上 hydra engine 立刻拒绝 worker.py:19-21;constants.py:249;CHANGELOG.md:11-20
compare_images 是 先 render 再和 observation 同名 view 做 mean absolute RGB difference 加差分图;尺寸必须一致 harness.py:447-494
look_up_materials 是 材料表一类或全部 harness.py:496-509
check 是 四个内建检查 harness.py:511-525
get_budget / submit 否 预算状态;冻结到 submission/specification.json + manifest.json harness.py:527-562;run_directory.py:153-165

预算 40(CFG/budget.yaml:2);参数错、重复调也计费;用完后计费工具拒绝,edit 和 submit 还能用(instructions.md:11)。

3.4 Isaac 侧:现在有什么,Stage 1 里值得搬什么

环节 现在的 worker Stage 1 里值得搬的
打开 stage open_stage,5 次 update,关 USD writeback,overwrite_gpu_setting(0)(CPU PhysX),attach,走一步,numpy tensor view(worker.py:118-150) 同一序列再加 contact report(S1/isaac/validate.py:104-173;KD/isaac/session.py:60-75)
θ 读回 runtime_read_back:PhysX 的 mass、material、dof damping / friction(isaac_sim_engine.py:902-910);USD 读回 read_back_usd,容差 USD_TOLERANCE (1e-5, 2e-8)(constants.py:76) 机器人 drive 增益按度存(400 和 80 各乘 π/180,S1/isaac/robot.py:166-174),读回时要换算
probes IsaacSimStage:settle / checkpoint / restore / gravity_ramp / apply_force / apply_joint_force / run / run_until(isaac_sim_engine.py:486-725);tilt 和 pull 有 live 测试(tests/test_scene_compilation.py:1473,容差 :126),push 和 drop 没有 V7 决定论自检:restore 后重跑同样步数,位姿差 < 1e-6(S1/isaac/validate.py:230-251, 508)
contacts 没有 contact 代码 PhysxContactReportAPI 阈值 0.0,get_contact_report() → intToSdfPath → pair 计数;robot_contacts 排除 pedestal 对 link0(S1/isaac/validate.py:183-196, 253-268)
session(policy) IsaacSimSession reset / step / state,力接口(isaac_sim_engine.py:728-802) 关节目标 set_dof_position_targets(S1/isaac/validate.py:201);grasp-and-pull 的 Rollout(KD/isaac/validate.py:79-233)
render 默认渲染器 PathTracing 64 spp × 8 subframes,warmup 64(KD/config.yaml:131-134;S1/render/isaac_render.py:73-74);姿态写进 session layer 不动文件(:36);instance_id_segmentation mask(:141)可给 compare_images 做 per-object 比较。注意 我们的集群 节点没有 OptiX 的权重文件(§6 末),搬过来时去噪不可用,只能靠 spp

3.5 submit 和 evaluate

submit 冻结规格;evaluate 先核 lock hash 和 evaluation engine(evaluate.py:113-123),再跑 EvaluationProtocol:checks → pairing → Parameters → Physical Probes(reference readings 有缓存)→ Policy Agreement,写到 evaluation/(:160)。e = d/(d+λ) 的 λ 和 w 来自 calibrate(calibrate.py:35-53)。

3.6 交给 policy teammate 的包

项 s(kitchen,Stage 1 已有) ŝ(我们要产出)
scene.usda /World/Kitchen/Drawer/drawer_slide:prismatic,limits [0, 0.4](HO/scene/scene.usda:1274-1275),damping 2.80644(:1262),friction effort 2.13293(:1276-1277);drawer mass 2.1217(:1120);/World/Robot 引用 ./robot/panda.usd;背景引用 ../simready_cache/...,所以目录必须和 simready_cache 平级(HO/HANDOFF.md:46) 同样的 prim 布局和 joint 名,自己的 θ;机器人引用见 §4 第 3 行
robot/panda.usd 从 franka_description URDF 导入(KD/config.yaml:66) 同一个文件,缓存一次
task ground_truth.json["task"]:kind grasp_and_pull_drawer(KD/sample.py:187),waypoints(q、fingers_m、slide_m),pull.distance_m: 0.20(KD/config.yaml:78),各阶段秒数(:83) 任务定义在 reference 上,不是生成出来的;ŝ 复用同一份
初始状态 demo/states.json 状态 A:抽屉关、home q、手指开 0.04 m(KD/config.yaml:74-75) 同一个 reset
相机 /World/Cameras/{reference_match, workspace};cameras.json 里 OpenCV camera_to_world 加内参(KD/finalize.py:207-236) 同两台相机写进 ŝ
成功判据 K14:0.9 * planned <= final_slide <= upper,slip < 0.01,tracking < 0.01,无其他接触(KD/isaac/validate.py:654-657);K16:松手后位移 < 2e-3(:715-717) package 现有规则是 abs(opening - 0.15) <= 0.02,hold 1.0 s(tasks.py:340;constants.py:160-162):两套判据要选一套(§5 末)
机器人常数 400/80,2000/100,disable_gravity,base (0.655, -0.026, 0),yaw 180,home q(KD/config.yaml:65-75) ŝ 里一模一样;不计入 θ
保密 scene.usda 带 θ,不能给扮演 agent 的任何人(HO/HANDOFF.md:102-104) ŝ 可以公开

4. 代码设计

# 步骤 模块 / 文件 状态 要做的事 量
1 配置 code/private/configs/isaac_cluster.yaml(新,带集群绝对路径,不进公开仓);CFG/isaac.yaml(新,python: "" 占位) new engines 三行加 isaac_sim.gpu,isaac_sim.python = 6.2 worker wrapper 的绝对路径(§2 第 1 行);其余和 sample.yaml 同键 25 行 + wrapper 10 行
2 版本 PKG/constants.py:228;engine.py:388-396 edit "6.2.0.0";engine_pins() 改读握手 1 + 15 行;新 lock
3 compile PKG/scene_compilation/isaac_sim/usd_file.py 的 write_usd port 机器人引用、base pose、pedestal、robot material(S1/isaac/compose.py:28-36, 87, 126-141, 200-212);把手要传 material 才有 CollisionAPI(usd_file.py:300-302 只在传 material 时加,:437-445 现在不传) 120 行;topology 变,新 lock
3b 机器人资产 code/private/tools/import_panda.py(新,要 Kit) port 一次性跑 S1/isaac/robot.py(292 行)的 URDF 导入,产出 robot/panda.usd 放进 data/robot/ 并记 sha256 60 行包装
4 simulate / checks worker.py port contact report op(S1/isaac/validate.py:183-196, 253-268);Execution 的 penetration 可改用 PhysX contact(现在是几何,isaac_sim_engine.py:1132-1133) 80 行
5 probes PKG/evaluation_protocol/physical_probes/* exists push 和 drop 没有 live Isaac 测试,各跑一次 0 行,1 次 GPU
6 observe(kitchen) code/private/overlay/ 里的 kitchen_observation.py(新) new 把 KD 的 observation 转成 package(补 disclosed_parameters.json、manifest.json),并对 kitchen θ 跑 disclose;θ 映射用 KD/truth.py:20-47 最后一列 150 行
7 披露规则 partial_information.py 新 rule 类 new kitchen:joint 二选一不变;handle.contact_friction 按 §3.2 末的建议;drawer.contact_friction 沿用 fixture 跳过 60 行
8 schema PKG/scene_specification/schema.py 等 决策 (a) A:cabinet fixture(schema 0.2),约 15 个模块;B:tabletop 加 pull task;C:kitchen 薄前端(估算见 §5)
9 policy session engine.py 的 Action,worker.py 的 session ops,IsaacSimSession new RobotAction(joint_targets, finger_m) 和 session_robot_step op:set_dof_position_targets(S1/isaac/validate.py:201);scripted drawer pull 走机器人(KD/plan.py 204 行 + Rollout) 200 行
10 calibrate PKG/steps/calibrate.py exists 在 Isaac 里跑;产出新 score_scales.json、task_weights.json、lock、CHANGELOG 0 行,GPU 小时级
11 render worker.py render op optional PathTracing 加 instance mask(S1/render/isaac_render.py) 60 行
12 policy level PKG/policy_level/trainer.py、policy_performance_gap.py exists teammate B 填 LearningSetting、注册 trainer;我们给 §3.6 的包 0 行(我们)
13 grid loop simgenprobe_private(code/private/overlay/README.md 说还没写) new Codex 账号接线、CODEX_HOME、GPU 节点 worker 启动、9 × 4 循环加 repeats、telemetry、.env + setup_env.sh(DESIGN_v0.1.md:1124-1135) 400 行

公开仓 vs 私有 overlay:第 2 到 5、7 到 12 行和 CFG/isaac.yaml 占位进 code/github-code。仓库实际的 pre-commit hook 是 no-internal-names,pattern /home/|/Users/|<path-pattern>|@[[:alnum:].-]+\.(com|edu|org|net)\b(.pre-commit-config.yaml:27-29):它挡得住 $PROJECTS/... 这种路径和邮箱,挡不住 project、<node>、<账号名>、<账号名> 这些名字;DESIGN_v0.1.md:1135 写的那条更宽的 grep 是设计意图,没有落地。两个选项:(1) 推荐:把 hook 的 pattern 补上 <集群和账号的名字>(一行改动,进公开仓前自检);(2) 不动 hook,靠人工把关。第 1 行的真实配置、3b、6、13 行和所有 我们的集群 包装进 code/private:S1/isaac_python_cluster.sh(今天 18:19 ET 写的,指向 ENVS/simgenprobe,:11)、tools/create_simgenprobe_env.sh、tools/jobs/stage1_smoke.sbatch、日志。Stage 1 归档保持只读;parent 今天没有 clone 到 code/stage1,而是用 wrapper 默认的 STAGE1_ROOT=code/private(:12)加一条 code/private/data -> ../github-code/data 符号链接(18:53)让 REPOSITORY_ROOT(S1/config.py:13,即 code/private)下有 data/;输出落在 code/runs/stage1/。

5. 三个关键决策

(a) demo 用哪个场景

选项 有什么 缺什么 工作量
1. tabletop held_out_00 符合 schema;V1 到 V9 今天在 L40S 上通过(smoke job 3506650);抽屉在:size [0.3, 0.25, 0.08],closed_center [0.25, 0, 0.315],行程 [0, 0.25],把手 [0.02, 0.1, 0.015](data/development_scenes/development_00/scene.json 的 fixtures.drawer);Panda 在 (0.4, -0.45)、yaw 90、0.2 m pedestal 上 任务只有 push(S1/ground_truth.py:188 kind: Literal["push"]);把手没有 collider(usd_file.py:437-445);没有拉抽屉的 IK 计划和 rollout;Panda 能否够到桌面下的把手不在代码里(V9 只验 push) 几天,但画面是一张桌子加随机房间
2. kitchen kitchen_drawer_pull_00 拉抽屉已经建好并验过:K14 抽屉拉到 0.1980 m(计划 0.20,KD/PROGRESS.md:166),K16 松手后停在 0.1986 m(:168);今天 L40S 上 DRAWER_TEST pull PASS final 0.1988 m planned 0.200 m;viewer 有 Scripted pull;demo 状态 A/B 不符合 SceneSpecification(14 个错):LLM 生成这一侧要先走第 8 行的 A 或 C;observation 只有 NONE 一级 C 路线 1 到 2 周
3. 两个都要 tabletop 跑锁定的 9 条件协议(分数、λ、w、4 个 LLM);kitchen 做 demo 两套前端 1 + 2

推荐 3,顺序是 kitchen 先、tabletop 后:你描述的 demo 就是 kitchen,拉抽屉在那里已经能跑;tabletop 负责论文里的协议数字,不必为 demo 改它。只能选一个就选 2。

(b) MuJoCo 去到什么程度

选项 做法 代价
1. 彻底删 去掉依赖(pyproject.toml:14);删 mujoco_build.py 448 行、mujoco_engine.py 544 行、mujoco_stage.py 540 行、robot_fixture.py 269 行;改 scene_compilation/__init__.py、generate.py:32, 369;删 cross-engine 测试;Stage 1 finalize 去掉交叉验证;development views 重渲 1 到 2 天重构,外加本来就要的新 lock
2. 只留 CPU 交叉验证 engines.names: [Isaac Sim];agent 的工具和分数里完全没有 MuJoCo;保留 test_isaac_probe_readings_agree_with_mujoco(tests/test_scene_compilation.py:1473)当回归,保留 Stage 1 finalize 的 settle 对照(S1/finalize.py:237-262) 0 行
3. 留作第二编译目标 engines.names: [MuJoCo, Isaac Sim],只给 Isaac 打分,Engine Agreement 比两个文件 与"一律 Isaac"相悖

用户 11-04 23:1x ET 拍板:选 1,彻底删,这个项目只用 Isaac(论文正文也只写 Isaac Sim,body/method.tex 的 3.1 和 3.2)。执行上和 T2 的版本钉合并成一次 lock 切换(T2b),顺序:先 kitchen demo 线,再 T2 + T2b。

(c) 交互编辑

选项 做法 代价
1. 只用 viewer 面板 Panda Control(关节滑条、夹爪、IK Go、Play / Pause / Reset,S1/isaac/robot_panel.py:1-8)和 Kitchen Drawer(Scripted pull、Reset drawer、Travel limits 三个按钮,KD/isaac/drawer_panel.py:169-171;成功 = 0.9 * planned <= final <= limits[1] + 1e-3,:146)。什么都不写回文件(S1/isaac/stream_scene.py:8-9),job 打开的是副本(HO/jobs/kitchen_webrtc.sbatch:17-19) 0 行。Mac 上只装 Isaac Sim WebRTC Streaming Client(NVIDIA 的 6.2.0 下载页列的是 2.0.0,有 macOS x86_64 和 aarch64 两个 .dmg),加 Python 3.8+ 和 udp_tcp_relay.py(S1/README.md:181-183)。集群侧的 WebRTC 插件问题已修(§6 末)
2. 同步回代码 dump_theta.py(usd-core)读五个 θ 属性:physics:mass(/World/Kitchen/Drawer/drawer)、drive:linear:physics:damping 和 physxJointAxis:linear:{static,dynamic}FrictionEffort(drawer_slide)、physics:{static,dynamic}Friction(/World/PhysicsMaterials/{drawer,handle})(HO/scene/scene.usda:1120, 1262, 1276-1277, 58-60, 69-71)→ theta_edit.json → KD/sample.py 加 --theta-json(现在 θ 只来自 seed)→ build → render → finalize。改的是隐藏侧 约 200 行,动 teammate A 的代码;UI 里改 mass 不会更新惯量,所以只能经 sample 回去,不能直接用存下的 USD
3. 编辑 ŝ 而不是 s 在 viewer 里改生成场景再存 harness 没有 USD 回 spec 的路,不在代码里

推荐 1,外加 2 的只读一半(dump_theta.py,便宜,能把你在 UI 里的试验记成 JSON);完整同步只在你真要手调 reference 时做,因为每次手改都打破 seed 决定论、finalize 的 stage 对照和渲染哈希。关于 Mac 要装什么:Isaac Sim 本体只有 Linux x86_64 / aarch64 和 Windows x86_64 的包(NVIDIA 6.2.0 下载页,不在代码里),Mac 跑不了;Isaac Lab 只在集群上以 --no-deps 装,为的是它的 kit 文件(S1/README.md:122-124;S1/isaac/launch.py:20-21),Mac 完全不用装。装法细节在 RUN_PLAN_and_MAC_BRIEF 那个 tab。

决策之外还要你点头的一件小事:机器人 demo 的成功判据用 K14(0.9 × 0.20 = 0.18 m 到上限)还是 package 的 0.15 ± 0.02 m 加 1 s hold。我的建议:demo 和 teammate B 用 K14,Policy Agreement 的力式 scripted policy 保持原规则,两者互不影响。

6. 任务清单(你的部分)

"完成"一栏写的是能检查的东西。估时不含排队。

本周

# 任务 依赖 估时 完成的标志
T1 simgenprobe env(Isaac Sim 6.2.0.0 + 我们的包)。已完成:第 2 次尝试 18:21:45 到 18:39:39 EST(code/private/tools/logs/create_simgenprobe_env.log 首末行;第 1 次死在 tinyobjloader==2.0.0rc13 无解,create_simgenprobe_env.attempt1.log:94-95,已加 --prerelease=allow);version('isaacsim') 6.2.0.0。requirements.txt:10 拉进来的 usd-core==26.8(log :394, 414)18:52 已拿掉:importlib.metadata 报 PackageNotFoundError,site-packages/pxr/ 只剩 usd-exchange 3.0.1 的 .pyi 桩(pxr/Usd/ 只有 __init__.pyi),Kit 启动前 from pxr import Usd 得到 Usd.__file__ 为 None 的空模块;Stage 1 脚本无碍(build_scene.py:68-70 在 start_app 之后才 import),CPU 侧 pxr 留在 ENVS/848x。hook simgenprobe.sh 18:52 写好(按驱动版本读 848x-isaac 的 615 set,:27-30)。验收不用 code/private/isaac/env_fix_1026/check_env.sh:它探的是 6.0 env(:5 source isaac_env_848x.sh,:11-12 用 848x-isaac 的 loader 和 python)。smoke job 3506650(<node>,L40S,615.71.09,18:56:42 到 19:10:09 EST,COMPLETED)已证明 Kit 6.2 在 L40S 上有 RTX 设备:dlss/supported=True,STAGE1_BUILD passed=True,STAGE1_RENDER passed=True 无 已完成 剩一项:我们的 worker 在 L40S 上回一帧 render(要 T2 的 wrapper 和版本钉)
T2b 彻底删 MuJoCo(决策 (b) 选 1):去掉依赖(pyproject.toml:14)、删 mujoco_build.py / mujoco_engine.py / mujoco_stage.py / robot_fixture.py、改 scene_compilation/__init__.py 和 generate.py:32, 369、删跨引擎测试、Stage 1 finalize 去掉 settle 对照、六个 development bundle 的 views 用 Isaac 重渲、calibrate 在 Isaac 里重跑(T6);和 T2 同一次换 lock T2 1 到 2 天 pip show mujoco 在两个 env 里都不再是依赖;grep -ri mujoco src tests 为空;全套测试在 Isaac 下通过;新 lock
T2 版本钉和配置:constants.py:228 改 6.2.0.0(握手 isaac_sim_engine.py:251-256);写 6.2 worker wrapper 和 code/private/configs/isaac_cluster.yaml,公开仓 CFG/isaac.yaml 占位;从 ENVS/848x 跑 pytest --run-isaac --isaac-python <6.2 wrapper 绝对路径> --isaac-gpu 0 -m isaac(形式同 code/private/isaac/env_fix_1026/run_pytest_v013.sh:10-12;engine fixture 要 MuJoCo,所以 pytest 本身在 848x env 里跑)。只给 -m isaac 不行:isaac 标记 "runs only with --run-isaac"(tests/conftest.py:20-23),还要 --isaac-python 和 --isaac-gpu(:30-41),缺了就全部 skipped、exit 0(test_scene_compilation.py:1478-1479 的 assert 只在测试真跑到时触发) T1 0.5 天 pytest 摘要里 test_isaac_probe_readings_agree_with_mujoco 是 PASSED 不是 SKIPPED;新 lock
T3 Stage 1 tabletop 在 我们的集群 走通。已做(布局见 §4 末):sample 18:53;build V1 到 V9 PASS 和 render 两张图由 smoke job 完成(code/runs/stage1/stage1/held_out_00/{robot/, scene.usda, validation.json, renders/})。没做:verify_views、finalize、observe × 3(命令见 RUN PLAN A4) T1 剩约 0.5 h CPU renders/verify.json verified=True;finalize.json passed;NONE / PARTIAL / ALL 三个 observation package
T4 kitchen 在 我们的集群 走通。已做:simready 取到 763M(18:55);handoff 场景拷成 $K/kitchen_drawer_pull_00/(HO/HANDOFF.md:49-50 的目录名;scene.usda 与 HO/scene/scene.usda sha256 相同);sample 的 ground_truth.json、scene_spec.json、scene_physics.usda 也写进了同一目录(18:55);viewer 两个 test 在副本上 PASS。没做:build(会覆盖 scene.usda)→ render → verify → finalize(RUN PLAN A5 的选项) T1 0.5 天 finalize.json passed,observation/kitchen_drawer_pull_00/ leak scan 0 findings
T7 机器人进 write_usd,把手加 collider(§4 第 3、3b 行) T1 1 到 2 天 agent 的 render 里有 Panda;read_back_usd 无 findings;Engine Agreement 通过
T5 第一次 Isaac-only harness 跑 held_out_00:observe + generate,先 client: scripted,再 client: codex,预算 40 T2, T3, T7 0.5 天 run 目录里有 submission/specification.json,events.jsonl 里每次 compile / simulate / render 的 engine 都是 Isaac Sim
T6 在 Isaac 里 simgenprobe calibrate:新 score_scales、task_weights、lock、CHANGELOG;再 evaluate T5 的 run T2, T7(放在 T7 后,省一次切 lock) 1 个 GPU 日(Isaac 里 calibrate 的时长没测过) lock verify 通过;T5 的 run 有分数

smoke job 3506650 暴露的两件事(都不在代码里,要定):

  1. libomni.kit.livestream.webrtc.plugin.so 加载失败(libatomic.so.1: cannot open shared object file,节点没有 /usr/lib64/libatomic.so.1):已修并复查。env 的 conda libgcc 自带 lib/libatomic.so.1,19:13 ET 加了 lib/extra/libatomic.so.1 符号链接并写进 hook 的 LD_LIBRARY_PATH(simgenprobe.sh:29, 35;lib/glvnd/ 18:52 起就有 5 个 glvnd 符号链接,不是空目录)。复查 job 3507469(<node>,2 min,default 渲染模式):插件错误 0 条,omni.kit.livestream.webrtc-10.7.3 startup,STAGE1_STREAM ready ... startup=70.6s,DRAWER_TEST summary passed=True。
  2. optixDenoiserCreate(...) failed. Optix Error: OPTIX_ERROR_INTERNAL_ERROR:robot test 6170 条,drawer test 1639 条,isaac_render 353 条,build 0 条。三处都开着 /rtx/pathtracing/optixDenoiser/enabled=True(stream_scene.py:67;isaac_render.py:103, 125;KD/isaac/render.py:96, 119),OptiX 库来自 615 set(nvidia-userspace/615.71.09/lib/libnvoptix.so.615.71.09)。后果:reference 渲染是没去噪的 512 spp(render.json:spp 64,totalSpp 512),front_right.png 肉眼可见细颗粒但结构完整,render.py 自己的 mean/std 检查过了,verify_views 还没跑;viewer 的 PathTracing 模式同样没去噪,而 dlss/supported=True,所以 viewer 先试 default 模式(和 README :221-224 在 队友的集群 上的结论相反)。原因已查明:log 里同时报 Unable to load denoiser weights: Could not open optix denoiser weights file /usr/share/nvidia/nvoptix.bin,节点没有这个文件,路径写死、没有环境变量可改(NVIDIA 论坛只有 root 放文件或容器 bind 两种办法)。verify_views 19:1x ET 在两张 tabletop view 上跑过:噪声门 PASS,verified=True,reference 渲染不动;viewer 走 default 模式(复查 job 3507469 就是 default,DLSS 可用)。

下周

# 任务 依赖 估时 完成的标志
T8 决策 (a) 的实现:C 路线(kitchen 薄前端:agent 编辑 kitchen spec,usd_scene.write_scene_physics 编译,K1 到 K17 当 checks,§4 第 6、7 行的 observation 和披露) T4 1 到 2 周 三级 observation 下 agent 各交一个能过 K1 到 K17 的 kitchen ŝ
T9 机器人驱动的 session 和走 Panda 的 scripted drawer pull(§4 第 9 行) T2 2 到 3 天 在 s 和一个 ŝ 里拉抽屉都按 K14 成功
T10 给 teammate B 的包(§3.6)和 LearningSetting 的三项 T9 我们 1 天 B 报出 §1 表的四个成功率
T11 simgenprobe_private 的 9 × 4 循环加 repeats,L40S scavenger T5, T6 2 天 36 个 run 目录各有 submission 和 evaluation
T12 demo 录制:rollout 在 s 和 ŝ 里逐帧 Replicator 渲染,PNG 回 Mac 编 H.264(<node> 没有 ffmpeg) T9 1 天 两段同机位视频
T13 给你看的 viewer:kitchen_webrtc.sbatch 的 我们的集群 版(改法在 RUN PLAN A6:L40S 的 gres、去掉 SIF 和 NGX bind、wrapper 绝对路径、主机名 .<cluster-domain> 而不是 :34 的 .<their-domain>);节点侧已写好 code/private/tools/jobs/stage1_live_viewer.sbatch(不用再改 Viet 的),libatomic 已修(复查 job 3507469);剩 Mac 装客户端 T4 0.5 天(可提前到本周) job log 里没有 failed to load native plugin ... livestream.webrtc,有 STAGE1_STREAM ready;Streaming Client 里按 Play、Scripted pull,抽屉开到约 0.20 m

7. 和 midpoint report 的对应

报告部分 文件 喂它的任务
Question body/question.tex:7-12 T10:fidelity 能不能转成 policy 表现
3.1 Reference Scenes and Input Conditions body/method.tex,\subsection{Reference Scenes and Input Conditions} T3、T4(Isaac 里的 reference),§3.2 的披露表(T5、T8)
3.2 Scene Generation body/method.tex,\subsection{Scene Generation} T5、T7、T8、T11
3.3 Evaluation Protocol body/method.tex,\subsection{Evaluation Protocol} T6(λ、w 在 Isaac 重拟合),T9(Policy Agreement 走机器人)
Evaluation Plan body/evaluation.tex T11(9 × 4 LLM),T10(G_t)
Risks body/risks.tex 的三条 第一条的 fallback 就是 kitchen 这种指定场景;第三条对应 T10 的子集
Figure 1 figures/fig_pipeline_P1m.pdf(body/method.tex:4) T2 之后把 "engine" 改成单数的 Isaac Sim

路径:GT848 = $SCRATCH(用 S1/config.yaml 加 github-code 的模板跑 sample,attempts 1,isaac_sim_target 6.2.0.0);今天 smoke 之后 code/runs/stage1/stage1/held_out_00/ground_truth.json 是同一 seed 加 build 补上的 isaac 和 robot 字段。

Stage 1 on 我们的集群: 运行计划 + Mac 观看简报

2026-11-04 18:4x ET 写, 19:1x ET 按审查修订 (21 条) 并更新现状。缩写: 848x = $848X; S1 = 848x/code/private/stage1_reference (只读, 等于 branch step_1_hidden_reference_scene_generation @ e5dcd30); HO = 848x/code/private/_asset/kitchen_drawer_pull_handoff_extracted/kitchen_drawer_pull_handoff; ENVS = $ENVS; K = 848x/code/runs/stage1/kitchen_drawer_pull。

19:3x ET 更新 (主会话): libatomic 已修并复查 (A8 第 1 行); OptiX 原因查明, tabletop 的 verify_views 已 PASS (A4, A8 第 2 行); live viewer 和 headless 自检的 我们的集群 版 sbatch 已写好 (A6)。

A-1 Mac 上看 Isaac Sim / Isaac Lab 的几种办法(2026-11-04 21:2x ET 加)

除了 PART B 那条「ssh 隧道 + Isaac Sim WebRTC Streaming Client」,Mac 上还有这几条路,按实用程度排:

  1. 浏览器版 WebRTC 客户端(6.2 官方有)。NVIDIA 给 6.2 提供了一个 Chromium 浏览器直接看的 web client,用 Docker Compose 和 Isaac Sim 一起部署,Mac 什么都不用装(6.2 Livestream Clients,6.2 release notes 还提到一个 isaac-sim-web-viewer 的预构建镜像)。障碍在集群侧:我们的集群没有 Docker,只有 Apptainer,要把那个 web viewer 镜像转成 .sif 再接到我们 headless 的 Isaac 上,而且浏览器的 WebRTC 媒体流(UDP)过不了 ssh 隧道,要么节点上再起一个 TURN 服务走 TCP,要么试让信令把服务端地址报成 127.0.0.1 让浏览器把媒体发到本机的 relay(没人试过)。乐观半天、悲观两天,排在 kitchen 线之后做。
  2. 不交互,只看图和视频。节点上 stream_scene.py --capture-dir --capture-every 或 Replicator 逐帧渲染,PNG/MP4 放进 vis link(就是任务清单里的 T12 demo 录制)。Mac 零安装,适合给老师和队友看结果,不适合调参。
  3. Isaac Lab 的训练过程,和 Isaac Sim 是同一个屏幕:Isaac Lab 的 AppLauncher 加 --livestream 2 就把训练中的 viewport 走同一个 WebRTC 流(Isaac Lab app docs),Mac 端还是那个 Streaming Client;一个 Isaac 实例只能接一个客户端。训练曲线走 TensorBoard 或 W&B,那是普通的 ssh 隧道,和以前连 Jupyter 一样。
  4. 离线看 USD 几何:把 scene.usda(加 robot/ 和 simready_cache)拷到 Mac,用 Blender 的 USD 导入打开,能看布局、尺寸、材质贴图,看不到 PhysX 参数也不能驱动机械臂。查几何对不对够用。
  5. VNC 远程桌面跑完整 GUI:节点上 Xvfb + VirtualGL + TurboVNC。能用但画面慢、搭起来麻烦,Isaac 官方早就用 WebRTC 替代了这条路,不建议。
  6. 换一台有 RTX 卡的 Linux 或 Windows 机器本地装 Isaac Sim,或者 NGC 容器在云上跑再流到 Mac:都不是 Mac 本机,而且后者最终也是 WebRTC。

结论:现在这条隧道路线就是官方推荐、也是集群上最省事的;想零安装就等第 1 条的 Apptainer 版试出来;给别人看结果用第 2 条。

PART A 在 我们的集群 上把 Stage 1 跑一遍

A0 现状 (19:1x ET)

项 状态 证据
6.2 env ENVS/simgenprobe 建好 848x/code/private/tools/logs/create_simgenprobe_env.log 首行 18:21:45 EST start; free: 137G, 末行 18:39:39 EST done; env size: 23G; free: 71G; version('isaacsim') 6.2.0.0, isaaclab 3.0.0, usd-exchange 3.0.1, usd-core PackageNotFoundError (18:52 拿掉, 见 A1)
activation hook 有 ENVS/simgenprobe/etc/conda/activate.d/simgenprobe.sh (18:52): 按 /sys/module/nvidia/version 选 848x-isaac 里的 615.71.09 set (:17-30), 只认 615.71.09 / 610.57.04, 其他报 ERROR 不设变量 (:38-41); OPTIX_CACHE_PATH = .cache/optix-simgenprobe (:43), TMPDIR 和 EULA (:44-45)。simgenprobe/lib/glvnd/ 有 5 个 glvnd 符号链接 (18:52 建), lib/extra/libatomic.so.1 (19:13 加, 给 WebRTC 插件), 两个目录都在 hook 的 LD_LIBRARY_PATH 里 (:29, 35)
wrapper 有 S1/isaac_python_cluster.sh: :11 ENV, :12 STAGE1_ROOT 默认 code/private, :13 SIMGENPROBE_SRC 默认 github-code/src, :16 source hook, :18 TMPDIR 默认 $SCRATCH, :20 ISAAC_GPU 转 CUDA_VISIBLE_DEVICES, :21 PYTHONPATH, :22 cd, :23 exec
布局 选项 2 (直接用 S1) code/private/data -> ../github-code/data 符号链接 (18:53), 所以 S1/config.yaml:5 的 template_scene 能解析; REPOSITORY_ROOT = code/private (S1/config.py:13), 输出 ../runs/stage1 = 848x/code/runs/stage1 (config.yaml:4)。code/stage1 clone 没做
tabletop held_out_00 sample, build, render 完成 code/runs/stage1/stage1/held_out_00/: scene.json, scene_physics.usda, ground_truth.json (18:53, sample); robot/, scene.usda, validation.json (smoke: V1 到 V9 PASS, STAGE1_BUILD passed=True steps=2761, build exit 0); renders/{front_right,top_down}.png, 两个 _instances.npz, render.json (passed: true, engine_version 6.2.0.0, PathTracing, spp 64, totalSpp 512, STAGE1_RENDER passed=True)。verify / finalize / observe 没跑
kitchen simready 完成; 场景目录是选项 A 加选项 B 的第一步 $K/simready_cache/ 763M (18:55, tools/logs/simready_download.log); $K/kitchen_drawer_pull_00/: scene.usda 和 robot/ 来自 handoff (scene.usda sha256 ab10b950… 与 HO/scene/scene.usda 相同), ground_truth.json, scene_spec.json, scene_physics.usda 来自 sample (18:55)。build / render / verify / finalize 没跑
smoke job 3506650 COMPLETED 00:13:29, <node> (L40S, 615.71.09), 18:56:42 到 19:10:09 EST 脚本 848x/code/private/tools/jobs/stage1_smoke.sbatch, log code/runs/stage1/logs/stage1-smoke-3506650.log: robot test exit 0, STAGE1_STREAM ready ... startup=254.2s, ROBOT_TEST panel PASS; drawer test exit 0, startup=88.2s, DRAWER_TEST attach PASS limits=(0.0, 0.4000000059604645), DRAWER_TEST pull PASS final 0.1988 m planned 0.200 m, best 0.1988 m, 1539 frames, sim 17.14 s, DRAWER_TEST reset PASS slide 0.00000 m, DRAWER_TEST summary passed=True, scene copy not saved, hidden files unchanged; 两次都 /rtx-transient/post/dlss/supported=True
同名 job 3506632 PENDING, 永远不会起 reason Job's QOS not permitted to use this partition (scavenger allows scavenger not normal): 第一次提交漏了 --qos=scavenger。要不要取消由你定, 我不动它
两个问题的现状 见 A8 第 1、2 行 WebRTC 插件: 已修, 复查 job 3507469 (19:13 到 19:15 ET) 插件错误 0 条, STAGE1_STREAM ready ... startup=70.6s; OptiX denoiser: 权重文件路径写死在 /usr/share/nvidia/nvoptix.bin, 改不了, 但 tabletop 两张 view 的 verify_views 已 PASS (verified=True)
磁盘 project 卷接近满, home 很小 构建期间 free 从 137G 掉到 71G (log 首末行), 现在回到 112G: 脚本指定的 UV_CACHE_DIR=$SCRATCH 和 PIP_CACHE_DIR=.../pip-cache (create_simgenprobe_env.sh:11, 13) 19:11 ET 已不存在

A1 Step 1: 6.2 env (已完成)

脚本 create_simgenprobe_env.sh 18-31 行: conda env (python=3.12) → uv pip install "isaacsim[all,extscache]==6.2.0.0" pydantic pyyaml pillow scipy (flags 同 S1/README.md:120-121, 加 --prerelease=allow; 第一次因 tinyobjloader==2.0.0rc13 是预发布版而解析失败, create_simgenprobe_env.attempt1.log:94-95) → isaaclab==3.0.0 --no-deps, 只为 isaaclab.python.headless.kit (S1/isaac/launch.py:20-21) → -r github-code/requirements.txt -e github-code[dev,mcp,robot,render], 失败退到 --no-deps -e。

usd-core 的风险发生过又处理了: github-code/requirements.txt:10 固定 usd-core==26.8, 装进去了 (log :394 + usd-core==26.8, :414); 18:52 site-packages 被改后 pip list 里没有它, importlib.metadata 报 PackageNotFoundError; site-packages/pxr/ 只剩 usd-exchange 3.0.1 的 .pyi 桩 (pxr/Usd/ 只有 __init__.pyi), 裸 6.2 env 里 Kit 启动前 from pxr import Usd 得到空 namespace 模块 (Usd.__file__ 为 None)。Stage 1 脚本无碍 (build_scene.py:68-70 在 start_app 之后才 import), smoke 的 build 和 render 都过了; CPU 侧的 pxr 用法 (verify, finalize, observe, 我们的 compile) 必须留在 ENVS/848x。

hook: 实际写的不是 source 848x_isaac.sh, 而是把它的规则抄了一份, 库集仍读 848x-isaac (simgenprobe.sh:4-6, 27-30), 615 set 只维护一份, OptiX cache 单独 (:43)。simgenprobe/lib/glvnd/ 放着 libEGL.so.1, libGL.so.1, libGLX.so.0, libGLdispatch.so.0, libOpenGL.so.0 五个符号链接 (18:52); lib/extra/libatomic.so.1 (19:13) 给 WebRTC 插件 (A8 第 1 行, 已修)。

时间与磁盘: 6.2 的 uv 步骤 18:21:45 到 18:39:39 共 18 min (6.0 的 pip 步骤 33 min, 848x/tools/build_isaac_env.log:80, 122); env 23G (log), du 25G; 构建期间占用峰值约 66 GB (137G 到 71G), 其中 cache 约 43 GB, 现已释放。再建一次按约 65 GB 临时空间预算。

A2 Step 2: wrapper 与目录布局

S1/isaac_python_cluster.sh (:10-23): 不用 apptainer (glibc 2.39, wheel 只要 2.35, S1/isaac_python.sh:3), source hook, EULA, TMPDIR 默认 $SCRATCH (:18; 原版是每用户子目录 isaac_python.sh:20-22, 想分开就传 TMPDIR=$SCRATCH), ISAAC_GPU 转 CUDA_VISIBLE_DEVICES (只给交互 shell 用; Slurm job 里别设, Kit 会警告 Setting CUDA_VISIBLE_DEVICES can lead to undesired behavior, cgroup 已经限定了那张卡, 三份 sbatch 19:16 起都不设), PYTHONPATH=$SIMGENPROBE_SRC:$STAGE1_ROOT, cd $STAGE1_ROOT 后 exec python。

布局 (相对路径以 stage1_reference/ 的父目录为 REPOSITORY_ROOT, S1/config.py:13, 108):

  1. 已采用: STAGE1_ROOT=code/private (wrapper 默认), code/private/data -> ../github-code/data 链接 (18:53) 补上 template_scene (config.yaml:5); 输出 code/runs/stage1/。github-code 与 S1 都不被写 (sample 只读模板)。
  2. 备选: git clone --branch step_1_hidden_reference_scene_generation 848x/code/github-code 848x/code/stage1 (46M 含 .git; branch 的 src/ data/ configs/ prompts/ 与 main 无差异), 不需要链接。只有想在副本里改 Stage 1 (A9 第 2 项的选项 2) 才值得做。

CPU 环境 ENVS/848x (Python 3.11.16; simgenprobe editable, pip show 的 Version 0.1.0 是安装时的 metadata, simgenprobe.__version__ 是 0.1.3, lock 读的是后者, 无害; mujoco 3.12.0, pxr), conda activate 848x 以拿到 mujoco_gl.sh 的 GL 变量。下文:

R=$PRIVATE
PY=$ENVS/848x/bin/python
IPY=$PRIVATE/stage1_reference/isaac_python_cluster.sh

$IPY 的默认值已经指向 code/private 和 github-code/src, 交互 shell 里不用再传环境变量; sbatch 里要写字面绝对路径, 不要引用 shell 变量 (stage1_smoke.sbatch:18 就是这么写的; --export=ALL 只带已 export 的变量)。

A3 sbatch 头 (L40S scavenger)

#SBATCH --partition=scavenger --qos=scavenger
#SBATCH --gres=gpu:nvidia_l40s:1
#SBATCH --cpus-per-task=4 --mem=32G
#SBATCH --time=<每个 job 自己的>
#SBATCH --no-requeue
#SBATCH --output=$RUNS/stage1/logs/%x-%j.log

依据: 分区 AllowQos=scavenger, 漏写 --qos 就是 3506632 的下场; --account 可不写 (3506650 没写, 起了); sinfo 的 GRES 串 gpu:nvidia_l40s:4 (RTX 6000 Ada: gpu:nvidia_rtx_6000_ada_generation:8); 时限按 job: viewer test 00:50:00 (kitchen_viewer_test.sbatch:13), live viewer 04:00:00 (kitchen_webrtc.sbatch:12), smoke 给了 01:30:00 实跑 13.5 min; 分区 PreemptMode=REQUEUE, 所以 --no-requeue; logs 目录已有。不用 H200/H100: NVIDIA 要求页写 "GPUs without RT Cores (A100, H100) are not supported", 是"不支持"不是"不能" (10-26 我们的 worker 在 H200 上回过 development_00 的一帧, CHANGELOG.md:15-17); 排除它们的实际理由是 scavenger 里 H200/H100 job 起不来。19:0x ET L40S 多台(少数在 drain), 其余 mix/alloc, 有空卡。GPU job 开头自检: cat /sys/module/nvidia/version (必须 615.71.09), viewer 再加 ss -ltnu | grep -E ':(49100|47997|47998) '。

L40S 探针已由 smoke job 做掉, 顺序正确 (simready → 复制场景 → 探针: 场景引用 ../simready_cache/..., HO/scene/scene.usda:1347,1761,1899,2124, 缺 MDL 背景渲成 error-red, KD/PROGRESS.md:81-82): STAGE1_STREAM render mode=PathTracing ... /rtx-transient/post/dlss/supported=True, 冷启动 254.2 s, 同节点第二次 88.2 s。要再探别的节点就复制场景到 $K/view-<x>/ (kitchen_webrtc.sbatch:17-19 的做法, 别开 hidden 文件) 后跑 $IPY stage1_reference/isaac/stream_scene.py --scene $K/view-<x>/scene.usda --probe-seconds 30 --no-robot-panel, 读 STAGE1_STREAM render mode= 和 fps= (stream_scene.py:172-173, 232)。

A4 桌面 held_out_00 (seed 848)

已跑: sample (18:53, CPU), build 和 render (smoke), verify (19:1x, PASS)。剩两步, 都是 CPU (verify 那行留着做记录):

cd $R
$PY -m stage1_reference.render.verify_views --config stage1_reference/config.yaml       # renders/verify.json
MUJOCO_GL=egl $PY -m stage1_reference.finalize --config stage1_reference/config.yaml    # finalize.json + bundle
cd $REPO                         # observe 的相对路径按 cwd 解析
MUJOCO_GL=egl $PY -m simgenprobe observe --config $R/stage1_reference/observe_held_out.yaml

observe 为什么换目录: load_config 不解析相对路径 (PKG/config.py:157-183), agent.models: configs/models.yaml、protocol.budget: configs/budget.yaml 都按 cwd 打开, code/private 下有 data 链接但没有 configs/; 从 github-code 跑, held_out_root: ../runs/stage1/held_out 和 output_dir: ../runs (observe_held_out.yaml:13, 16) 同样落到 code/runs/, github-code 本身不被写。三个 physical level 各跑一次: S1 只读, 把 observe_held_out.yaml 复制三份到 code/private/configs/, :9 分别填 NONE 的原值、partial information、all reference physical parameters。命令和时间来自 README.md:50-61。证据:

步 文件 (code/runs/stage1/stage1/held_out_00/) log 行 状态
sample scene.json, scene_physics.usda, ground_truth.json (isaac: null, isaac_sim_target: 6.2.0.0; ground_truth.py:274, sample.py:189) 跑两次 byte-identical (tests/test_stage1_reference.py:114-125) 完成
build robot/panda.usd, scene.usda, validation.json; ground_truth 补上 robot links/joints 和 isaac (build_scene.py:104-146) V1 PASS 到 V9 PASS, STAGE1_BUILD passed=True steps=2761, exit 0 (:147-153) 完成
render renders/render.json passed: true, front_right.png, top_down.png, 两个 _instances.npz STAGE1_RENDER passed=True (isaac_render.py:181); 353 条 optixDenoiserCreate 错误 (A8 第 2 行) 完成, 未去噪
verify renders/verify.json engine: Isaac Sim 6.2.0.0; verified=True (verify_views.py:354) 完成 (19:1x ET, CPU): 全部 PASS, verified=True
finalize finalize.json; bundle code/runs/stage1/held_out/held_out_00/{scene.json, manifest.json, views/} 每行 PASS, bundle: held_out/held_out_00 (views: front_right, top_down) (finalize.py:287-291); 含 MuJoCo settle 交叉检查 (:237-262) 待跑
observe code/runs/observations/held_out_00/<combination slug>/package/{base_text.md, disclosed_parameters.json, cameras.json, views/, manifest.json} 和旁边的 record.json (steps/__init__.py:27; observation.py:41-47, PACKAGE_DIRECTORY :46; build.py:175) 条件见 observe_held_out.yaml:8-9; engines.names: [MuJoCo] (:19): EngineSet 仍被构造 (observe.py:66-68), 但两视图已 ship, 不渲染 (build.py:192-202) 待跑 × 3

A5 kitchen kitchen_drawer_pull_00 (seed 2611)

cd $R; K=$RUNS/stage1/kitchen_drawer_pull
# 已做: simready (763M); handoff 场景 -> $K/kitchen_drawer_pull_00/ (HANDOFF.md:49-50 的目录名); sample (同一目录)
$IPY stage1_reference/kitchen_drawer_pull/isaac/build.py     # 选项 B: GPU, 约 2 min; 覆盖 scene.usda 和 robot/, 写 demo/
$IPY stage1_reference/kitchen_drawer_pull/isaac/render.py    # GPU, 约 1.5 min
$PY -m stage1_reference.kitchen_drawer_pull.verify_views
MUJOCO_GL=disable $PY -m stage1_reference.kitchen_drawer_pull.finalize
  • 目录名必须是 kitchen_drawer_pull_00, 不是 handoff_00: 两份 sbatch 写死了它 (kitchen_viewer_test.sbatch:17 HIDDEN=$ROOT/kitchen_drawer_pull_00, 不接受参数; kitchen_webrtc.sbatch:16 默认 .../kitchen_drawer_pull_00/scene.usda, 可用 $1 覆盖), sample 的 hidden_dir 也是 root / scene_id (KD/config.py:257), parent 的 stage1_smoke.sbatch:22 同名。任何场景副本都要是 $K 的直接子目录 (../simready_cache 引用, sample 读 simready_cache/simready_assets.json, sample.py:222)。
  • 现在这个目录里 A 和 B 混着: scene.usda / robot/ 是 handoff 的, ground_truth.json / scene_spec.json / scene_physics.usda 是 sample 的。选项: (1) 推荐: 直接跑 build 重建 (覆盖 scene.usda; 之后 render / verify / finalize 都有依据; 重建是否与 handoff 逐字节相同, 跑完 sha256sum 对 ab10b950… 一比就知道); (2) 保留 handoff 的 scene.usda 只做 viewer: render 需要 ground_truth.json 和 demo/states.json (render.py:36), 后者由 build 写, 所以不重建就没有 bundle 和 observation; (3) 两者都要: sample --scene-id <别名> 换名重建 (KD/README.md:44), 但 sbatch 里写死的名字要跟着改。
  • 证据: build K1 PASS 到 K17 PASS, KITCHEN_BUILD passed=True steps=… (build.py:163-171); render renders/{benchmark,demo}/{reference_match,workspace}.png, render.json (render.py:36), KITCHEN_RENDER passed=True (:195); verify KITCHEN_VERIFY passed=True (verify_views.py:274, 引擎版本门 :151-153); finalize 四个 gate 和 leak_scan 都 PASS, KITCHEN_FINALIZE published=True (finalize.py:442-450), 产物 $K/bundle/kitchen_drawer_pull_00/ 和 $K/observation/kitchen_drawer_pull_00/{base_text.md, cameras.json, views/} (config.py:259-267)。simready 证据: 四行 … CC-BY-4.0 verified N files (simready.py:236-239)。
  • kitchen 的 render 同样开着 OptiX denoiser (KD/isaac/render.py:96, 119), 在 <node> 上它创建失败 (A8 第 2 行), verify 过不过要看 KITCHEN_VERIFY。

A6 viewer test 与 live viewer

我们的集群 版 sbatch 已写好, 不用再改 Viet 的: 848x/code/private/tools/jobs/stage1_viewer_check.sbatch (headless 自检, 2 min) 和 stage1_live_viewer.sbatch (live viewer: L40S scavenger, 4 h, 场景副本放在 $K/view-<job>/, 自动识别 kitchen 加 --drawer-panel, PUBLIC_IP 默认 127.0.0.1, RENDER_MODE 默认 default, 节点端 relay 自动起, log 打印 Mac 端两条命令; 传 tabletop 的 scene.usda 路径就看 tabletop)。

  1. headless test: 已由 smoke 完成 (A0), 19:13 ET 又用 stage1_viewer_check.sbatch 跑了一次 (job 3507469, 2 min)。要重跑: sbatch $PRIVATE/tools/jobs/stage1_viewer_check.sbatch。log 应有 ROBOT_TEST ... PASS, DRAWER_TEST summary passed=True, scene copy not saved, hidden files unchanged (HANDOFF.md:70-71; sbatch :29-32)。启动时长 (L40S, 这个 env): 冷 254.2 s, 同节点第二次 88.2 s (smoke log); README :192 的"约 1 min"是 队友的集群 的数; 驱动换版本后 shader cache 要重建 (10-26 从 610 到 615 的经验, gpu_isaac_1026.md:195)。
  2. live viewer: libatomic 已修 (A8 第 1 行)。提交 PUBLIC_IP=127.0.0.1 sbatch --export=ALL $PRIVATE/tools/jobs/stage1_live_viewer.sbatch (默认就是 127.0.0.1, 可省)。就绪行 STAGE1_STREAM ready signal=49100/tcp stream=47998/udp public_ip=127.0.0.1 startup=…s (stream_scene.py:174-179); Mac 连上时 relay 打印 node: tunnel from (...) (udp_tcp_relay.py:158)。渲染模式: 先用 default (<node> 上 dlss/supported=True, 615 set 带 NGX); PathTracing 在这台机器上 OptiX denoiser 失败, 会是颗粒画面 (RENDER_MODE=PathTracing, sbatch :25), 和 README :221-224 在 队友的集群 上的结论相反。关 client 即结束 session (quitOnSessionEnded = true, 6.2 env 的 isaacsim/apps/isaacsim.exp.full.streaming.kit:65), 否则 timeout 14000 (:41)。
  3. Mac 怎么连, 三选一: (1) 推荐: VPN 上直接 ssh 到节点 (Mac 今天 14:55 ET 起从 <ip> 直连 <node>; job 在跑时 pam_slurm_adopt 放行), -L 49100:127.0.0.1:49100 -L 58997:127.0.0.1:47997; relay 在节点端 bind 0.0.0.0:47997 (udp_tcp_relay.py:128), 这一侧成立; Kit signalling 监听哪个地址不在代码里, 不通则 (2); (2) 经 <login-host> (README.md:202 形式), 需要登录 VM 到节点的 TCP 通路, 未验证; (3) 不走隧道: client 的 server 填 <node>, 提交时不设 PUBLIC_IP, 需要节点开放 TCP 49100 + UDP 47998 (firewalld 在跑, 规则要 root 才能看), 用 nc -vz <node> 49100 测。

A7 时间与磁盘

阶段 时间 磁盘
env 已完成 (18 min) 25G 常驻; 再建一次临时约 65 GB
hook + 链接 + sbatch 副本 已完成 46 MB 以内
L40S 探测 已完成 (smoke)
held_out_00 剩三步 (verify, finalize, observe × 3) 约 10 min CPU < 100 MB
kitchen build → finalize 约 20 min GPU + 排队 renders MB 级
viewer test / live viewer 已 PASS / 修 libatomic 后就绪 1.5 到 4.5 min captures 可选

合计剩 1 到 2 h 含排队。home 所剩无几, Kit 还往 ~/.cache/ov (527M) 和 ~/.nv (96M) 写。

A8 风险与退路

风险 事实 退路
WebRTC 插件 已修 (19:13 ET): lib/extra/libatomic.so.1 -> ../libatomic.so.1 + hook LD_LIBRARY_PATH (simgenprobe.sh:29, 35); 复查 job 3507469: 插件错误 0 条, omni.kit.livestream.webrtc-10.7.3 startup, STAGE1_STREAM ready ... startup=70.6s, DRAWER_TEST summary passed=True 无
OptiX denoiser 原因已查明: Unable to load denoiser weights: Could not open optix denoiser weights file /usr/share/nvidia/nvoptix.bin; 节点没有这个文件, 路径写死, 没有环境变量可改 (NVIDIA 论坛: root 放文件或容器 bind); 我们的拷贝在 nvidia-userspace/615.71.09/share/nvidia/nvoptix.bin, 指不过去 reference 渲染不去噪照样过: tabletop 两张 view verify_views 19:1x ET 全 PASS, verified=True; viewer 用 default 模式 (DLSS 可用, job 3507469 验证)
NGX/DLSS /usr/lib64/libnvidia-ngx.so.1 在 <node> 等几台 都没有; 615 set 的 libnvidia-ngx.so.1 走 LD_LIBRARY_PATH; <node> 上 dlss/supported=True 已验证可用
RT cores / NVENC H200/H100 无 RT cores, NVIDIA 写 not supported (10-26 H200 回过一帧, CHANGELOG.md:15-17); NVENC 未在此测 只用 L40S 或 RTX 6000 Ada, 真正的理由是 scavenger 能起
驱动版本, 615 set 在 L40S hook 只认 615.71.09 / 610.57.04; 615 set 10-26 在 H200 验证, 今天在 L40S <node> 验证 新版本按 848x_isaac.sh:10-12 加 set, simgenprobe.sh 也要加一个 case
SimReady 网络 18:55 四个资产下完 (763M) 失败则背景缺失; 缺 MDL 时背景渲染 error-red (KD/PROGRESS.md:81-82)
端口被占 共享节点 --signal-port/--stream-port (stream_scene.py:81-82) + relay 的 --tcp-listen/--udp-target; Mac 本地 49100/tcp 和 47998/udp 不能改, 只改 ssh -L 的远端
抢占 scavenger PreemptMode=REQUEUE, 普通分区的 job 可杀掉 live viewer --no-requeue 后重交; 要稳就用 普通分区的槽

A9 要你定的

  1. Isaac 版本: Stage 1 钉 6.2.0.0 (config.yaml:52; kitchen :129), 我们的 worker 钉 6.0.0.1 (constants.py:228, 握手 isaac_sim_engine.py:251-256 必须对上)。(1) 推荐: 现在双 env 并存, 零改动, 先把 Stage 1 跑完; (2) 本周内 worker 改到 6.2 (改 ISAAC_SIM_VERSION 即新 lock, isaac 测试按 TAB 2 T2 的方式重跑), reference 和生成场景同一模拟器。
  2. MuJoCo 残留: finalize.py:237-262 的交叉检查和 observe_held_out.yaml:19-20 的 MuJoCo 引擎, 与 Isaac-only 冲突。(1) 推荐: 本轮照跑, 档案只读, 它不产视图; (2) clone 一份 (A2 选项 2) 去掉或换成 Isaac 检查。
  3. Demo 通道: (1) scavenger, 随到随起但可被抢占; (2) 腾一个 普通分区的槽, 不可抢占但要排队。
  4. (已解决) libatomic: 用 lib/extra 目录加 hook 的办法, 复查通过, 不用再定。

PART B. Mac setup brief (English, for the local Codex agent)

Goal: view and drive the Isaac Sim 6.2 scene running on a 我们的集群 GPU node through an ssh tunnel; the Mac only decodes video and sends input.

1. Install (three things, nothing else)

  1. Isaac Sim WebRTC Streaming Client, macOS build. NVIDIA's Isaac Sim 6.2.0 download page (docs.isaacsim.omniverse.nvidia.com, Installation > Download) lists "Isaac Sim WebRTC Streaming Client 2.0.0" with "macOS (aarch64)" and "macOS (x86_64)" .dmg builds next to Isaac Sim 6.2.0 (aarch64 = Apple Silicon). The README wants the client that matches the 6.2 server (stage1_reference/README.md:181-182); 2.0.0 is the one the page offers.
  2. Python 3.8 or newer (README.md:182): python3 --version. No packages; the relay is standard library only (udp_tcp_relay.py:14).
  3. The relay file: mkdir -p ~/isaac && scp <user>@<login-host>:$PRIVATE/stage1_reference/udp_tcp_relay.py ~/isaac/ (:13).

2. Do not install

Isaac Sim itself (the download page has Linux x86_64, Linux aarch64 and Windows x86_64 builds only), Isaac Lab (section 8), Omniverse Launcher, Docker.

3. Before connecting (the user provides these)

  • <NODE>: the node of the running viewer job; the first line of the job log prints node <NODE>, and its connect block prints the exact ssh and relay commands (stage1_live_viewer.sbatch).
  • The job log must show STAGE1_STREAM ready ... public_ip=127.0.0.1 (stream_scene.py:174-179); the tunnel needs that setting.
  • The job log must not contain failed to load native plugin for omni.kit.livestream.webrtc. That failure (libatomic.so.1 missing on the node) was fixed on the cluster side on 2026-11-04 19:13 ET and re-verified (job 3507469); nothing to do on the Mac.
  • The Mac must be on the 学校 VPN: the nodes (<ip>) and the login VM (<ip>) have private addresses.

4. Connect (two terminals, then the client)

Terminal 1, the tunnel. Option A, recommended, straight to the node (allowed while the user's job runs there):

ssh -N -L 49100:127.0.0.1:49100 -L 58997:127.0.0.1:47997 <user>@<NODE>.<cluster-domain>

Option B, through the login host (README.md:202): ssh -N -L 49100:<NODE>:49100 -L 58997:<NODE>:47997 <user>@<login-host>.

Terminal 2, the relay (README.md:203):

cd ~/isaac && python3 udp_tcp_relay.py client --udp-listen 47998 --tcp-connect 127.0.0.1:58997

Expect client: udp 127.0.0.1:47998 <-> tcp 127.0.0.1:58997, then client: tunnel connected (udp_tcp_relay.py:72,84).

Client: open the Isaac Sim WebRTC Streaming Client, server 127.0.0.1, connect. When media flows, terminal 2 prints client: new udp source ... -> channel 0 (:98-101).

5. What to click

  1. "Panda Control" window: press Play (HANDOFF.md:95). Joint sliders, gripper and IK work only after Play (README.md:205).
  2. "Kitchen Drawer" window: press Scripted pull; the drawer opens about 20 cm and the status line reports success (HANDOFF.md:96). Reset drawer closes it; Travel limits shows the closed and fully open positions (:97).
  3. Camera: Option + left-drag orbits, scroll zooms, F frames the selection; the panel's Camera buttons do the same (README.md:205-206,247-250).
  4. Nothing is written unless File > Save is used, and the job opened a private copy of the scene (README.md:207; kitchen_webrtc.sbatch:17-19).

6. Verify the stream

The viewport shows a white kitchen island, the Panda arm and background furniture. After Play, the Panda Control status line counts simulation time. The job log prints STAGE1_STREAM fps=... every 10 s (stream_scene.py:231-233).

7. Troubleshooting

Symptom Cause Fix
Client cannot connect tunnel down, the job not ready, or the WebRTC plugin did not load on the node terminal 1 running? log has STAGE1_STREAM ready and no failed to load native plugin?
Connects, stays black no media: terminal 2 not running, or the job started without PUBLIC_IP=127.0.0.1 start terminal 2; ask for a resubmit with PUBLIC_IP=127.0.0.1
Grainy, noisy image PathTracing mode with the OptiX denoiser failing on the node (seen 2026-11-04), or DLSS unavailable (README.md:221-224) ask for a resubmit in the default mode (DLSS was reported supported on the L40S node); RENDER_MODE=PathTracing (HANDOFF.md:99) only if default is worse
Address already in use 58997 or 47998 taken on the Mac 58997: another local port in both commands; 47998 and 49100 must stay (README.md:198-199)
Stream ends by itself closing the client ends the session (stream_scene.py:5-6); or the job was preempted ask for a new job, reconnect
VPN direct option no tunnel or relay if the node's TCP 49100 and UDP 47998 are open from the VPN: server <NODE>.<cluster-domain>, job started without PUBLIC_IP test nc -vz <NODE>.<cluster-domain> 49100; unverified on 我们的集群

8. Isaac Sim vs Isaac Lab

  • Isaac Sim is the simulator application (Kit, PhysX, RTX); Linux and Windows only. The cluster job runs it; the Streaming Client is its remote screen.
  • Isaac Lab is a Python framework on top of Isaac Sim for robot learning. Viewing or editing needs none of it; the teammate's code takes one file from it, the Kit experience isaaclab.python.headless.kit (launch.py:20, installed with --no-deps, README.md:122-124).
  • Editing: the stream carries the full Isaac Sim UI, Stage and Property panels included (README.md:235); edits happen there on a private copy and a save writes only that copy (README.md:218-219).