与刚性物体交互#
在以前的教程中,我们学习了独立脚本的基本工作原理以及如何将不同的对象(或 对象 )生成到模拟中。本教程展示了如何创建和与刚性物体交互。为此,我们将使用 Isaac Lab 中提供的 assets.RigidObject
类。
代码#
该教程对应于 source/standalone/tutorials/01_assets
目录中的 run_rigid_object.py
脚本。
run_rigid_object.py 的代码
1# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
2# All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5
6"""
7This script demonstrates how to create a rigid object and interact with it.
8
9.. code-block:: bash
10
11 # Usage
12 ./isaaclab.sh -p source/standalone/tutorials/01_assets/run_rigid_object.py
13
14"""
15
16"""Launch Isaac Sim Simulator first."""
17
18
19import argparse
20
21from omni.isaac.lab.app import AppLauncher
22
23# add argparse arguments
24parser = argparse.ArgumentParser(description="Tutorial on spawning and interacting with a rigid object.")
25# append AppLauncher cli args
26AppLauncher.add_app_launcher_args(parser)
27# parse the arguments
28args_cli = parser.parse_args()
29
30# launch omniverse app
31app_launcher = AppLauncher(args_cli)
32simulation_app = app_launcher.app
33
34"""Rest everything follows."""
35
36import torch
37
38import omni.isaac.core.utils.prims as prim_utils
39
40import omni.isaac.lab.sim as sim_utils
41import omni.isaac.lab.utils.math as math_utils
42from omni.isaac.lab.assets import RigidObject, RigidObjectCfg
43from omni.isaac.lab.sim import SimulationContext
44
45
46def design_scene():
47 """Designs the scene."""
48 # Ground-plane
49 cfg = sim_utils.GroundPlaneCfg()
50 cfg.func("/World/defaultGroundPlane", cfg)
51 # Lights
52 cfg = sim_utils.DomeLightCfg(intensity=2000.0, color=(0.8, 0.8, 0.8))
53 cfg.func("/World/Light", cfg)
54
55 # Create separate groups called "Origin1", "Origin2", "Origin3"
56 # Each group will have a robot in it
57 origins = [[0.25, 0.25, 0.0], [-0.25, 0.25, 0.0], [0.25, -0.25, 0.0], [-0.25, -0.25, 0.0]]
58 for i, origin in enumerate(origins):
59 prim_utils.create_prim(f"/World/Origin{i}", "Xform", translation=origin)
60
61 # Rigid Object
62 cone_cfg = RigidObjectCfg(
63 prim_path="/World/Origin.*/Cone",
64 spawn=sim_utils.ConeCfg(
65 radius=0.1,
66 height=0.2,
67 rigid_props=sim_utils.RigidBodyPropertiesCfg(),
68 mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
69 collision_props=sim_utils.CollisionPropertiesCfg(),
70 visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0), metallic=0.2),
71 ),
72 init_state=RigidObjectCfg.InitialStateCfg(),
73 )
74 cone_object = RigidObject(cfg=cone_cfg)
75
76 # return the scene information
77 scene_entities = {"cone": cone_object}
78 return scene_entities, origins
79
80
81def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, RigidObject], origins: torch.Tensor):
82 """Runs the simulation loop."""
83 # Extract scene entities
84 # note: we only do this here for readability. In general, it is better to access the entities directly from
85 # the dictionary. This dictionary is replaced by the InteractiveScene class in the next tutorial.
86 cone_object = entities["cone"]
87 # Define simulation stepping
88 sim_dt = sim.get_physics_dt()
89 sim_time = 0.0
90 count = 0
91 # Simulate physics
92 while simulation_app.is_running():
93 # reset
94 if count % 250 == 0:
95 # reset counters
96 sim_time = 0.0
97 count = 0
98 # reset root state
99 root_state = cone_object.data.default_root_state.clone()
100 # sample a random position on a cylinder around the origins
101 root_state[:, :3] += origins
102 root_state[:, :3] += math_utils.sample_cylinder(
103 radius=0.1, h_range=(0.25, 0.5), size=cone_object.num_instances, device=cone_object.device
104 )
105 # write root state to simulation
106 cone_object.write_root_state_to_sim(root_state)
107 # reset buffers
108 cone_object.reset()
109 print("----------------------------------------")
110 print("[INFO]: Resetting object state...")
111 # apply sim data
112 cone_object.write_data_to_sim()
113 # perform step
114 sim.step()
115 # update sim-time
116 sim_time += sim_dt
117 count += 1
118 # update buffers
119 cone_object.update(sim_dt)
120 # print the root position
121 if count % 50 == 0:
122 print(f"Root position (in world): {cone_object.data.root_state_w[:, :3]}")
123
124
125def main():
126 """Main function."""
127 # Load kit helper
128 sim_cfg = sim_utils.SimulationCfg(device=args_cli.device)
129 sim = SimulationContext(sim_cfg)
130 # Set main camera
131 sim.set_camera_view(eye=[1.5, 0.0, 1.0], target=[0.0, 0.0, 0.0])
132 # Design scene
133 scene_entities, scene_origins = design_scene()
134 scene_origins = torch.tensor(scene_origins, device=sim.device)
135 # Play the simulator
136 sim.reset()
137 # Now we are ready!
138 print("[INFO]: Setup complete...")
139 # Run the simulator
140 run_simulator(sim, scene_entities, scene_origins)
141
142
143if __name__ == "__main__":
144 # run the main function
145 main()
146 # close sim app
147 simulation_app.close()
代码解释#
在此脚本中,我们将 main
函数拆分为两个单独的函数,这两个函数强调了在模拟器中设置任何模拟的两个主要步骤:
设计场景: 顾名思义,这一部分负责将所有对象添加到场景中。
运行模拟: 这部分负责推进模拟器,与场景中的对象交互,例如改变它们的姿势,并对其施加任何命令。
这两个步骤之间的区别是必需的,因为只有在第一步完成并且模拟器被重置后,第二步才会发生。一旦模拟器被重置(自动播放模拟),就不应该再向场景中添加新的(带有物理效果)对象,因为这可能会导致意外行为。但是,可以通过它们各自的句柄与对象进行交互。
设计场景#
与之前的教程类似,我们使用一个地面平面和一个光源填充场景。此外,我们使用 assets.RigidObject
类将一个刚性物体添加到场景中。该类负责在输入路径处生成对象,同时初始化其对应的刚性物理句柄。
在本教程中,我们使用与 Spawn Objects 教程中刚性锥体类似的生成配置创建一个圆锥形刚性物体。唯一的区别是现在我们将生成配置封装到 assets.RigidObjectCfg
类中。该类包含有关资产生成策略、默认初始状态和其他元信息的信息。当将此类传递给 assets.RigidObject
类时,当播放模拟时,它会生成对象并初始化相应的物理句柄。
作为多次生成刚性物体对象的示例,我们创建其父级 Xform 对象, /World/Origin{i}
,它们对应不同的生成位置。当将正则表达式 /World/Origin*/Cone
传递给 assets.RigidObject
类时,它会在每个 /World/Origin{i}
位置生成刚性物体对象。例如,如果场景中存在 /World/Origin1
和 /World/Origin2
,则刚性物体对象会分别生成在位置 /World/Origin1/Cone
和 /World/Origin2/Cone
上。
# Create separate groups called "Origin1", "Origin2", "Origin3"
# Each group will have a robot in it
origins = [[0.25, 0.25, 0.0], [-0.25, 0.25, 0.0], [0.25, -0.25, 0.0], [-0.25, -0.25, 0.0]]
for i, origin in enumerate(origins):
prim_utils.create_prim(f"/World/Origin{i}", "Xform", translation=origin)
# Rigid Object
cone_cfg = RigidObjectCfg(
prim_path="/World/Origin.*/Cone",
spawn=sim_utils.ConeCfg(
radius=0.1,
height=0.2,
rigid_props=sim_utils.RigidBodyPropertiesCfg(),
mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
collision_props=sim_utils.CollisionPropertiesCfg(),
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0), metallic=0.2),
),
init_state=RigidObjectCfg.InitialStateCfg(),
)
cone_object = RigidObject(cfg=cone_cfg)
因为我们想要与刚性物体交互,我们将此实体传递回主函数。然后,该实体用于在模拟循环中与刚性物体交互。在后续教程中,我们将看到如何使用 scene.InteractiveScene
类更方便地处理多个场景实体。
# return the scene information
scene_entities = {"cone": cone_object}
return scene_entities, origins
运行模拟循环#
我们修改了模拟循环以与刚性物体交互,包括三个步骤——在固定间隔重置模拟状态,推进模拟,以及更新刚性物体的内部缓冲区。为了方便本教程,我们从场景字典中提取刚性物体的实体并将其存储在一个变量中。
重置模拟状态#
为了重置生成的刚性物体对象的模拟状态,我们需要设置其姿势和速度。它们共同定义了生成的刚性物体对象的根状态。重要的是要注意,此状态定义在 模拟世界坐标系 中,而不是它们父级 Xform 对象的坐标系。这是因为物理引擎只能理解世界坐标系,而不能理解父级 Xform 对象的坐标系。因此,在设置之前,我们需要将刚性物体对象的期望状态转换为世界坐标系。
我们使用 assets.RigidObject.data.default_root_state
属性获取生成的刚性物体对象的默认根状态。该默认状态可以从 assets.RigidObjectCfg.init_state
属性中配置,我们在本教程中将其保留为单位状态。然后,我们随机化根状态的平移,并使用 assets.RigidObject.write_root_state_to_sim()
方法设置刚性物体对象的期望状态。顾名思义,此方法将刚性物体对象的根状态写入模拟缓冲区。
# reset root state
root_state = cone_object.data.default_root_state.clone()
# sample a random position on a cylinder around the origins
root_state[:, :3] += origins
root_state[:, :3] += math_utils.sample_cylinder(
radius=0.1, h_range=(0.25, 0.5), size=cone_object.num_instances, device=cone_object.device
)
# write root state to simulation
cone_object.write_root_state_to_sim(root_state)
# reset buffers
cone_object.reset()
推进模拟#
在推进模拟之前,我们执行 assets.RigidObject.write_data_to_sim()
方法。此方法将其他数据,例如外部力,写入模拟缓冲区。在本教程中,我们没有对刚性物体施加任何外部力,因此此方法不是必需的。但是,为了完整性,我们还是加入了它。
# apply sim data
cone_object.write_data_to_sim()
更新状态#
在推进模拟后,我们使用 assets.RigidObject.update()
方法更新刚性物体对象的内部缓冲区,以反映其在 assets.RigidObject.data
属性中的新状态。
# update buffers
cone_object.update(sim_dt)
代码执行#
现在我们已经浏览了代码,让我们运行脚本并查看结果:
./isaaclab.sh -p source/standalone/tutorials/01_assets/run_rigid_object.py
这应该打开一个场景,上面有一个地面平面、灯光和几个绿色圆锥体。圆锥体应该从一个随机高度掉落并落到地面上。要停止模拟,你可以关闭窗口,或者在 UI 中按下 STOP
按钮,或者在终端中按下 Ctrl+C
本教程展示了如何生成刚性物体并将它们封装在一个 RigidObject
类中以初始化它们的物理句柄,从而允许设置和获取它们的状态。在下一个教程中,我们将看到如何与由关节连接的一系列刚性物体组成的关节物体进行交互。