Isaac Capture#

Isaac Capture 是用于高保真第一视角数据和机器人数据采集的统一框架。它提供标准化设备接口及灵活的计算图式重定向流水线,可用于仿真和真实机器人。

备注

名称变更。 Isaac Teleop 已更名为 Isaac Capture 。Isaac Lab 当前固定使用 1.4 版本,该版本的 Python 发行包和导入包仍名为 isaacteleop 。上游在 1.6 中将两者改名为 isaaccapture ,因此本文档中的 isaacteleop 命令和导入名是有意保留的。详见 Isaac Capture 迁移指南 。

Isaac Capture 替代了 Isaac Lab 原有的原生 XR 遥操作组件( isaaclab.devices.openxr )。迁移说明见 迁移到 3.0 。

小技巧

想先运行起来? 请按 配置 Isaac Capture 与 CloudXR 指南完成安装和首次运行,再回到本页了解更深入的内容。

支持的设备#

Isaac Capture 支持多种 XR 头显和跟踪外设。不同设备提供的输入模式不同,决定了可使用的重定向器和控制方案。

设备

输入模式

客户端 / 连接方式

说明

Apple Vision Pro

手部跟踪(26 个关节)、空间控制器

原生 visionOS 应用( Isaac XR Teleop 示例客户端 )

从源代码构建,见 构建并安装客户端应用 。

Meta Quest 3

运动控制器(扳机、摇杆、握持按钮)、手部跟踪

CloudXR.js WebXR 客户端(浏览器)

CloudXR 客户端 ,见 连接指南 。

Pico 4 Ultra

运动控制器、手部跟踪

CloudXR.js WebXR 客户端(浏览器)

要求 Pico OS 15.4.4U 或更新版本,必须使用 HTTPS 模式。

Manus 手套

高保真手指跟踪(Manus SDK)

Isaac Capture 插件(附带)

从现已弃用的 isaac-teleop-device-plugins 仓库迁移而来。需搭配外部手腕跟踪源,提供手腕位置。见 Manus 手套 。

Haptikos 外骨骼

外骨骼手部跟踪,搭配控制器手腕位姿

Isaac Capture 插件(独立可执行文件)

需要 Haptikos App、外骨骼,以及带控制器的 OpenXR 头显。见 配合 Quest 使用 Haptikos 外骨骼 。

选择控制方案#

输入设备与重定向器的合适组合取决于任务。可先参考下表,再查看后面的详细流水线示例。

任务类型

推荐输入

重定向器

动作维度

参考配置

操作(如 Franka)

运动控制器

Se3AbsRetargeter + GripperRetargeter

8

stack_ik_abs_env_cfg.py

双手灵巧操作 + 移动(如 G1 TriHand)

运动控制器

双手 Se3AbsRetargeter + TriHandMotionControllerRetargeter + LocomotionRootCmdRetargeter

32

locomanipulation_g1_env_cfg.py

固定基座的双手灵巧操作(如 G1)

运动控制器

双手 Se3AbsRetargeter + TriHandMotionControllerRetargeter

28

fixed_base_upper_body_ik_g1_env_cfg.py

复杂灵巧手(如 GR1T2、G1 Inspire)

手部跟踪 / Manus 手套 / Haptikos 外骨骼

双手 Se3AbsRetargeter + DexBiManualRetargeter

36+

pickplace_gr1t2_env_cfg.py

为什么操作任务推荐运动控制器? 控制器通过握持位姿提供精确的空间控制,并用实体扳机控制夹爪,非常适合抓取放置任务。

为什么复杂灵巧手推荐手部跟踪? 手部跟踪能采集完整的 26 关节手部位姿,满足高保真灵巧重定向的要求。需要单独控制手指时,这一点尤为关键。

工作原理#

IsaacTeleopDevice 是 Isaac Capture 与 Isaac Lab 的主要集成入口,由三个协作组件组成:

  • XrAnchorManager :在仿真中创建并同步 XR 锚点 prim,计算 world_T_anchor 变换矩阵,将 XR 跟踪数据映射到仿真坐标系。

  • TeleopSessionLifecycle :构建重定向流水线,从 Isaac Sim 的 XR 桥接层获取 OpenXR 句柄(独立模式下则通过 CloudXR 运行时自行创建 OpenXR 会话,见 不使用头显运行(独立 I/O) ),创建 TeleopSession ,并逐帧推进会话以生成动作张量。

  • CommandHandler :轻量级 START / STOP / RESET 命令回调注册表。脚本可通过 add_callback() 注册回调,但主要控制流程使用 poll_control_events() (见 遥操作控制状态(Start / Stop / Reset) )。

会话生命周期详情

会话采用 延迟创建 :如果用户尚未在 Isaac Sim 界面中点击“Start XR”,就不会立即创建会话。每次调用 advance() 时都会重试,直到 OpenXR 句柄可用。连接成功后, advance() 返回位于所配置设备上的展平动作张量( torch.Tensor )。会话尚未就绪或已销毁时,返回 None 。

在独立模式( 不使用头显运行(独立 I/O) )下,创建会话 不需要 等待 Kit XR 句柄,CloudXR 运行时可用时即可启动。

显示 XR 跟踪数据#

Isaac Capture 可在 Isaac Lab 世界坐标系中绘制原始 XR 跟踪位姿。通过可视化可确认跟踪数据是否可用、是否与仿真机器人对齐:

  • 重定向流水线包含 HandsSource 时,红色球体显示每只被跟踪手的 26 个关节;

  • RGB 坐标轴显示每个被跟踪控制器的 OpenXR 指向位姿。X、Y、Z 轴分别为红、绿、蓝;控制器的 -Z 轴沿其自然指向方向朝前。

启动遥操作会话时启用可视化:

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit \
    --xr \
    --enable_debug_visualization
./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit \
    --xr \
    --enable_debug_visualization

scripts/tools/record_demos.py 和 scripts/environments/teleoperation/teleop_replay_agent.py 也提供 --enable_debug_visualization 标志。此选项在创建 Isaac Capture 设备时应用,设备会话运行期间无法切换。标记仅用于诊断,不会改变重定向流水线生成的动作。

备注

只有启用 Kit 可视化器时才能看到跟踪标记。对应的手或控制器首次提供有效跟踪数据后,才会创建标记。

遥操作控制状态(Start / Stop / Reset)#

Isaac Lab 支持从 XR 头显向仿真发送 start 、 stop 和 reset 远程遥操作控制命令。它们用于开始或结束示范录制、暂停机器人或重置环境,无需接触仿真主机。没有头显时,也可通过 request_start() / request_stop() 及 reset() 在 本地 触发相同命令(见 不使用头显运行(独立 I/O) )。

它是如何工作的#

默认情况下,每个 IsaacTeleopCfg 都使用约定的 UUID uuid5(NAMESPACE_DNS, "teleop_command") 启用控制消息通道。该通道作为 teleop_control_pipeline 创建于 TeleopCore 的 TeleopSession 内,具体流程如下:

  1. MessageChannelSource 使用约定 UUID,打开一个 OpenXR 不透明数据通道( XR_NV_opaque_data_channel )。

  2. CloudXR JS 客户端(或其他客户端)通过 UUID 发现通道,并发送 UTF-8 编码的 JSON 命令:

    {"type": "teleop_command", "message": {"command": "start teleop"}}
    {"type": "teleop_command", "message": {"command": "stop teleop"}}
    {"type": "teleop_command", "message": {"command": "reset teleop"}}
    
  3. TeleopMessageProcessor 解析这些消息,生成布尔脉冲信号( run_toggle 、 kill 、 reset )。

  4. DefaultTeleopStateManager 接收布尔信号,运行其状态机(边沿检测、故障保护),并输出 teleop_state (独热编码)及 reset_event (布尔脉冲)。

  5. TeleopCore 将这些输出解码为 ExecutionEvents ,注入每个重定向器的 ComputeContext ,使有状态的重定向器能够响应状态变化,例如重置时重新初始化跨步状态。

在脚本中轮询控制事件#

使用 poll_control_events() 逐帧读取最新控制状态:

from isaaclab_teleop import poll_control_events

with IsaacTeleopDevice(cfg) as device:
    running = False
    while sim_app.is_running():
        action = device.advance()

        ctrl = poll_control_events(device)
        if ctrl.is_active is not None:
            running = ctrl.is_active      # True after "start", False after "stop"
        if ctrl.should_reset:
            env.reset()                    # "reset" command received this frame

        if action is not None and running:
            env.step(action.repeat(num_envs, 1))
        else:
            env.sim.render()

ControlEvents 有两个字段:

  • is_active :收到“start”命令后为 True ,收到“stop”后为 False ;尚未收到任何命令时为 None ,此时调用方应保留自己的标志值。

  • should_reset :收到“reset”命令后,仅一帧为 True 。

关闭控制通道#

如果不需要由头显触发开始、停止及重置(如仅使用键盘的工作流),在配置中设置 control_channel_uuid=None :

IsaacTeleopCfg(
    pipeline_builder=_build_my_pipeline,
    control_channel_uuid=None,   # no opaque data channel created
)

使用自定义通道 UUID#

要使用其他通道 UUID(如用于独立控制协议),传入任意 16 字节的 bytes 值:

import uuid

MY_UUID = uuid.uuid5(uuid.NAMESPACE_DNS, "my_custom_control").bytes

