Nvidia Isaac Sim 6 - 快速教程 2 - 机器人基础教程
机器人基础教程介绍如何向 Stage 添加机器人,移动机器人以及查看机器人属性。
1. GUI
1.1. 向 Stage 添加机器人
- 新建 Stage(
File > New)。
- 从顶部菜单栏选择
Create > Robots > Franka Emika Panda Arm,将机器人添加到场景中。
1.2. 检查机器人
使用 Physics Inspector 查看机器人的关节属性。
- 依次点击
Tools > Physics > Physics Inspector,右侧将打开一个窗口。
- 选择 Franka 进行检查。窗口将默认显示关节信息,比如上下限位及默认位置。
- 点击右上角的汉堡图标,可查看更多选项,比如关节刚度和阻尼。
- 修改这些数值,机器人将随之移动,同时出现绿色对勾标记。
- 若要提交更改,并且将其设置为机器人的新默认值,请点击绿色对勾标记。
1.3. 控制机器人
基于 GUI 的机器人控制器位于 Omniverse 的可视化编程工具 OmniGraph 中。本教程将使用快捷工具生成图,然后在 OmniGraph 编辑器中检查该图。
- 依次点击
Tools > Robotics > Omnigraph Controllers > Joint Position,打开图生成器。
- 在随后出现的“Articulation Position Controller Inputs”弹窗中,点击“Robot Prim”字段旁边的“Add”。
- 选择 Franka 作为目标。
- 点击“OK”生成图。
要移动机器人:
- 在右上角的“Stage”选项卡中,选择
Graph > Position_Controller。
- 选择 JointCommandArray 节点。可以通过 Stage 树选择该节点,也可以在图编辑器中选择该节点。
- 在右下角的“Property”选项卡中,可以看到关节命令值。“Construct Array Node”下的“Inputs”对应机器人上的各个关节,从基座关节开始。
- 点击+保持+拖拽各个数值字段,或输入不同的数值,可看到机器人手臂的位置发生变化。
- 点击“Play”启动仿真。
要可视化生成的图:
- 打开图编辑器窗口,
Window > Graph Editors > Action Graph。编辑器窗口在包含机器人的Viewport选项卡下方的标签页中打开。
- 将新打开的浏览器标签页拉起。
- 点击图编辑器窗口中间的
Edit Action Graph。
- 在列表中选择唯一已有的图。
- 选择一个数组,通过
Stage和Property选项卡,查看与每个数组节点关联的值。
- 选择图中的
Articulation Controller对象,查看其属性。
2. Extension
2.1. 向 Stage 添加机器人
开启新 Stage(File > New)。要向场景中添加机器人,将以下代码片段复制粘贴到 Script Editor 中,然后运行。
import carb
from isaacsim.core.prims import Articulation
from isaacsim.core.utils.stage import add_reference_to_stage
from isaacsim.storage.native import get_assets_root_path
import numpy as np
assets_root_path = get_assets_root_path()
if assets_root_path is None:
carb.log_error("Could not find Isaac Sim assets folder")
usd_path = assets_root_path + "/Isaac/Robots/FrankaRobotics/FrankaPanda/franka.usd"
prim_path = "/World/Arm"
add_reference_to_stage(usd_path=usd_path, prim_path=prim_path)
arm_handle = Articulation(prim_paths_expr=prim_path, name="Arm")
arm_handle.set_world_poses(positions=np.array([[0, -1, 0]]))2.2. 检查机器人
Isaac Sim Core API 提供许多可用于获取机器人信息的函数调用。下面的示例用于查找关节数量、关节名称、各种关节属性以及关节状态。
在 Script Editor 中打开新标签页,复制粘贴以下代码片段。该代码只能在前面的添加机器人步骤完成后运行,因为只有到那一步之后,arm_handle 才可用。运行代码片段前需先按下 Play。这些命令需要在物理仿真运行时才能工作。
# Get the number of joints
num_joints = arm_handle.num_joints
print("Number of joints: ", num_joints)
# Get joint names
joint_names = arm_handle.joint_names
print("Joint names: ", joint_names)
# Get joint limits
joint_limits = arm_handle.get_dof_limits()
print("Joint limits: ", joint_limits)
# Get joint positions
joint_positions = arm_handle.get_joint_positions()
print("Joint positions: ", joint_positions)注意,当按下“Run”时,将只打印一次状态,即便仿真仍在运行。如果想查看更新的状态,必须持续按“Run”。如果想在每个物理步都打印信息,则需要将这些命令插到在每个物理步都运行的物理回调中。
要将这些命令插到物理回调中,请在 Script Editor 的单独选项卡中运行以下代码片段。
import asyncio
from isaacsim.core.api.simulation_context import SimulationContext
async def test():
def print_state(dt):
joint_positions = arm_handle.get_joint_positions()
print("Joint positions: ", joint_positions)
simulation_context = SimulationContext()
await simulation_context.initialize_simulation_context_async()
await simulation_context.reset_async()
simulation_context.add_physics_callback("printing_state", print_state)
asyncio.ensure_future(test())按下 Play 启动仿真,然后运行该代码片段。可以看到信息在每个物理步都被打印到终端中。
如果不再需要每个物理步都打印,可以通过运行以下代码片段移除物理回调。
simulation_context = SimulationContext()
simulation_context.remove_physics_callback("printing_state")2.3. 控制机器人
在 Isaac Sim 中,可以通过多种方法控制机器人。最底层的方法是直接发送关节命令设置位置、速度和力矩。下面是使用 Articulation API 在关节级别控制机器人的示例。
在 Script Editor 中打开新标签页,复制粘贴下面的代码片段。该代码只能在前面的添加机器人步骤完成后运行,因为只有到那一步之后,arm_handle 才可用。运行代码片段前请先按下 Play 按钮。必须启动物理仿真,这些命令才能生效。下面提供两个位置,可以在它们之间切换。如果已经将上面的打印状态代码片段添加到每个物理步中,应该能看到随着机器人移动,打印出的关节数值发生变化。
# Set joint position randomly
arm_handle.set_joint_positions([[-1.5, 0.0, 0.0, -1.5, 0.0, 1.5, 0.5, 0.04, 0.04]])# Set all joints to 0
arm_handle.set_joint_positions([[0.0, 0.0, 0.0 , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])与上面的 get_joint_positions 函数类似,这里的 set_joint_positions 只在按下“Run”时执行一次。如果希望在每个物理步都发送命令,则需要将这些命令插到在每个物理步都运行的物理回调中。
3. Standalone Python
运行本教程的脚本位于 standalone_examples/tutorials/getting_started_robot.py。要运行该脚本,请打开终端,切换到 Isaac Sim 安装目录的根目录,然后运行以下命令:
./python.sh standalone_examples/tutorials/getting_started_robot.py3.1. 代码解析
getting_started_robot.py 脚本中的第 14 到 50 行用于设置场景,以及将机器人添加到 Stage 中。脚本首先导入必要的模块、添加地平面、设置相机角度,并且向场景中添加两个机器人:一个机械臂机器人和一个移动机器人。这里使用的 API 与 Extension 工作流中使用的相同。
Extension 工作流中的 Python 与 Standalone Python 的主要区别包括:
3.1.1. 从顶部启动仿真器
独立脚本启动仿真应用并且设置 Stage(创建新 Stage、地平面,添加 Franka 和 Carter)。以下代码片段展示该模式:先启动应用,然后使用实验性 API 创建 Stage 及添加机器人。
from isaacsim import SimulationApp
simulation_app = SimulationApp({"headless": False})
import isaacsim.core.experimental.utils.stage as stage_utils
from isaacsim.core.experimental.objects import GroundPlane
from isaacsim.core.experimental.prims import Articulation, XformPrim
from isaacsim.storage.native import get_assets_root_path
assets_root_path = get_assets_root_path()
stage_utils.create_new_stage()
GroundPlane("/World/GroundPlane", positions=[0, 0, 0])
asset_path = assets_root_path + "/Isaac/Robots/FrankaRobotics/FrankaPanda/franka.usd"
stage_utils.add_reference_to_stage(usd_path=asset_path, path="/World/Arm")
arm_transform = XformPrim("/World/Arm")
arm_transform.set_world_poses(positions=[0.0, 1.0, 0.0])
arm = Articulation("/World/Arm")3.1.2. 显式地步进仿真
在脚本底部的循环中,每次迭代都调用步进函数 my_world.step()。在这个步进函数内部,它向前推进固定次数的渲染和物理计算。
该脚本将运行 4 个周期;在每个周期中,机械臂和小车将移动或停止,并且在最后一个周期中,在每个物理步都打印小车的关节位置。
for i in range(4):
print("running cycle: ", i)
if i == 1 or i == 3:
print("moving")
# move the arm
arm.set_joint_positions([[-1.5, 0.0, 0.0, -1.5, 0.0, 1.5, 0.5, 0.04, 0.04]])
# move the car
car.set_joint_velocities([[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]])
if i == 2:
print("stopping")
# reset the arm
arm.set_joint_positions([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
# stop the car
car.set_joint_velocities([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
for j in range(100):
# step the simulation, both rendering and physics
my_world.step(render=True)
# print the joint positions of the car at every physics step
if i == 3:
car_joint_positions = car.get_joint_positions()
print("car joint positions:", car_joint_positions)get_dof_positions 和 set_dof_positions 函数与 Extension 工作流中使用的相同。因为在 Standalone 中步进是显式的,所以这些命令位于循环内部,并且默认在每个物理步运行。这是 Extension 和 Standalone Python 工作流之间的主要区别。