
강체와 상호작용을 해보자
$ python source/standalone/tutorials/01_assets/run_rigid_object.py
import argparse
from omni.isaac.lab.app import AppLauncher
parser = argparse.ArgumentParser(description="Tutorial on spawning and interacting with a rigid object.")
AppLauncher.add_app_launcher_args(parser)
args_cli = parser.parse_args()
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app
import torch
import omni.isaac.core.utils.prims as prim_utils
import omni.isaac.lab.sim as sim_utils
import omni.isaac.lab.utils.math as math_utils
from omni.isaac.lab.assets import RigidObject, RigidObjectCfg
from omni.isaac.lab.sim import SimulationContext
def design_scene():
cfg = sim_utils.GroundPlaneCfg()
cfg.func("/World/defaultGroundPlane", cfg)
cfg = sim_utils.DomeLightCfg(intensity=2000.0, color=(0.8, 0.8, 0.8))
cfg.func("/World/Light", cfg)
'''
origins는 4개 원뿔 각각의 위치를 정의하는 x,y,z 좌표
create_prim() : 새로운 prim을 만듦.
f"/World/Origin{i}" : prim이 생성될 경로. /World 루트 아래에 Origin0. Origin1.....등이 생성됨.
Xform이란? Xform 자체는 물리적 존재나 시각적 외관이 없다. 빈 컨테이너 또는 상위 노드라고 생각하면 된다. 나중에 위치, 방향 등을 구성하고 적용하는 방법일 뿐이다.
이 코드는 Xform을 origins 좌표에 원뿔을 구성하고 배치하는데 사용한다.
Xform을 통해 모든 원뿔을 집합적으로 변환을 더 쉽게 할 수 있다.
'''
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)
'''
RigidObjectCfg() : 강체(여기서는 원뿔)를 생성하는 객체이다.
prim_path="/World/Origin.*/Cone" : 각 con을 Origin0,1,2,3에 배치한다는 의미
sim_utils.ConeCfg() : 원뿔의 물리적 속성을 설정하는 객체이다.
radius는 반지름, height는 원뿔의 높이, rigid_props는 강체의 물리적 속성, mass_props는 원뿔의 질량을 1.0으로 설정, collision_props는 충돌 처리를 위한 속성
visual_material() : 원뿔의 시각적 속성을 설정함. 여기서는 녹색 원뿔이 생성되고 약간의 금속성 효과가 적용됨.
'''
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_entities = {"cone": cone_object}
return scene_entities, origins
def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, RigidObject], origins: torch.Tensor):
cone_object = entities["cone"]
sim_dt = sim.get_physics_dt()
sim_time = 0.0
count = 0
while simulation_app.is_running():
if count % 250 == 0:
sim_time = 0.0
count = 0
root_state = cone_object.data.default_root_state.clone()
'''
root_state : 슬라이싱을 사용하여 root_state 텐서의 특정 부분을 선택
원뿔의 위치, 회전 및 기타 물리적 속성이 포함됨
각 행은 위치(x,y,z), 회전(쿼터니언) 같은 속성을 저장함
[:, :3] : root_state 텐서에서 특정 요소를 선택함. 첫번째 : 는 모든 원뿔 즉 4개의 원뿔을 모두 선택함. 두번째 :3 은 각 행의 처음 3개 요소(열)을 선택함을 의미. 해당 경우는 x,y,z 즉 위치를 참조함
root_state[:, :3] += origins는 위 origins 좌표를 더해 모든 원뿔 위치를 업데이트함.
root_state[:, :3] += math_utils.sample_cylinder() : 임의의 오프셋을 추가하여 원점 주변의 원통형 영역 내의 임의 위치에 각 원뿔을 배치한다.
반경 0.1과 h_range(0.25, 0.5)는 원뿔이 배치될 수직 높이를 정의함 0.25~0.5 사이의 랜덤한 값으로 원뿔 높이가 정의됨.
size=cone_object.num_instances : 원뿔 개체 수만큼 임의의 위치를 생성하도록함 즉 무작위 위치 4개가 설정됨
'''
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
)
cone_object.write_root_state_to_sim(root_state)
cone_object.reset()
print("----------------------------------------")
print("[INFO]: Resetting object state...")
cone_object.write_data_to_sim()
sim.step()
sim_time += sim_dt
count += 1
cone_object.update(sim_dt)
if count % 50 == 0:
print(f"Root position (in world): {cone_object.data.root_state_w[:, :3]}")

def main():
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device)
sim = SimulationContext(sim_cfg)
sim.set_camera_view(eye=[1.5, 0.0, 1.0], target=[0.0, 0.0, 0.0])
scene_entities, scene_origins = design_scene()
scene_origins = torch.tensor(scene_origins, device=sim.device)
sim.reset()
print("[INFO]: Setup complete...")
run_simulator(sim, scene_entities, scene_origins)
if __name__ == "__main__":
main()
simulation_app.close()