설치 성공과 과업 환경 완성을 구분한다
MuJoCo는 관절 구조와 접촉 등을 계산하는 물리 엔진이다. Python 패키지 mujoco는 엔진과 연결하는 바인딩을 제공한다. 공식 Python 안내는 pip 설치와 모델 로딩·상태/step API를 설명한다. 별도의 오래된 mujoco-py 예제를 그대로 같은 API라고 읽지 않는다. GPU/영상 창이 있어야 아래의 모델 구조를 배울 수 있는 것도 아니다.
선택 설치는 격리된 가상환경에서 수행하고 Python/운영체제와 선택한 MuJoCo 버전의 지원 조건을 확인한다. 다음은 사용자가 별도 환경에서 선택할 수 있는 명령 예다. 이번 집필/기본 활동에서는 실행하지 않았으며 특정 최신 버전의 설치 성공을 보장하지 않는다. 재현하려면 설치 후 확인한 버전과 의존성/모델 파일을 기록한다.
python3 -m venv .venv-mujoco
source .venv-mujoco/bin/activate
python -m pip install mujoco
python -c "import mujoco; print(mujoco.__version__)"
import가 되더라도 모델 컴파일·물리 step·렌더 창은 서로 다른 확인 단계다. 영상 창 실패를 곧바로 엔진 계산 실패로 해석하지 않는다. 패키지가 없으면 아래 XML/합성 로그를 읽는 경로로 진행한다. 환경을 추가 변경하지 않고도 세 학습 목표를 확인할 수 있다.
MJCF의 모델과 실행 중 상태를 나눈다
MJCF는 MuJoCo의 XML 기반 모델 형식이다. body의 중첩으로 연결 관계를 표현하고 joint가 부모에 대한 움직임 자유도를 만든다. geom은 형상/접촉·관성 추론 등에 영향을 주며 actuator는 관절 등으로 작용을 전달하는 구동 모형을 정의한다. 공식 Modeling 자료의 모델 설명과 실제 선택 버전의 XML 규칙을 함께 확인한다.
다음은 하나의 hinge와 position actuator를 가진 최소 교육용 모델이다. 각도 표현을 radian으로 명시하고 중력을 0으로 두어 특정 실제 팔과 구분한다. body가 움직일 수 있도록 질량이 있는 capsule을 넣었다. mass/크기·damping/kp는 합성값이며 실제 부품 식별 결과가 아니다.
<mujoco model="single_hinge_example">
<compiler angle="radian"/>
<option timestep="0.01" gravity="0 0 0"/>
<worldbody>
<body name="link">
<joint name="hinge" type="hinge" axis="0 0 1"
damping="0.1"/>
<geom type="capsule" fromto="0 0 0 0.2 0 0"
size="0.01" mass="0.1"/>
</body>
</worldbody>
<actuator>
<position name="target" joint="hinge" kp="10"
ctrllimited="true" ctrlrange="-1 1"/>
</actuator>
</mujoco>
MjModel은 컴파일된 구조/설정, MjData는 실행 중 위치·속도/시간 등의 상태와 계산 자료를 담는다. 이 단순 모델에서는 일반화 위치 qpos/속도 qvel/제어 ctrl의 길이가 각각 1이라고 예상할 수 있다. 하지만 모든 로봇에서 같은 길이는 아니다. 예를 들어 free joint는 위치 3개/회전 quaternion4개의 7개 위치 성분에 비해 속도는 병진 3/각속도 3의 6개다. 관절 이름/타입과 각 배열의 주소/차원을 확인하고 하나의 인덱스를 모든 필드에 무조건 재사용하지 않는다.
목표를 넣는 것과 실제 위치를 바꾸는 것은 다르다
이 모델의 position actuator에 ctrl=0.3을 주는 것은 해당 구동 모형의 위치 목표다. 모든 actuator의 ctrl이 위치(rad)를 뜻하는 것은 아니다. motor/velocity 등 다른 모형과 transmission/gear가 있으면 의미를 따로 확인한다. ctrl을 썼다고 관측 qpos가 즉시 0.3으로 바뀌었다고 기록해서는 안 된다. qpos는 동적 상태이며 실제 추종은 설정/초기 상태와 계산 결과에 달려 있다.
위 XML을 model.xml로 저장한 경우의 미실행 선택 예시는 다음과 같다. 파일의 XML 문법은 별도 확인할 수 있지만 이번 환경에서 MuJoCo 컴파일/step을 성공했다고 주장하지 않는다.
import mujoco
model = mujoco.MjModel.from_xml_path("model.xml")
data = mujoco.MjData(model)
data.ctrl[0] = 0.3
for _ in range(100):
mujoco.mj_step(model, data)
print(mujoco.__version__, model.nq, model.nv, model.nu)
print(data.time, data.qpos.copy(), data.qvel.copy())
dt=0.01 s로 100회 step이면 모형 시간은 원리상 1 s 진행한다. 부동소수점 출력은 정확한 문자열 1.0이 아닐 수도 있다. 최종 qpos/qvel의 실제 값은 이 글에서 제공하지 않는다. 목표 0.3을 최종 관측의 예상 정답으로 복사하지 않는다. wall time과 모형 시간도 별도 기록한다.
과업 환경은 엔진 밖의 계약도 정의한다
로봇 과업의 환경은 초기화(reset), action을 적용해 관측을 만드는 step, 성공/실패와 종료 조건 등을 묶은 인터페이스다. MuJoCo 패키지만 설치했다고 특정 Pick 과업의 관측/보상/종료가 자동 정의되지는 않는다. 이번 예에서는 reward 학습을 하지 않고 단순 상태/목표 기록을 읽는다. 관측에 어떤 관절/영상·단위/시각을 넣을지와 행동을 몇 물리 step 동안 적용할지 정한다.
physics dt=0.01 s이고 한 환경 step에서 같은 action을 5회 물리 step 동안 유지하면 제어 간격은 0.05 s, 모형 시간 기준 20 Hz다. 물리는 100 Hz이므로 두 빈도는 다르다. 환경 step20회는 물리 100회/모형 1 s다. 화면은 따로 그릴 수 있으며 렌더 횟수를 물리 횟수로 세지 않는다. action을 유지하는 구간 중 내부 제어/접촉 계산이 수행될 수 있다는 점도 구분한다.
합성 상태 로그가 (t,q)=(0,0)/(0.05,0.08)/(0.10,0.14), 단위 s/rad라면 구간 평균 속도는 1.6/1.2 rad/s다. 이것은 두 위치 차이를 시간으로 나눈 값이며 각 순간의 qvel을 측정한 값이 아니다. 목표 ctrl=0.3이 유지되었다면 위치 오차는 0.3/0.22/0.16 rad다. 이 자료만으로 토크/접촉 힘이나 실제 과업 성공을 추정하지 않는다.
상태 재생은 영상 검토, 행동 재실행은 모형 검토에 가깝다
상태 재생은 기록한 qpos/자세를 장면에 넣어 당시 모양을 다시 살피는 방법이다. 해당 상태에서 파생 위치 등을 갱신할 때 mj_forward를 사용할 수 있지만 이것은 mj_step처럼 시간을 적분해 다음 상태를 만드는 호출이 아니다. 기록 상태를 계속 덮어쓴 영상은 장치의 동적 추종/접촉이 재현됐다는 증거가 아니다. 위치만 있다면 속도/접촉·내부 구동 상태의 정보도 빠질 수 있다.
행동 재실행은 기록된 초기 상태·모델/설정에서 ctrl 시퀀스를 다시 적용하고 물리 step으로 결과를 생성한다. 같은 action이라도 초기 qpos/qvel·구동 내부 상태/접촉·외력이나 dt/제어 간격이 달라지면 다른 결과가 나올 수 있다. 재현 목적에 맞는 상태 범위와 버전/솔버·모델/asset hash를 기록한다. 상태의 모든 필요한 성분을 저장했는지 확인하지 않고 'qpos만 같으므로 완전 재현'이라 쓰지 않는다.
기존 2.3 시뮬레이션 시간과 기존 3.1 모델 연결은 이 구분을 다른 모형에 연결하는 자료다. 기본 활동은 합성 XML/로그만 읽고 계산하며 실제 MuJoCo나 로봇 제어를 요구하지 않는다.