이번 단계 목표: 걷는 G1을 옆·앞·뒤에서 밀쳐도 휘청하고 회복하게 만듭니다. 학습 중에 로봇을 계속 밀쳐서, “밀리면 버티는 법”까지 스스로 배우게 하는 방식입니다. 로봇 회사 데모 영상에서 사람이 로봇을 발로 차는 장면, 그걸 우리도 해봅니다.
재검증 노트 — “학습 중 밀치면 회복을 배운다”는 이 글의 원리와 4/4 회복 수치는 유효합니다. 하지만 나중에 밝혀진 두 가지: ① 이 정책의 걸음은 셔플이었고(10번), ② 이 회복력의 상당 부분은 셔플의 넓은 스탠스(발 간격 23cm+잔발)라는 방어적 자세 덕이었습니다 — 실제로 걸음을 교정하자 회복력이 사라졌다가(0/4), 결합 학습으로 되찾았습니다. 그 반전은 11. 걸음과 강건함에서.
지금까지의 로봇은 밀면 넘어질까?
08번까지의 정책은 평평한 바닥 + 아무도 안 건드리는 세상에서만 살아봤습니다. 관측에 몸 기울기·속도가 들어가니 작은 흔들림은 잡겠지만, 학습 중 한 번도 겪어 본 적 없는 ‘강한 밀침’에도 대응할 수 있을까요?
궁금하면 실험해 보면 됩니다. 이번 단계의 평가 시나리오는 걷는 로봇을 3초 간격으로 왼쪽 → 오른쪽 → 앞 → 뒤에서 밀치는 것입니다. 이 시나리오를 08번 정책(밀침 없이 학습)에게 먼저 시켜 봤습니다:
| 밀치기 (0.8~1.0 m/s 임펄스) | 08번 정책(밀침 무경험) |
|---|---|
| 왼쪽에서 밀기 | 회복 |
| 오른쪽에서 밀기 | 회복 |
| 앞에서 밀기(뒤로 밀림) | 넘어짐 |
| 뒤에서 밀기(앞으로 밀림) | 회복 |
의외로 선전합니다! 관측 속 기울기·속도를 보고 매 순간 다리를 고치는 피드백 제어를 이미 배웠기 때문에, 겪어 본 적 없는 밀침도 어느 정도 처리하는 겁니다(이걸 일반화라고 부릅니다). 하지만 뒤로 밀리는 상황엔 무너졌습니다. 앞으로 걷도록 학습된 로봇에게 ‘뒤로 가는 몸’은 학습 분포에서 가장 먼 상황이었을 테니까요. 이 구멍을 메워 봅시다.
해법: 학습 중에 계속 밀쳐 버릇하기
원리는 08번과 똑같습니다. 08번에서 “명령을 알아듣게 하려면 학습 중 명령을 계속 바꿔라”였다면, 이번엔 “밀침에 버티게 하려면 학습 중 계속 밀쳐라”입니다. RL에서는 이렇게 학습 환경에 무작위 변화를 섞는 걸 통틀어 도메인 랜덤화(domain randomization)라 부릅니다.
‘밀치기’는 물리적으로 베이스(몸통)의 수평 속도에 순간적으로 속도를 더하는 것으로 구현했습니다(속도 임펄스). 옆에서 훅 미는 것과 같은 효과입니다 (g1_env.py):
def push_robots(self, mask=None, delta=None):
"""베이스의 수평 속도에 임펄스를 더한다 — 옆에서 훅 밀치는 것과 같은 효과."""
base_xy_dofs = [0, 1] # 몸통의 x·y 이동 속도
# (학습 땐 크기 0.3~1.0 m/s, 방향 360° 무작위)
vel = self.robot.get_dofs_velocity(base_xy_dofs)
self.robot.set_dofs_velocity(vel + dv, base_xy_dofs)
학습 설정(g1_train.py --task push)은 08번(steer)에 딱 두 줄을 얹은 것입니다:
env_cfg["push_interval_s"] = 4.0 # 4초마다 밀친다
env_cfg["push_vel_range"] = [0.3, 1.0] # 세기는 0.3~1.0 m/s에서 무작위
4096개 환경 각각이 서로 다른 타이밍·방향·세기로 얻어맞으며 걷습니다. 밀려서 넘어지면 에피소드가 끝나 보상을 못 받으니, 버티고 회복하는 것 자체가 보상이 됩니다. 보상 함수는 하나도 안 바꿨습니다.
cd scripts/train
python g1_train.py --task push --max_iterations 2000 # 학습 (GPU)
python g1_eval.py --task push --ckpt 1999 --record # 밀치기 시나리오 + 녹화
python g1_eval.py --task push -e g1-steering --ckpt 1499 --record # 08번 정책과 비교
sim-to-real의 핵심 재료. 시뮬레이션에서 학습한 정책을 실제 로봇에 옮기면, 시뮬레이션과 현실의 미세한 차이(마찰, 모터 특성, 예상 못 한 접촉…) 때문에 잘 안 되는 경우가 많습니다. 그래서 실전에서는 밀치기뿐 아니라 마찰·질량·지연까지 온갖 것을 랜덤화해 “어떤 세상에 떨어져도 대충 통하는” 정책을 만듭니다. 이번 단계는 그 세계로 들어가는 첫걸음입니다.
학습 결과
4096개 병렬 환경 × 2000 iteration, 24분 걸렸습니다.
| 학습 진행 | 평균 보상 | 평균 에피소드 길이 | 상태 |
|---|---|---|---|
| iter 1 | −0.6 | 48 스텝 (~1초) | 픽픽 쓰러짐 |
| iter 101 | 6.9 | 866 스텝 | 웬만한 밀침엔 버팀 |
| iter 301 | 15.6 | 1001 (최대) | 무작위 밀침 속에서도 안 넘어짐 |
| iter 1999 | 17.3 | 1001 (최대) | 보상 수렴 |
수렴 보상(17.3)이 08번(27.1)보다 낮은데, 이건 못 배웠다는 뜻이 아닙니다. 4초마다 얻어맞으니 그때마다 명령 추종 보상을 잃는 게 당연하죠. 과제가 다르면 보상 수렴값을 직접 비교하면 안 됩니다. 진짜 지표는 에피소드 길이가 최대치라는 것 — 계속 밀쳐도 20초를 버틴다는 뜻입니다.
같은 밀치기 시나리오를 두 정책에게 시킨 결과:
| 밀치기 | 08번 정책(밀침 무경험) | 09번 정책(밀침 단련) |
|---|---|---|
| 왼쪽에서 0.8 m/s | 회복 (기울기 2.6°) | 회복 (기울기 3.6°) |
| 오른쪽에서 0.8 m/s | 회복 (4.7°) | 회복 (2.3°) |
| 앞에서 1.0 m/s | 넘어짐 | 회복 (2.3°) |
| 뒤에서 1.0 m/s | 회복 (3.5°) | 회복 (2.2°) |
| 08번 정책 — 뒤로 밀리자 넘어짐 | 09번 정책 — 같은 밀침을 받아냄 |
|---|---|
![]() |
![]() |
한계는 어디일까요? 학습 때 최대 1.0 m/s로 밀쳤는데, 더 세게 밀어 봤습니다:
| 임펄스 세기 | 옆에서 | 앞에서(뒤로 밀림) |
|---|---|---|
| 1.5 m/s | 회복 | 회복 |
| 2.0 m/s | 넘어짐 | 회복 |
| 2.5 m/s | 넘어짐 | 회복 |
학습 범위 밖인 1.5 m/s까지도 회복합니다(일반화). 그리고 앞뒤 밀침(2.5까지)이 옆 밀침(2.0에서 한계)보다 훨씬 강한 비대칭이 보입니다.

