Skip to main content
Summary

보상 설계 다음에 반드시 오는 질문

앞 장에서 우리는 보상을 설계하는 일이 단순히 숫자를 정하는 작업이 아니라는 것을 보았다. 로봇이 목표에 가까워지면 보상을 주고, 충돌하면 벌점을 주고, 부드럽게 움직이면 조금 더 칭찬하는 식으로 정책의 방향을 만들어 간다. 그런데 여기서 아주 현실적인 문제가 생긴다.

"이 보상이 정말 잘 작동하는지 어떻게 확인할까?"

가장 단순한 대답은 실제 로봇을 움직여 보는 것이다. 로봇팔에게 목표 위치에 도달하라고 시키고, 실패하면 다시 시도하게 하면 된다. 하지만 강화학습에서는 이 방식이 거의 곧바로 벽에 부딪힌다. 강화학습 에이전트는 처음부터 똑똑하지 않다. 처음의 정책은 대부분 엉뚱하다. 로봇팔을 갑자기 책상 아래로 내리거나, 그리퍼를 허공에서 열고 닫거나, 목표와 반대 방향으로 관절을 꺾을 수 있다. 이동 로봇이라면 벽을 향해 돌진할 수도 있다.

사람이 처음 자전거를 배울 때 넘어지는 것처럼, 강화학습 에이전트도 수많은 실패를 통해 배운다. 차이가 있다면 사람의 넘어짐은 몇 번으로 끝나지만, 로봇의 실패는 수천 번, 수만 번, 때로는 수백만 번까지 이어진다는 점이다. 그래서 실제 로봇에서 바로 강화학습을 시작하는 것은 대개 좋은 선택이 아니다. 먼저 안전한 가상 세계에서 충분히 넘어지고, 부딪히고, 다시 일어나 보는 과정이 필요하다.

그 가상 세계가 바로 시뮬레이션이다.

시뮬레이션에서 학습하기

실제 로봇에서 무작위 탐색이 위험한 이유

강화학습은 탐색을 필요로 한다. 탐색이란 아직 확실히 알지 못하는 행동을 실제로 해 보는 것이다. 로봇이 "이 방향으로 조금 움직이면 보상이 오를까?", "그리퍼를 지금 닫으면 물체가 잡힐까?", "속도를 더 높이면 더 빨리 목표에 도달할까?" 같은 질문을 행동으로 실험하는 과정이다.

문제는 로봇의 행동이 물리 세계에서 일어난다는 데 있다. 소프트웨어 함수 하나를 잘못 호출하면 에러 메시지가 뜨고 끝날 수 있지만, 로봇팔이 잘못 움직이면 책상을 치고, 물체를 떨어뜨리고, 그리퍼를 망가뜨릴 수 있다. 더 심각하게는 주변 사람에게 위험을 줄 수도 있다.

실제 로봇 학습이 어려운 이유는 크게 네 가지로 볼 수 있다.

  • 안전 문제: 무작위 행동은 충돌, 낙하, 끼임, 과속 같은 위험을 만든다.

  • 비용 문제: 모터, 감속기, 그리퍼, 센서는 반복적인 충격과 마모에 약하다.

  • 시간 문제: 한 번 실패할 때마다 물체를 다시 놓고, 로봇을 초기 자세로 되돌리고, 환경을 정리해야 한다.

  • 데이터 부족 문제: 실제 로봇 한 대는 한 순간에 하나의 경험밖에 만들지 못한다.

예를 들어 로봇팔이 작은 블록을 집어 목표 위치에 놓는 작업을 배운다고 하자. 처음 정책은 블록 근처에도 가지 못할 수 있다. 운 좋게 블록에 접근하더라도 너무 세게 밀어 블록을 테이블 밖으로 떨어뜨릴 수 있다. 그리퍼를 닫는 타이밍이 늦으면 허공을 집고, 너무 빠르면 물체를 밀어 버린다. 이 모든 실패는 학습에는 유용한 정보지만, 실제 실험실에서는 계속 사람이 개입해야 하는 골칫거리가 된다.

강화학습에서 가장 비싼 것은 알고리즘 자체가 아니라 시행착오다. 그리고 실제 로봇에서의 시행착오는 느리고, 위험하고, 귀찮고, 비싸다.

시뮬레이션은 로봇의 연습장이다