IsaacTeleopCfg(
    pipeline_builder=_build_my_pipeline,
    control_channel_uuid=MY_UUID,
)

必须同步更新 CloudXR JS 客户端,使它发送命令时能发现该 UUID。

不使用头显运行(独立 I/O)#

默认情况下,遥操作脚本通过 Isaac Sim 的 Kit XR 桥接层驱动 Isaac Capture,将场景渲染到已连接的 XR 头显。如果只需要将 Isaac Capture 用作 输入/输出传输通道 ,例如主控机械臂传输关节编码器角度,或使用其他非 XR 设备,则可采用 独立 模式,无需 Kit XR 渲染。

teleop_se3_agent.py 和 record_demos.py 通过 --xr 标志选择模式:

  • 传入 --xr :完整 Kit XR 流程,包括头显渲染、锚点及手部/控制器跟踪。

  • 不传入 --xr :Isaac Capture 通过 CloudXR 运行时创建并管理自己的 OpenXR 会话( create_isaac_teleop_device(..., use_kit_xr_bridge=False) );遥操作输入/输出可无界面运行,无需 Kit XR 渲染。

不使用头显启动遥操作#

没有头显时,也没有客户端发送 start 命令,因此脚本在本地驱动状态机:

  • 启动时调用 request_start() ,将遥操作状态机切换为 RUNNING(见 遥操作控制状态(Start / Stop / Reset) ),使无界面会话立即开始运行,无需头显界面。

  • 存在 Kit 视口窗口时,还会绑定交互控制按键:

    按键

    操作

    B

    开始或恢复遥操作。

    P

    暂停遥操作(机器人保持当前位置)。

    R

    重置环境。

两种方式使用同一状态机,因此 request_start() / request_stop() 与头显远程命令可以互换使用, poll_control_events() 始终提供权威状态。

备注

没有客户端连接的 CloudXR 运行时不会报告头显,因此独立 OpenXR 会话需要一种在未连接客户端时也会报告系统的设备配置。省略 --xr 时,脚本默认将 --cloudxr_env 设为 CLOUDXR_STANDALONE_ENV ;传入该标志时则默认为 cloudxrjs 。见 CloudXR 环境配置文件 。

示例:SO-101 主控臂关节遥操作#

IsaacContrib-Stack-Cube-SO101-Joint-Teleop-v0 将真实 SO-101 主控臂传输的关节角直接映射到仿真从动臂,无需 XR 头显、逆向运动学或锚点。流水线为 JointStateSource -> JointStateRetargeter (mode="joint") -> TensorReorderer 。

完整流程,包括插件构建、硬件配置、校准、启动及数据集录制,见 Isaac Capture 文档中的 仿真中的数据采集 。以下前提条件是运行本示例的最低要求。

先决条件#

  • SO-101 硬件 :通过 USB 连接到工作站的真实 SO-101 主控臂。

  • 从 Isaac Capture 源代码构建的 so101_leader 插件 :主控臂关节状态由独立的 C++ 插件传输,需要与仿真同时运行。

    重要

    so101_leader_plugin 不随 Isaac Lab 提供, 不属于 isaacteleop pip 包,也不在任何发布压缩包中。只有从源代码构建 Isaac Capture 仓库后才会生成。如果 Isaac Capture 仓库中不存在 install/plugins/so101_leader/so101_leader_plugin ,说明尚未完成此步骤。

    先安装构建依赖。Linux 默认强制执行格式检查,因此缺少 clang-format-14 是构建失败最常见的原因:

    sudo apt-get update
    sudo apt-get install -y build-essential cmake libx11-dev clang-format-14 ccache patchelf
    

    然后克隆仓库,切换到与 Isaac Lab 固定的 isaacteleop 版本匹配的发布分支,再配置、构建并安装。根目录 pyproject.toml 的 teleop 额外依赖指定 isaacteleop~=1.4.145 ;分支匹配可确保插件的通信格式与 Isaac Lab 安装的 isaacteleop 包一致。要指定 Python 版本,在配置命令中传入 -DISAAC_TELEOP_PYTHON_VERSION=3.12 (或 3.11 、 3.13 );同时构建多个版本时,每个版本需要单独的构建目录:

    git clone https://github.com/NVIDIA/IsaacCapture.git
    cd IsaacCapture
    git checkout release/1.4.x
    
    cmake -B build                       # configure (default: Python 3.11)
    cmake --build build --parallel       # build
    cmake --install build                # install into ./install
    

    备注

    Isaac Lab 更新遥操作依赖时,应改为检出匹配的 release/<version>.x 分支。

    插件安装到 <IsaacCapture>/install/plugins/so101_leader/so101_leader_plugin 。本节后续所有命令都在 Isaac Capture 仓库根目录运行,请将 /path/to/IsaacCapture 替换为实际路径。先 不传任何参数 运行插件,以验证构建;此时会使用合成后端,无需连接硬件即可启动:

    cd /path/to/IsaacCapture
    ./install/plugins/so101_leader/so101_leader_plugin
    

    完整依赖列表及全部构建选项,见 从源代码构建 ;常见失败原因见 仿真中的数据采集 的构建故障排查表,包括 CMake 错误 clang-format not found but ENABLE_CLANG_FORMAT_CHECK is ON 。

  • 校准 :SO-101 机械臂使用前必须校准。插件直接与 FEETECH 舵机通信,不依赖 lerobot 或 FEETECH SDK,因此应使用它自身的 calibrate 子命令,无需 OpenXR 运行时。

    先确定串口。最简单的方法是使用 uvx ,它会在临时环境中运行 lerobot-find-port ,无需安装:

    uvx --from "lerobot[hardware]" lerobot-find-port
    

    也可以插入 USB 线后立即运行:

    sudo dmesg | grep tty | tail -1
    

    tail -1 只显示最近一条内核消息,因此输出会明确指出刚连接的设备,例如 [12345.6] usb ... ttyACM0 。将该路径( /dev/ttyACM0 、 /dev/ttyACM1 等)用于下文命令。

    cd /path/to/IsaacCapture
    ./install/plugins/so101_leader/so101_leader_plugin calibrate /dev/ttyACM0 so101_leader.calib
    

    校准包含两个交互步骤:先将机械臂保持在行程中间,再让每个关节走遍完整行程。随后写出校准文件,插件启动时读取它,将原始编码器值映射为关节角。也可传入现有的 LeRobot 校准 .json 。未经校准运行会使关节映射错误,从动臂无法跟踪主控臂。

    SO-101 主控臂保持在行程中间的校准姿态

    SO-101 主控臂处于第一步校准使用的行程中间姿态。#

    小技巧

    在行程中间校准这一步,也应如图所示将夹爪置于行程中点。完全打开或闭合可能导致夹爪映射错误。

运行仿真#

SO-101 工作流支持两种观察方式,根据是否有 XR 头显选择:

无头显(仅本地视口)

省略 --xr 。仿真以独立模式运行,启动时自动开启遥操作状态机,无需连接头显(见 不使用头显运行(独立 I/O) )。传入 --visualizer kit 可在本地 Kit 视口中观察从动臂;默认为无界面模式。

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-Stack-Cube-SO101-Joint-Teleop-v0 \
    --num_envs 1 \
    --visualizer kit \
    physics=isaacsim_physx
./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-Stack-Cube-SO101-Joint-Teleop-v0 \
    --num_envs 1 \
    --visualizer kit \
    physics=isaacsim_physx

有头显(沉浸式 XR 视图)

添加 --xr 可将仿真串流到 Quest、Pico 或 Apple Vision Pro 头显,同时仍由 SO-101 主控臂驱动从动臂关节。重定向流水线不变, --xr 只决定是否将场景渲染到头显。启动后,按 连接 XR 设备 的步骤连接头显。

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-Stack-Cube-SO101-Joint-Teleop-v0 \
    --num_envs 1 \
    --visualizer kit --xr \
    physics=isaacsim_physx
./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-Stack-Cube-SO101-Joint-Teleop-v0 \
    --num_envs 1 \
    --visualizer kit --xr \
    physics=isaacsim_physx

启动插件#

Isaac Lab 不会代您启动插件。请先启动仿真,它会启动插件连接所需的 CloudXR 运行时。然后在 另一个终端 中,加载运行时启动时写出的环境文件(将 OpenXR 加载器指向 CloudXR),再使用主控臂串口启动插件。请将 /dev/ttyACM0 替换为实际设备,串口识别方法见上文校准步骤:

cd /path/to/IsaacCapture
source ~/.cloudxr/run/cloudxr.env
./install/plugins/so101_leader/so101_leader_plugin /dev/ttyACM0 so101_leader so101_leader.calib

参数按位置传入: [device_path] [collection_id] [calibration_file] 。 collection_id 必须保持为 so101_leader ,它是该任务的 JointStateSource 订阅的张量集合。

完全不传参数 运行插件时,会向默认的 so101_leader 集合传输合成轨迹,适合在连接硬件前确认仿真侧连接正确。由于参数是位置参数,无法只跳过设备路径、却仍传入后两个参数:

./install/plugins/so101_leader/so101_leader_plugin   # synthetic, no hardware needed

全部配置选项见 SO-101 插件 README 和 仿真中的数据采集 。

启动遥操作#

