2.isaacsim4.2 教程-初识OmniGraph

1. OmniGraph(视觉编程)

OmniGraph 是 Omniverse 的可视化编程框架。它提供了一个图状结构,将 Omniverse 内多个系统的功能节点串联起来;同时也是一个计算框架,允许你编写高度自定义的节点,将自己的功能无缝集成到 Omniverse 中,并自动利用其高效的计算后端。

在 Isaac Sim 中,OmniGraph 是:

  • Replicators(批量场景生成器)

  • ROS / ROS2 桥接

  • 传感器访问

  • 控制器

  • 外部输入/输出设备

  • 用户界面等功能的核心引擎

本教程将带你入门 OmniGraph 的世界。我们强烈建议你同时阅读《OmniGraph》官方文档,因为它是 Omniverse Kit 的关键组件。

学习目标

  • 了解 OmniGraph 的基本概念

  • 教你构建一个动作图(Action Graph),在 Isaac Sim 中控制 Jetbot 机器人

  • 演示如何使用 OmniGraph 快捷生成功差控制器(differential controller)图

图编辑器(Graph Editors)

Isaac Sim 中有两种图编辑器:Action Graph(动作图)和 Generic Graph(通用图)。它们都在菜单 Window > Visual Scripting 下可见。在大多数 Isaac Sim 场景中,你会用到的是 Action Graph

节点搜索(Node Search)

OmniGraph 中提供了丰富的节点库。打开图编辑器后,左侧面板会按类别列出所有节点。你也可以在面板顶部的搜索框中输入关键词,快速找到需要的节点。

基本概念

Action Graph(动作图) vs Push Graph(通用图)

  • Action Graph

    • 需要有一个“执行”节点(Execution Node)作为触发器,才会在触发时运行。

    • 常见触发器是 Tick 节点——它在仿真每帧开始时触发,这样当仿真未播放时图不会运行,播放后每渲染一帧就执行一次。

    • 如果你把 Tick 节点从动作图中删掉,按下 Play 后动作图就不会运行了。

    • 其它触发方式还包括键盘/鼠标输入或舞台事件,对应的节点可在 “Event” 节点分类中找到。

  • Push Graph

    • 不需要执行节点,默认情况下每个渲染帧都会自动执行。

    • 因为视口一直在渲染,即使仿真未播放,节点也会持续运行。

    • 举例:在 Push Graph 中拖一个 “Print Text” 节点,打开控制台并允许显示 Info 级别日志,输入完文字后即刻会在控制台打印出来。

    • 如果图中节点有连线依赖,它会按照连线顺序执行;若无连线,则各节点按无保证的顺序并行执行。

这样,你就对 OmniGraph 的基础概念和使用场景有了初步了解。接下来,我们将手把手创建一个控制 Jetbot 的动作图,让它在仿真中动起来!

2. 自建OmniGraph

build

  1. 在编辑器顶部菜单中依次选择 Window > Visual Scripting > Action Graph,此时图编辑器会在与内容浏览器相同的面板中打开。

  2. 点击 New Action Graph,创建一个空白动作图。

  3. 在图编辑器右上角的搜索栏中输入 controller

  4. Articulation ControllerDifferential Controller 节点拖入画布。

Articulation Controller 会对任何带有关节根(articulation root)的 Prim,向指定关节施加力、位置或速度驱动命令。

  1. 配置要控制的机器人:

    • 选中 Articulation Controller 节点,在属性面板中进行设置:

      • 方案 A:点击 usePath,在 robotPath 字段中输入机器人路径 /World/jetbot

      • 方案 B:点击属性面板顶部的 Add Targets,在弹出的选择窗口中选中 JetBot

Differential Controller 根据目标的线速度和角速度,为双轮机器人计算驱动命令。它同样需要配置关键参数。

  1. 配置 Differential Controller:

    • 选中 Differential Controller 节点,在属性面板中设置:

      • wheelDistance(轮距)= 0.1125

      • wheelRadius(轮半径)= 0.03

      • maxAngularSpeed(最大角速度)= 0.2

配置 Articulation Controller 的关节列表