시뮬레이션은 로봇이 마음껏 실패할 수 있는 연습장이다. 가상의 로봇팔이 테이블을 치더라도 실제 모터는 망가지지 않는다. 물체가 바닥으로 떨어져도 사람이 주워 올 필요가 없다. 버튼 하나로 모든 것을 처음 상태로 되돌릴 수 있다.

강화학습에서 시뮬레이션이 중요한 가장 큰 이유는 반복 속도다. 실제 로봇은 물리 시간보다 빠르게 움직일 수 없다. 로봇팔이 5초 동안 움직이는 작업은 실제로도 5초가 걸린다. 여기에 초기화, 확인, 기록 시간이 더해진다. 반면 시뮬레이션은 컴퓨터 성능이 허락하는 한 실제 시간보다 빠르게 돌릴 수 있다. 물리 계산을 단순화하거나 여러 환경을 병렬로 실행하면, 짧은 시간 안에 엄청난 양의 경험을 모을 수 있다.

강화학습에서는 하나의 시도를 보통 에피소드라고 부른다. 에피소드는 로봇이 초기 상태에서 시작해 성공하거나 실패하거나 제한 시간에 도달할 때까지의 한 번의 실험이다. "로봇팔이 컵을 집어 목표 위치에 놓기"라는 작업이라면, 한 에피소드는 컵이 놓인 상태에서 시작해 컵을 성공적으로 옮기거나, 컵을 떨어뜨리거나, 시간이 초과되면 끝난다.

시뮬레이션 학습의 기본 흐름은 다음과 같다.

for episode in range(num_episodes):
    state = env.reset()

    while True:
        action = policy(state)
        next_state, reward, done, info = env.step(action)

        agent.learn(state, action, reward, next_state, done)
        state = next_state

        if done:
            break

이 짧은 구조 안에 강화학습의 대부분이 들어 있다. 환경을 초기화하고, 현재 상태를 보고, 행동을 선택하고, 환경이 그 행동의 결과를 계산한다. 그 결과로 다음 상태와 보상, 종료 여부가 돌아온다. 에이전트는 이 경험을 사용해 정책을 조금씩 수정한다.

중요한 점은 이 과정이 아주 많이 반복된다는 것이다. 열 번이나 백 번으로는 부족하다. 로봇 제어 문제에서는 수천 에피소드가 기본이고, 복잡한 작업에서는 훨씬 더 많은 시행착오가 필요하다. 시뮬레이션은 이 지루하고 긴 반복을 감당해 주는 장치다.

학습 환경은 작은 세계다

시뮬레이션 환경은 단순한 3D 그림이 아니다. 강화학습을 위한 환경은 로봇이 살아 움직이는 작은 세계에 가깝다. 이 세계에는 로봇, 물체, 바닥, 센서, 물리 법칙, 성공 조건이 함께 들어 있어야 한다.

로봇팔 목표 도달 문제를 예로 들어 보자. 로봇팔 끝이 공간 안의 특정 목표점에 가까워지는 것이 목적이라면, 환경에는 먼저 로봇팔 모델이 필요하다. 각 관절이 어느 방향으로 움직이는지, 관절 각도의 한계가 어디까지인지, 링크의 길이는 얼마인지, 엔드 이펙터가 어디에 있는지 정의해야 한다. 그리퍼가 포함된다면 열림과 닫힘 상태도 표현해야 한다.

그다음에는 작업 공간이 필요하다. 로봇팔이 놓인 바닥이나 테이블, 목표 물체, 장애물, 목표 위치가 있어야 한다. 물체를 집는 작업이라면 물체의 크기, 질량, 마찰, 충돌 모양도 중요하다. 너무 미끄러운 물체는 잡기 어렵고, 너무 가벼운 물체는 조금만 건드려도 날아가 버린다. 시뮬레이션 속 물체가 현실과 완전히 같을 필요는 없지만, 학습하려는 행동을 만들 만큼은 그럴듯해야 한다.

센서도 빠질 수 없다. 로봇은 환경의 모든 정보를 마법처럼 알 수 없다. 실제 로봇이 카메라 이미지, 깊이 이미지, 관절 각도, 속도, 힘 센서 값을 읽듯이, 시뮬레이션 로봇도 관측값을 받아야 한다. 강화학습에서 이 관측값이 바로 상태 또는 상태에 가까운 입력이 된다.