不使用 --xr :脚本启动时自动调用 request_start() ,从动臂立即开始跟随主控臂,无需其他输入。

使用 --xr :可从已连接头显的界面发送 start 命令。Quest / Pico 使用 CloudXR.js 的 Connect 按钮,Apple Vision Pro 使用 Isaac XR Teleop Sample Client 的 Play 按钮。头显发送启动命令后,SO-101 开始驱动从动臂。

无论采用哪种模式,打开 Kit 视口时也可用键盘快捷键控制会话:

按键

操作

B

开始或恢复遥操作。

P

暂停遥操作(从动臂保持当前位置)。

R

重置环境。

备注

按 R 会重置环境, 同时暂停遥操作 ,不会自动恢复。这是有意设计的:该任务的关节遥操作流水线直接将主控臂原始关节角映射到从动臂,不做重新锚定,也没有离合控制。重置后立即恢复,会让从动臂突然移动到真实主控臂的当前位置,产生幅度较大的关节运动。按 B 恢复前,请先移动真实主控臂,使它与从动臂的重置姿态一致。

移动真实 SO-101 主控臂,仿真从动臂会实时跟随其关节角。要录制该任务的示范,请用相同的 --task 运行 scripts/tools/record_demos.py ,并在另一个终端保持插件运行。完整录制流程及运行时故障排查见 仿真中的数据采集 。

备注

堆好立方体后,请在结束回合前将夹爪 完全打开 。任务的成功判定要求夹爪全开;即使立方体已正确放置,夹爪仅部分打开并停在堆叠上方,也不会被判定为成功。

重定向框架#

Isaac Capture 使用基于计算图的重定向流水线。数据从 源节点 流经 重定向器 ,最终合并为一个动作张量。

源节点#

  • HandsSource :提供手部跟踪数据,左右手各 26 个关节。

  • ControllersSource :提供运动控制器数据,包括握持位姿、扳机、摇杆等。

可用的重定向器#

重定向器由 Isaac Capture 仓库的 isaacteleop 包提供。以下列出 Isaac Lab 内置环境使用的重定向器。Isaac Capture 可能提供其他未列出的重定向器,完整列表见 Isaac Capture 仓库 。

Se3AbsRetargeter / Se3RelRetargeter

将手部或控制器跟踪数据映射到末端执行器位姿。 Se3AbsRetargeter 输出 7 维绝对位姿(位置 + 四元数), Se3RelRetargeter 输出 6 维增量。可配置旋转偏移(以度为单位的滚转、俯仰、偏航角)。

GripperRetargeter

输出单个浮点数(-1.0 为闭合,1.0 为打开)。优先使用控制器扳机,也可使用手部跟踪中的拇指与食指捏合距离。

DexHandRetargeter / DexBiManualRetargeter

通过 dex-retargeting 库,将完整的 26 关节手部跟踪数据重定向为特定机器人手的关节角。需要机器人手的 URDF 及 YAML 配置文件。

警告

用于重定向的连杆必须定义在真实指尖处,而非手指中部,以保证优化准确。

TriHandMotionControllerRetargeter

将 VR 控制器按钮(扳机、握持按钮)映射到 G1 TriHand 关节,每只手 7 自由度。映射方式简单:扳机控制食指,握持按钮控制中指,两者同时按下控制拇指。

LocomotionRootCmdRetargeter

将控制器摇杆映射为 4 维移动命令: [vel_x, vel_y, rot_vel_z, hip_height] 。

TensorReorderer

将多个重定向器的输出展平并重新排序,组成单个一维动作张量。 output_order 必须与环境要求的动作空间一致。

Isaac Lab 内置环境按以下方式使用重定向器:

环境

使用的重定向器

Franka 操作(堆叠、抓取放置)

Se3AbsRetargeter, GripperRetargeter, TensorReorderer

G1 Inspire 灵巧抓取放置

Se3AbsRetargeter, DexHandRetargeter, TensorReorderer

GR1-T2 灵巧抓取放置

Se3AbsRetargeter, DexHandRetargeter, TensorReorderer

G1 上半身(固定基座)

Se3AbsRetargeter, TriHandMotionControllerRetargeter, TensorReorderer

G1 移动操作

Se3AbsRetargeter, TriHandMotionControllerRetargeter, LocomotionRootCmdRetargeter, TensorReorderer

遥操作环境参考#

下表按输入方式列出所有支持遥操作的 Isaac Lab 内置环境。闭环策略评估时,回放脚本会自动应用各环境配置的 play_mode 覆盖设置;传入 --train_env_cfg 可直接使用原始训练配置回放。

Isaac Capture(XR 头显)环境#

这些环境使用 Isaac Capture XR 流水线,支持运动控制器或手部跟踪。

任务 ID

输入模式

使用的手

操作者交互方式

IsaacContrib-Stack-Cube-Franka-IK-Abs

控制器

右手

机械臂: 右控制器握持位姿驱动末端执行器。 夹爪: 右扳机。

IsaacContrib-Stack-Cube-SO101-IK-Abs-v0 ,使用 physics=isaacsim_physx

控制器

右手

机械臂: 右控制器握持位姿通过绝对 IK 驱动末端执行器,离合操作会重设参考基准;IK 跟踪位置,朝向作为加权软目标。 夹爪: 右扳机(模拟量)。

IsaacContrib-PickPlace-GR1T2-Abs

手部跟踪

双手

机械臂: 左右手手腕位姿分别驱动对应末端执行器。 手: 完整的 26 关节手部跟踪数据通过 DexHandRetargeter 重定向到每只 Fourier 手的 11 个自由度。

IsaacContrib-PickPlace-GR1T2-WaistEnabled-Abs

手部跟踪

双手

与 IsaacContrib-PickPlace-GR1T2-Abs 相同,但启用腰部自由度。

IsaacContrib-NutPour-GR1T2-Pink-IK-Abs

手部跟踪

双手

重定向流水线与 IsaacContrib-PickPlace-GR1T2-Abs 相同,任务场景不同。

IsaacContrib-ExhaustPipe-GR1T2-Pink-IK-Abs

手部跟踪

双手

重定向流水线与 IsaacContrib-PickPlace-GR1T2-Abs 相同,任务场景不同。

IsaacContrib-PickPlace-G1-InspireFTP-Abs

手部跟踪

双手

机械臂: 左右手手腕位姿分别驱动对应末端执行器。 手: 完整的 26 关节手部跟踪数据通过 DexHandRetargeter 重定向到每只 Inspire 手的 12 个自由度。

IsaacContrib-PickPlace-FixedBaseUpperBodyIK-G1-Abs

控制器

双手

机械臂: 左右控制器握持位姿分别驱动对应末端执行器。 手: 扳机闭合食指,握持按钮闭合中指,两者同时按下闭合拇指;每只 TriHand 有 7 个自由度。

IsaacContrib-PickPlace-Locomanipulation-G1-Abs

控制器

双手

机械臂: 与上述固定基座 G1 相同。 手: 使用相同 TriHand 映射。 移动: 左摇杆控制线速度(x/y),右摇杆 X 控制转动速度,右摇杆 Y 控制髋部高度。

小技巧

控制器 提供握持位姿及实体按钮(扳机、握持按钮、摇杆),适合需要夹爪或简单手部映射的任务。 手部跟踪 采集每只手的 26 个手腕和手指关节,是复杂机器人手灵巧重定向所必需的数据。

键盘与 SpaceMouse 环境#

备注

键盘和 SpaceMouse 遥操作使用原有的 Isaac Lab 原生遥操作组件( isaaclab.devices ),不使用 Isaac Capture。这些环境无需 XR 头显。

以下设备按键布局适用于本节所有环境。各环境的差异,如夹爪是否启用、灵敏度设置,见后面的环境表。

键盘

功能

按键

描述

X 方向位置

W / S

末端执行器向前 / 向后移动。

Y 方向位置

A / D

末端执行器向左 / 向右移动。

Z 方向位置

Q / E

末端执行器向上 / 向下移动。

滚转

Z / X

绕 X 轴旋转。

俯仰

T / G

绕 Y 轴旋转。

偏航

C / V

绕 Z 轴旋转。

切换夹爪状态

K

打开 / 关闭夹爪或吸附装置(Reach 环境中禁用)。

重置

L

清除累计位姿增量和夹爪状态。

SpaceMouse

功能

控制方式

描述

平移

6 自由度控制帽

推、拉或平移控制帽,使末端执行器沿 X/Y/Z 方向移动。

旋转

6 自由度控制帽

倾斜或扭转控制帽,控制末端执行器的滚转、俯仰和偏航。

切换夹爪状态

左侧按钮

打开 / 关闭夹爪或吸附装置(Reach 环境中禁用)。

重置

右侧按钮

清除累计位姿增量和夹爪状态。

游戏手柄 (仅 Reach 环境)

功能

控制方式

描述

X / Y 方向位置

左摇杆

末端执行器前后、左右移动。

Z 方向位置

右摇杆(上下)

末端执行器向上 / 向下移动。

滚转 / 俯仰

方向键

左右控制滚转,上下控制俯仰。

偏航

右摇杆(左右)

绕 Z 轴旋转。

切换夹爪状态

X 按钮

打开 / 关闭夹爪(Reach 环境中禁用)。

任务 ID

设备

操作者交互方式

