Study Archives/Robotics

[자율 조작 로봇 이해 ②] MuJoCo로 로봇 팔 띄우고 움직여보기

ns4A

본 포스팅은 광운대학교 "AID와 로봇을 활용한 자율 조작 학습" 강의 자료를 기반으로 작성되었습니다. 강의 내용을 블로그 형식으로 재구성한 글로, 학습 목적의 정리 포스팅임을 밝힙니다.

 

 

 

이번 글에서는 로봇 학습에서 가장 널리 쓰이는 시뮬레이터인 MuJoCo를 설치하고, ROBOTIS의 로봇 팔 모델을 직접 띄워서 움직여보는 과정을 정리했습니다.


1. MuJoCo가 뭔가요

MuJoCo는 Multi-Joint dynamics with Contact의 약자입니다. 이름 그대로, 여러 관절이 연결된 로봇이 물체와 접촉할 때의 물리 현상을 수치적으로 계산해주는 소프트웨어입니다.

딥러닝으로 비유하자면 PyTorch가 텐서 연산의 기반이 되는 것처럼, MuJoCo는 로봇 시뮬레이션의 기반 엔진 역할을 합니다.

왜 MuJoCo를 쓰는지는 실제 로봇과 비교해보면 바로 와닿습니다.

속도 면에서는 로봇 모델 기준으로 다른 엔진보다 빠릅니다. 강화학습에서 수백만 번 반복해야 할 때 이 차이가 상당히 큽니다. 정확도 측면에서는 접촉력(Contact Force) 계산 안정성이 높아서, 물건을 집는 동작처럼 섬세한 조작을 시뮬레이션할 때 유리합니다. 학술적으로도 2016~2020년 사이 논문 인용 횟수 기준으로 압도적 1위를 기록했고, OpenAI와 DeepMind 같은 주요 연구기관이 강화학습 환경으로 채택해왔습니다. 2022년부터는 Apache 2.0으로 무료 공개되어 누구나 사용할 수 있습니다.


2. 환경 구성

실습 환경은 다음과 같습니다.

  • OS: Ubuntu 24 (저의 경우에는 Windows 데스크탑 위에 VMware로 구성했습니다)
  • 코드 편집: Windows VSCode에서 Remote-SSH로 Ubuntu에 접속
  • Python 환경: Miniconda로 가상환경 분리

VSCode Remote-SSH 덕분에 VMware 화면을 열지 않고도 코드를 작성할 수 있었습니다. 다만 MuJoCo 뷰어(GUI)는 디스플레이가 필요하기 때문에 실행만 VMware 터미널에서 했습니다. 코드 작성과 실행을 역할에 따라 나눈 셈입니다.

Miniconda로 Python 3.11 가상환경을 만들고 MuJoCo를 설치하는 건 몇 줄이면 됩니다.

conda create -n mani python=3.11 -y
conda activate mani
pip install mujoco

3. 로봇 모델은 XML로 정의

MuJoCo에서 로봇은 XML 파일로 정의됩니다. 처음엔 낯설 수 있지만 구조를 보면 생각보다 직관적입니다.

<mujoco>
  <worldbody>
    <geom name="red_box" type="box" size=".2 .2 .2" rgba="1 0 0 1"/>
    <geom name="green_sphere" pos=".2 .2 .2" size=".1" rgba="0 1 0 1"/>
  </worldbody>
</mujoco>

worldbody 안에 물체(geom)를 정의하고, 색상·크기·위치를 지정하는 방식입니다. 실제 로봇 팔 모델은 이 구조가 훨씬 복잡해서 body(링크)와 joint(관절)가 번갈아 중첩되고, mesh 파일을 불러와 3D 형상을 구성합니다.

이번 실습에서 사용한 모델은 ROBOTIS의 OpenManipulator-Y(OMY)입니다. GitHub에 공개된 저장소에서 받을 수 있습니다.

git clone https://github.com/ROBOTIS-GIT/robotis_mujoco_menagerie.git
cp -r robotis_mujoco_menagerie/robotis_omy .