학습 환경의 주요 구성 요소를 정리하면 다음과 같다.

  • 로봇 모델: 관절, 링크, 엔드 이펙터, 그리퍼, 관절 한계와 속도 한계를 포함한다.

  • 작업 공간: 테이블, 바닥, 목표 위치, 장애물, 조작 대상 물체를 배치한다.

  • 센서 모델: 관절 상태, 엔드 이펙터 위치, 카메라, 깊이 센서, 접촉 정보 등을 제공한다.

  • 물리 엔진: 중력, 충돌, 마찰, 관성, 접촉 힘을 계산한다.

  • 작업 규칙: 성공 조건, 실패 조건, 제한 시간, 보상 함수를 정의한다.

여기서 물리 엔진은 가상 세계의 심장 역할을 한다. 로봇이 어떤 행동을 했을 때 링크가 어떻게 움직이고, 물체가 밀리는지, 충돌이 발생했는지를 계산한다. 물리 엔진이 없다면 로봇은 허공의 숫자만 바꾸는 존재가 된다. 강화학습에서 로봇이 "행동의 결과"를 배우려면, 행동이 세계를 어떻게 바꾸는지 계산해 주는 물리 법칙이 필요하다.

상태, 행동, 보상, 종료 조건으로 환경 바라보기

시뮬레이션 환경을 만들 때는 그래픽 화면보다 먼저 강화학습의 네 가지 입구를 생각해야 한다. 상태, 행동, 보상, 종료 조건이다. 화면이 멋져 보여도 이 네 가지가 정리되지 않으면 학습은 시작되지 않는다.

상태는 에이전트가 현재 상황을 이해하기 위해 받는 정보다. 로봇팔 목표 도달 문제라면 현재 관절 각도, 관절 속도, 엔드 이펙터 위치, 목표 위치까지의 상대 벡터가 상태가 될 수 있다. 카메라 기반 조작 문제라면 이미지나 깊이 맵도 상태에 들어갈 수 있다. 상태를 너무 적게 주면 에이전트가 상황을 판단할 수 없고, 너무 많이 주면 학습이 어려워질 수 있다.

행동은 에이전트가 환경에 내리는 명령이다. 로봇팔에서는 관절별 목표 속도, 관절별 목표 위치 변화량, 엔드 이펙터의 이동 방향 등이 행동이 될 수 있다. 중요한 것은 행동이 실제 로봇에서 실행 가능한 형태여야 한다는 점이다. 시뮬레이션에서만 가능한 순간이동 같은 행동을 허용하면, 학습된 정책은 현실 로봇으로 옮겨갈 수 없다.

보상은 앞 장에서 다룬 것처럼 행동의 좋고 나쁨을 숫자로 알려 준다. 목표에 가까워지면 양의 보상을 주고, 충돌하면 벌점을 주며, 성공하면 큰 보상을 줄 수 있다. 다만 시뮬레이션에서는 보상을 더 자세히 관찰할 수 있다. 목표 거리 보상, 충돌 벌점, 시간 벌점, 에너지 벌점이 각각 얼마나 영향을 주는지 로그로 남기면 보상 설계를 디버깅하기 쉬워진다.

종료 조건은 에피소드가 언제 끝나는지를 정한다. 성공했을 때 끝낼 수도 있고, 심각한 충돌이 발생했을 때 끝낼 수도 있다. 제한 시간이 지나면 실패로 종료할 수도 있다. 종료 조건이 없다면 에이전트는 끝없이 같은 행동을 반복하며 시간을 낭비할 수 있다.

예를 들어 로봇팔이 목표점에 도달하는 환경은 다음처럼 설계할 수 있다.

def compute_reward(state):
    distance = norm(end_effector_pos - target_pos)
    reward = -distance

    if distance < 0.03:
        reward += 10.0

    if collision_detected:
        reward -= 5.0

    reward -= 0.01  # 시간을 끌지 않도록 작은 벌점
    return reward


def check_done(state):
    if distance_to_target < 0.03:
        return True, "success"
    if collision_detected:
        return True, "collision"
    if step_count > max_steps:
        return True, "timeout"
    return False, "running"