IsaacContrib-Stack-Cube-Galbot-Left-Arm-Gripper-RmpFlow

键盘、SpaceMouse

机械臂: 通过 RMPFlow 控制末端位姿。 夹爪: 键盘 K 或 SpaceMouse 左侧按钮。

IsaacContrib-Stack-Cube-Galbot-Right-Arm-Suction-RmpFlow

注意: 使用 RMPFlow 控制器遥操作时,应避免碰撞立方体;接触力会导致控制器过度调整,机械臂发生漂移。请将末端移到立方体正上方附近,停住,再闭合吸盘。

仅支持 CPU 仿真: 遥操作时传入 --device cpu 。

键盘、SpaceMouse

机械臂: 通过 RMPFlow 控制末端位姿。 吸附: 键盘 K 或 SpaceMouse 左侧按钮。

IsaacContrib-Stack-Cube-Galbot-Left-Arm-Gripper-Visuomotor

键盘、SpaceMouse

与上述左臂夹爪任务相同,但增加相机观测。

IsaacContrib-Place-Mug-Agibot-Left-Arm-RmpFlow

键盘、SpaceMouse

机械臂: 通过 RMPFlow 控制左臂末端位姿。 夹爪: 键盘 K 或 SpaceMouse 左侧按钮。

IsaacContrib-Place-Toy2Box-Agibot-Right-Arm-RmpFlow

键盘、SpaceMouse

机械臂: 通过 RMPFlow 控制右臂末端位姿。 夹爪: 键盘 K 或 SpaceMouse 左侧按钮。

IsaacContrib-Stack-Cube-UR10-Long-Suction-IK-Rel

仅支持 CPU 仿真: 遥操作时传入 --device cpu 。

键盘、SpaceMouse

机械臂: 相对 IK 末端控制。 吸附: 键盘 K 或 SpaceMouse 左侧按钮。

IsaacContrib-Stack-Cube-UR10-Short-Suction-IK-Rel

仅支持 CPU 仿真: 遥操作时传入 --device cpu 。

键盘、SpaceMouse

与上述长吸盘 UR10 任务相同,但使用较短吸盘。

Isaac-Reach-Franka ,使用 physics=isaacsim_physx presets=diffik

键盘、游戏手柄、SpaceMouse

机械臂: 相对 IK 末端控制。夹爪禁用。

Isaac-Reach-Franka ,使用 physics=newton_mjwarp presets=newton_ik

键盘、游戏手柄、SpaceMouse

机械臂: 相对 Newton IK 末端控制。夹爪禁用。

备注

人形机器人机械臂(如 Galbot、Agibot)存在逆向运动学必须遵守的关节限位。微分 IK 控制器忽略这些限位,因此遥操作时更推荐 RMPFlow,它在求解 IK 时会约束关节范围。由此,目标位姿在限位内不可达时,机械臂偶尔会停止响应;这是预期行为,并非错误。

主控臂环境#

这些环境由真实的 主控臂 驱动,通过 Isaac Capture 张量传输通道发送关节角,直接映射到仿真从动臂,无需 XR 头显或逆向运动学。运行命令及流水线见上文 示例:SO-101 主控臂关节遥操作 。

任务 ID

设备

操作者交互方式

IsaacContrib-Stack-Cube-SO101-Joint-Teleop-v0 ,使用 physics=isaacsim_physx

SO-101 主控臂

机械臂 + 夹爪: 主控臂的六个关节角(5 个机械臂自由度 + 夹爪)通过 JointStateRetargeter ( mode="joint" )映射到从动臂。

在控制器与手部跟踪之间切换#

重定向流水线决定环境采用运动控制器还是手部跟踪。切换输入模式需要修改环境配置的 pipeline_builder 函数。只要动作空间( TensorReorderer 输出顺序)不变,就不需要其他环境级修改。

从控制器切换到手部跟踪

主要修改如下:

  1. 创建 HandsSource 并对其应用世界坐标系与锚点之间的变换,替代 ControllersSource 。

  2. 将 Se3RetargeterConfig.input_device 指向对应的 HandsSource 键。

  3. 设置 use_wrist_rotation=True 和 use_wrist_position=True ,使 SE3 重定向器读取手腕关节,而非控制器握持位姿。

  4. GripperRetargeter 已支持两种输入:连接 ControllersSource 时使用控制器扳机,连接 HandsSource 时使用拇指与食指捏合。

以下并列展示 Franka 堆叠环境基于控制器的流水线及其手部跟踪变体,便于比较。

原始版本(基于控制器):

# SE3: tracks right controller grip pose
se3_cfg = Se3RetargeterConfig(
    input_device=ControllersSource.RIGHT,
    use_wrist_rotation=False,
    use_wrist_position=False,
    target_offset_roll=90.0,
)
se3 = Se3AbsRetargeter(se3_cfg, name="ee_pose")
connected_se3 = se3.connect({
    ControllersSource.RIGHT: transformed_controllers.output(
        ControllersSource.RIGHT
    ),
})

修改后(基于手部跟踪):

se3_cfg = Se3RetargeterConfig(
    input_device=HandsSource.RIGHT,
    use_wrist_rotation=True,
    use_wrist_position=True,
    target_offset_roll=0.0,
)
se3 = Se3AbsRetargeter(se3_cfg, name="ee_pose")

transformed_hands = hands.transformed(transform_input.output(ValueInput.VALUE))
connected_se3 = se3.connect({
    HandsSource.RIGHT: transformed_hands.output(HandsSource.RIGHT),
})

GripperRetargeter 无需修改,它接受控制器和手部输入,并使用已连接的数据源。

从手部跟踪切换到控制器

反向执行上述步骤:将 input_device 设为 ControllersSource 的键,对控制器而非手部应用变换,设置 use_wrist_rotation=False 和 use_wrist_position=False 。调整 target_offset_roll/pitch/yaw ,补偿控制器握持坐标系的朝向;Franka 类夹爪通常需要 90 度滚转偏移。

备注

切换输入模式时,可能需要调整 target_offset_roll 、 target_offset_pitch 和 target_offset_yaw 。相对于机器人末端执行器,控制器握持坐标系与手腕坐标系的默认朝向不同。

构建重定向流水线#

流水线构建器是一个可调用对象,负责构建重定向计算图,并返回仅包含 "action" 键的 OutputCombiner 。以下是 Franka 机械臂的完整示例,来自 stack_ik_abs_env_cfg.py :

def _build_franka_stack_pipeline():
    from isaacteleop.retargeting_engine.deviceio_source_nodes import ControllersSource, HandsSource
    from isaacteleop.retargeting_engine.interface import OutputCombiner, ValueInput
    from isaacteleop.retargeters import (
        GripperRetargeter, GripperRetargeterConfig,
        Se3AbsRetargeter, Se3RetargeterConfig,
        TensorReorderer,
    )
    from isaacteleop.retargeting_engine.tensor_types import TransformMatrix

    # 1. Create input sources
    controllers = ControllersSource(name="controllers")
    hands = HandsSource(name="hands")

    # 2. Apply coordinate-frame transform (world_T_anchor provided by IsaacTeleopDevice)
    transform_input = ValueInput("world_T_anchor", TransformMatrix())
    transformed_controllers = controllers.transformed(
        transform_input.output(ValueInput.VALUE)
    )

    # 3. Create and connect retargeters
    se3_cfg = Se3RetargeterConfig(
        input_device=ControllersSource.RIGHT,
        target_offset_roll=90.0,
    )
    se3 = Se3AbsRetargeter(se3_cfg, name="ee_pose")
    connected_se3 = se3.connect({
        ControllersSource.RIGHT: transformed_controllers.output(ControllersSource.RIGHT),
    })

    gripper_cfg = GripperRetargeterConfig(hand_side="right")
    gripper = GripperRetargeter(gripper_cfg, name="gripper")
    connected_gripper = gripper.connect({
        ControllersSource.RIGHT: transformed_controllers.output(ControllersSource.RIGHT),
        HandsSource.RIGHT: hands.output(HandsSource.RIGHT),
    })

    # 4. Flatten into a single action tensor with TensorReorderer
    ee_elements = ["pos_x", "pos_y", "pos_z", "quat_x", "quat_y", "quat_z", "quat_w"]
    reorderer = TensorReorderer(
        input_config={
            "ee_pose": ee_elements,
            "gripper_command": ["gripper_value"],
        },
        output_order=ee_elements + ["gripper_value"],
        name="action_reorderer",
        input_types={"ee_pose": "array", "gripper_command": "scalar"},
    )
    connected_reorderer = reorderer.connect({
        "ee_pose": connected_se3.output("ee_pose"),
        "gripper_command": connected_gripper.output("gripper_command"),
    })

    # 5. Return OutputCombiner with "action" key
    return OutputCombiner({"action": connected_reorderer.output("output")})

小技巧

TensorReorderer 的 output_order 必须与环境动作空间一致。不一致会导致控制错误,却不会报错。

配置环境#

通过 IsaacTeleopCfg 在环境配置中注册流水线:

from isaaclab_teleop import IsaacTeleopCfg, XrCfg

@configclass
class MyTeleopEnvCfg(ManagerBasedRLEnvCfg):

    xr: XrCfg = XrCfg(anchor_pos=(0.5, 0.0, 0.5))

    def __post_init__(self):
        super().__post_init__()

        self.isaac_teleop = IsaacTeleopCfg(
            pipeline_builder=_build_my_pipeline,
            sim_device=self.sim.device,
            xr_cfg=self.xr,
        )