Articulation Controller 还需要知道要驱动哪些关节,以令其按指定方式运动。它期望接收一个 token 列表或索引值列表。JetBot 在其底盘下有两个旋转关节:left_wheel_jointright_wheel_joint。你可以在 Stage Context Tree 中的 /World/jetbot/chassis 下找到它们。

  1. 在图编辑器的搜索栏中输入 token

  2. Constant Token 节点拖入画布两次。

  3. 选中第一个 Constant Token,在属性面板中将其 value 设置为 left_wheel_joint

  4. 选中第二个 Constant Token,将其 value 设置为 right_wheel_joint

  5. 在搜索栏中输入 make array(制作成数组),将 Make Array 节点拖入画布。

  6. 选中 Make Array 节点,点击属性面板中输入列表旁的 + 图标,添加第二个输入端口;

    1. arraySize 设置为 2

    2. Array Type 的下拉菜单中,将输入类型(Input Type)设为 token[]

  7. 将两个 Constant Token 节点的输出,分别连接到 Make Array 的 input0input1

  8. 再将 Make Array 的输出连接到 Articulation Controller 节点的 Joint Names 输入。

添加事件触发节点

最后,需要一个事件节点来驱动整个图表在仿真播放时持续执行。

  1. 在搜索栏中输入 playback,将 On Playback Tick 节点拖入画布。

    • 该节点在仿真播放时,每帧都会发出一次执行事件

  2. 将 On Playback Tick 的 Tick 输出,分别连接到 Articulation Controller 和 Differential Controller 节点的 Exec In 输入。

  3. 将 Differential Controller 的 Velocity Command 输出,连接到 Articulation Controller 的 Velocity Command 输入。

概括

下面用简洁的流程图和说明,概括一下上文中通过 OmniGraph 节点来控制 JetBot 小车的整体流程:

  1. 事件触发(On Playback Tick)

    • On Playback Tick 节点在仿真播放时,每一帧都会发出一次 “Tick” 执行信号。

    • “Tick” 信号分别输入到 Differential ControllerArticulation ControllerExec In 端口,驱动后续计算。

  2. 差速控制(Differential Controller)

    • 接收到 Tick 信号后,Differential Controller 根据设定的目标线速度(linear velocity)和角速度(angular velocity),结合轮距(wheelDistance)和轮半径(wheelRadius),计算出左右两个车轮的驱动速度——即 Velocity Command

    • 此输出通过连线传给 Articulation Controller。

  3. 关节列表准备(Constant Token → Make Array)

    • 两个 Constant Token 节点分别存储 left_wheel_jointright_wheel_joint 两个关节名称。

    • Make Array 节点将这两个 token 组合为一个 token[] 数组,作为 Articulation Controller 的 Joint Names 输入,告诉它要驱动哪两个关节。

  4. 关节驱动(Articulation Controller)

    • 接收 Tick 执行信号(Exec In)、差速控制输出(Velocity Command)以及关节名称数组(Joint Names)后,Articulation Controller 将 Velocity Command 转换为对指定关节的速度驱动命令,并下发给物理模拟引擎。

    • 从而实现两个轮子的协同运动,带动小车前进或转向。

  5. 仿真运行(Play)

    • 按下 Play,以上节点开始按序运转:每个仿真帧触发一次 Differential → Articulation 的计算链,持续地通过物理引擎驱动小车运动。

可以通过修改角速度和线速度让小车移动。

使用键盘控制

探索可用的 OmniGraph 节点,并尝试搭建一个通过键盘控制 JetBot 的图。

目前我们只有:

我们需要键盘输入进行控制,所以需要键盘输入节点:

 分别设置成WASD

这里的键盘输入之后输出的值是布尔值 IsPressed。需要把布尔值(true/false)转成数值(1.0/0.0),方便后续运算。这里就要用到 To Double

这里是通过线速度和角速度控制小车移动和转向,那么这两个输入肯定要被键盘输入所控制,我们当前只是将bool值转化成了数值,并不是实际的速度值,所以需要进一步转化:

首先需要一个乘法,将按键状态值(0/1)承上我们设置的速度,就是最终速度值,用来存储这个速度常量的节点就是Constant Double。

我们有两种速度,角速度和线速度,所以需要两个速度常量节点。有4个键盘输入,每个都要和速度常量相乘,所以需要4个multiply,每个multiply都要接收速度常量值和键盘输入值,最终输出的就是实际的速度值。

 在来看这里,w/s就是控制线速度,a/d就是控制角速度