이 코드는 완성된 환경이라기보다 설계 사고방식을 보여 주는 예다. 중요한 것은 성공, 충돌, 시간 초과를 구분한다는 점이다. 그냥 done=True만 반환하면 에피소드가 끝났다는 사실은 알 수 있지만 왜 끝났는지는 알 수 없다. success, collision, timeout 같은 이유를 함께 기록하면 학습 상태를 훨씬 잘 이해할 수 있다.

빠른 반복은 어떻게 데이터를 만드는가

강화학습에서 데이터는 사람이 미리 준비한 정답 묶음이 아니다. 에이전트가 환경과 상호작용하면서 직접 만든 경험이다. 상태를 보고 행동하고, 보상을 받고, 다음 상태로 이동하는 이 한 조각의 경험이 계속 쌓인다.

이 경험은 보통 다음과 같은 형태로 저장된다.

transition = {
    "state": state,
    "action": action,
    "reward": reward,
    "next_state": next_state,
    "done": done,
    "info": info,
}

이 한 조각을 전이 경험, 즉 transition이라고 부른다. 에피소드 하나에는 여러 transition이 들어 있다. 시뮬레이션에서 천 개의 에피소드를 실행하면 수십만 개의 transition이 모일 수 있다. 에이전트는 이 데이터를 사용해 "어떤 상태에서 어떤 행동을 했을 때 장기적으로 보상이 좋았는가"를 추정한다.

여기서 시뮬레이션의 장점이 다시 드러난다. 실제 로봇에서 하루 동안 몇백 번의 시도만 가능하다면, 시뮬레이션에서는 같은 시간에 훨씬 많은 시도를 할 수 있다. 또한 여러 개의 환경을 동시에 실행할 수도 있다. 예를 들어 가상의 로봇팔 32개가 각자 다른 위치의 물체를 집는 연습을 동시에 한다고 생각해 보자. 실제 실험실에 로봇팔 32대를 놓는 것은 어렵지만, 시뮬레이션에서는 컴퓨터 자원만 충분하다면 가능한 전략이다.

병렬 시뮬레이션은 강화학습에서 매우 강력하다. 한 환경에서 우연히 비슷한 경험만 반복하는 대신, 여러 환경에서 다양한 초기 상태를 동시에 경험할 수 있다. 물체 위치를 조금씩 바꾸고, 목표 위치를 다르게 설정하고, 마찰이나 질량도 약간씩 바꾸면 에이전트는 더 넓은 상황을 만나게 된다. 이는 나중에 실제 로봇으로 옮길 때도 도움이 된다.

초기 상태 재설정은 생각보다 중요하다

시뮬레이션에서 reset()은 단순히 장면을 처음으로 되돌리는 함수처럼 보인다. 하지만 강화학습에서는 reset 설계가 학습의 난이도와 품질을 크게 좌우한다.

항상 같은 위치에서 시작하면 에이전트는 그 상황에만 익숙해질 수 있다. 예를 들어 컵이 항상 로봇팔 정면 30cm 위치에만 있다면, 정책은 그 위치의 컵을 집는 데는 능숙해질지 몰라도 컵이 조금 옆으로 이동하면 당황할 수 있다. 그래서 학습 환경에서는 초기 상태를 어느 정도 무작위로 바꾸는 것이 일반적이다.

컵 집기 작업이라면 매 에피소드마다 컵 위치를 조금씩 다르게 놓을 수 있다. 목표 위치도 바꿀 수 있다. 로봇팔의 시작 관절 각도 역시 안전한 범위 안에서 약간씩 달라질 수 있다. 이렇게 하면 에이전트는 특정 장면을 외우는 대신, 다양한 상황에서 목표를 달성하는 일반적인 방법을 배운다.

다만 무작위성이 너무 크면 학습이 어려워진다. 처음부터 컵을 로봇팔이 닿을 수 없는 곳에 놓거나, 장애물을 지나치게 복잡하게 배치하면 에이전트는 성공 경험을 거의 얻지 못한다. 강화학습은 실패에서 배우지만, 가끔은 성공의 냄새도 맡아야 한다. 성공이 너무 희귀하면 보상 신호가 약해져 학습이 멈춘 것처럼 보일 수 있다.

