UniSim 统一接口

UniSim 是 FastSim 与底层仿真引擎之间的唯一接口层。它将"启动仿真器、推进物理、查询运行状态"这三件事抽象成一组固定接口,使得 SceneManager、ControllerManager 等上层模块完全不感知当前运行的是 IsaacLab、Mujoco 还是其他引擎。

职责边界

UniSim 只做以下几件事:

  • 启动底层仿真 App 或 SimulationContext
  • 推进物理引擎一个时间步(step()
  • 查询仿真器是否仍在运行(is_running()
  • 提供少量全局级辅助能力(如 viewport 相机设置)

不属于 UniSim 职责的事情:

  • 实体的创建与管理 → SceneManager
  • 控制命令的执行 → ControllerManager
  • 录制、服务化等扩展功能 → ExtensionManager
  • 任务编排与目标检查 → TaskManager

这个边界划分使得每一层都可以独立测试和扩展,也是 FastSim 能够支持多后端的基础。

核心接口

UniSim 抽象基类定义在 fastsim/unisim/unisim.py,所有后端均需实现以下方法:

方法调用时机说明
initialize_simulation()setup_all_before_loop() 阶段启动仿真 App / SimulationContext,完成底层初始化
setup_viewport_camera()初始化后(可选)设置默认视角,调试时使用
reset()场景构建完成后复位仿真状态,执行初始化步骤
step()每个仿真帧推进物理引擎一个时间步(dt
is_running()主循环判断条件查询底层 App 是否仍在运行

UniSim 在仿真主循环中的位置

FastSim.step() 的执行顺序如下。UniSim 的 step() 是其中的物理推进核心,前后各有一个 SceneManager 的读写阶段:

text
ControllerManager.run_all_commands()     ← 执行控制命令队列
SceneManager.pre_physics_update()        ← 将目标值/脏数据写入仿真器
UniSim.step()                            ← 物理引擎推进一帧(dt)
SceneManager.post_physics_update()       ← 从仿真器读取最新状态
[step callbacks]                         ← record、benchmark 等扩展挂接点

UniSim.step() 本身只负责推进物理,不涉及任何实体读写。实体的写入发生在它之前(pre_physics_update),读取发生在它之后(post_physics_update)。

后端选择:从配置到实例

后端由配置文件中的 simulation.stereotype 字段决定。UniSimFactory.create(config)FastSim.__init__() 中被调用,根据 stereotype 实例化对应后端:

yaml
simulation:
  stereotype: isaaclab   # 决定使用哪个后端
  dt: 0.01667
  device: cuda:0

对应的工厂逻辑(源码:fastsim/unisim/unisim.py):

text
simulation.stereotype
    ↓
UniSimFactory.create(config)
    ↓
IsaacLab(UniSim) / Mujoco(UniSim) / ...

stereotype 的可用值由注册表决定。可通过以下 CLI 工具查看当前注册的所有后端:

bash
fastsim show-registry

IsaacLab 后端

simulation.stereotype: isaaclab 时,实际运行的是 fastsim/simulators/isaaclab/isaaclab_app.py 中的 IsaacLab(UniSim)

初始化行为:

  1. AppLauncher(**launch_config) 启动 Isaac Sim 进程
  2. 构造 SimulationCfg(包含 dtgravityphysxrender 等参数)
  3. 创建 SimulationContext 并绑定到物理场景

步进行为:

  • step() 调用 sim.step(render=True),推进物理并渲染一帧
  • is_running() 对应 app.is_running()

IsaacLab 专有配置字段(在 simulation 块下扩展):

字段说明
device计算设备,如 cuda:0cpu
dt物理时间步长(秒),通常 0.01667(60Hz)
gravity重力向量,默认 [0, 0, -9.81]
enable_scene_query_support是否启用场景查询(碰撞检测等)
use_gpu_pipeline是否使用 GPU 物理流水线

详细字段定义见 fastsim/simulators/isaaclab/isaaclab_config.py

实现自定义后端

如需接入新的仿真器,只需继承 UniSim 并实现上述五个接口方法,然后通过 stereotype 注册机制注册:

python
from fastsim.unisim.unisim import UniSim
from fastsim.annotations.stereotype import stereotype

@stereotype("my_simulator")
class MySimulator(UniSim):
    def initialize_simulation(self): ...
    def step(self): ...
    def reset(self): ...
    def is_running(self) -> bool: ...

注册后,在配置中写 simulation.stereotype: my_simulator 即可使用,上层代码无需任何改动。