前后、左右按键的速度分量合并成线速度和角速度。

  • Subtract

    • 上半部分:线速度 = “前进(W)”分量 − “后退(S)”分量

    • 下半部分:角速度 = “右转(D)”分量 − “左转(A)”分量

a/d乘出来的速度值相减就是实际的角速度,w/s乘出来的速度值相减就是实际的线速度:

记得修改一下差速控制中的最大角速度,之前设置的0.2太小了,我们这里5就差不多了。

3. OmniGraph 快捷方式

从头搭图可能很繁琐,尤其在你需要频繁迭代时。我们为常用的图提供了一些快捷生成方式 —— 只需几次点击,就能生成包含多个节点和连线的复杂图。它们位于菜单 Isaac Utils > Common Omnigraphs 下,对应的使用说明在 Commonly Used Omnigraph Shortcuts 文档中。

使用菜单快捷方式生成差速控制器图的步骤:

  1. 删除(或禁用,如果有此选项)之前任何用于控制 JetBot 的 Omnigraph。

  2. 在菜单栏点击 Isaac Utils > Common Omnigraphs > Differential Controller

  3. 弹出参数填写对话框后,按提示输入必要参数:

    • Articulation Root:填入 /World/jetbot

    • Wheel Distance(轮距):0.1125

    • Wheel Radius(轮半径):0.03

    • JetBot 只有两个可控关节,其余字段可留空。

  4. 打开 Use Keyboard Control (WASD) 开关,以启用键盘控制。

  5. 点击 OK,OmniGraph 会在 /Graph/differential_controller 下自动生成完整的控制图。

  6. Play 开始仿真。

  7. 验证可用键盘的 WASD 键控制 JetBot 前进、后退和转向。

4. OmniGraph:输入设备

本教程将带你使用 OmniGraph,将输入设备(如游戏手柄或键盘)连接到 Isaac Sim 仿真中,实现:

  • 通过游戏手柄控制移动机器人

  • 使用键盘操作舞台上的物体

我这没手柄,就先用键盘了,后续有了手柄在进行研究

运行示例

OmniGraph 的键盘示例展示了如何接收键盘输入并将它们连接到场景中。连接完成后,就可以用按键来修改舞台上物体的特定属性。

  1. 在菜单栏依次点击 Isaac Examples > Input Devices > Omniverse Keyboard,打开示例。

  2. Play 开始仿真。

  3. 在舞台上的立方体,可通过按 A 键变大,按 D 键变小。

1. 读键盘状态

  • Read Keyboard State(两个节点)

    • 第一个监听 A 键,第二个监听 D 键。

    • 输出 IsPressed 布尔值。

  • To Double

    • 将布尔值 (true/false) 转为数值 (1.0/0.0),方便做算术运算。


2. 计算缩放增量

  • Constant Int

    • 存储一个“单位增量”,比如 1(你可以把它理解为“每按一下 A/D,就放大或缩小 1 单位”)。

  • Multiply(两个节点)

    • A_pressed * +1 → 得到 “放大贡献”

    • D_pressed * +1 → 得到 “缩小贡献”

  • Add

    • 将上面两者相加:deltaRaw = (A?1:0) + (D?1:0)

    • 由于按 D 时希望“缩小”,实际上你会把 D 那路乘以 -1 或在后面做一次相减,总之合成一个能表示“正向放大/负向缩小”的数值。


3. 考虑帧率(时间因子)

  • Constant Double

    • 存一个小数(例如 0.1),表示“每秒变化的比例”或用来和帧间隔相乘,保证不同帧率下效果一致。

  • Multiply

    • 把上面算出的 deltaRaw 乘上这个 0.1,得到 deltaPerFrame


4. 读取当前属性并累加

  • Read Prim Attribute

    • 读出立方体当前的某个属性(比如 x 轴缩放值,Attribute Name 里填 "xformOp:scale:1" 之类的路径,Prim Path 指你的 /World/Cube)。

  • Add

    • 把当前值和 deltaPerFrame 相加,得到 newScale


5. 每帧执行与写回

  • On Tick

    • 每个渲染帧都会发出一次 Tick(仿真播放时才会触发),为所有带 Exec In 的节点提供执行脉冲。

  • Write Prim Attribute

    • 接收 Exec InPrim PathAttribute Name、以及新算好的 Value(即 newScale),把它写回到立方体上,实时更新尺寸。

