08. 보상 절제 사다리 — 항목을 하나씩 옮겨 봤습니다

이번 단계 목표: R01에서 해부한 “범용 대 제조사 보상”의 격차를, 내장 환경에 Unitree 공식 항목을 한 번에 하나씩 얹어 재학습하며 분해합니다. 각 단의 결과를 06편 걸음 지표로 재고, 예측을 학습 전에 등록해 적중 여부를 함께 기록합니다. 스포일러를 하나 드리면, 첫 단부터 보기 좋게 틀립니다.


사다리 구성

기준선(L0)은 05편의 내장 환경 그대로입니다. 각 단은 이전 단에 항목 하나를 더합니다 (L5만 예외 — 계보 대조용 갈림길이에요).

추가 항목 (Unitree 공식 값) 문헌 근거
L0 — (내장 그대로, 05편에서 학습 완료) ETH 계열 4족 보상의 상속
L1 feet_gait +0.5 — 주기 0.8초 위상 게이트, 좌우 offset [0, 0.5] Siekmann 2021
L2 + foot_clearance +1.0 — 스윙 발 목표 높이 10cm
L3 + base_height −10 — 골반 목표 높이 0.72m
L4 + energy −2e-5, action_rate −0.005→−0.05 Fu 2021
L5 갈림길: L0 + energy/action_rate만 (클록 없이) 계보 A 대 계보 B의 대결

몸통 높이 목표만 손댔습니다. Unitree 29관절 모델은 0.78m지만 우리 37관절 모델은 기립 실측이 0.711m(03편)라 0.72로 조정했어요.

학습 조건은 05편과 동일하게 고정합니다. 4096 환경 × 1500 iteration, RSL-RL PPO, 같은 네트워크. 측정은 06편 지표(빈도·보폭·들림·대칭·추종)입니다.


예측 선등록 — 학습 전에 고정

# 예측 근거
P1 L1에서 걸음 빈도 2.85Hz → 1.25Hz ± 0.15 게이트가 접촉 타이밍을 직접 명세
P2 L1에서 보폭 13.5cm → 25cm 이상 속도 = 빈도 × 보폭
P3 L1에서 발 들림 비대칭(37%)이 절반 이하로 감소 offset [0, 0.5]가 교대를 명세
P4 L2에서 발 들림이 좌우 모두 10cm ± 2로 수렴 clearance 목표의 직접 효과
P5 L3에서 보행 중 골반 높이가 0.70m 이상 높이 벌점의 직접 효과
P6 L4에서 걸음 형태 유지한 채 에너지 감소 항목의 역할 분담
P7 L5(클록 없는 에너지)로는 잰걸음이 안 고쳐진다 Fu 2021은 4족·자연지형 결과
P8 전 단에서 명령 추종 미달(−22%)은 크게 개선 안 됨 추종은 스타일 항목의 문제가 아니라는 분리 가설

빗나가면 빗나간 대로 기록합니다. 그게 이 실험의 목적이니까요.

bash scripts/train/run_ladder.sh          # L1~L5 순차 실행 (각 ~50분)

L1 (게이트 추가) — 대차게 빗나갔고, 그게 발견입니다

지표 L0 (기준선) L1 예측 판정
걸음 빈도 (좌/우) 2.80 / 2.90 Hz 3.00 / 2.90 Hz P1: 1.25 ± 0.15 Hz 실패
보폭 13.4 / 13.6 cm 14.6 / 14.7 cm P2: 25cm 이상 실패
발 들림 (좌/우) 10.6 / 7.7 cm 8.9 / 6.8 cm P3: 비대칭 절반 이하 실패 (소폭만)
전진 실측 0.39 m/s (−22%) 0.46 m/s (−8%) P8: 개선 안 될 것 실패 (반대 방향)

영상:

게이트는 무시당했습니다. 결정적 증거는 학습 로그에 있어요. 이 항목의 획득 점수가 초당 0.47~0.51에서 정체합니다. 만점이 1.0/s인데, 클록과 무관하게 아무렇게나 번갈아 걸어도 통계적으로 0.5쯤은 나오거든요. 즉 정책은 클록에 정렬하지 않고 동전 던지기 수준의 점수만 챙기면서 기존 3Hz 잰걸음을 유지했습니다.