IsaacTeleopCfg 的主要字段:

  • pipeline_builder :返回 OutputCombiner 的可调用对象,该对象包含 "action" 输出。

  • retargeters_to_tune :可选的可调用对象,返回要在实时调参界面中显示的重定向器。

  • xr_cfg :用于锚点配置的 XrCfg ,见下文。

  • xr_camera_feeds :按顺序选择现有任务相机,并设置各路画面的面板。列表默认为空,任务需显式启用画中画(PiP)。

  • xr_camera_feed_layout :查看者参考位姿、固定世界位姿,以及手动、水平、垂直或网格面板布局。

  • plugins :Isaac Capture 插件配置列表,如 Manus。

  • sim_device :torch 设备字符串,默认为 "cuda:0" 。

  • retargeting_execution :Isaac Capture 重定向执行设置。默认使用 RetargetingExecutionConfig(mode="pipelined") ,搭配 DeadlinePacingConfig(safety_margin_s=0.025) ,让重定向在 Isaac Capture 工作线程上运行,避免阻塞仿真循环。25 ms 安全余量使 Isaac Capture 的 Python 执行稍晚于 Isaac Lab 仿真步的 Python 执行,让渲染等原生操作有机会并行,而非两套 Python 组件在仿真步开始时争用 GIL。

警告

pipeline_builder 和 retargeters_to_tune 必须是 可调用对象 (函数或 lambda),不能是预先构建的对象。 @configclass 装饰器会深拷贝可变属性,破坏预先构建的流水线计算图。

CloudXR 环境配置文件#

Isaac Lab 附带三份配置 CloudXR 运行时的 .env 文件,两份用于 XR 设备,一份用于无界面的独立模式。它们包含在 isaaclab_teleop 包中,可通过常量引用:

常量

文件

NV_DEVICE_PROFILE

NV_CXR_ENABLE_PUSH_DEVICES

NV_ENABLE_POSE_WAIT

CLOUDXR_JS_ENV

cloudxrjs-cloudxr.env

auto-webrtc

0

0

CLOUDXR_AVP_ENV

avp-cloudxr.env

auto-native

0

0

CLOUDXR_STANDALONE_ENV

cloudxr-standalone.env

quest3

0

0

三份配置均设置 NV_CXR_ENABLE_PUSH_DEVICES=0 ,适用于头显光学手部跟踪这一最常见配置。对于 Manus 手套等主动推送数据的外部设备,请在自定义配置中改为 1 ,见下文。它们也设置 NV_ENABLE_POSE_WAIT=0 ,防止帧耗时突增时 CloudXR 限制应用速度。这优先保证低延迟,而非采用 CloudXR 的位姿等待平滑机制。

不使用 --xr 时,默认采用 CLOUDXR_STANDALONE_ENV (见 不使用头显运行(独立 I/O) )。它固定使用模拟的 quest3 设备配置,使没有客户端连接的 CloudXR 运行时仍能报告 OpenXR 系统,避开 XR_ERROR_FORM_FACTOR_UNAVAILABLE 。

启动时覆盖配置#

teleop_se3_agent.py 和 record_demos.py 的 --cloudxr_env 标志选择 .env 配置文件。未设置时,使用 --xr 默认采用 cloudxrjs (Quest/Pico),不使用则采用 standalone 。Apple Vision Pro 可使用 avp 简写,无界面配置可使用 standalone ,自定义配置可传入完整文件路径:

# Use the AVP profile
uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-GR1T2-WaistEnabled-Abs \
    --visualizer kit --xr \
    --cloudxr_env avp
# Use the AVP profile
./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-PickPlace-GR1T2-WaistEnabled-Abs \
    --visualizer kit --xr \
    --cloudxr_env avp

创建自定义配置#

复制附带的配置文件并编辑:

# Start from the Quest/Pico profile
cp $(uv run --extra teleop,isaacsim python -c \
    "from isaaclab_teleop import CLOUDXR_JS_ENV; print(CLOUDXR_JS_ENV)") ~/my-cloudxr.env

编辑 ~/my-cloudxr.env ,修改所需值,如为 Manus 手套设置 NV_CXR_ENABLE_PUSH_DEVICES=1 ,然后通过 --cloudxr_env ~/my-cloudxr.env 传入。

关闭自动启动#

如果希望在另一终端手动运行 CloudXR 运行时( python -m isaacteleop.cloudxr ),可通过以下方式关闭自动启动:

  • 命令行标志 :遥操作脚本的 --no-auto_launch_cloudxr 。

  • 完全禁用 CloudXR : --cloudxr_env none 。

  • 环境变量 : ISAACLAB_CXR_SKIP_AUTOLAUNCH=1 在运行时覆盖命令行标志。

# Disable via CLI flag
uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit --xr \
    --no-auto_launch_cloudxr

# Or disable via environment variable
ISAACLAB_CXR_SKIP_AUTOLAUNCH=1 uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit --xr
# Disable via CLI flag
./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit --xr \
    --no-auto_launch_cloudxr

# Or disable via environment variable
ISAACLAB_CXR_SKIP_AUTOLAUNCH=1 ./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit --xr

非交互式接受 CloudXR 许可证#

NVIDIA CloudXR 许可证与 Omniverse 许可证相互独立。运行时首次启动会从标准输入请求接受许可证:

NVIDIA CloudXR EULA must be accepted to run. View: <license URL>

Accept NVIDIA CloudXR EULA? [y/N]:

无界面、容器或 CI 运行中没有终端可响应,启动会失败并报 RuntimeError: CloudXR EULA was not accepted; cannot start the runtime 。设置 ISAACLAB_CXR_ACCEPT_EULA=1 可预先接受许可证,方式与 Omniverse 许可证的 OMNI_KIT_ACCEPT_EULA 相同:

ISAACLAB_CXR_ACCEPT_EULA=1 ./isaaclab.sh -p scripts/environments/teleoperation/teleop_se3_agent.py \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --xr

y 、 yes 和 1 表示接受,不区分大小写,忽略首尾空白,与 OMNI_KIT_ACCEPT_EULA 的取值相同。未设置变量或设为其他值时,仍保留交互提示。接受记录存储在 ~/.cloudxr/run/eula_accepted ;一旦通过交互或此变量接受许可证,后续运行就不再询问。该变量适用于所有启动运行时的脚本,包括 teleop_replay_agent.py 中进程级的启动器。

配置 XR 锚点#

XrCfg 控制仿真在 XR 设备视野中的位置和朝向。

anchor_pos / anchor_rot

静态锚点位置。仿真中位于这些坐标的点,会出现在 XR 设备的局部原点(地面高度)。将其设为机器人下方的地面点,可把机器人放到用户面前。

anchor_prim_path

将锚点附着到 USD prim,实现动态定位。适用于机器人移动、XR 相机需要跟随的运动任务。

anchor_rotation_mode

控制锚点旋转行为:

模式

描述

FIXED

根据 anchor_rot 设置一次旋转,适合静态操作场景。

FOLLOW_PRIM

旋转持续跟随所附着的 prim,适合用户应面向机器人前进方向的运动任务。

FOLLOW_PRIM_SMOOTHED

与 FOLLOW_PRIM 相同,但使用球面线性插值(slerp)。由 anchor_rotation_smoothing_time 控制,单位为秒,默认为 1.0。可减轻旋转突变引起的晕动不适,典型范围为 0.3–1.5 秒。

CUSTOM

用户提供的可调用对象 anchor_rotation_custom_func(headpose, primpose) -> quaternion ,用于完全自定义逻辑。

fixed_anchor_height

为 True (默认)时,锚点高度保持初始值,避免运动过程中上下起伏。

near_plane

XR 设备的最近渲染距离,默认为 0.15 m。

备注

在 Apple Vision Pro 上,本地坐标系可以通过按住数字表冠重置到用户下方的地板上的位置。

小技巧

相机传感器会增加 GPU 开销。工作流既不需要图像观测,也不需要 XR 相机反馈时,可用 --disable_external_cameras 移除它们;该标志也会跳过已配置的画中画画面。

XR 相机反馈#

有序的 XrCameraFeedCfg 对象列表用于选择任务场景中现有的相机。管理器在渲染后发布每个新 RGBA 帧, XrCameraFeedLayoutCfg 则按手动、水平、垂直或网格布局放置面板。以下已注册任务默认启用画中画:

  • IsaacContrib-PickPlace-GR1T2-Abs

  • IsaacContrib-NutPour-GR1T2-Pink-IK-Abs

  • IsaacContrib-ExhaustPipe-GR1T2-Pink-IK-Abs

  • IsaacContrib-PickPlace-Locomanipulation-G1-Abs

  • IsaacContrib-PickPlace-FixedBaseUpperBodyIK-G1-Abs

两个 G1 任务都在 head_locked 面板中显示已校准的头部相机画面,面板随头显位置和朝向移动。移动操作任务保留相机作为录制的策略观测;固定基座 G1 仅将其用于画中画,策略观测结构不变。

使用默认的头部锁定画中画运行固定基座 G1 上半身遥操作:

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-FixedBaseUpperBodyIK-G1-Abs \
    --num_envs 1 --xr --device cpu