5. 其他常用 OmniGraph 快捷方式

快捷方式列表

控制器图(Controller Graphs)
  • Articulation Position Controller

  • Articulation Velocity Controller

  • Differential Controller

  • Gripper Controller

ROS 图(ROS Graphs)
  • ROS2 Clock

  • ROS2 Camera

  • ROS2 RTX Lidar

  • ROS2 Joint State Publisher and Subscriber

  • ROS2 TF Publisher

  • ROS2 Odometry Publisher

  • ROS2 Generic Publisher

注意:

  1. 系统不会自动检测场景中是否已有功能重复或控制同一机器人的图;请务必保证各图在场景中的唯一性。

  2. 这只是生成图的快捷方式;生成后,你仍可根据需求自由编辑和扩展这些图。

  3. 带星号(*)的参数为必填

ROS图暂时不做学习,先看一下其他的控制图

用于驱动机器人的控制器快捷方式有:

  • Articulation 控制器(关节位置和速度)

  • 差速驱动控制器(Differential Drive Controller)

  • 夹爪控制器(Gripper Controller)

我们之前已经演示过了第二个差速控制,这里演示一下剩下两个。

Articulation Controllers

Articulation Position/Velocity Controllers 会直接向机器人的每个关节下发命令。

  • Robot Prim:机器人的父级 prim(根节点)。

  • Graph Path*:生成的图存放路径。默认会建在独立树下,比如 /Graph/position_controller/Graph/velocity_controller。如果该路径已存在,系统会自动在末尾加数字寻找下一个可用路径。

  • Add to Existing Graph:默认为 False。不勾选时,生成新图;勾选后,会把节点添加到已有图里,并复用已有的 Tick 节点(如果有)。不管怎样,总会再添加新的控制器节点。


使用 Articulation Controller 驱动机器人
  1. 在新建的图里,选中 JointCommandArray 节点(属性面板中可修改)。

  2. 点击 Play,开始仿真。

  3. 在属性面板里调整 JointCommandArray 的值,机器人就会按你给的命令移动。

如果 USD 原始场景里已经保存了某些初始目标位置或速度,按下播放后,机器人会立刻往这些目标运动。

夹爪控制器(Gripper Controller)

夹爪控制器适用于每个手指只有一个自由度驱动的末端执行器,包括所有的平行 Jaw 夹爪,以及那些多指但每指单自由度的机械手。


快捷参数说明
  • Parent Robot*:包含夹爪的机器人 prim。可以直接选夹爪本身,或若夹爪是手臂一部分,则选整条机械臂的根 prim。

  • Graph Path*:生成的图存放路径,默认位置为 /Graph/{type}_controller。如该路径已存在,会自动在末尾追加数字以寻找可用路径。

  • Gripper Root*:包含所有夹爪关节的 prim 根节点。

  • Gripper Speed*:夹爪开合速度,单位为米/秒(对棱柱关节)或弧度/秒(对旋转关节)。

  • Gripper Joint Names*:所有控制夹爪手指的关节名称,逗号分隔。

  • Open/Close Position Limit:认为“完全打开”或“完全闭合”时的关节位置值,单位同上。留空时默认读取 USD 文件里的关节极限。

  • Use Keyboard Control:默认不启用。勾选后,会自动在图里添加接收键盘 “O”(Open)、“C”(Close)、“N”(停止)三个输入的节点。

  • Add to Existing Graph:默认 False。勾选后,会把节点添加到已有图中,复用已有的 Tick 节点(若存在),但会无条件再添加新的控制器节点。


使用夹爪控制器
  • 如果不指定 Open/Close Position Limit,控制器会使用 USD 里预设的关节极限。

  • 如果你填反了“打开”和“闭合”数值,控制器会自动检测并纠正——它假设“打开”的关节极限值大于“闭合”的极限值。若你的夹爪定义相反,可自行交换这两个数值,或修改对应的 Python 脚本来适配。

如果你想用Articulation Controller 驱动机械臂,而用gripper控制夹爪,你可以:

在Articulation Controller 的图里把最后两个输入(左右夹爪关节)删除

这是就是两个图在同时工作,只不过他们控制的部位不同,仍然可以按CON控制夹爪