01. Isaac Lab 기본 구조 — 손으로 짰던 것들의 정리함

이번 단계 목표: 코드를 더 쓰기 전에, Isaac Lab이 세상을 어떻게 조직하는지 뼈대를 잡습니다. 시즌 1에서 익힌 Genesis 개념에 하나씩 대응시키는 방식으로 가면 러닝커브가 생각보다 완만합니다.


네 개의 패키지

Isaac Lab을 설치하면 실제로는 패키지 여러 개가 들어옵니다. 우리가 만질 것은 넷입니다.

패키지 역할 이 시리즈에서
isaaclab 코어 — 시뮬레이션·에셋(Articulation)·센서·매니저 00~03편의 직접 조작
isaaclab_assets 로봇 설정 모음 (G1, H1, Anymal, …) G1_CFG를 여기서 가져옵니다
isaaclab_tasks 완성된 RL 환경들 (Isaac-Velocity-Flat-G1-v0 등) 04편부터의 주 무대
isaaclab_rl RSL-RL 등 러너 연동 래퍼 05편 학습부터

Cfg 문화 — “설정이 곧 코드”

Genesis에서는 씬을 함수 호출로 조립했습니다(scene.add_entity(...)). Isaac Lab의 문법은 다릅니다. 모든 것이 설정 클래스(*Cfg)로 먼저 선언되고, 실체는 그 설정에서 생성됩니다.

# Genesis 방식 — 호출로 조립
robot = scene.add_entity(gs.morphs.URDF(file="g1.urdf", pos=(0, 0, 0.8)))

# Isaac Lab 방식 — 선언 후 생성
robot_cfg = G1_CFG.replace(prim_path="/World/G1")   # 설정(불변)을 복제·수정
robot = Articulation(robot_cfg)                      # 설정 → 실체

처음엔 번거롭습니다. 대신 이 문화 덕분에 “환경 전체”가 하나의 설정 트리로 표현되고, 상속·복제(replace, copy)로 변형됩니다. 04편에서 볼 내장 보행 환경도 결국 ~EnvCfg라는 커다란 설정 클래스 하나예요. 설정 클래스를 읽을 줄 알면 Isaac Lab의 절반을 읽을 줄 아는 겁니다.


용어 대응표 (시즌 1 → 시즌 2)

Genesis (시즌 1) Isaac Lab (시즌 2) 메모
gs.init() AppLauncher 앱 기동. import 순서 제약이 생김 (00편)
gs.Scene SimulationContext + InteractiveScene 물리 문맥과 씬 구성이 분리됨
scene.add_entity(URDF) Articulation(ArticulationCfg) 로봇 = Articulation
robot.joints / DOF 인덱스 robot.joint_names / 정규식 매칭 관절 그룹을 이름 정규식으로 지정하는 문화 (".*_knee_joint")
robot.control_dofs_position(...) robot.set_joint_position_target(...) + write_data_to_sim() 쓰기가 명시적 2단계
위치/속도 읽기 robot.data.* (root_pos_w, joint_pos, …) 읽기 전 robot.update(dt) 필요
PD 게인 (kp/kd 직접 설정) ImplicitActuatorCfg(stiffness=, damping=) 액추에이터가 설정 계층으로 분리
scene.build(n_envs=4096) InteractiveSceneCfg(num_envs=4096) 병렬 환경 복제 개념은 동일
손으로 짠 보상 함수들 Manager (Reward/Observation/Event/…) 아래에서 따로

Manager — 시즌 1에서 손으로 짰던 것들의 정리함

시즌 1의 train/ 코드는 관측 조립, 보상 항목, 밀치기 이벤트, 종료 판정을 전부 한 클래스에 손으로 짰습니다. Isaac Lab의 manager-based 환경은 그 각각을 표준 슬롯으로 분리합니다.

Manager 시즌 1에서의 대응물
ObservationManager get_observations()에 이어붙이던 텐서들
RewardManager _reward_* 함수 + 가중치 딕셔너리
EventManager 4초마다 밀치기, 스폰 랜덤화 (시즌 1 09편)
TerminationManager “넘어지면 리셋” 판정
CommandManager 속도·회전 명령 샘플링 (시즌 1 08편)
CurriculumManager 지형 난이도 승급 (시즌 1 15·18편에서 손으로 하던 것)

각 슬롯에 “항목(term) = 함수 + 가중치 + 대상”을 등록하면 환경이 됩니다. 즉 시즌 1에서 우리가 발명하며 배운 구조가, 여기서는 프레임워크의 공식 문법인 거예요. 개념은 이미 다 아는 것이고 이름만 새로 익히면 됩니다.

개념 박스 — manager-based vs direct Isaac Lab에는 환경 작성 방식이 둘 있습니다. manager-based는 위의 슬롯 문법 (선언적, 내장 환경 대부분이 이 방식), direct는 시즌 1처럼 한 클래스에 전부 직접 쓰는 방식(자유도 높음)입니다. 이 시리즈는 내장 환경을 해부해야 하니 manager-based를 주로 쓰고, 03편의 자세 유지 같은 소품만 direct 감각으로 만듭니다.


태스크 레지스트리 — 환경을 이름으로 부른다

완성된 환경은 gym 스타일 ID로 등록되어 있습니다. G1 보행이라면:

  • Isaac-Velocity-Flat-G1-v0 — 평지 보행 (04~05편)
  • Isaac-Velocity-Rough-G1-v0 — 거친 지형 + 높이맵 관측 (다음 시즌의 주인공)
  • ...-Play-v0 — 평가·재생용 (환경 수 적고 랜덤화 꺼짐)

그래서 학습 실행이 한 줄이 됩니다.

python train.py --task Isaac-Velocity-Flat-G1-v0 --num_envs 4096 --headless

시즌 1과의 결정적 차이가 여기 있습니다. Genesis에서는 g1_train.py에 환경이 통째로 들어 있어 전부 우리 것이었습니다. Isaac Lab에서는 환경이 남이 튜닝해 둔 완성품으로 옵니다. 편하지만, 해부하지 않고 쓰면 아무것도 배우지 못해요.


다음 단계

그래서 04편은 학습 버튼을 누르기 전에 이 환경의 관측·보상·종료를 시즌 1의 손코딩과 항목별로 대조하는 데 통째로 씁니다. 그 전에 먼저 로봇부터 무대에 세우죠 → 02. G1 불러오기

댓글 남기기

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터가 어떻게 처리되는지 알아보세요.