此任务使用运动控制器操纵机械臂及 TriHand 手指,机器人根部保持固定。面板跟随头显,但画面来自机器人头部相机,而非头显视图。 --device cpu 选择 CPU 仿真,相机渲染和 CloudXR 编码仍使用 GPU。

启用 Isaac Capture 的环境使用 --xr 运行时, teleop_se3_agent.py 和 record_demos.py 会显示所有已启用的画面。只有任务通过 xr_camera_feeds 显式选择现有的 CameraCfg 时,才会显示画中画。除固定基座 G1 外,被选中的 robot_pov_cam 也作为策略图像观测,因此常规示范录制器会保存与操作者看到的相同画面。每个相机都以机器人的实体连杆为父对象,因此视图随机器人运动:

XR 遥操作视图,画中画面板显示机器人视角相机画面

XR 遥操作期间,以画中画面板显示机器人视角相机反馈。#

警告

没有场景分区隔离时,画中画面板进入其源相机视野,会产生递归的镜中镜效果。请移动面板或调整相机朝向,让面板保持在相机视野之外。

两个 G1 任务都启用 use_scene_partition ,避免递归。环境构造前的准备阶段,会暂时禁用所选 Isaac RTX 相机渲染器的逐环境分区。绑定阶段在渲染器初始化后、创建面板前,将 /rtx/scenePartitioning/showAllPartitionsByDefault=False 。几何体一开始必须是共享且未分区的背景;相机初始化后才清除其分区,可能导致它在 XR 中不可见。其他场景相机也必须设置 enable_scene_partitioning=False 。

SceneUI 适配器将 XR 相机和 /ui 分配到 isaaclab_teleop_xr_camera_pip ,在 SceneUI 子对象出现时刷新继承。机器人相机看到不含 UI 的共享背景,XR 则同时看到两者。XR/UI 覆盖写入会话层。最后一个使用者关闭后,原先的相机、渲染器和分区设置会恢复,除非期间被外部修改。最后一个完成准备的会话关闭后恢复相机配置;最后一个已绑定会话关闭后,将全局设置恢复为绑定时的值。即使环境构造失败,已准备的会话也必须关闭;遥操作与录制脚本会处理这项清理。跟踪或隔离不可用时,面板保持隐藏,恢复后重新显示。其他任务保留原有行为,因为 use_scene_partition 默认为 False 。

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-GR1T2-Abs \
    --xr --device cpu

XR 相机画中画目前仅支持一个环境。任务启用画中画时,启动阶段会拒绝任何不为 1 的 --num_envs 值;不使用画中画时,Isaac Capture XR 的行为不变。对于两个 G1 任务,都可设置 env.isaac_teleop.xr_camera_feeds=[] 来关闭画中画,同时保留相机传感器及已配置的相机观测。

参考画面配置通过 XrCameraFeedCfg 请求渲染产物局部的 DLSS 光线重建,以及 quality 执行模式。内部画中画适配器只在所选相机的渲染产物上写入这两个属性。光线重建还需要进程全局的响应式降噪设置;所选画面请求光线重建时,遥操作和录制脚本会在构造环境前启用它。

相机选择#

任务通过 IsaacTeleopCfg.xr_camera_feeds 声明默认选择:

from isaaclab_teleop import IsaacTeleopCfg, XrCameraFeedCfg

self.isaac_teleop = IsaacTeleopCfg(
    pipeline_builder=_build_my_pipeline,
    xr_camera_feeds=[
        XrCameraFeedCfg(
            camera_name="left_wrist_camera",
            enable_dlss_ray_reconstruction=True,
            dlss_exec_mode="quality",
        ),
        XrCameraFeedCfg(camera_name="overview_camera", enabled=False),
    ],
)

要录制训练视图,请在任务场景中定义命名的 CameraCfg ,并在 observations.policy 中定义匹配的 mdp.image_rgb 项。常规录制器随后会存储该观测,上面的画中画声明只负责选择显示内容。任务声明中已启用的条目控制相机选择、面板数量、显示顺序和自动布局顺序,不修改可复用的任务配置。

放置方式#

默认 placement 为 "viewer_start" 。显示组件等待首个有效头显位姿,记录眼部位置和水平偏航角,再将布局放到眼睛高度、前方 0.8 m 处。用户移动时,该位姿仍固定在世界坐标系中。XR 显示断开时面板隐藏,重新连接后采集新的起始位姿;重置环境不会重新居中。

支持三种放置参考:

放置方式

行为

viewer_start

记录首个有效眼部位置及水平偏航角,然后将布局固定在世界坐标系中。这是默认方式。

head_locked

按所配置的偏移和距离,跟随当前头显位置及朝向。

world

以 world_position_m 和 world_orientation_xyzw 指定 Isaac Lab USD 舞台世界坐标系中的固定位姿。此时不使用 distance_m 。

from isaaclab_teleop import XrCameraFeedLayoutCfg

# Default: fixed in the world at the user's starting eye pose.
self.isaac_teleop.xr_camera_feed_layout = XrCameraFeedLayoutCfg()

# Follow the headset and pack feeds left to right.
self.isaac_teleop.xr_camera_feed_layout = XrCameraFeedLayoutCfg(
    placement="head_locked",
    mode="horizontal",
    distance_m=0.8,
)

# Place a grid in an Isaac Lab Z-up world. This example assumes an eye at
# (0, 0, 1.6) looking along world +Y.
self.isaac_teleop.xr_camera_feed_layout = XrCameraFeedLayoutCfg(
    placement="world",
    mode="grid",
    world_position_m=(0.0, 0.8, 1.6),
    world_orientation_xyzw=(0.7071067812, 0.0, 0.0, 0.7071067812),
    max_columns=2,
)

manual 模式保留各路画面的 offset_m 和 distance_m 。 horizontal 、 vertical 和 grid 模式根据 panel_gap_m ,围绕 center_offset_m 排列已启用的画面;网格模式还遵循 max_columns 。偏移在所选布局平面内测量。采用 viewer_start 和 head_locked 时, distance_m 将该平面放在查看者参考位置前方。手动模式下,相同偏移的画面会重叠;显示多个面板时,请选自动模式或分别设置不同偏移。

采用 world 时,显式位姿以米为单位,定义在 Isaac Lab USD 舞台世界坐标系中,而非 OpenXR 物理空间。Isaac Lab 舞台以 Z 轴朝上。 world_orientation_xyzw 将面板局部坐标映射到世界坐标系:局部 +X 指向图像右方,+Y 指向上方,+Z 从可读面朝向查看者。各路画面及自动布局的偏移都应用在面板局部 XY 平面内。

关闭相机与画中画#

将 enabled 设为 False 可隐藏一路画面,设置 xr_camera_feeds=[] 可隐藏全部画中画。列表默认为空。这些设置不会移除任务独立持有的相机传感器。

--disable_external_cameras 是 teleop_se3_agent.py 和 record_demos.py 的相机渲染总开关,会移除相机传感器,并禁用所有已配置的画中画。

Kit Scene UI 显示方式#

画中画通过 Kit Scene UI 显示,并使用 SpatialSource 定位。只有请求已启用的画面时,才会导入 Kit 模块。如果 Scene UI 模块无法导入,脚本会记录警告,继续运行但不显示画中画;任务自身的相机及录制观测不变。因此,未来不再提供 Scene UI 的无 Kit 入口仍可使用相机选择配置。渲染产物调优也会尽可能应用:没有兼容渲染产物的后端保留 Camera 缓冲区方式,模式属性写入失败时发出警告,但画中画继续运行。其他配置、相机缓冲区及面板初始化错误仍会导致启动失败。

触觉反馈#

Isaac Capture 可将仿真侧信号转换为操作者设备上的 触觉反馈 ,在遥操作和示范录制时提供抓取感觉的闭环反馈。目前附带两种后端:

  • 控制器振动 :运动控制器按对应机器人手的总接触力大小振动。

  • 触觉手套 :每根手指按该手指抓紧被操作物体的程度振动。

反馈是一条 输出 通路,可看作输入重定向流水线的反向映射。每步, HapticFeedbackDriver 从场景读取各只手的信号向量,并推送给 IsaacTeleopDevice ,后者通过 Isaac Capture 的 HapticSink 输出触觉反馈。信号到设备的映射在重定向计算图内运行,环境中无需包含设备专用代码。

设计将三部分做成可替换组件,让同一接口适用于两种设备:

  • 信号源 :如何从环境读取各只手的向量。

  • 输出端口 : HapticFeedbackReceiver 协议,传输的是 向量,振动电机为一个标量,手套则每根手指一个值。

  • 设备后端 :由具体的 HapticFeedbackCfg 子类选择,在 HapticSink 后连接重定向器和设备。

启用反馈时,为每只手在场景中添加 ContactSensor ,并将 HapticFeedbackCfg 子类配置放在与 isaac_teleop 同级的位置。遥操作脚本( teleop_se3_agent.py 和 record_demos.py )会自动检测 haptic_feedback 属性,无需额外标志。如果当前设备无法输出触觉反馈(如键盘),或环境没有 haptic_feedback ,则直接跳过该功能。

控制器振动#

使用 ControllerHapticFeedbackCfg 。它将每只手的接触力汇总为一个振幅,通过 amplitude = clamp(gain * (force - deadband), 0, saturation) 映射。字段包括 gain [1/N]、 deadband [N]、 saturation ,以及脉冲的 frequency_hz / duration_s 。