같은 항목이 같은 가중치로 Unitree 스택에서는 작동하는데 여기서는 왜 안 될까요? 그때 제가 세운 설명은 이랬습니다.

  1. 경쟁 항목 — 내장 환경의 feet_air_time(+0.75)은 발을 뗄 때마다 점수를 주는 구조라 잦은 스텝과 공존합니다. 게이트(+0.5)보다 큰 가중치로 현 상태를 지지하는 거죠. Unitree 세트에는 air_time이 없습니다.
  2. 빠른 스텝의 비용 — Unitree는 action_rate를 10배로, 액션 스케일을 절반으로 두어 “빠르게 젓는 것” 자체를 비싸게 만듭니다. 내장 설정에서 잰걸음은 공짜예요.
  3. 따라서 게이트에 정렬하려면 일시적으로 보상이 꺼지는 골짜기를 건너야 하는데, 건너편의 추가 보상이 골짜기 비용보다 작습니다.

이 설명들은 나중에 전부 시험대에 오릅니다. 결론부터 말씀드리면 1번은 기각되고, 진짜 범인은 저 목록에 없습니다.

뜻밖의 수확도 있었어요. 추종 오차가 −22%에서 −8%로 크게 개선됐습니다(P8의 반대). 게이트가 정렬은 못 시켰어도 스텝의 규칙성을 높여 추진 효율이 좋아진 것으로 보입니다.


L2 (+발 들림) — 목표 높이는 못 맞추고, 좌우는 맞춥니다

지표 L1 L2 판정
걸음 빈도 3.00/2.90 Hz 2.90/2.90 Hz 여전히 잰걸음
발 들림 (좌/우) 8.9 / 6.8 cm 7.5 / 6.9 cm P4(10±2cm): 절반만
들림 좌우 차 2.1 cm 0.6 cm 대칭화 성공
파워 132 W 117 W 소폭 개선

재미있는 대목입니다. foot_clearance는 학습에서 1.0 만점에 0.97을 받았는데 실측 들림은 7cm대예요. 모순이 아니라 좌표계의 산수입니다. 이 항목의 목표 0.1m는 발목 링크의 월드 절대 높이이고, 기립 시 발목 링크가 이미 4cm쯤에 있으니 실효 들림은 6cm가 됩니다.

시즌 1의 13편에서 우리가 같은 좌표계 함정에 빠진 적이 있어(의도 8cm → 실효 4cm) 눈에 띈 건데, Unitree 쪽이 “실수”인지는 판정할 수 없습니다. 0.1이라는 값 자체가 오프셋을 포함해 실효 6~7cm가 나오도록 경험적으로 맞춘 것일 수 있고, 그렇다면 잘 튜닝된 파라미터일 뿐이니까요. 여기서 확실한 사실은 하나입니다. 명세값과 실효값은 다르고, 지표로 실측하기 전엔 그 간극을 모른다.

그리고 이 단의 진짜 교훈. 정책은 새 항목 중 “정렬 없이 만점 받을 수 있는 것”만 골라서 최적화했습니다. 보상 해킹의 교과서적 행동이 사다리 위에서 실시간으로 보입니다.


L3 (+몸통 높이) — 키는 컸고, 절뚝임은 자리를 옮겼습니다

지표 L2 L3 판정
몸통 높이 0.671 m 0.699 m P5(0.70 이상): 경계선 적중
보폭 14.7 cm 17.5 cm 개선
전진 실측 0.44 m/s 0.47 m/s (−6%) 사다리 최고
접지율 (좌/우) 54/58% 49% / 67% 새 비대칭
스윙 시간 (좌/우) 160/140 ms 190 / 124 ms 동상

높이 벌점은 즉시 흡수됐습니다. 웅크림이 0.671에서 0.699로 펴졌어요(목표 0.72에는 못 미치지만 다른 항목들과의 균형점입니다). clearance처럼 “걸음 구조를 안 바꾸고 얻을 수 있는 항목은 곧바로 흡수된다”는 패턴이 반복됩니다. 게이트는 여전히 0.49 정체고요.

주목할 부작용이 있습니다. L2에서 들림 대칭을 얻었더니 L3에서 비대칭이 타이밍 영역으로 이사했습니다. 왼발은 오래 젓고 오른발은 짧게 딛는 시간 절뚝임이에요. 시즌 1의 11편(“하나를 고치면 다른 게 돌아온다”)의 재림 같아서 “두더지 잡기” 가설을 하나 세워 뒀습니다. 이것도 나중에 채점 대상이 됩니다.


L4 (+에너지·액션 비용) — 골짜기 서사가 타격을 입다

지표 L3 L4 예측 판정
걸음 빈도 2.60/2.70 Hz 2.50/2.50 Hz P10: 2Hz 미만으로 하락 실패
게이트 획득 0.49 (정체) 0.49~0.50 (정체) (정렬 신호) 정렬 없음
전진 실측 0.47 m/s 0.49 m/s (−2%) 시즌 1 최종과 동급
파워 127 W 107 W P6 방향 개선
몸통 높이 0.699 m 0.711 m 목표 근접

