오늘은 'spawn_prims.py'에 대해서 배워볼것이다.
우선 실행을 해보면 다양한 객체들과 물리 법칙이 적용됨을 볼 수 있다.
옴니버스의 scene은 USD(Univeral Scene Description)라는 소프트웨어 시스템과 파일 형식을 중식으로 구축된다.
USD는 포괄적인 프레임워크이다.
Isaac Lab은 scene을 더 쉽게 디자인할 수 있도록 USD API 구성 기반 인터페이스를 제공.
import argparse
from omni.isaac.lab.app import AppLauncher
# create argparser
parser = argparse.ArgumentParser(description="Tutorial on spawning prims into the scene.")
# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
# parse the arguments
args_cli = parser.parse_args()
# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app
# 위 코드까지는 거의 기본값임
"""Rest everything follows."""
# prim_utils : 시뮬레이션 장면에서 object(prims)를 생성하고 관리하는 라이브러리
import omni.isaac.core.utils.prims as prim_utils
# sim_utils : 시뮬레이션의 물리, 조명, 기타 요소를 생성하고 제어하는 라이브러리
import omni.isaac.lab.sim as sim_utils
# ISAAC_NUCLEUS_DIR : 3d 모델(mesh등)과 같은 assets을 저장하고 공유하기 위한 디렉토리 경로. 이를 통해 시뮬레이션에서 기존 모델(테이블,로봇 등) 사용 가능
from omni.isaac.lab.utils.assets import ISAAC_NUCLEUS_DIR
def design_scene():
# GroundPlaneCFG() : 접지면 생성
cfg_ground = sim_utils.GroundPlaneCfg()
# 접지면을 생성하고 'World/defaultGroundPlane'에 배치하는 함수 호출.
# defaultGroundPlane은 접지면 object의 이름
cfg_ground.func("/World/defaultGroundPlane", cfg_ground)
# 원거리 광원 추가
# DistantLightCfg : scene에 햇빛 추가
# intensity=3000.0 : 빛의 밝기를 의미. 숫자가 높을수록 빛이 더 강해짐
# color=(0.75, 0.75, 0.75) : RGB값을 이용해 조명의 색상 설정
cfg_light_distant = sim_utils.DistantLightCfg(
intensity=3000.0,
color=(0.75, 0.75, 0.75),
)
# '/World/lightDistant' 경로 아래 조명 생성
# translation=(1, 0, 10)은 3D 공간의 (1, 0, 10) 좌표에 빛을 배치
cfg_light_distant.func("/World/lightDistant", cfg_light_distant, translation=(1, 0, 10))
# object 만들기
# 추후 만들 원뿔, 큐브 등을 넣을 상위 폴더 생성
# 'Xform'은 다른 개체를 담을 수 있는 빈 폴더와 같기 때문에 함께 구성하고 조작하기 더 수월함
prim_utils.create_prim("/World/Objects", "Xform")
# ConeCfg(): 원뿔 객체를 생성하기 위한 함수
# radius=0.15는 원뿔의 기본 반경을 설정. height=0.5는 원뿔의 높이를 설정.
cfg_cone = sim_utils.ConeCfg(
radius=0.15,
height=0.5,
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0)),
)
ex)
visual_material=sim_utils.PreviewSurfaceCfg(
diffuse_color=(0.5, 0.5, 0.5), # A gray color
roughness=0.8, # A matte surface, not shiny
metallic=0.0 # Non-metallic, like plastic
)
색깔은 회색, 표면은 무광택, 금속이 아닌 object가 형성된다.
# scene의 '/World/Objects/Cone1' 경로에 원뿔을 생성하고 (-1.0, 1.0, 1.0) 좌표에 생성
cfg_cone.func("/World/Objects/Cone1", cfg_cone, translation=(-1.0, 1.0, 1.0))
# 똑같이 원뿔을 생성하고 다른 위치인 (-1.0, -1.0, 1.0) 좌표에 생성
cfg_cone.func("/World/Objects/Cone2", cfg_cone, translation=(-1.0, -1.0, 1.0))
# ConeCfg() : 원뿔 object를 생성하는 이전과 동일한 함수.
# 하지만 이번에는 실제 object처럼 동작하도록 물리적 속성을 부여함.
cfg_cone_rigid = sim_utils.ConeCfg(
radius=0.15,
height=0.5,
# RigidBodyPropertiesCfg() : 원뿔에 강체 물리학이 추가됨. 즉 원뿔은 움직일 수 있으며 다른 물체와 충돌하고 중력의 영향을 받음
# 물리학에서 강체는 힘이 가해질 때 변형되지 않는 물체를 의미함.
rigid_props=sim_utils.RigidBodyPropertiesCfg(),
# MassPropertiesCfg(mass=1.0) : 원뿔의 질량(mass)가 1.0 단위로 설정됨. 1kg을 의미. 값을 더 키우면 물체가 무거워짐(움직이기 더 어려움)
mass_props=sim_utils.MassPropertiesCfg(mass=1.0),
# CollisionPropertiesCfg() : object의 충돌 속성을 정의. 이렇게 하면 원뿔이 다른 개체에 닿을때 시뮬레이션이 상호작용을 감지하고 물리적 반응(바운싱, 중지)가 발생할 수 있음
collision_props=sim_utils.CollisionPropertiesCfg(),
# PreviewSurfaceCfg() : 원뿔의 색깔이 녹색으로 설정됨 (RGB값중 G만 1임)
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)),
)
# scene에 녹색 원뿔 생성
# '/World/Objects/ConeRigid' 경로에 object가 배치되고
# cfg_cone_rigid 라는 이름을 부여
# translation=(-0.2, 0.0, 2.0)의 좌표에 배치됨
# orientation=(0.5, 0.0, 0.5, 0.0) 원뿔의 방향을 설정. 여기서는 3D에서 회전을설정하는 방법인 쿼터니언을 나타냄. 이 회전으로 원뿔이 약간 기울어짐
cfg_cone_rigid.func(
"/World/Objects/ConeRigid", cfg_cone_rigid, translation=(-0.2, 0.0, 2.0), orientation=(0.5, 0.0, 0.5, 0.0)
)
# 변형 가능한 파란색 직육면체 생성
# MeshCuboidCfg() : 직육면체 object를 구성
# DeformableBodyPropertiesCfg() : 개체가 단단하지 않음을 의미. 힘이 가해지면 구부러지거나 늘어날 수 있음
# PreviewSurfaceCfg() : 파란색 설정
# DeformableBodyMaterialCfg() : 직육면체에 변형 가능한 물리 재료 추가
cfg_cuboid_deformable = sim_utils.MeshCuboidCfg(
size=(0.2, 0.5, 0.2), # 크기 정의
deformable_props=sim_utils.DeformableBodyPropertiesCfg(),
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 0.0, 1.0)),
physics_material=sim_utils.DeformableBodyMaterialCfg(),
)
# '/World/Objects/CuboidDeformable' 경로에 변형 가능한 직육면체를(0.15, 0.0, 2.0) 좌표에 생성
cfg_cuboid_deformable.func("/World/Objects/CuboidDeformable", cfg_cuboid_deformable, translation=(0.15, 0.0, 2.0))
# USD 파일에서 테이블 생성
# UsdFileCfg() : 복잡한 3D 모델, scene 및 시뮬레이션의 USD 파일 로드 가능
# usd_path : 해당 경로는 3D 모델이 퐇마된 Nucleus 디렉토리에 있는 특정 USD 파일을 가리킴
# {ISAAC_NUCLEUS_DIR} 은 usd 파일이 있는 디렉토리를 참조
cfg = sim_utils.UsdFileCfg(usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Mounts/SeattleLabTable/table_instanceable.usd")
# cfg.func : 이 함수는 테이블 모델을 장면에 로드함
# '/World/Objects/Table' 위치에 테이블 저장하고 (0.0, 0.0, 1.05) 좌표에 배치
cfg.func("/World/Objects/Table", cfg, translation=(0.0, 0.0, 1.05))
def main():
"""Main function."""
# SimulationCfg(dt=0.01) : 시뮬레이션 프레임이 0.01초씩 진행. dt값이 작아질수록 물리 시뮬레이션은 더 정확해지지만 더 많은 컴퓨팅 자원이 소모
sim_cfg = sim_utils.SimulationCfg(dt=0.01)
# SimulationContext(sim_cfg) : 이전 줄에 정의한 'sim_cfg'를 사용하여 실제 시뮬레이션 초기화
sim = sim_utils.SimulationContext(sim_cfg)
# 카메라 위치 설정
sim.set_camera_view([2.0, 0.0, 2.5], [-0.5, 0.0, 0.5])
# design_scene() : 지면, 원뿔, 직육면체, 테이블, 조명 등을 생성하는 함수를 트리거
design_scene()
# sim.reset() : 시뮬레이션을 초기화. 이전 상태를 모두 지우고 올바른 설정이 불러지도록 준비하는 단계
sim.reset()
# Now we are ready!
print("[INFO]: Setup complete...")
# 에플리케이션이 활성화되고 있는 동안 계속 실행됨
while simulation_app.is_running():
# 시뮬레이션이 0.01초 프레임 간격으로 진행됨
sim.step()
if __name__ == "__main__":
# run the main function
main()
# close sim app
simulation_app.close()