from isaaclab.sensors import ContactSensorCfg
from isaaclab_teleop import ControllerHapticFeedbackCfg

@configclass
class MySceneCfg(InteractiveSceneCfg):
    left_hand_contact = ContactSensorCfg(
        prim_path="{ENV_REGEX_NS}/Robot/left_hand_.*_link", update_period=0.0, history_length=3
    )
    right_hand_contact = ContactSensorCfg(
        prim_path="{ENV_REGEX_NS}/Robot/right_hand_.*_link", update_period=0.0, history_length=3
    )

# in the env cfg __post_init__:
self.scene.robot.spawn.activate_contact_sensors = True
self.haptic_feedback = ControllerHapticFeedbackCfg(
    left_sensor_name="left_hand_contact",
    right_sensor_name="right_hand_contact",
)

两个 G1 遥操作环境( IsaacContrib-PickPlace-Locomanipulation-G1-Abs 、 IsaacContrib-PickPlace-FixedBaseUpperBodyIK-G1-Abs )已启用该功能。控制器振动通过 OpenXR( xrApplyHapticFeedback )传输,无需修改 CloudXR .env 配置。

触觉手套(逐指抓握反馈)#

使用 GloveHapticFeedbackCfg 。每只手的接触传感器 只筛选与被抓取物体的接触 ( filter_prim_paths_expr ),因此 normal_force_matrix_w 仅报告各手指对该物体的力。驱动器按拇指到小指排序各指的力大小,通过 finger_order 匹配传感器刚体名称,组成 FingerPowerVector ,由 collection_id 上跨进程的手套设备输出。

from isaaclab.sensors import ContactSensorCfg
from isaaclab_teleop import GloveHapticFeedbackCfg

@configclass
class MySceneCfg(InteractiveSceneCfg):
    object = RigidObjectCfg(prim_path="{ENV_REGEX_NS}/Object", ...)
    left_hand_contact = ContactSensorCfg(
        prim_path="{ENV_REGEX_NS}/Robot/.*L_(thumb_distal|index_intermediate|"
        "middle_intermediate|ring_intermediate|pinky_intermediate)_link",
        filter_prim_paths_expr=["{ENV_REGEX_NS}/Object"],
        update_period=0.0, history_length=3,
    )
    right_hand_contact = ContactSensorCfg(
        prim_path="{ENV_REGEX_NS}/Robot/.*R_(...)_link",
        filter_prim_paths_expr=["{ENV_REGEX_NS}/Object"],
        update_period=0.0, history_length=3,
    )

# in the env cfg __post_init__:
self.haptic_feedback = GloveHapticFeedbackCfg(
    left_sensor_name="left_hand_contact",
    right_sensor_name="right_hand_contact",
)

两个 GR1T2 抓取放置遥操作环境( IsaacContrib-PickPlace-GR1T2-Abs 、 IsaacContrib-PickPlace-GR1T2-WaistEnabled-Abs )已启用该功能。

备注

手套是 跨进程 设备: GloveHapticFeedbackCfg 将逐指功率值通过 collection_id (默认 "manus_glove_haptic" )推送给厂商插件。请运行该插件,并在自定义 CloudXR 配置中设置 NV_CXR_ENABLE_PUSH_DEVICES=1 (见 CloudXR 环境配置文件 )。接触传感器的 prim_path 正则表达式必须匹配机器人的手指刚体名称;不确定时,可通过 print(robot.data.body_names) 核对。

录制用于模仿学习的示范#

Isaac Capture 与 Isaac Lab 的 record_demos.py 集成,用于录制遥操作示范,并提供 isaaclab teleop record 命令。

环境配置有 isaac_teleop 属性时,脚本会自动使用 create_isaac_teleop_device() ,无需 --teleop_device 标志:

uv run --extra teleop,isaacsim isaaclab teleop record \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit \
    --xr
./isaaclab.sh -p scripts/tools/record_demos.py \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit \
    --xr

run 、 record 和 replay 工作流接受 Hydra 风格的 key=value 任务配置选择项,前面不加 -- 。例如,使用 PhysX 和微分 IK 预设录制 Franka Reach 任务:

uv run --extra teleop,isaacsim isaaclab teleop record \
    --task Isaac-Reach-Franka \
    --visualizer kit \
    --dataset_file ./datasets/dataset.hdf5 \
    --num_demos 1 \
    --teleop_device keyboard \
    physics=isaacsim_physx presets=diffik

回放按预设配置的数据集时,需再次传入相同选择项。HDF5 元数据保存已注册的任务 ID,但不保存命令行选择项的值:

uv run --extra teleop,isaacsim isaaclab teleop replay \
    --task Isaac-Reach-Franka \
    --visualizer kit \
    --dataset_file ./datasets/dataset.hdf5 \
    physics=isaacsim_physx presets=diffik

部分环境仍使用原有的 teleop_devices 配置,而非 isaac_teleop ,如 Galbot RmpFlow 相对模式任务。这些环境需传入 --teleop_device 选择输入设备:

uv run --extra teleop,isaacsim isaaclab teleop record \
    --task IsaacContrib-Stack-Cube-Galbot-Left-Arm-Gripper-RmpFlow \
    --visualizer kit \
    --teleop_device keyboard
./isaaclab.sh -p scripts/tools/record_demos.py \
    --task IsaacContrib-Stack-Cube-Galbot-Left-Arm-Gripper-RmpFlow \
    --visualizer kit \
    --teleop_device keyboard

工作流如下:

  1. 使用 IsaacTeleopCfg 配置环境(见 配置环境 );原有设备(键盘、SpaceMouse)则使用 teleop_devices 。

  2. 运行 record_demos.py ,指定任务名及任务所需的 physics= 、 renderer= 或 presets= 选择项。

  3. XR 任务:启动 AR,连接 XR 设备并遥操作。原有设备任务:直接使用所配置的输入设备。

  4. 示范录制为 HDF5 文件。

  5. 将录制数据用于 Isaac Lab Mimic 或其他模仿学习框架。

更完整的模仿学习流水线,包括回放、数据扩充和策略训练,见 使用 Isaac Lab Mimic 进行合成数据生成与模仿学习 。

添加新机器人#

为 Isaac Lab 中的新机器人添加遥操作支持:

  1. 选择控制方案。 参考 选择控制方案 表,确定与机器人能力匹配的重定向器。

  2. 构建流水线。 如果已有重定向器足够使用,例如新机械臂采用 Se3AbsRetargeter + GripperRetargeter ,可按 构建重定向流水线 编写流水线构建函数。设置 TensorReorderer 输出顺序,与环境动作空间一致。

  3. 对于灵巧手 :为 DexHandRetargeter 创建机器人手的 URDF 和 YAML 配置,确保指尖连杆位于实际指尖,而非手指中部。

  4. 对于自定义重定向器 :见下文 添加新重定向器 。

  5. 为机器人 配置 XR 锚点 :操作任务使用静态锚点,运动任务使用动态锚点。见 配置 XR 锚点 。

  6. 通过 IsaacTeleopCfg 在环境配置中注册 (见 配置环境 )。

添加新重定向器#

如果内置重定向器不能满足需求,可在 Isaac Capture 仓库 中实现自定义重定向器:

  1. 继承 BaseRetargeter ,实现 input_spec() 、 output_spec() 和 compute() 。

  2. 可选添加 ParameterState ,为需要在重定向调参界面中实时调整的参数提供状态。

  3. 连接现有源节点( HandsSource 、 ControllersSource ),或为自定义输入设备创建新的 IDeviceIOSource 子类。

详见 Isaac Capture 仓库 及 贡献指南 。

添加新设备#

设备集成有两个层级:

Isaac Capture 插件(C++ 层)

适用于需要自定义驱动或 SDK 的新硬件。插件通过 OpenXR 张量集合推送数据。现有插件包括 Manus 手套、Haptikos 外骨骼、OAK-D 相机、控制器合成手部和脚踏板。创建插件后,更新重定向流水线配置,读取新插件源节点的数据。

示例见 插件目录 。

仅配置流水线

适用于 Isaac Capture 已支持的设备,或其数据能以手部/控制器跟踪形式提供的设备。只需更新 pipeline_builder ,选用与设备数据格式匹配的源节点和重定向器。

优化 XR 性能#

配置物理和渲染时间步

确保仿真渲染步长大致匹配 XR 设备的显示频率,且能够持续实时运行。Quest 3 和 Pico 4 Ultra 通常为 90 Hz,因此建议将仿真 dt 设为对应 90 Hz 的步长, render_interval 设为 2,即以 45 Hz 渲染:

@configclass
class XrTeleopEnvCfg(ManagerBasedRLEnvCfg):

    def __post_init__(self):
        self.sim.dt = 1.0 / 90        # physics steps at 90 Hz
        self.sim.render_interval = 2  # one render per 2 physics steps -> 45 Hz

sim.render_interval 表示两次渲染之间的物理仿真步数。增大该值可降低渲染频率及 GPU 开销,不改变物理行为,适合物理计算能跟上、渲染却跟不上的情况。

