跳转至

Viser 时序可视化接口

交互播放器与业务数据加载已经解耦。所有 reconstruction、physics rollout 或其他时序结果,都应先适配成 pipeline.utils.viser_timeline.TimelineScene,再交给统一的 render_timeline() / ViserTimelineViewer

核心数据类型

类型 数据 每帧更新 典型用途
MeshTrack(deformable) vertices=(T,V,3)faces=(F,3) handle.vertices SMPL-X、布料、软体
MeshTrack(rigid) vertices=(V,3)faces=(F,3) 不更新 mesh object link、physics rigid body
TransformTrack transforms=(T,4,4) position + quaternion articulated links、刚体骨架
CameraTrack KT_c2w、可选 RGB 帧 frustum 输入相机或 simulator camera
TimelineGroup key、显示名称 visibility human/object/contact 等分组

所有同帧的 deformable vertices、rigid transforms、颜色和透明度更新都由 播放器统一放进一次 server.atomic();adapter 不应直接操作 Viser handle。

Reconstruction adapter

pipeline.utils.viser_utils.build_hoi_result_timeline() 当前完成:

  • SMPL-X body / left hand / right hand → 三条 deformable MeshTrack
  • target hand 逐帧颜色与透明度 → frame_colors / frame_opacities
  • articulated object link → 一条 TransformTrack 加若干静态 MeshTrack
  • object contact region → 同一 link 下的红色静态 MeshTrack
  • result camera、ground、joint qpos 文本 → CameraTrack 和 frame info。

原有 render_result() 仍然兼容,但内部已经调用标准播放器。

Physics rollout adapter

pipeline.physics.vis.rollout.load_physics_rollout_timeline() 直接接受 common_rollout.npzcase JSON + result.pt 和共享 humanoid XML。 其中只有 common rollout 提供逐帧状态;这和任意方法数量的 comparison 使用同一条 数据接口:

  1. 读取 case-specific humanoid.xml,把其中的 box/capsule body 转成 link-local 静态 MeshTrack;不再反解或显示光滑 SMPL-X skin。
  2. human_body_state[..., :3] + human_body_state[..., 3:7] 直接生成 TransformTrack。各刚体 mesh 只初始化一次,播放时只更新 scene-node pose。
  3. Humanoid 使用既有 Isaac Gym replay 的亮绿色 (0.2, 0.95, 0.2); object 继续使用统一的橙色,contact-region 继续使用红色。
  4. object_root_state (T,13) + object_joint_qpos (T,J):通过现有 articulated FK 得到 object link 的 (T,4,4),继续复用 object 静态 mesh 与 contact-region mesh。
  5. 各方法的 state、坐标系、时间轴、joint order 已在 common contract 中统一; renderer 不读取原生 pkl,也不写第二份 human/object 动态播放文件。
  6. Object scale 在由 case/result 重建的共享 URDF 中一次性 bake;common rollout 不重复保存几何 scale。
  7. MP4 renderer 可直接传入 camera.views[].eye/look_athorizontal_fov_deg;缺省使用共享自动 full-body/hand-object 取景,且永不回读 result.pt 以外的原生文件。Viser 使用自由视角。
  8. 水平地面从 result.world.ground_offset 直接得到;桌面等静态几何只从冻结 case JSON.world.static_boxes 读取。CoDA native obj.table_pos 仅用于与这个 shared table 的中心做 parity 校验,不是 renderer 输入,也不写进动态 rollout。
  9. Common rollout 始终保存 canonical \(T\)valid_frame_count。单方法 renderer/Viser 只播放有效前缀;comparison 在某方法终止后隐藏该方法并标记 fail,不显示冻结尾帧。

最小调用形式:

from pipeline.physics.vis.rollout import render_physics_rollout

viewer = render_physics_rollout(
    "output/runs/<case>/<method>/common_rollout.npz",
    method="ours",
    case_json_path="output/runs/<case>/runtime/case.json",
    result_path="output/runs/<case>/recon/output/result.pt",
    humanoid_xml="output/runs/<case>/<method>/reference/humanoid.xml",
    host="0.0.0.0",
    port=8921,
    autoplay=True,
)
viewer.run_forever()

命令行入口为 scripts/visualization/serve_physics_rollout_viser.py,传入 --common-rollout--case-json--result--humanoid-xml。Physics adapter 只负责读取 common rollout、坐标/四元数约定 转换和构造 tracks; 播放控制、自由视角、材质、同步更新与性能策略全部复用通用层。

Physics 方法对比

scripts/visualization/serve_physics_method_comparison.py 按 manifest 的有序 methods 列表,把各方法 render state 放进同一个 TimelineScene。所有列共享一个播放 时间轴;viewer 内的 Case 下拉框会原地替换 scene,不会启动多个需要额外同步的播放器。 右侧指标直接读取统一 evaluator 的 evaluation.json

每个 case 的 runs 必须与 methods 一致。PHC-X 是 diagnostic,可在 diagnostic manifest 中出现,不是主 comparison 的固定必选列。每列只写该次运行的 run_record.json;viewer 从 outputs.common_rollout、静态 renderer 输入和 outputs.evaluation 读取结果,不重复填写派生路径:

{
  "methods": [
    {"name": "coda", "label": "CoDA"},
    {"name": "intermimic", "label": "InterMimic"},
    {"name": "repho", "label": "RePHO"},
    {"name": "ours", "label": "Ours"}
  ],
  "cases": [
    {
      "name": "b005-0113_cad10347",
      "runs": {
        "coda": "/abs/case/physics/coda/run_record.json",
        "intermimic": "/abs/case/physics/intermimic/run_record.json",
        "repho": "/abs/case/physics/repho/run_record.json",
        "ours": "/abs/case/physics/ours/run_record.json"
      }
    }
  ]
}

启动命令:

python scripts/visualization/serve_physics_method_comparison.py \
  --manifest /abs/physics_method_comparison.json \
  --host 0.0.0.0 \
  --port 8931