그래서 좋은 reset 설계는 적당한 다양성을 만든다. 처음에는 쉬운 상태에서 시작해 점점 어려운 상태를 늘리는 방식도 자주 사용된다. 이를 커리큘럼이라고 부를 수 있다. 사람도 처음부터 좁은 골목길에서 운전 연습을 하지 않는다. 넓은 공터에서 출발하고, 그다음 도로로 나가며, 나중에 복잡한 주차를 배운다. 로봇도 마찬가지다.

실패를 안전하게 끝내는 법

시뮬레이션이라고 해서 실패를 아무렇게나 둬도 되는 것은 아니다. 실패를 어떻게 처리하느냐에 따라 에이전트가 배우는 내용이 달라진다.

로봇팔이 테이블을 세게 누르는 상황을 생각해 보자. 실제 로봇이라면 즉시 멈춰야 한다. 시뮬레이션에서도 이런 상황을 그냥 계속 진행하면 에이전트는 이상한 경험을 쌓을 수 있다. 물리 엔진의 계산이 불안정해지거나, 로봇 링크가 비정상적으로 튀어 오르거나, 물체가 말도 안 되는 속도로 날아갈 수 있다. 이런 경험은 학습에 도움이 되지 않는다.

따라서 위험한 상황은 빠르게 감지하고 에피소드를 종료해야 한다. 충돌이 발생하면 벌점을 주고 종료한다. 관절 한계를 넘으려 하면 행동을 잘라 내거나 종료한다. 엔드 이펙터가 작업 공간을 벗어나면 실패로 처리한다. 로봇이 오랫동안 거의 움직이지 않으면 stuck 상태로 보고 종료할 수도 있다.

안전한 실패 처리를 위해 흔히 넣는 장치는 다음과 같다.

  • 행동 제한: 관절 속도, 힘, 위치 변화량을 안전한 범위로 자른다.

  • 작업 공간 제한: 로봇팔 끝이 허용된 공간 밖으로 나가지 못하게 한다.

  • 충돌 감지: 테이블, 바닥, 장애물, 자기 몸체와의 충돌을 확인한다.

  • 시간 제한: 정해진 step 안에 성공하지 못하면 에피소드를 끝낸다.

  • 자동 초기화: 실패 후 물체와 로봇을 즉시 안전한 초기 상태로 되돌린다.

이 장치들은 단지 시뮬레이션을 안정적으로 만들기 위한 것이 아니다. 나중에 실제 로봇에 적용할 안전 제어의 뼈대가 된다. 학습 단계에서부터 "이 행동은 금지된다", "이 상태는 즉시 중단해야 한다"는 규칙을 명확히 두면, 정책이 현실에 가까운 제약 안에서 배운다.

충돌은 나쁜가, 필요한가

로봇 학습에서 충돌은 무조건 제거해야 할 대상처럼 보인다. 하지만 조금 더 섬세하게 볼 필요가 있다. 모든 접촉이 나쁜 것은 아니다. 물체를 집으려면 그리퍼가 물체에 닿아야 한다. 문을 열려면 손잡이를 밀거나 당겨야 한다. 박스를 옮기려면 박스와 접촉해야 한다.

문제는 의도한 접촉과 위험한 충돌을 구분하는 것이다. 그리퍼 손가락이 컵 옆면을 부드럽게 잡는 것은 좋은 접촉이다. 로봇팔 링크가 테이블 모서리를 때리는 것은 나쁜 충돌이다. 엔드 이펙터가 물체를 살짝 밀어 정렬하는 것은 작업의 일부일 수 있지만, 물체를 바닥으로 떨어뜨리는 것은 실패다.

시뮬레이션 환경에서는 이러한 차이를 규칙으로 표현해야 한다. 예를 들어 그리퍼와 목표 물체의 접촉은 허용하고, 로봇 링크와 테이블의 충돌은 벌점 또는 종료 조건으로 둘 수 있다. 물체가 목표 영역 안으로 이동하면 보상을 주되, 테이블 밖으로 떨어지면 큰 벌점을 준다.

이처럼 충돌 처리는 단순한 금지 규칙이 아니라 작업 의미를 반영하는 설계다. 로봇은 물리 세계에서 행동해야 하므로 접촉을 완전히 피할 수 없다. 대신 어떤 접촉이 작업 수행에 필요한지, 어떤 접촉이 위험한지 구분해야 한다.

로그는 시뮬레이션의 블랙박스다