4. Python에서 시뮬레이션을 실행하는 구조

XML로 모델을 정의했으면, Python에서 불러와 실행합니다. 핵심 구조는 다음과 같습니다.

import mujoco
import mujoco.viewer as mj_view
import time

xml_path = "robotis_omy/scene.xml"
model = mujoco.MjModel.from_xml_path(xml_path)
data = mujoco.MjData(model)

with mj_view.launch_passive(model, data) as viewer:
    while viewer.is_running():
        mujoco.mj_step(model, data)
        viewer.sync()
        time.sleep(0.001)

여기서 두 객체의 역할을 구분하는 것이 중요합니다.

  • MjModel: 로봇의 구조 정보입니다. 관절 개수, 링크 길이, 질량 등 고정된 설계 정보를 담고 있습니다. 딥러닝으로 치면 모델 아키텍처에 해당합니다.
  • MjData: 시뮬레이션의 상태 정보입니다. 현재 관절 각도, 속도, 접촉력 등 매 스텝마다 바뀌는 값들이 들어 있습니다. 딥러닝으로 치면 실행 중 텐서 값들에 해당합니다.

mj_step()이 이 구조의 핵심입니다. 이 함수 하나가 물리 법칙에 따라 다음 스텝을 계산합니다. 중력, 관성, 관절 제한, 접촉력을 모두 반영해서 data를 업데이트합니다.


5. 로봇을 움직이려면 ctrl 배열을 수정

시뮬레이션을 띄우는 것까지는 됐습니다. 그런데 로봇을 실제로 움직이려면 어떻게 해야 할까요?

MuJoCo에서 로봇 관절을 제어하는 방법은 data.ctrl 배열에 값을 넣는 것입니다. 각 인덱스가 XML에 정의된 actuator와 순서대로 대응합니다. OMY 모델 기준으로 0~5번은 팔 관절, 6~9번은 그리퍼(손가락)입니다.

아래 코드는 시간 t에 따라 사인 함수로 관절 값을 바꿔서, 로봇 팔이 자연스럽게 흔들리도록 만든 예시입니다.

import math

start_time = time.time()

while viewer.is_running():
    t = time.time() - start_time
    for i in range(1, 4):
        data.ctrl[i] = -math.sin(t) if i == 1 else math.sin(t)

    mujoco.mj_step(model, data)
    viewer.sync()
    time.sleep(0.001)

루프 안에서 data.ctrl을 바꾸면, mj_step()이 그 값을 목표 관절 각도로 해석해서 물리 계산을 진행합니다. 실제로 실행하면 로봇 팔이 리듬에 맞춰 좌우로 움직이는 것을 볼 수 있습니다.


6. 왜 이게 로봇 학습과 연결되나요

여기까지 보면 "그래서 이게 딥러닝이랑 무슨 상관인가?" 싶으실 수 있습니다.

연결 고리는 바로 data.ctrl입니다.

지금은 수식(math.sin)으로 관절 값을 직접 계산했지만, 이 자리에 신경망의 출력값을 넣을 수 있습니다. 카메라 영상과 현재 관절 상태를 입력으로 받아서, 다음 행동(ctrl 값)을 예측하는 정책 네트워크를 학습시키면 됩니다.

카메라 영상 + 현재 관절 상태 → 정책 네트워크(Policy) → data.ctrl 값

이것이 모방학습(Imitation Learning)과 강화학습(Reinforcement Learning)이 시뮬레이터와 연결되는 방식입니다. 시뮬레이터는 학습 환경을 제공하고, 신경망은 그 환경에서 어떻게 행동할지를 학습합니다.


마치며

이번 실습에서 한 것을 정리하면 다음과 같습니다.

  • MuJoCo 시뮬레이터 설치 및 환경 구성
  • XML 기반 로봇 모델 구조 이해
  • Python에서 MjModel, MjData, mj_step()으로 시뮬레이션 실행
  • data.ctrl 배열로 관절 제어