前置条件

请把 FastSim 和 Isaac Lab provider 安装到同一个 Python 环境。本 Run 使用 Isaac Lab 3.0 / Isaac Sim 6.0,并打开可见窗口。

逐项理解配置

yaml
schema: fastsim/2                    # FastSim vNext Run 配置规范。
name: demo-control-generic-articulation
backend: isaaclab                    # 解析门组件的 Isaac Lab USD 变体。

runtime:
  launch_profile: visible            # 显示真实仿真器窗口。
  physics_hz: 60                     # 物理积分频率。
  control_hz: 60                     # 控制帧接收频率。
  seed: 37                           # 可复现的 reset 随机种子。

scenario:
  scene:
    articulations:                   # 非机器人的铰接资产。
      door:                          # 之后传给控制 API 的别名。
        use: articulation://fastsim/demo-door
        pose:
          xyz_m: [0.0, 0.0, 0.0]    # 世界坐标系根位置,单位米。
          quat_xyzw: [0.0, 0.0, 0.0, 1.0]
        initial_state:
          joints:
            door_hinge: 0.0          # 初始角度,单位弧度。

门组件声明了 door 资源组,并把它映射到物理轴 door_hinge。应用只选择资源组, 不依赖 USD Prim 路径。

逐行理解 Python

  1. 导入部分提供异步事件循环、有限数检查、可靠的 run.yaml 路径和公共 fastsim 包。
  2. 常量负责定位 Run、让最终姿态短暂停留,并定义严格的三帧结果和 0.20 +/- 0.08 rad 验收区间。
  3. main() 使用异步函数,因为等待控制完成时不能阻塞 FastSim 事件循环。
  4. fastsim.app(..., planning_reads=True) 创建直接开发应用的 facade,并开启末尾 所需的 Scene State 读取服务。
  5. async with 在代码块内持有应用,并保证退出时完整清理。
  6. start() 启动真实后端;第一次等待一秒,让用户先看到门的初始位置。
  7. control.targets() 向 FastSim 查询当前 Run 中真正可控制的实体和资源组。
  8. next(...) 选择规范 ID 为 articulations.door 的 descriptor;打印结果可确认 最终解析到的绑定。
  9. control.joints(...) 提交一个有序 chunk,并异步等待它进入终态。
  10. actor="door" 使用 Scenario 别名;FastSim 会把它解析为 articulations.door,不会泄漏后端路径。
  11. group="door" 选择组件声明的单轴资源组。
  12. path=[[0.0], [0.75], [0.20]] 表示从关闭状态打开到 0.75 rad,再返回 0.20 rad。每行都必须严格符合资源组声明的轴顺序。
  13. dt=0.75 表示相邻路径帧之间相隔 0.75 秒仿真时间。
  14. timeout=20.0 只限制调用方最长等待时间,不是休眠时间或物理轨迹时长。
  15. pause() 保留最终世界,同时建立稳定的读取边界。
  16. scene.state() 获取可移植实时状态;next(...) 取出门的 articulation state。
  17. 验证块要求终态为 succeeded、帧数严格为 3/3、状态中只有一个 rad 关节、 角度有限且误差不超过 0.08 rad;失败时会抛错并返回非零退出码。
  18. 三行打印分别报告 chunk 终态、帧数,以及实测角度、误差和阈值。
  19. 最后的等待让暂停后的门在窗口中保留三秒。
  20. asyncio.run(main()) 在直接运行文件时启动程序。

验收门禁

  • 终态必须为 succeeded,帧数必须严格为 3/3
  • 最终状态必须恰好包含一个有限的 rad 关节值。
  • 实测角度必须落在 0.20 +/- 0.08 rad 内。这个显式范围覆盖控制器终态容差, 但不会接受明显错误的门姿态。
  • 2026-08-25 的可见 Isaac Lab 真机验收实测为 0.236 rad,误差 0.036 rad,退出码为 0。

运行

从本案例目录运行:

bash
cd demo/fundamentals/08_control_generic_articulation
fastsim config validate run.yaml --json
python main.py

可见窗口中的门应先打开,再返回到半开状态。程序会主动执行上述门禁,不能把 “只打印了结果”当作通过。

验证等级

真实可见 Isaac 已通过。 真机运行完成 3/3 帧,实测 0.236 rad,满足 0.20 +/- 0.08 rad 门禁;程序正常退出,并且没有遗留 Isaac worker 进程。

为什么没有 open_door()

“打开”属于任务语义。FastSim 核心只需要知道:一个有序物理关节 chunk 正在控制某个 已声明资源组。Rulebased 插件、模型、遥操作源或直接应用可以各自决定 0.75 rad 在业务上代表什么。

常见错误

  • NO_RESOURCE_GROUP:通过 control.targets() 查看有效资源组,不要根据资产文件名猜测。
  • PATH_WIDTH_MISMATCH:这个门只有一个轴,因此路径的每一行必须恰好有一个数值。
  • 报错后窗口立刻关闭:请读取终态错误;async with 在失败时主动清理是预期行为。