1편 : IsaacSim, IsaacLab 설치하기, 예제 돌려보기, Miniconda 가상 환경 구성
0. tutorials 코드 위치
project 폴더의 scripts/tutorials/
![[Robot RL][IsaacLab][window][1] 초보 – IsaacSim, IsaacLab tutorial 코드 분석, {reinforcement learning project} 1 image](https://i0.wp.com/openpj.co.kr/wp-content/uploads/2025/04/image.png?resize=445%2C596&ssl=1)
1. Empty Scene (create_empty.py)
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""This script demonstrates how to create a simple stage in Isaac Sim.
.. code-block:: bash
# Usage
./isaaclab.sh -p scripts/tutorials/00_sim/create_empty.py
"""
"""Launch Isaac Sim Simulator first."""
import argparse # 표준 파이썬 모듈: 명령줄 인자를 파싱할 때 사용
from isaaclab.app import AppLauncher # Isaac Lab에서 제공하는 App 실행 유틸리티
# ArgumentParser 객체 생성 – 명령줄에서 인자를 받을 수 있게 함
parser = argparse.ArgumentParser(description="Tutorial on creating an empty stage.")
# AppLauncher에서 기본 제공하는 CLI 인자들(예: headless mode, livestream 등)을 추가
AppLauncher.add_app_launcher_args(parser)
# 명령줄 인자를 실제로 파싱
args_cli = parser.parse_args()
# AppLauncher 객체를 생성하고, 이를 통해 simulation app 실행
# 이때 환경 설정 및 시뮬레이터 설정도 같이 처리됨
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app # 실행된 시뮬레이터 앱 객체 저장
# 여기부터 실제 시뮬레이션 관련 코드 작성
from isaaclab.sim import SimulationCfg, SimulationContext # 시뮬레이션 설정 및 컨텍스트 제어 클래스
def main():
"""메인 실행 함수"""
# 시뮬레이션 설정 객체 생성 (물리 엔진 설정 포함)
sim_cfg = SimulationCfg(dt=0.01) # 시간 간격을 0.01초로 설정 (시뮬레이션 속도 결정)
sim = SimulationContext(sim_cfg) # 설정을 기반으로 시뮬레이션 컨텍스트 생성
# 카메라 위치 및 바라보는 지점 설정 (카메라는 [2.5, 2.5, 2.5] 위치에서 [0,0,0] 중심을 봄)
sim.set_camera_view([2.5, 2.5, 2.5], [0.0, 0.0, 0.0])
# 시뮬레이션 재설정: 타임라인 재생 및 물리 초기화 포함 (step 전에 반드시 호출 필요)
sim.reset()
print("[INFO]: Setup complete...") # 준비 완료 메시지 출력
# 시뮬레이션 루프 실행 (사용자가 시뮬레이터 창을 닫을 때까지 반복)
while simulation_app.is_running():
sim.step() # 물리 시뮬레이션 한 스텝 진행 (렌더링 포함)
if __name__ == "__main__":
# main 함수 실행
main()
# 시뮬레이션 종료 및 리소스 정리
simulation_app.close()
2. spawn_prims.py
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""This script demonstrates how to spawn prims into the scene.
.. code-block:: bash
# Usage
./isaaclab.sh -p scripts/tutorials/00_sim/spawn_prims.py
"""
"""Launch Isaac Sim Simulator first."""
import argparse # 명령줄 인자 파싱용 표준 Python 모듈
from isaaclab.app import AppLauncher # Isaac Lab에서 제공하는 시뮬레이터 런처 클래스
# 명령줄 인자를 처리하기 위한 parser 생성
parser = argparse.ArgumentParser(description="Tutorial on spawning prims into the scene.")
# AppLauncher에서 정의한 공통 인자 추가 (예: headless 모드, 디바이스 선택 등)
AppLauncher.add_app_launcher_args(parser)
# 실제로 인자들을 파싱
args_cli = parser.parse_args()
# 파싱한 인자를 이용해 AppLauncher 인스턴스 생성 → 내부적으로 Isaac Sim 실행
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app # 실행된 시뮬레이터 핸들 (렌더링 루프 등 제어 가능)
"""아래는 시뮬레이터 실행 이후에 호출되어야 합니다."""
import isaacsim.core.utils.prims as prim_utils # Prim(기본 단위 오브젝트) 관련 유틸 함수
import isaaclab.sim as sim_utils # 시뮬레이션 구성(Config) 및 생성 관련 클래스
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR # Omniverse Nucleus 서버 자산 경로
def design_scene():
"""씬에 여러 Prim들을 생성하여 환경을 구성하는 함수입니다."""
# 바닥(ground plane)을 생성하는 Config 객체 생성
cfg_ground = sim_utils.GroundPlaneCfg()
# func()은 해당 config를 사용하여 실제로 USD 스테이지에 prim을 생성합니다
cfg_ground.func("/World/defaultGroundPlane", cfg_ground)
# Distant Light(무한광): 강한 평행광 형태의 빛을 추가
cfg_light_distant = sim_utils.DistantLightCfg(
intensity=3000.0, # 광원 세기
color=(0.75, 0.75, 0.75), # 회색 톤
)
# 위치를 명시해도 distant light는 무한 원거리 광원이므로 사실 위치는 큰 영향 없음
cfg_light_distant.func("/World/lightDistant", cfg_light_distant, translation=(1, 0, 10))
# 객체들을 그룹화하기 위한 transform 노드 생성 (Xform Prim)
# 이 아래에 생성된 모든 prim은 함께 이동/회전 가능
prim_utils.create_prim("/World/Objects", "Xform")
# 빨간색 콘 두 개 생성 (visual만 존재하고, 물리 속성 없음)
cfg_cone = sim_utils.ConeCfg(
radius=0.15,
height=0.5,
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0)), # 빨간색
)
cfg_cone.func("/World/Objects/Cone1", cfg_cone, translation=(-1.0, 1.0, 1.0))
cfg_cone.func("/World/Objects/Cone2", cfg_cone, translation=(-1.0, -1.0, 1.0))
# 초록색 콘 생성: rigid body + 충돌 + 질량 설정 → 물리 시뮬레이션 가능
cfg_cone_rigid = sim_utils.ConeCfg(
radius=0.15,
height=0.5,
rigid_props=sim_utils.RigidBodyPropertiesCfg(), # 강체 설정
mass_props=sim_utils.MassPropertiesCfg(mass=1.0), # 질량 1kg
collision_props=sim_utils.CollisionPropertiesCfg(), # 충돌 가능
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.0, 1.0, 0.0)), # 초록색
)
# orientation은 쿼터니언 값으로 회전 상태를 설정
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)
)
# 파란색 변형 가능한 큐브 생성 (deformable body)
# 내부 응력/신축성 시뮬레이션을 위한 설정 포함
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(), # 마찰, 반발력 등 외부 물성
)
cfg_cuboid_deformable.func("/World/Objects/CuboidDeformable", cfg_cuboid_deformable, translation=(0.15, 0.0, 2.0))
# 외부 USD 파일(table_instanceable.usd)에서 테이블 로드
# Nucleus 서버에서 제공하는 자산으로, 실제 경로는 ISAAC_NUCLEUS_DIR에 저장
cfg = sim_utils.UsdFileCfg(usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Mounts/SeattleLabTable/table_instanceable.usd")
cfg.func("/World/Objects/Table", cfg, translation=(0.0, 0.0, 1.05)) # 테이블은 살짝 위에 배치
def main():
"""메인 함수 – 시뮬레이터 초기화, 씬 구성, 시뮬레이션 루프 실행"""
# 시뮬레이션 설정: 시간 간격(dt), 사용할 디바이스 등 지정
sim_cfg = sim_utils.SimulationCfg(dt=0.01, device=args_cli.device)
sim = sim_utils.SimulationContext(sim_cfg)
# 카메라 위치 설정 (시작 위치와 바라보는 포인트)
sim.set_camera_view([2.0, 0.0, 2.5], [-0.5, 0.0, 0.5])
# 위에서 정의한 씬 구성 함수 실행 → 여러 prim들을 스테이지에 배치
design_scene()
# 시뮬레이터 재설정 (physics 핸들 초기화 및 타임라인 시작)
sim.reset()
print("[INFO]: Setup complete...")
# 시뮬레이션 루프 실행: 앱이 종료될 때까지 계속 실행
while simulation_app.is_running():
sim.step() # 시뮬레이터 한 스텝 진행 (physics + 렌더링)
# 프로그램 실행 진입점
if __name__ == "__main__":
main() # 메인 함수 실행
simulation_app.close() # 시뮬레이터 정상 종료
![[Robot RL][IsaacLab][window][1] 초보 – IsaacSim, IsaacLab tutorial 코드 분석, {reinforcement learning project} 2 image 35](https://i0.wp.com/openpj.co.kr/wp-content/uploads/2025/04/image-35.png?resize=750%2C302&ssl=1)
3. Rigid Object (run_rigid_object.py)
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""
This script demonstrates how to create a rigid object and interact with it.
.. code-block:: bash
# Usage
./isaaclab.sh -p scripts/tutorials/01_assets/run_rigid_object.py
"""
"""Launch Isaac Sim Simulator first."""
import argparse # 명령줄 인자를 처리하는 표준 파이썬 모듈
from isaaclab.app import AppLauncher # Isaac Lab의 시뮬레이션 앱 실행을 위한 런처
# argparse 설정 – 명령줄에서 인자를 받을 수 있게 구성
parser = argparse.ArgumentParser(description="Tutorial on spawning and interacting with a rigid object.")
# AppLauncher에서 제공하는 공통 인자 추가 (예: --headless, --renderer 등)
AppLauncher.add_app_launcher_args(parser)
# 인자 파싱
args_cli = parser.parse_args()
# AppLauncher를 통해 시뮬레이션 앱 실행
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app # 시뮬레이션 핸들 얻기
"""아래부터 시뮬레이터가 실행된 이후에 동작해야 하는 코드입니다."""
import torch # PyTorch: 위치, 속도 등 텐서 기반 시뮬레이션 데이터 처리에 사용
import isaacsim.core.utils.prims as prim_utils # Prim 생성 및 조작 유틸
import isaaclab.sim as sim_utils # 시뮬레이터 설정 및 물리 객체 구성 유틸
import isaaclab.utils.math as math_utils # 무작위 위치 샘플링 등 수학 유틸
from isaaclab.assets import RigidObject, RigidObjectCfg # 강체 객체 클래스와 설정 객체
from isaaclab.sim import SimulationContext # 시뮬레이터 컨텍스트 클래스
def design_scene():
"""씬을 구성하는 함수입니다. 바닥, 조명, Xform 그룹, 강체 객체를 생성합니다."""
# 바닥 생성 (Ground Plane)
cfg = sim_utils.GroundPlaneCfg()
cfg.func("/World/defaultGroundPlane", cfg)
# 돔 라이트(Dome Light): 전체 조명 생성
cfg = sim_utils.DomeLightCfg(intensity=2000.0, color=(0.8, 0.8, 0.8))
cfg.func("/World/Light", cfg)
# Xform 그룹 생성 – 4개의 위치에 원점을 기준으로 그룹 생성 (Origin0 ~ Origin3)
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", # 정규 표현식으로 Origin0 ~ Origin3 하위 Cone 생성
spawn=sim_utils.ConeCfg( # 실제 생성할 객체 정의
radius=0.1,
height=0.2,
rigid_props=sim_utils.RigidBodyPropertiesCfg(), # 강체 속성 (물리 시뮬레이션 가능)
mass_props=sim_utils.MassPropertiesCfg(mass=1.0), # 질량 1kg
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(), # 초기 상태: 위치/회전/속도 모두 0
)
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 객체 가져오기 (실제로는 InteractiveScene에서 관리하게 됨)
cone_object = entities["cone"]
# 시뮬레이션 시간 간격(dt) 및 초기화
sim_dt = sim.get_physics_dt()
sim_time = 0.0
count = 0
# 시뮬레이션 루프 실행
while simulation_app.is_running():
# 매 250스텝마다 객체 상태 초기화 (reset)
if count % 250 == 0:
sim_time = 0.0
count = 0
# 기본 루트 상태를 복사 (위치, 회전, 속도 0)
root_state = cone_object.data.default_root_state.clone()
# 초기 위치 조정 – 지정된 origin 위치에 배치
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_pose_to_sim(root_state[:, :7])
cone_object.write_root_velocity_to_sim(root_state[:, 7:])
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)
# 50스텝마다 위치 출력
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()
# PyTorch 텐서로 변환 (GPU 시뮬레이션 지원)
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() # 시뮬레이션 종료
![[Robot RL][IsaacLab][window][1] 초보 – IsaacSim, IsaacLab tutorial 코드 분석, {reinforcement learning project} 3 image 36](https://i0.wp.com/openpj.co.kr/wp-content/uploads/2025/04/image-36.png?resize=750%2C313&ssl=1)
4. run_deformable_object.py
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""
This script demonstrates how to work with the deformable object and interact with it.
.. code-block:: bash
# Usage
./isaaclab.sh -p scripts/tutorials/01_assets/run_deformable_object.py
"""
"""Launch Isaac Sim Simulator first."""
import argparse # 명령줄 인자 처리를 위한 파이썬 표준 모듈
from isaaclab.app import AppLauncher # Isaac Lab에서 시뮬레이터 실행을 위한 런처 클래스
# argparse 설정
parser = argparse.ArgumentParser(description="Tutorial on interacting with a deformable object.")
AppLauncher.add_app_launcher_args(parser) # App 실행 관련 인자 추가
args_cli = parser.parse_args()
# 시뮬레이터 실행
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app # 실행된 시뮬레이터 핸들 저장
"""아래부터는 Isaac Sim이 실행된 이후에 호출되어야 하는 코드입니다."""
import torch # 텐서 연산용 (변형체의 상태 관리에 활용)
import isaacsim.core.utils.prims as prim_utils # prim (기본 오브젝트) 생성 유틸리티
import isaaclab.sim as sim_utils # 시뮬레이션 구성 클래스 및 설정
import isaaclab.utils.math as math_utils # 수학적 유틸 (회전, 무작위 샘플링 등)
from isaaclab.assets import DeformableObject, DeformableObjectCfg # 변형 객체 클래스 및 설정 객체
from isaaclab.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)
# Xform 그룹 4개 생성 (Origin0 ~ Origin3)
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)
# 변형 가능한 큐브 설정
cfg = DeformableObjectCfg(
prim_path="/World/Origin.*/Cube", # Origin 그룹 아래 위치
spawn=sim_utils.MeshCuboidCfg(
size=(0.2, 0.2, 0.2), # 큐브 크기
deformable_props=sim_utils.DeformableBodyPropertiesCfg(
rest_offset=0.0, contact_offset=0.001), # 변형 세부 설정
visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(0.5, 0.1, 0.0)), # 시각 재질 (갈색)
physics_material=sim_utils.DeformableBodyMaterialCfg(
poissons_ratio=0.4, youngs_modulus=1e5), # 포아송 비, 영률 → 변형 물성 정의
),
init_state=DeformableObjectCfg.InitialStateCfg(pos=(0.0, 0.0, 1.0)), # 초기 위치 (높이 1m)
debug_vis=True, # 디버그 시각화 활성화
)
cube_object = DeformableObject(cfg=cfg) # 실제 객체 생성
# 생성된 객체 및 그룹 반환
scene_entities = {"cube_object": cube_object}
return scene_entities, origins
def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, DeformableObject], origins: torch.Tensor):
"""시뮬레이션 루프 실행: deformable object를 제어하고 상태를 업데이트합니다."""
# 큐브 객체 가져오기
cube_object = entities["cube_object"]
# 시뮬레이션 시간 간격 및 변수 초기화
sim_dt = sim.get_physics_dt()
sim_time = 0.0
count = 0
# 변형 객체의 vertex(정점) 위치 제어용 배열 복사 (수정 가능한 형태)
nodal_kinematic_target = cube_object.data.nodal_kinematic_target.clone()
# 시뮬레이션 루프 실행
while simulation_app.is_running():
# 매 250 스텝마다 상태 초기화
if count % 250 == 0:
sim_time = 0.0
count = 0
# 초기 정점 상태 복사
nodal_state = cube_object.data.default_nodal_state_w.clone()
# 위치: 무작위 이동 → 기존 origin 위치 위에 무작위 오프셋 추가
pos_w = torch.rand(cube_object.num_instances, 3, device=sim.device) * 0.1 + origins
# 회전: 랜덤 쿼터니언 회전 적용
quat_w = math_utils.random_orientation(cube_object.num_instances, device=sim.device)
# 위치/회전 변환 적용
nodal_state[..., :3] = cube_object.transform_nodal_pos(nodal_state[..., :3], pos_w, quat_w)
# 정점 상태를 시뮬레이터에 적용
cube_object.write_nodal_state_to_sim(nodal_state)
# 정점 상태를 kinematic 타겟으로 복사 (위치 제어용)
nodal_kinematic_target[..., :3] = nodal_state[..., :3]
nodal_kinematic_target[..., 3] = 1.0 # 모든 정점은 자유 상태 (1.0 = unconstrained)
cube_object.write_nodal_kinematic_target_to_sim(nodal_kinematic_target)
# 내부 상태 초기화
cube_object.reset()
print("----------------------------------------")
print("[INFO]: Resetting object state...")
# 특정 정점(k=0)의 z축 위치를 조금씩 증가시켜 위로 움직임 생성
nodal_kinematic_target[[0, 3], 0, 2] += 0.001
# 해당 정점은 kinematic 제어 상태로 설정 (0.0 = constrained)
nodal_kinematic_target[[0, 3], 0, 3] = 0.0
# 시뮬레이터에 업데이트
cube_object.write_nodal_kinematic_target_to_sim(nodal_kinematic_target)
# 추가 데이터 시뮬레이터에 기록
cube_object.write_data_to_sim()
# 시뮬레이터 한 스텝 실행
sim.step()
# 시간 및 카운터 업데이트
sim_time += sim_dt
count += 1
# 객체 내부 버퍼 업데이트
cube_object.update(sim_dt)
# 50 스텝마다 루트 위치 출력
if count % 50 == 0:
print(f"Root position (in world): {cube_object.data.root_pos_w[:, :3]}")
def main():
"""메인 함수: 시뮬레이터 설정, 씬 구성, 시뮬레이션 실행"""
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device)
sim = SimulationContext(sim_cfg)
# 카메라 위치 설정
sim.set_camera_view(eye=[3.0, 0.0, 1.0], target=[0.0, 0.0, 0.5])
# 씬 구성 및 객체 가져오기
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()
![[Robot RL][IsaacLab][window][1] 초보 – IsaacSim, IsaacLab tutorial 코드 분석, {reinforcement learning project} 4 image 37](https://i0.wp.com/openpj.co.kr/wp-content/uploads/2025/04/image-37.png?resize=505%2C387&ssl=1)
5. run_articulation.py
![[Robot RL][IsaacLab][window][1] 초보 – IsaacSim, IsaacLab tutorial 코드 분석, {reinforcement learning project} 5 image 38](https://i0.wp.com/openpj.co.kr/wp-content/uploads/2025/04/image-38.png?resize=288%2C313&ssl=1)
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""This script demonstrates how to spawn a cart-pole and interact with it.
.. code-block:: bash
# Usage
./isaaclab.sh -p scripts/tutorials/01_assets/run_articulation.py
"""
"""Launch Isaac Sim Simulator first."""
import argparse # 명령줄 인자 파싱용
from isaaclab.app import AppLauncher # Isaac Lab 시뮬레이터 실행용 런처 클래스
# argparse 설정
parser = argparse.ArgumentParser(description="Tutorial on spawning and interacting with an articulation.")
AppLauncher.add_app_launcher_args(parser) # --headless 등 공통 인자 추가
args_cli = parser.parse_args() # 인자 파싱
# 시뮬레이터 실행
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app # Isaac Sim 앱 핸들 저장
"""아래부터는 시뮬레이터 실행 이후에 가능한 코드입니다."""
import torch # 텐서 연산용 (위치, 속도, 관절 상태 등 제어에 사용)
import isaacsim.core.utils.prims as prim_utils # prim(Xform 등) 생성 유틸
import isaaclab.sim as sim_utils # 시뮬레이터 설정 유틸
from isaaclab.assets import Articulation # 관절 기반 로봇 클래스
from isaaclab.sim import SimulationContext # 시뮬레이터 제어용 클래스
## 사전에 정의된 CartPole 설정 (ArticulationCfg 기반)
from isaaclab_assets import CARTPOLE_CFG # isort:skip
def design_scene() -> tuple[dict, list[list[float]]]:
"""씬 구성 함수: 바닥, 조명, Xform 그룹, CartPole 로봇 생성"""
# 바닥 생성
cfg = sim_utils.GroundPlaneCfg()
cfg.func("/World/defaultGroundPlane", cfg)
# 돔 라이트 조명 생성
cfg = sim_utils.DomeLightCfg(intensity=3000.0, color=(0.75, 0.75, 0.75))
cfg.func("/World/Light", cfg)
# Origin 그룹 생성 (Xform): 각각 CartPole을 담을 위치
origins = [[0.0, 0.0, 0.0], [-1.0, 0.0, 0.0]]
prim_utils.create_prim("/World/Origin1", "Xform", translation=origins[0])
prim_utils.create_prim("/World/Origin2", "Xform", translation=origins[1])
# Articulation 객체 생성 (CartPole): 관절 구성 정보를 담고 있음
cartpole_cfg = CARTPOLE_CFG.copy()
cartpole_cfg.prim_path = "/World/Origin.*/Robot" # 정규표현식으로 여러 개 생성
cartpole = Articulation(cfg=cartpole_cfg) # 실제 객체 생성
# 생성된 객체 반환
scene_entities = {"cartpole": cartpole}
return scene_entities, origins
def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Articulation], origins: torch.Tensor):
"""시뮬레이션 루프: CartPole 상태를 초기화하고 무작위 제어 명령을 적용"""
# CartPole 객체 가져오기
robot = entities["cartpole"]
# 시뮬레이션 시간 간격 및 카운터
sim_dt = sim.get_physics_dt()
count = 0
# 시뮬레이션 루프
while simulation_app.is_running():
# 매 500 스텝마다 상태 초기화
if count % 500 == 0:
count = 0 # 카운터 초기화
# 루트 상태 초기화 후 Origin에 맞게 위치 오프셋 적용
root_state = robot.data.default_root_state.clone()
root_state[:, :3] += origins # 월드 좌표계 기준 위치 보정
robot.write_root_pose_to_sim(root_state[:, :7]) # 위치 + 회전
robot.write_root_velocity_to_sim(root_state[:, 7:]) # 선속도 + 각속도
# 관절 상태 초기화 + 무작위 오프셋 추가
joint_pos, joint_vel = robot.data.default_joint_pos.clone(), robot.data.default_joint_vel.clone()
joint_pos += torch.rand_like(joint_pos) * 0.1 # 무작위 초기 위치
robot.write_joint_state_to_sim(joint_pos, joint_vel) # 관절 상태 반영
robot.reset() # 내부 버퍼 초기화
print("[INFO]: Resetting robot state...")
# 무작위 관절 토크 생성 및 적용
efforts = torch.randn_like(robot.data.joint_pos) * 5.0 # 무작위 토크 값 (스케일링 포함)
robot.set_joint_effort_target(efforts) # 목표 토크 설정
robot.write_data_to_sim() # 시뮬레이터에 반영
# 시뮬레이션 한 스텝 진행
sim.step()
count += 1 # 카운터 증가
# 내부 버퍼 업데이트 (관절 상태 동기화)
robot.update(sim_dt)
def main():
"""메인 함수: 시뮬레이터 설정, 씬 구성, 시뮬레이션 실행"""
sim_cfg = sim_utils.SimulationCfg(device=args_cli.device)
sim = SimulationContext(sim_cfg)
# 카메라 위치 설정 (옆에서 CartPole 2개가 잘 보이도록)
sim.set_camera_view([2.5, 0.0, 4.0], [0.0, 0.0, 2.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()
![[Robot RL][IsaacLab][window][1] 초보 – IsaacSim, IsaacLab tutorial 코드 분석, {reinforcement learning project} 6 image 39](https://i0.wp.com/openpj.co.kr/wp-content/uploads/2025/04/image-39.png?resize=750%2C338&ssl=1)
0 Comments