OvPhysX 后端#

警告

OvPhysX 仍处于 高度实验性 阶段,目前不建议普遍使用。后端正在积极开发,公共接口变化较快。在 Isaac Lab 3.0 各测试版本之间,功能支持和测试命令可能变化。

警告

不要将 OvPhysX 与 Kit 可视化器组合使用。physics=ovphysx --visualizer kit 等命令不受支持:ovphysx 从自身软件包加载依赖 USD 的 PhysX 插件,而 Kit 在同一进程内管理另一套独立的 USD 和插件。请使用 --visualizer newton_gl、--visualizer rerun 或 --visualizer viser;也可以不传 --visualizer,以无界面方式运行。

OvPhysX 是不依赖 Kit 的 PhysX 后端变体。它直接驱动 PhysX,无需 Omniverse Kit 运行时,并从 USD 的 PhysicsScene prim 读取场景级求解器参数,而不是从 Python 配置读取。Python 配置 OvPhysxCfg 只暴露少数 USD 模式中没有对应表示的 GPU 缓冲区大小。

通过 OvPhysxCfg 选择 OvPhysX:

from isaaclab.sim import SimulationCfg
from isaaclab_ov.physics import OvPhysxCfg

sim_cfg = SimulationCfg(physics=OvPhysxCfg())

为什么使用 OvPhysX?#

  • 不依赖 Kit 的运行。 OvPhysX 无需 Omniverse Kit,适合探索无界面部署,以及不需要 Kit 运行环境的后端。

  • 以 USD 为权威依据。 求解器参数来自 PhysicsScene USD prim,已有 USD 场景管理能力的创作工具无需再维护一份 Python 配置。

当前可用功能#

资源与传感器接口沿用 PhysX 的设计,但本文编写时仅实现并验证了其中一部分。以下组件已在 develop 中可用:

  • RigidObject:通过 PR #5426 合并。

  • Articulation:通过 PR #5459 合并。

  • RigidObjectCollection:通过 PR #5570 合并。

  • 接触传感器:通过 PR #5422 合并。

  • SceneDataProvider:通过 PR #5589 合并。

  • FrameView:通过 PR #5678 合并。

  • DeformableObject :在 CUDA 仿真设备上实验性支持体积和表面可变形体。

  • 对于原生张量布局相同的异构刚体与关节体几何变体,支持快速克隆。

其他 OvPhysX 功能仍在开发中。IMU、坐标系变换器、关节力与力矩传感器、PVA、射线投射器和渲染功能,在其实现进入 develop 并通过后端基本运行测试之前,本页不将其列为受支持功能。

异构克隆#

异构运行时克隆要求 OvPhysX 0.6.3。张量绑定按环境的数字顺序排列,保证索引式重置、动作和观测对应正确变体。变体的几何可以不同,但刚体、关节和肌腱布局必须一致。Isaac Lab 检查原型旋转轴和肌腱布局;OVPhysX 在绑定关节体时检查刚体与关节元数据。

克隆上下文只编译一次计划中的原型和仿真世界分配。物理管理器挂接一个导出的 USD 舞台,重放原生副本,并在资源和传感器绑定之前预热运行时。硬重置复用相同声明,不另设一次性消费队列。绑定路径来自计划的世界布局和环境模板,而不是原生克隆顺序。

所有写入 USD 的源对象均获得原生环境 ID 零。因此,包含源对象或仅通过 USD 定义物理的每个仿真世界,都会将其声明的全部资源作为原始对象导入。其他世界从组成相同、完整的原始世界克隆资源,每个目标世界使用一个原生环境 ID。这样,机器人、桌子和物体可以相互接触,无需目标占位对象。只复制声明的资源子树,其他写入 USD 的资源保持不变。

保持 filter_collisions 启用,以通过 USD 碰撞组隔离原始世界。GPU 副本还使用原生环境 ID 过滤。OvPhysX 0.6.3 的 CPU 模式没有原生环境 ID 过滤,会导入全部声明的 USD 副本,并使用碰撞组。大量重叠的原始布局仍可能耗尽粗检测碰撞对容量,因此应将环境在空间上分开。