sim.dt 需要在稳定性与性能之间取舍。较小的 dt (如 1.0 / 120 )能更精确地积分接触,对刚性强、接触多的任务更稳定,但每步实际耗时更高,降低可达帧率。较大的 dt (如 1.0 / 60 )开销较低,但可能产生接触抖动或不稳定。请选择任务能够容忍的最大 dt 。

将视口切换到 RTX - Minimal 渲染器

RTX - Minimal 以降低图像保真度换取显著减少的每帧 GPU 开销。如果仿真无法实时达到 XR 设备显示频率,例如 GPU 性能较低、场景包含大量灯光或复杂材质,或调整 sim.dt 和 sim.render_interval 后仍掉帧,建议采用此渲染器。

已知问题

在 RTX - Minimal 已是当前渲染器时启动 XR 会话,存在已知问题:机器人控制输入可能始终不被应用,遥操作无法工作,也没有错误提示。XR 会话启动且确认遥操作正常 之后 再切换到 RTX - Minimal,不受影响。

临时解决办法是先使用默认渲染器启动,再切换到 RTX - Minimal:

  1. 使用默认渲染器启动 Isaac Lab,并开启 XR 会话。

  2. 确认遥操作正常,机器人能响应手部动作。

  3. 按下文说明,将视口渲染器切换为 RTX - Minimal 。

点击 Isaac Lab 视口左上角的渲染器下拉菜单,选择 RTX - Minimal :

视口渲染器下拉菜单中选中 RTX - Minimal

从视口下拉菜单选择 RTX - Minimal 渲染器。#

为获得更好的效果,点击 Isaac Lab 界面右上角的 Render Settings ,切换到 Minimal 选项卡,将 Minimal Shading Mode 设为 Diffuse/Glossy/Emission :

Render Settings 面板中的 Minimal Shading Mode 选项

Render Settings 面板中展开的 Minimal Shading Mode 下拉菜单,推荐选择 Diffuse/Glossy/Emission 。#

备注

RTX Minimal 目前仅支持 DistantLight prim 照明,会忽略 DomeLight 。如果环境使用 DomeLight ,请将其替换为 DistantLight ,或额外添加 DistantLight ,确保 RTX Minimal 下场景有光照:

import isaaclab.sim as sim_utils
from isaaclab.assets import AssetBaseCfg

light = AssetBaseCfg(
    prim_path="/World/light",
    spawn=sim_utils.DistantLightCfg(color=(0.75, 0.75, 0.75), intensity=3000.0),
)

在某些环境中, DistantLight 的默认朝向可能让阴影覆盖机器人,影响遥操作时的可见性。此时,可通过 AssetBaseCfg 的 init_state 调整光源朝向,使照明角度更合适:

import isaaclab.sim as sim_utils
from isaaclab.assets import AssetBaseCfg

light = AssetBaseCfg(
    prim_path="/World/light",
    spawn=sim_utils.DistantLightCfg(color=(0.75, 0.75, 0.75), intensity=3000.0),
    init_state=AssetBaseCfg.InitialStateCfg(
        rot=(0.0, 0.0, 0.0, 1.0),  # quaternion (x, y, z, w); adjust to reduce shadow overlap
    ),
)

尝试不同朝向,找到不会让阴影遮住机器人的角度。可先从相机视角稍向外倾斜开始调整。

降低 XR 渲染分辨率

XR 渲染分辨率倍数缩放渲染缓冲区尺寸,再将画面放大到头显推荐显示分辨率。降低该值会牺牲清晰度,但显著减少每帧 GPU 开销,有助于性能较低的 GPU 或复杂场景维持实时帧率。

在 Isaac Lab 界面右侧打开 XR 选项卡,展开 Advanced Settings -> Render Resolution ,拖动 Resolution Multiplier 滑块:

Advanced Settings 面板中的 XR 渲染分辨率滑块

XR -> Advanced Settings -> Render Resolution 下的 Resolution Multiplier 。小于 1.0 时,先减小渲染缓冲区,再放大到头显分辨率。#

通常可先尝试 0.8 ,能明显节省 GPU 开销,而可感知的画质损失较小。只有仍无法达到头显显示频率时,才进一步降低。

关闭外部相机渲染

遥操作脚本( teleop_se3_agent.py 、 record_demos.py 、 teleop_replay_agent.py )默认渲染外部相机传感器。相机渲染产物会带来显著 GPU 开销,并与 XR 视图争用资源。如果遥操作时不需要相机观测,可通过 --disable_external_cameras 关闭:

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --visualizer kit --xr \
    --disable_external_cameras

该标志移除环境中的相机传感器(等同于对环境配置调用 remove_camera_configs() ),并选择更轻量的 Kit experience。对 teleop_se3_agent.py ,它也是画中画总开关:任务默认及用户配置的画面均被忽略,不创建相机面板。省略它则保持相机启用(默认);录制相机观测、显示 XR 相机反馈,或希望 teleop_replay_agent.py 复现实际运行中的渲染负载时,必须保留相机。

无界面运行(跳过本地视口)

传入 --visualizer kit 会打开本地 Kit 视口,除了 XR 视图外,还在主机上渲染窗口。在服务器、云实例上,或不需要本地窗口时,可无界面运行,只渲染 XR 视图,为头显腾出 GPU 资源:

uv run --extra teleop,isaacsim isaaclab teleop run \
    --task IsaacContrib-PickPlace-Locomanipulation-G1-Abs \
    --viz none --xr

无界面 XR 模式下,OpenXR/AR 会话 自动启动 。没有本地视口可点击 Start XR ,因此 CloudXR 客户端一连接,Isaac Lab 就开始串流。

备注

Isaac Lab 3.0 已移除 --headless 命令行标志。无界面模式现在是 默认行为 ,省略 --visualizer 即可。如果配置可能启用可视化器,可传入 --visualizer none / --viz none 强制关闭,或设置环境变量 HEADLESS=1 。

配置重定向执行方式

Isaac Capture 可在应用线程上同步执行重定向,也可通过流水线工作线程异步执行,由 RetargetingExecutionConfig 控制。

同步模式下,重定向直接在仿真步内执行。对于轻量或主要用 Python 实现的重定向,这可能是最佳选择,因为后台 Python 工作线程仍可能通过 GIL 与应用线程争用。

流水线模式下,Isaac Capture 将重定向提交给后台工作线程,应用使用最近完成的结果。如果重定向包含足够多的原生操作,可与仿真或渲染重叠,或重定向开销较大、同步执行会直接延长帧耗时,适合使用这种模式。

retargeting_execution=RetargetingExecutionConfig(
    mode="pipelined",
    pacing=DeadlinePacingConfig(safety_margin_s=0.025),
)

DeadlinePacingConfig 有意将后台重定向推迟到更接近下一次需要结果的时刻,而非提交请求后立即执行。这样可避免与 Isaac Lab 在帧开始时的 Python 工作争用,并倾向于让重定向与渲染或其他原生操作同时进行,获得更有效的重叠执行。

safety_margin_s 控制在预计截止时间前多久启动重定向。余量越大,启动越早,为开销较大或波动较大的重定向留出更多时间,确保下一帧使用结果前完成。代价是输入样本可能略旧,且主要使用 Python 的重定向可能带来更多 GIL 争用。

主要使用 Python 且开销较小的重定向,可考虑 mode="sync" 。包含大量原生操作或偶尔耗时突增时,使用 mode="pipelined" ,并增大 safety_margin_s ,让工作更早开始。

检查 CloudXR 帧节奏

CloudXR Runtime 的帧节奏控制器旨在保持客户端体验平滑。如果应用反复出现帧耗时突增,它可能稳定在较低帧率,而非在不同帧率间振荡。因此,即使 Isaac Lab 性能分析未显示仿真侧有相应幅度的性能下降,已连接客户端仍可能看起来变慢。

附带的 CloudXR 配置通过 NV_ENABLE_POSE_WAIT=0 缓解这种情况,优先降低延迟,而非采用位姿等待平滑。使用自定义 .env 时,请复制此设置,再通过 --cloudxr_env 让 teleop_se3_agent.py 或 record_demos.py 使用它。配置覆盖方法见 CloudXR 环境配置文件 。

已知问题#

  • 默认隐藏 OpenXR 运行时错误( XR_ERROR_... )

    Isaac Lab 为遥操作会话设置 OXR_NO_PRINTING=true 。调试 XR 连接时,可在启动前设置 OXR_NO_PRINTING=false 查看这些错误。

  • 停止 AR 模式时报错 XR_ERROR_VALIDATION_FAILURE: xrWaitFrame(frameState->type == 0)

    可以安全忽略,由退出处理器中的竞态条件引起。

  • XR_ERROR_INSTANCE_LOST in xrPollEvent

    CloudXR 运行时先于 Isaac Lab 退出时出现,重启运行时即可恢复。

  • 启动或停止 AR 模式时报错 [omni.usd] TF_PYTHON_EXCEPTION

    可以安全忽略,由进入/退出处理器中的竞态条件引起。

  • Invalid version string in _ParseVersionString

    由采用旧版 USD 编写的着色器资产引起,通常可以安全忽略。

  • XR 设备已连接但没有视频画面(视口响应跟踪)

    主机与容器中的 GPU 索引可能不同。请在运行时将 NV_GPU_INDEX 设为与主机 GPU 对应的 0 、 1 或 2 。

API 参考#

完整类与函数文档见 isaaclab_teleop :