전체 영상:
(비교: 08번 정책이 같은 시나리오에서 넘어지는 영상
)
회고 — 막혔던 점 & 배운 것
- “겪게 하면 배운다”의 재확인. 08번(명령을 바꿔 주면 명령을 알아듣는다)과 정확히 같은 원리였습니다. 밀쳐 버릇하니 버티는 법을 배웁니다. 보상 함수는 한 줄도 안 바꿨는데도요 — “넘어지면 보상이 끊긴다”는 기존 구조만으로 회복 기술이 유도됐습니다. RL에서는 무엇을 경험시키느냐가 무엇을 채점하느냐만큼 중요합니다.
- 기준선(08번 정책)이 의외로 선전했다. 밀침을 한 번도 안 겪은 정책이 4번 중 3번을 버텼습니다. 피드백 제어를 배웠다는 건 ‘기울면 고친다’는 일반 능력이 생겼다는 뜻이라, 처음 보는 외란도 어느 정도 처리합니다. 하지만 뒤로 밀리는, 학습 분포에서 가장 먼 상황에서 무너졌고, 밀침을 겪은 정책만 그 구멍을 메웠습니다.
- 회복의 비대칭 — 03번 교훈의 반전. 03번 정적 실험에선 좌우 지지면이 넓어 ‘옆’이 유리했는데, 걷는 중 회복은 반대로 앞뒤가 훨씬 강했습니다(2.5 vs 2.0 m/s). 걷기란 원래 앞뒤로 발을 내딛는 동작이라, 앞뒤 외란은 ‘걸음을 조금 고치는 것’으로 흡수되지만 옆 외란은 배운 적 없는 ‘옆으로 발 내딛기’를 요구하기 때문일 겁니다. 같은 로봇이라도 정적 균형과 동적 균형의 논리가 다르다는 걸 수치로 봤습니다.
- 학습 범위 밖에서도 통했다. 최대 1.0 m/s로 학습했는데 1.5 m/s도 회복했습니다. 무작위 경험이 만드는 여유 마진(robustness margin)입니다. 실제 로봇을 세상에 내보낼 때 이 마진이 안전의 근거가 됩니다.
- 보상 숫자는 과제끼리 비교하지 말 것. 09번의 수렴 보상(17.3)은 08번(27.1)보다 낮지만 더 어려운 과제를 더 잘하는 정책입니다. 곡선의 ‘수렴 여부’와 ‘에피소드 길이’를 보는 게 옳았고, 절대값 비교는 함정이었습니다.
다음 단계
여기까지의 로봇, 정말 ‘걷고’ 있는 걸까요? 그 의심에서 다음 이야기가 시작됩니다 → 10. 제대로 된 걸음
이 시리즈의 전체 글 목록 → 시리즈 목차