可变形体限制#

目前 OvPhysX 要求同一个 DeformableObject 匹配到的所有物体具有相同数量的仿真节点。节点数量不同时,初始化会报错,而不会暴露填充后的状态,以免产生错误的归约结果。

可变形体场景还要求将整个 USD 舞台实例化展开,因此启动开销会随已定义环境数量增加。这条路径适合小规模验证场景,目前不支持数千个环境的训练规模工作负载。异构快速克隆器不支持可变形体。

安装#

ovphysx 扩展依赖要求 OvPhysX 0.6.4.72118723。在仓库根目录执行以下命令安装:

uv sync --inexact --extra ovphysx

--inexact 会保留通过其他扩展依赖安装的软件包。使用 --extra ov 可同时安装公开发行的 OvPhysX 和 OVRTX 运行时。这组扩展依赖将 OVRTX 0.5.1.385782 与 OVStage 0.2.1 配套使用;OVRTX 0.4.1 与该组合不兼容。旧版 Isaac Lab 安装器也支持 ./isaaclab.sh -i 'ov[ovphysx]' 和 ./isaaclab.sh -i 'ov[all]'。

测试安装#

先检查 Python 软件包和运行时 wheel 能否正常导入:

uv run --extra ovphysx --extra test python -c "import ovphysx.types; from isaaclab_ov.physics import OvPhysxCfg; print('OvPhysX runtime OK')"
./isaaclab.sh -p -c "import ovphysx.types; from isaaclab_ov.physics import OvPhysxCfg; print('OvPhysX runtime OK')"

然后运行一个小规模后端基本运行测试:

uv run --extra ovphysx --extra test python -m pytest source/isaaclab_ov/test/assets/test_rigid_object.py::test_initialization -k cpu
./isaaclab.sh -p -m pytest source/isaaclab_ov/test/assets/test_rigid_object.py::test_initialization -k cpu

要运行声明了 OvPhysX 物理预设的任务,使用与其他后端相同的预设 CLI 语法:

uv run --extra ovphysx isaaclab zero_agent --task Isaac-Cartpole-Direct \
    --num_envs 128 --max_steps 64 --viz none physics=ovphysx
./isaaclab.sh -p scripts/environments/zero_agent.py --task Isaac-Cartpole-Direct \
    --num_envs 128 --max_steps 64 --viz none physics=ovphysx

此命令以无界面方式运行 64 步零动作轨迹,然后退出。

受支持的足式运动环境#

以下足式运动训练环境声明了 ovphysx 物理预设。支持时,通过 uv run isaaclab play 运行策略也使用相同后端。

  • Isaac-Ant-Direct

  • Isaac-Humanoid-Direct

  • IsaacContrib-Velocity-Rough-AnymalB

  • IsaacContrib-Velocity-Rough-AnymalC

  • Isaac-Velocity-Flat-AnymalD

  • Isaac-Velocity-Rough-AnymalD

  • IsaacContrib-Velocity-Rough-UnitreeA1

  • IsaacContrib-Velocity-Rough-UnitreeGo1

  • Isaac-Velocity-Rough-UnitreeGo2

  • Isaac-Velocity-Rough-Cassie

  • Isaac-Velocity-Rough-G1

  • Isaac-Velocity-Rough-H1

当前状态与后续工作#

OvPhysX 仍处于实验阶段,因此上方功能列表有意采用保守表述。更广泛的功能支持和文档完善工作记录在 issue #5634 中。

架构背景见 后端架构 。

访问原生接口#

基本概念#

OvPhysX 暴露通用的 TensorBinding 对象。一个绑定将 prim 选择与已安装的一种 TensorType 结合,并不是某个资源专用的原生存储对象。调用方通过 read() 显式将值读入自己的缓冲区,再通过 write() 将缓冲区写回。Isaac Lab 可以选择使用 OvPhysxView 包装这些绑定,提供以字符串为键、带检查的便捷接口。

生命周期前提#

仅在 OvPhysX 仿真完成初始化和重置、原生运行时已就绪后创建绑定。重新加载 USD 舞台、重建舞台或运行时的重置流程,以及管理器清理,都会使所有已有绑定和视图失效,之后需要重新获取。