시뮬레이션에서 학습한다고 해서 모든 것이 자동으로 좋아지지는 않는다. 정책이 전혀 나아지지 않을 수도 있고, 이상한 꼼수를 배울 수도 있다. 목표에 가까워지는 대신 보상 함수의 허점을 이용하거나, 성공처럼 보이지만 실제로는 물체를 밀어 버리는 행동을 반복할 수 있다.

그래서 로그가 중요하다. 로그는 학습 중 무슨 일이 일어났는지 알려 주는 블랙박스다. 에피소드마다 총 보상, 성공 여부, 실패 이유, 충돌 횟수, 평균 목표 거리, 에피소드 길이를 기록하면 정책이 어떤 방향으로 변하고 있는지 볼 수 있다.

특히 실패 이유를 나누어 기록해야 한다. 실패가 모두 failed 하나로 묶이면 문제를 고치기 어렵다. 성공률이 낮은 이유가 목표에 도달하지 못해서인지, 충돌이 너무 많아서인지, 시간이 부족해서인지, 물체를 떨어뜨려서인지 알아야 한다. 원인을 알아야 보상이나 환경을 수정할 수 있다.

예를 들어 학습 로그가 다음과 같다고 하자.

episode: 1200
success_rate: 0.12
avg_return: -18.4
collision_rate: 0.63
timeout_rate: 0.21
drop_rate: 0.04
avg_distance_to_goal: 0.18

이 경우 가장 큰 문제는 충돌이다. 보상을 더 크게 주기 전에, 행동 범위가 너무 큰지, 초기 위치가 너무 어려운지, 충돌 벌점이 충분한지 확인해야 한다. 반대로 충돌은 거의 없지만 timeout이 많다면 로봇이 너무 조심스럽게 움직이고 있을 수 있다. 이때는 시간 벌점이나 목표 접근 보상을 조정할 수 있다.

앞 장에서 말한 것처럼 보상 설계는 디버깅이다. 그리고 시뮬레이션은 그 디버깅을 빠르게 반복할 수 있게 해 준다.

시뮬레이션이 너무 쉬우면 생기는 문제

좋은 시뮬레이션은 편해야 하지만, 지나치게 친절해서는 안 된다. 현실보다 너무 쉬운 환경에서 학습한 정책은 실제 로봇에서 쉽게 무너진다.

예를 들어 시뮬레이션에서 물체 위치를 완벽하게 알려 준다고 하자. 카메라 오차도 없고, 깊이 노이즈도 없고, 좌표 변환 오차도 없다. 로봇 관절은 명령한 대로 정확히 움직이며, 그리퍼는 항상 같은 힘으로 물체를 잡는다. 이런 환경에서 학습한 정책은 가상 세계에서는 멋지게 성공할 수 있다. 하지만 실제 로봇에서는 카메라 좌표가 몇 밀리미터씩 흔들리고, 물체 표면이 미끄럽고, 관절 제어에도 작은 오차가 생긴다. 그 순간 정책은 예상하지 못한 상태를 만나게 된다.

반대로 시뮬레이션이 지나치게 어렵거나 불안정해도 문제다. 물리 파라미터가 현실과 너무 다르거나, 센서 노이즈가 과도하거나, 충돌 계산이 자주 폭발하면 에이전트는 일관된 패턴을 배우기 어렵다. 좋은 학습 환경은 현실의 핵심 어려움을 담되, 학습이 가능할 만큼 정돈되어 있어야 한다.

처음에는 단순한 환경에서 시작하는 것이 좋다. 장애물이 없는 목표 도달 문제, 고정된 물체 집기 문제, 낮은 속도의 이동 문제처럼 작은 작업부터 만든다. 그다음 물체 위치를 바꾸고, 장애물을 추가하고, 센서 노이즈를 넣고, 마찰이나 질량을 조금씩 바꾼다. 이렇게 단계적으로 난이도를 올리면 정책이 무너지지 않고 성장할 가능성이 높아진다.

현실로 옮기기 위한 준비

시뮬레이션의 최종 목적은 시뮬레이션 안에서만 잘하는 로봇을 만드는 것이 아니다. 결국 우리는 실제 로봇이 자연어 명령을 받아 물체를 집고, 장소로 이동하고, 실패를 감지해 다시 계획하는 시스템을 만들고 싶다. 그러려면 시뮬레이션 단계부터 현실을 의식해야 한다.

