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