满足生命周期前提后,从管理器获取当前 OvPhysX 句柄:

from isaaclab_ov.physics import OvPhysxManager

physx = OvPhysxManager.get_physx_instance()
if physx is None:
    raise RuntimeError("OvPhysX has not been constructed; initialize and reset the simulation first.")

句柄非 None 只说明管理器已构建 OvPhysX 实例,并不表示当前仿真上下文已经就绪。管理器清理时会释放实例并清空句柄。访问前先初始化并重置当前上下文,创建新绑定或视图前始终重新获取句柄。

复用 Isaac Lab 持有的访问对象#

如果选择符合需要,复用 Isaac Lab 资源已经持有的便捷视图:

object_view = scene["object"].root_view
poses = object_view.get_attribute("rigid_body_pose")

创建底层访问#

所需选择尚未由 Isaac Lab 资源持有时,创建原始绑定。以下示例位姿绑定使用 float32 和仿真设备,并不是适用于所有张量类型的通用分配器:

import warp as wp
from isaaclab.physics import PhysicsManager
from ovphysx.types import TensorType

binding = physx.create_tensor_binding(
    pattern="/World/envs/env_*/Object",
    tensor_type=TensorType.RIGID_BODY_POSE,
)
try:
    poses = wp.empty(
        tuple(binding.shape),
        dtype=wp.float32,
        device=PhysicsManager.get_device(),
    )
    binding.read(poses)
    binding.write(poses)
finally:
    binding.destroy()

分配缓冲区前,检查 binding.shape 、 binding.dtype 、绑定数量和路径元数据。必须精确匹配绑定形状与 DLPack 标量元数据,并遵守原生设备和访问模式要求。 RIGID_BODY_POSE 使用上方的 float32 布局,但其他张量类型的数据类型、形状、原生设备或写入权限可能不同。

对于新选择,使用原生运行时和 Tensor API 模式构建 OvPhysxView :

from isaaclab.physics import PhysicsManager
from isaaclab_ov.sim.views import OvPhysxView

view = OvPhysxView(
    physx,
    pattern="/World/envs/env_*/Object",
    device=PhysicsManager.get_device(),
)
try:
    if view.try_binding_for("rigid_body_pose") is not None:
        poses = view.get_attribute("rigid_body_pose")
        view.set_attribute("rigid_body_pose", poses)
        view.read_into("rigid_body_pose", poses)
finally:
    view.close()

try_binding_for 尝试为该选择创建绑定,没有有效类型时返回 None 。 binding_for 返回原始绑定,会绕过视图的设备、数据类型、形状和只读检查。

读写语义#

原始 binding.read(buffer) 将值读入调用方持有的缓冲区, binding.write(buffer) 则将值写入仿真。仅修改本地缓冲区不会改变仿真。带检查的 get_attribute() 、 read_into() 和 set_attribute() 具有相同的读取与写回边界,同时验证绑定形状、标量数据类型、原生设备和写入权限。

所有权、同步与失效#

在绑定要求的设备上分配缓冲区,并匹配其形状与 DLPack 标量元数据。状态张量通常使用仿真设备,部分属性张量则仅支持 CPU。 OvPhysxView 验证这些要求,并可将受支持的平坦标量布局重新解释为结构化 Warp 值,但不会在 CPU 与 GPU 之间移动数据。

如果某个张量类型可能不适用于选定 prim,请使用 try_binding_for 。重置流程重建舞台或运行时之后,以及清理之后,应重新获取原始绑定和便捷视图。不再需要时,应销毁原始绑定并关闭自定义视图。管理器清理会先关闭已跟踪的 OvPhysxView 实例,再释放运行时;显式清理可以避免在长时间运行的仿真中一直保留这些绑定。

权威参考#

生成的 Isaac Lab OvPhysxView 参考文档介绍了便捷视图。仓库元数据固定了 OvPhysX 版本,但没有提供带版本的官方 OvPhysX 文档 URL,因此应在运行时检查已安装的 TensorType 与绑定元数据。