가장 먼저 행동 인터페이스를 현실 로봇과 비슷하게 맞추어야 한다. 실제 로봇이 관절 속도 명령을 받는다면 시뮬레이션 정책도 관절 속도 명령을 내는 것이 좋다. 실제 시스템에서 엔드 이펙터 목표 자세를 MoveIt2로 보내는 구조라면, 학습 환경에서도 유사한 수준의 행동 표현을 고려할 수 있다. 시뮬레이션에서만 가능한 완벽한 제어 명령을 사용하면 나중에 연결이 어려워진다.

센서 입력도 마찬가지다. 실제 로봇에서 사용할 수 없는 정보를 정책에 주면 안 된다. 예를 들어 실제 카메라로는 물체의 정확한 3D 중심을 항상 알 수 없는데, 시뮬레이션에서는 정답 좌표를 그대로 제공한다면 정책은 현실에서 필요한 인식 오차를 견디지 못할 수 있다. 물론 학습 초기에는 정답 정보를 사용해 단순한 문제를 풀 수 있다. 하지만 최종적으로는 실제 센서와 비슷한 관측으로 옮겨 가야 한다.

또한 안전 제한은 시뮬레이션과 현실 모두에 있어야 한다. 학습된 정책이 아무리 좋아 보여도 실제 로봇에 바로 모든 권한을 주면 안 된다. 관절 한계, 속도 제한, 작업 공간 제한, 비상 정지, 충돌 감지 같은 보호막은 정책 바깥에 따로 존재해야 한다. 정책은 행동을 제안하지만, 안전 제어는 그 행동이 실행 가능한지 마지막으로 확인한다.

이 관점은 나중에 LLM 로봇 에이전트를 설계할 때도 그대로 이어진다. LLM은 계획을 세우고, 강화학습 정책은 특정 스킬을 수행할 수 있지만, 최종 실행은 항상 안전 계층을 통과해야 한다.

작은 예제: 목표에 도달하는 로봇팔 환경

이제 간단한 환경 하나를 머릿속에 그려 보자. 6축 로봇팔이 있고, 엔드 이펙터가 공중의 목표점에 도달해야 한다. 아직 물체를 집지는 않는다. 그저 목표 위치에 손끝을 가져가는 작업이다. 단순해 보이지만 강화학습의 기본 구조를 익히기에 아주 좋다.

상태에는 현재 관절 각도, 관절 속도, 엔드 이펙터 위치, 목표 위치까지의 상대 벡터를 넣는다. 행동은 각 관절의 작은 위치 변화량으로 둔다. 보상은 목표와의 거리에 음수를 주고, 목표에 충분히 가까워지면 성공 보상을 준다. 충돌하거나 작업 공간을 벗어나면 실패로 종료한다.

환경의 한 step은 다음 순서로 진행된다.

  1. 에이전트가 관절 변화량을 출력한다.

  2. 환경이 행동을 안전 범위로 제한한다.

  3. 물리 엔진이 로봇팔의 다음 자세를 계산한다.

  4. 엔드 이펙터와 목표 사이의 거리를 측정한다.

  5. 보상과 종료 여부를 계산한다.

  6. 다음 상태와 로그 정보를 반환한다.

이 작업에서 정책이 충분히 학습되면 로봇팔은 목표 방향으로 자연스럽게 움직이는 방법을 익힌다. 이후에는 목표점을 물체 중심으로 바꾸고, 그리퍼 동작을 추가하고, 장애물을 배치하고, 카메라 관측을 넣을 수 있다. 복잡한 Pick and Place도 결국 이런 작은 능력들이 쌓인 결과다.

좋은 로봇 학습 프로젝트는 거창한 최종 작업에서 바로 시작하지 않는다. 먼저 목표 도달, 그다음 접근, 그다음 접촉, 그다음 집기, 그다음 옮기기처럼 단계를 나누어 검증한다. 시뮬레이션은 이 단계를 빠르게 실험하게 해 주는 실험실이다.

시뮬레이션 학습을 시작할 때의 체크리스트