P10은 L1 결과를 보고 추가한 사후 예측이었습니다. “빠른 스텝의 비용이 생기면 게이트 정렬이 이득이 된다”는 골짜기 서사였죠. 이 형태로는 틀렸습니다. 액션 비용을 10배로 올려도 정책은 잰걸음을 조금 늦출 뿐(2.9→2.5Hz), 클록 정렬로의 상전이는 없었습니다.

한편 “구조 불변 항목은 흡수된다”는 패턴은 다섯 번째 지지를 얻습니다. 들림·높이·에너지· 액션 비용은 전부 즉시 흡수되어 각자의 직접 효과(파워 −19%, 추종 −2%, 높이 0.711)를 냈고, 걸음 구조를 요구하는 게이트만 네 단 연속 무시됐어요.


L5 (클록 없이 비용만) — 비용은 박자를 못 정합니다

지표 L0 L4 (클록+비용) L5 (비용만) 판정
걸음 빈도 2.85 Hz 2.50 Hz 3.05 Hz P7 적중
보폭 13.5 cm 19.2 cm 14.3 cm
파워 107 W 118 W

에너지·액션 비용만 준 L5는 기준선과 같은 3Hz 잰걸음으로 돌아갔습니다(들림도 얕아졌고요). Fu 2021의 “에너지 최소화 → 자연 걸음 창발”은 적어도 이 설정에서는 재현되지 않습니다.

다만 이 문장은 그들의 주장에 대한 반박이 아니라 적용 범위의 경계 데이터입니다. 그쪽은 4족·자연 지형·실기였고 우리는 2족·평지·이 가중치·1500 iteration이에요. 조건이 다르면 결과가 다른 건 반박이 아닙니다.


사다리 종합

L0 L1 +게이트 L2 +들림 L3 +높이 L4 +비용 L5 비용만
빈도 (Hz) 2.85 2.95 2.90 2.65 2.50 3.05
보폭 (cm) 13.5 14.7 14.7 17.5 19.2 14.3
들림 좌/우 (cm) 10.6/7.7 8.9/6.8 7.5/6.9 6.6/7.1 6.1/7.7 6.6/7.9
몸통 높이 (m) 0.665 0.677 0.671 0.699 0.711 0.681
추종 오차 −22% −8% −12% −6% −2% −8%
파워 (W) 132 117 127 107 118
게이트 획득 (만점 1.0) 0.49 0.48 0.49 0.49

단단한 사실 두 개.

  1. 위상 게이트는 네 단 전부에서 동전 던지기(0.48~0.50)에 정체했습니다. 어떤 조합에서도 클록 정렬이 일어나지 않았어요.
  2. 구조를 요구하지 않는 항목들은 전부 즉시 흡수되어 각자의 직접 효과를 냈습니다. 최종적으로 “잘 추종하고(−2%) 덜 쓰는(107W) 잰걸음”이 됐습니다.

격차의 “형태(박자)” 성분만 사다리가 못 닫은 겁니다.

예측 채점: 사전 등록 8개 중 3승 5패(P5·P6·P7 적중), 사후 등록 3개 중 1승 2패. 전적 자체가 이 실험의 핵심 데이터입니다. 명세를 다 읽고도 학습 결과의 사전 예측은 어렵다 — 특히 “무엇이 바뀐다”는 방향은 맞혀도 “얼마나·언제”는 계속 빗나갔습니다.


남은 용의자 넷

게이트는 왜 무시당했을까요? 살아남은 가설이 넷입니다.

  1. 경쟁 항목feet_air_time이 잰걸음을 지지하고 있다
  2. 최적화 실패 — 명세상 정렬이 최적인데 탐색이 그 근처를 못 간다
  3. 가중치 부족 — 0.5라는 절대 크기가 작다
  4. 학습량 부족 — 1500 iteration이 모자라다

다음 편은 이 넷을 하나씩 지워 나가는 이야기입니다. 그리고 넷 중 어느 것도 정답이 아니었어요 → 09. 보이지 않는 심판

주장의 지위 여기까지의 수치는 전부 단일 seed(42)입니다. “게이트 0.49 정체”, “빈도 불변”, “clearance 만점”은 측정이고, “골짜기의 경제학”이나 “두더지 잡기”는 결과를 본 뒤에 만든 사후 가설입니다. 둘을 같은 문단에 섞어 쓰면 사후 설명이 필연처럼 읽히니 갈라 적습니다. 09편에서 핵심 단들을 5개 seed로 재학습해 어느 쪽이 살아남는지 봅니다.