0. 介绍

参考:

  1. Isaac Sim Documents

Isaac Sim 是 NVIDIA 开发的,基于 NVIDIA Omniverse 平台构建的,一个物理精确的虚拟环境,用于开发、测试和管理基于 AI 的机器人,它为构建虚拟机器人实验提供了基本功能,包括导入机器人模型以及仿真 RGB-D、激光雷达、接触、超声波和 IMU 等传感器。

Isaac Sim 使用 USD 交换文件格式来表示场景。通用场景描述(USD)是一种易于扩展的开源三维场景描述和文件格式。当然也支持从 URDF、Mujoco XML 文件导入。

*.usd/*.usdc: 一般的USD文件,以二进制存储与压缩,因此读取速率会快一些 *.usda: 纯文本形式的USD文件,更方便阅读 *.usdz: 以zip压缩文件形式存储的USD文件,可以将多个USD文件打包成一个 *.drc: 其它自定义的文件格式

Isaac 是一个“专为机器人和AI打造的加速平台”。

在硬件层面它支持各种类型的硬件,比如RTX的GPU等等。在系统软件层面,依赖于RTX、CUDA、PhysX等框架。在平台层面,依赖于NVIDIA AI和NVIDIA Omniverse,最终就可以实现各类应用,比如机器人数据采集、环境仿真等等。甚至还有专门针对ROS提供的一些硬件加速的函数包,叫Isaac ROS。

1. Isaac Sim 的安装 - WorkStation 版

WorkStation 版相当于安装了一个独立的应用程序,适合便捷打开 GUI 界面调试,适合通过 GUI 和扩展的方式进行程序开发。如果想通过这种方式运行代码,需要使用安装目录的 isaac-sim.sh,限制了 python 环境的可能性,例如运行 test.py 文件需要:

1
~/isaacsim/isaac-sim.sh ~/path/test.py

本文使用有显示器的服务器安装 Isaac Sim Workstation 演示,流程参考:https://docs.isaacsim.omniverse.nvidia.com/latest/installation/install_workstation.html
如果你使用无显示器的服务器,可以通过 Docker 安装,参考:https://docs.isaacsim.omniverse.nvidia.com/latest/installation/install_container.html

参考 Isaac Sim Requirements 查看系统是否满足要求。

  • 系统:Ubuntu 20.04/22.04、Windows 10/11
  • GPU:必须有 RT Cores,如 RTX 30 系、RTX 40 系
  • NVIDIA 驱动:535.129.03 以上(2024 年 10 月要求,参考官网更新内容)

(1)下载 IsaacSim

打开 Isaac Sim Latest Release 网页:https://docs.isaacsim.omniverse.nvidia.com/latest/installation/download.html#isaac-sim-latest-release

下载第一行最新版的 Isaac Sim 4.5.0 压缩包。

1
2
3
4
5
6
mkdir ~/isaacsim
cd ~/Downloads
unzip "[email protected]+release.19112.f59b3005.gl.linux-x86_64.release.zip" -d ~/isaacsim
cd ~/isaacsim
./post_install.sh
./isaac-sim.selector.sh

image.png

点击 Start 即可运行 Isaac Sim 主程序。

第一次运行会 warm up shader cache 可能会比较慢比较卡。
后续可以运行 ~/isaacsim/isaac-sim.sh 启动

1. Isaac Sim 的安装 -Python 版

Python 版在创建的虚拟环境中直接安装 Isaac Sim,更容易和其他代码程序的依赖组合,个人认为更便于机器人开发。

本节参考:Isaac Sim Documents - Python Environment Installation

(1)创建虚拟环境

1
2
conda create -n env_isaacsim python=3.10
conda activate env_isaacsim

(2)安装 Isaac Sim 包

首先更新 pip

1
pip install --upgrade pip

安装 Isaac Sim 完整版包

1
pip install isaacsim[all]==4.5.0 --extra-index-url https://pypi.nvidia.com

安装 Isaac Sim 缓存扩展

1
pip install isaacsim[extscache]==4.5.0 --extra-index-url https://pypi.nvidia.com

(3)示例

创建 python 程序如下:

1
2
3
4
5
import isaacsim
from isaacsim.simulation_app import SimulationApp

simulation_app = SimulationApp({"headless": True})
## perform any Isaac Sim / Omniverse imports after instantiating the class

运行后效果为打开 Isaac Sim 窗口。

第一次运行会 warm up shader cache 可能会比较慢比较卡。

2. Isaac Sim GUI 基本使用

本节参考:Isaac Sim UI and Workflow Tutorials

2.1 UI 界面

(1)添加并操作一个立方体

点击 Create->Shape->Cube 添加一个立方体:

  • 选中立方体,拖动坐标轴移动立方体
  • E 切换到旋转控制,调整立方体姿态,再按 E 切换到局部坐标系旋转控制
  • R 切换到比例控制,调整立方体形状
  • W 切换回位置控制,调整立方体位置,再按 W 切换到局部坐标系位置控制
  • Esc 取消选中立方体

所有的操作都会在右下角的属性面板显示属性变化,也可以直接在右下角输入数值设置立方体参数。

image.png

(2)视角控制

  • F:相机居中并缩放到合适位置
  • Alt+鼠标左键拖动:绕当前视角的中心旋转
  • 滚轮Alt+鼠标右键拖动:缩放
  • 鼠标中间拖动:平移视角
  • 鼠标右键拖动:旋转视角

(3)Stage

在窗口右侧有一个 Stage 面板。

此时如果点击 Create->Xform 可以创建一个空坐标系。

可以将方块移动到坐标系内,此时移动坐标系,方块也会跟着移动,因为此时方块是 Xform 的子级,两者之间的变换关系不会因为移动 Xform 而变化。

(4)Property

窗口右下角是属性面板(Property),不同的单元(Xform, Shape, Light)都有着不同的属性数据格式,这是因为它们在 Issac Sim 中都是不同的数据类型。

2.2 环境设置

(1)重力

点击 Create->Physics->Physics Scene 添加 Physics Scene 到右侧的 Stage Tree 中。可以通过它的属性设置重力方向为 -Z 方向,大小为 9.8(默认为国际标准单位)

(2)地面

点击 Create->Physics->Ground Plane 添加地面。

(3)照明

每个创建的 Stage 都会有默认的光源。可以通过点击 Create->Light->Sphere Light 添加一个额外的光源。

  • 在属性面板中,将其 Z 轴设为 7,回复 X,Y 的默认旋转为 0
  • Main 中点击右侧的白色方块调整颜色
  • Main 中点击 Intensity 修改光照强度为 1e6
  • Shaping 中点击 cone:angle 将光照范围限制为 45 度,点击 cone:angle 设置边缘柔滑为 0.05。
  • 为了使新的聚光灯更容易看到,打开默认光源的属性,设置其强度 Main->Intensity 为 300。

效果如下:

image.png

2.3 添加物体

(1)向场景中添加形状

  • 点击 Create->Shapes->Cube 创建立方体
  • 选中立方体并将其提到地面以上
  • 点击左侧的 Scale 按钮,或按 R 键,激活缩放小部件,调整立方体形状
  • 在右下角属性中的 Transform->translate 中设置物体的位置

同样,我们可以将其中加入其它形状。

(2)添加物理属性

  • 选中所有的物体,在属性选项卡中,点击 + Add,选择 Physics->Rigid Body with Colliders Preset,设置三个形状的物理属性都是带有碰撞的刚体
  • 点击 Play 三个物体都会掉落到地面上
  • 查看右下角属性,往下滚能看到 Rigid BodyCollider,可以点击这两个 APIs 的右上角 x 删除属性

image.png

(3)添加接触和摩擦

  • 点击 Create->Physics->Physics Material ,选择 Rigid Body Materials 创建新的物理材质,可以在右侧的 Stage 栏中看到
  • 选中该材质,在下方的属性选项卡中可以调整摩擦系数、密度等等。
  • 选中任意物体,在属性选项卡中找到 Physics materials on selected models,设置零件的材质。

(4)添加外观

刚才添加的是物理材质,但是实际上物体没有颜色反光属性(可以通过关闭光源查看),需要为物体创建外观

  • 点击 Create->Materials->OmniPBR
  • 选中任意物体,在属性选项卡中找到 Materials on selected models,设置零件的外观。
  • 可以修改外观的属性中的 Material and Shader->Shader->Albedo 修改基础颜色,或修改反射率、粗糙度等查看变化

image.png

2.4 保存和加载场景,引用机器人

Isaac 使用 USD 格式作为所有的场景格式。

(1)保存场景

点击 File->Save As... 将当前场景保存为新 USD 文件。(如果点击 Save Flattened As 则是将所有组件保存到同一个 mesh 中)

可以选择 .usd 格式(二进制),.usda(人类可阅读格式)。

image.png

(2)加载场景

  • 点击 Files->Open 打开 USD 文件直接编辑。
  • 点击 Files->Add Reference 将 USD 文件作为引用添加,无法直接编辑。(直接将文件拖入到文件窗口也是以引用方式添加)

(3)引用文件添加的注意事项

引用的文件最好将所有刚体排列成有意义的分层结构,以前面场景中的物体为例,将其视为两轮小车:

  1. File->Open 打开刚才保存的 USD 文件
  2. 在 Stage 中右键创建一个 Xform,双击将其重命名为 mock_robot,并将其拖动到空白位置,使其和 World 以及 Environment 同级,右键设置为默认坐标系 Set as Default Prim
  3. 重命名 Cubebody,两个 Cylinder 分别为 wheel_left, wheel_right,将刚刚创建的刚体(cube, Cylinder),以及 Physics Material 和 Looks 都拖到 mock_robot 坐标系下
  4. 保存文件

image.png

新建一个文件,点击 File->Add Reference,可以看到只有机器人被添加进来

image.png

2.5 关节配置

使用 File->Open 打开刚才的文件(最好和图中的一样,后面要添加关节)

(1)添加关节

  1. 点击 Create->Scope 创建一个 Scope 来存储关节,重命名为 joints
  2. 创建关节时:先点击父实体,再点击子实体,然后点击 Create->Physics->Joint->Revolute Joint 创建一个旋转关节。
  3. 检查关节的属性面板中,body0 是父实体(如 body),body1 是子实体(如 wheel_right)。
  4. 在属性面板的 Revolute Joint 中将旋转轴更改为 Y/Z,根据模型的情况。
  5. 将创建的 joint 重命名为 joint_wheel_right 并拖动到 joints 的 scope 中
  6. 重复 2-5 步添加另一个关节

点击运行,可以观察到机器人落到了地面,按住 shift 拖动方块,可以发现两个圆柱旋转带动机器人在地面上滚动。

image.png

(2)添加关节驱动器

为了能够更好地控制关节,必须添加关节驱动器(位置控制或速度控制)实现驱动。

添加方法:选中关节,点击属性选项卡的 +Add 按钮,选择 Physics->Angular Drive 向关节添加驱动,可以在属性面板下滑找到 Drive 以设置属性。

  • 位置控制:设置高刚度和零阻尼
  • 速度控制:设置高阻尼和零刚度

对于该轮子来说,可以设置高阻尼如 Damping=1e4,目标速度可以设为 Target Velocity=200,点击播放可以看到机器人运动。

(3)添加 Articulation 关节

Articulation 是 Issac 中的另一种关节,与 joint 不同之处在于,它是由一系列 joint 组成的关节组。

添加方法:选择机器人的基坐标系 mock_robot,在属性选项卡中点击 +Add,添加 Physics->Articulation Root

这样就添加完成了。

(4)添加控制器

这部分主要是用来测试。

点击 Issac Utils->Common Omnigraphs->Articulation Velocity Control 添加一个速度控制图表。

Robot Prim 选择机器人基坐标系 mock_robot

image.png

点击 Stage 中的 Graphs->Velocity_Controller->JointCommandArray,修改 Input0 和 Input1,例如设置成相反数让机器人差速原地转,点击播放看效果。

2.5 添加相机和传感器

(1)创建相机

点击 Create->Camera,会在 Stage 栏中创建一个 camera,同时界面中会出现一个灰色框,代表相机视图。

image.png

可以像正常的刚体一样调整相机的位置。

(2)相机扩展

相机扩展可以实现根据相机创建不同可视化视角,查看摄像头覆盖范围,获取和设计相机姿态。

可以点击 Issac Utils->Workflows->Camera Inspector 打开相机扩展

image.png

可以看到面板中有 Camera State 一栏,显示了相机的位置姿态,便于编写代码时查看。

(3)创建相机视角

点击面板中的 Create Viewport,可以创建相机视角的窗口,如下图所示:

image.png

在该窗口中,点击左上角的菜单中的 Viewport 选项可以调整相机分辨率。

如果在仿真环境中移动相机位置,相机的状态属性等都会自动更新。

(4)将相机连接到机器人

例如现在需要添加一个车载摄像头,将其固定在 body 上,使其能够跟随 body 运动:

  1. 将新添加的摄像头重命名为 car_camera
  2. 为了便于我们观察相机,可以点击 Window->Viewport 启动 Viewport2 视窗,并点击上方的电影机按钮将其切换为 car_camera 的视角(注意选中 mock_robot,在视窗内按 f 可以帮助切换到中心画面)
  3. 在右侧 stage 中将 car_camera 拖动到 body 下方,将相机与机器人连接在一起
  4. 调整相机属性中的位置和方向,使其看向机器人前方地面,点击 Play 观察相机是否跟随机器人运动

image.png

4. Python 程序

4.1 独立 Python 程序的基本框架

Isaac Sim 仿真程序大概可以分成 InitializationSimulation 两步骤,即首先初始化环境,创建世界和添加各种物体,然后是仿真的 Step 执行,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
##################################################
# Initialization
##################################################
# 导包
from isaacsim import SimulationApp # 第一行一定是导入SimulationApp,就像 Omniverse 打开 Isaac Sim 一样
simulation_app = SimulationApp({"headless": False}) # 创建一个 SimulationApp 对象,参数是一个字典,headless: False 表示显示图形界面

from omni.isaac.core import World
from omni.isaac.core.objects import DynamicCuboid
import numpy as np

# 创建世界,下面相当于 setup_scene
world = World() # 实例化一个 World 对象
world.scene.add_default_ground_plane() # 添加一个默认的地面

# 创建物体
first_cube = world.scene.add(
DynamicCuboid(
prim_path = "/World/first_cube", # 该物体的路径
name = "first_cube", # 该物体的名字
position = np.array([0, 0, 1.0]), # 该物体的位置
scale = np.array([0.5, 0.5, 0.5]), # 该物体的缩放
color = np.array([0.0, 0.0, 1.0]) # 该物体的颜色
)
)

# 重置世界
world.reset() # 重置世界,创建完成之后,一定不要忘了

##################################################
# Simulation
##################################################

# 开始仿真
for i in range(1000): # 或者while True:
position, orientation = first_cube.get_world_pose() # 获取物体的位置和姿态
linear_velocity = first_cube.get_linear_velocity() # 获取物体的线速度
angular_velocity = first_cube.get_angular_velocity() # 获取物体的角速度
print("Cube position: ", position)
print("Cube orientation: ", orientation)
print("Cube linear velocity: ", linear_velocity)
print("Cube angular velocity: ", angular_velocity)

world.step(render=True) # 仿真一步,render=True 表示显示图形界面

# 关闭仿真
simulation_app.close() # 关闭仿真

4.2 独立 Python 程序控制移动机器人

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from isaacsim import SimulationApp

simulation_app = SimulationApp({"headless": False}) # start the simulation app, with GUI open

import sys

import carb
import numpy as np
from isaacsim.core.api import World
from isaacsim.core.prims import Articulation
from isaacsim.core.utils.stage import add_reference_to_stage, get_stage_units
from isaacsim.core.utils.viewports import set_camera_view
from isaacsim.storage.native import get_assets_root_path

# preparing the scene
assets_root_path = get_assets_root_path()
if assets_root_path is None:
carb.log_error("Could not find Isaac Sim assets folder")
simulation_app.close()
sys.exit()

my_world = World(stage_units_in_meters=1.0)
my_world.scene.add_default_ground_plane() # add ground plane
set_camera_view(
eye=[5.0, 0.0, 1.5], target=[0.00, 0.00, 1.00], camera_prim_path="/OmniverseKit_Persp"
) # set camera view

# Add Franka
# asset_path = assets_root_path + "/Isaac/Robots/Franka/franka.usd"
asset_path = '/home/mahaofei/Programs/01_MR+VLM+RL/Simulation/asset/isaac_sim/ur5e_hand/ur5e_hand.usd'
add_reference_to_stage(usd_path=asset_path, prim_path="/World/Arm") # add robot to stage
arm = Articulation(prim_paths_expr="/World/Arm", name="my_arm") # create an articulation object

# set the initial poses of the arm so they don't collide BEFORE the simulation starts
arm.set_world_poses(positions=np.array([[0.0, 1.0, 0.0]]) / get_stage_units())
# initialize the world
my_world.reset()

init_joint_positions = np.array([0.0, -np.pi/2, np.pi/2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])
arm.set_joint_positions([init_joint_positions])
arm_joint_positions = init_joint_positions

while True:
# 机器人的关节位置每次变动一点,连续变动
arm_joint_positions[:6] += 0.001
arm.set_joint_positions([arm_joint_positions])
if arm_joint_positions[0] >= np.pi/2:
arm_joint_positions = init_joint_positions

# step the simulation, both rendering and physics
my_world.step(render=True)

simulation_app.close()

4.x 常用 Python 程序及解释

(1)常规代码逻辑

simulation_app 的创建必须在所有 isaac sim 引用之前完成,启动 isaacsim 的仿真窗口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 启动 Simulation APP
from isaacsim import SimulationApp # 第一行一定是导入SimulationApp

simulation_app = SimulationApp({"headless": False}) # 创建一个 SimulationApp 对象,参数是一个字典,headless: False 表示显示图形界面

import sys
import carb
import numpy as np
from isaacsim.core.api import World
from isaacsim.storage.native import get_assets_root_path

# 准备场景,获取NVIDIA官方asset路径
assets_root_path = get_assets_root_path()
if assets_root_path is None:
carb.log_error("Could not find Isaac Sim assets folder")
simulation_app.close()
sys.exit()

# 创建世界,添加地面,添加相机视角
my_world = World(stage_units_in_meters=1.0)
my_world.scene.add_default_ground_plane() # add ground plane
set_camera_view(
eye=[5.0, 0.0, 1.5], target=[0.00, 0.00, 1.00], camera_prim_path="/OmniverseKit_Persp"
) # set camera view

# 初始化world
arm.set_world_poses(positions=np.array([[0.0, 1.0, 0.0]]) / get_stage_units())
my_world.reset()

# some code

while True:
# some code

my_world.step(render=True)

simulation_app.close() # 关闭仿真

Coming Soon …