시뮬레이션 환경을 만들 때는 알고리즘보다 먼저 환경 자체가 제대로 작동하는지 확인해야 한다. 정책이 학습되지 않는다고 해서 항상 PPO나 SAC 같은 알고리즘이 문제인 것은 아니다. 관측값이 잘못되었거나, 보상이 반대로 들어갔거나, 종료 조건이 너무 빨리 걸리거나, 행동 스케일이 지나치게 클 수 있다.

처음 환경을 만들었다면 랜덤 정책으로 몇 에피소드를 돌려 보는 것이 좋다. 로봇이 이상한 방향으로 튀지 않는지, 충돌이 감지되는지, 성공 조건이 실제로 작동하는지 확인한다. 그다음 사람이 만든 간단한 규칙 정책을 넣어 본다. 예를 들어 목표 방향으로 엔드 이펙터를 조금씩 움직이는 규칙이다. 이런 단순한 정책도 전혀 성공하지 못한다면, 환경 난이도가 너무 높거나 상태·행동 설계에 문제가 있을 수 있다.

실험을 안정적으로 관리하려면 다음 항목을 기록하는 습관이 필요하다.

  • 환경 버전: 로봇 모델, 물체 설정, 보상 함수, 종료 조건이 바뀔 때마다 버전을 남긴다.

  • 랜덤 시드: 같은 실험을 재현할 수 있도록 난수 초기값을 기록한다.

  • 학습 곡선: 평균 보상, 성공률, 실패 원인을 시간에 따라 저장한다.

  • 영상 기록: 일정 간격으로 에피소드를 녹화해 정책이 실제로 무엇을 하는지 확인한다.

  • 평가 환경: 학습에 사용하지 않은 초기 조건에서 정책을 따로 평가한다.

특히 영상은 숫자 로그가 놓치는 사실을 보여 준다. 평균 보상이 올라가고 있어도 로봇이 물체를 살짝 밀어 목표 영역에 넣는 꼼수를 쓰고 있을 수 있다. 성공률이 높아 보여도 충돌 직전의 아슬아슬한 움직임을 반복할 수 있다. 로봇 학습에서는 그래프와 영상을 함께 봐야 한다.

시뮬레이션은 완벽한 답이 아니라 빠른 질문이다

시뮬레이션을 사용한다고 해서 현실 문제가 모두 사라지는 것은 아니다. 가상 세계와 현실 세계는 다르다. 마찰, 탄성, 센서 노이즈, 조명, 카메라 왜곡, 모터 지연, 케이블 장력 같은 작은 차이들이 실제 로봇의 행동을 바꾼다. 그래서 시뮬레이션에서 100% 성공하는 정책이 실제 로봇에서 그대로 100% 성공한다고 기대하면 안 된다.

하지만 시뮬레이션은 질문을 빠르게 던질 수 있게 해 준다. 이 보상 설계가 말이 되는가? 이 상태 표현으로 목표를 찾을 수 있는가? 행동 범위가 너무 큰가? 충돌 벌점이 충분한가? 초기 상태 다양성이 부족한가? 이런 질문들을 실제 로봇으로만 실험하면 너무 오래 걸린다. 시뮬레이션에서는 몇 시간, 때로는 몇 분 안에 방향을 확인할 수 있다.

시뮬레이션은 정답지가 아니라 가속기다. 로봇이 현실에서 덜 위험하게 배우도록, 먼저 가상 세계에서 많이 넘어지게 하는 장치다. 제대로 만든 시뮬레이션 환경은 강화학습 알고리즘에게 연습장을 제공하고, 개발자에게 디버깅 도구를 제공하며, 실제 로봇에게는 안전한 출발점을 제공한다.

다음 단계에서는 이 연습장에서 실제로 정책을 어떻게 업데이트할지 살펴본다. 로봇 제어에서 자주 등장하는 PPO와 SAC는 각각 다른 방식으로 시행착오를 정책 개선으로 바꾼다. 알고리즘의 수식보다 중요한 것은 구조다. 에이전트가 경험을 모으고, 그 경험으로 정책을 고치고, 다시 환경에 들어가 더 나은 행동을 시도하는 흐름을 이해하면 된다. 시뮬레이션은 그 반복이 일어나는 무대이고, 강화학습 알고리즘은 그 무대 위에서 로봇을 조금씩 능숙하게 만드는 연출가다.

책 목록

AI 로봇 에이전트 만들기: 비전·로봇팔·학습·LLM으로 자연어 명령을 실행하는 로봇

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기