로봇이 브라우저 안에서 걷는 장면은 보기보다 작습니다. 화면에는 네발 로봇이 앞으로 움직이고, 슬라이더를 밀면 방향이 바뀝니다. 그 밑에서는 훨씬 덜 낭만적인 일이 계속 벌어집니다. 숫자 48개, 103개, 81개가 매 프레임 같은 순서와 같은 부호로 들어가야 하는 일입니다.
지난 글에서는 하드웨어 없이 로봇을 걷게 하는 길을 적은 기록이다. Go1과 G1을 학습시키고 ONNX로 뽑아 브라우저에서 돌렸다. 그 뒤로 하나를 더 붙였습니다. Boston Dynamics Spot. 세 번째 정책을 붙이고 나서야 이 일이 플랫폼 문제라는 게 분명해졌습니다.
정책보다 관측이 먼저 깨집니다
강화학습 정책은 겉으로 보면 신경망 파일 하나입니다. 입력을 넣으면 관절 명령이 나온다. 처음에는 ONNX export가 가장 큰 벽일 줄 알았습니다. 실제로는 다른 문제였다. 벽은 입력 쪽에 있었습니다.
정책은 세상을 눈으로 보지 않습니다. 정해진 순서의 숫자 배열로 본다. 몸의 기울기와 관절 각도, 직전 행동과 명령 속도. 어떤 환경은 걸음 박자를 넣고, 어떤 환경은 발끝 위치를 넣습니다. 이 배열이 학습할 때와 브라우저에서 다르면 정책은 다른 세계에 놓이는 셈입니다.
- PPO로 정책을 학습한다
- ONNX로 export한다
- 브라우저에서 onnxruntime-web으로 실행한다
- 관측값 배열의 순서와 부호를 맞춘다
- 학습 환경의 숨은 런타임 변경을 찾아낸다
- 웹 물리 엔진이 만든 숫자를 golden fixture와 대조한다
Go1은 48차원 관측값이었다. G1은 103차원이고, 걸음 박자를 알려주는 외부 clock이 붙었습니다. Spot은 네발 로봇이니 Go1과 비슷할 것이라고 생각했습니다. 틀린 가정입니다. Spot은 81차원이고, qpos_error_history라는 3스텝짜리 관절 오차 히스토리와 발끝 위치가 들어갑니다. 같은 네발이어도 정책이 보는 세계는 전혀 달랐습니다.
세 번째 로봇이 알려 준 것
첫 번째 로봇은 길을 찾는 일입니다. 두 번째 로봇은 그 길이 우연이 아니었는지 확인하는 일입니다. 세 번째 로봇은 구조가 버티는지 묻습니다.
Spot을 붙일 때 가장 위험했던 가정은 "Go1과 비슷하겠지"였습니다. 네발이고 joystick 명령으로 걷는다. 겉모양은 비슷합니다. 그런데 학습 환경의 소스 코드를 열어 보니 관측 구조가 달랐습니다. 더 까다로운 부분도 있었다. XML에 적힌 물리 파라미터와 학습 중 실제로 쓰는 파라미터가 서로 달랐습니다. 환경 코드가 로드 뒤에 PD 게인을 덮어쓰는 구조였습니다.
브라우저 번들은 정적 XML을 읽는다. 학습 환경이 런타임에 값을 바꿨다면 브라우저는 그 사실을 모른다. 처음에는 관측값이 0.15까지 벌어졌다. 겉으로 로봇이 조금 걷는다고 넘어갈 수 있는 차이입니다. 이런 차이를 놓치면 "되는 것처럼 보이는 데모"에서 멈추게 됩니다.
해법은 눈대중 대신 diff였습니다. 컴파일된 모델 필드를 비교했다. dof_damping, gainprm 같은 값을 하나씩 맞췄고, 번들 XML에 학습 환경의 실제 값을 박았습니다. 그제야 브라우저에서 만든 관측값이 학습 golden과 2.91e-7 수준으로 붙은 것입니다.
이 숫자가 작아 보일 수 있습니다. 실제로 사용자가 보는 것은 소수점보다 걸음입니다. 정책 이식에서는 작은 오차가 큰 행동 차이로 번집니다. 한 프레임의 관측이 어긋나고, 다음 행동이 달라지고, 다시 다음 관측이 더 멀어집니다. parity는 장식용 지표를 넘어 출발선입니다.
숫자를 맞추는 파이프라인
이 작업을 매번 손으로 하면 오래 못 갑니다. 정책을 옮기는 길을 파이프라인으로 눌러 담은 이유입니다.
- 01학습
- 02Export
- 03Native 검증
- 04번들 parity
- 05Live QA
중요한 건 각 단계가 성공했다는 느낌이 아니라 파일로 남는다는 점입니다. golden 관측값과 ONNX parity, native rollout과 웹 QA 스크린샷이 남습니다. 모델이 걷는다는 주장을 눈으로만 믿지 않기 위한 장치입니다.
새 로봇을 갤러리에 붙이는 쪽도 같은 이유로 정리했습니다. 설정 파일은 한 곳만 고치고, 웹 사본은 자동으로 동기화합니다. 메시 감축은 watertight인지 먼저 보고, 열린 shell은 줄이지 않습니다. 새 씬을 붙이는 명령은 manifest 생성부터 웹 QA까지 한 번에 돕습니다. 작은 자동화처럼 보입니다. 이런 것들이 쌓여야 데모가 플랫폼이 됩니다.
특히 메시 감축은 보기보다 위험했습니다. 닫힌 물체는 면을 줄여도 형태가 유지됩니다. 열린 shell은 같은 알고리즘을 적용하는 순간 표면이 찢어집니다. 로봇이 못 걷는 문제와 별개로, 보는 사람이 "왜 모델이 깨졌지"라고 느끼는 문제입니다. 플랫폼은 이런 사소한 실패를 사람이 기억하지 않아도 되게 만들어야 합니다.
브라우저가 좋은 이유
왜 굳이 브라우저인가. 로봇 정책은 보통 로컬 시뮬레이터나 연구 코드 안에서 끝납니다. 보는 사람은 논문 표나 mp4를 봅니다. 그걸 브라우저로 옮기면 관계가 조금 바뀝니다. 보는 사람이 직접 속도를 바꾸고, 방향을 틀고, 팔을 잡아 움직일 수 있습니다.
물론 브라우저가 더 정확해서는 아닙니다. 오히려 제약이 많습니다. WASM이 지원하지 않는 센서가 있고, 모델 파일 용량도 신경 써야 합니다. 그래도 브라우저는 공유 가능한 실험실입니다. 링크 하나로 같은 물리와 같은 정책, 같은 QA 결과를 보여줄 수 있습니다.
이번 갤러리에는 Go1, G1, Spot 세 정책이 들어갔습니다. SO-100 로봇팔은 마우스로 끝단을 잡아 움직일 수 있고, 키보드는 보행 정책의 command에 직접 연결됩니다. 처음 만든 것은 관전용 트윈이었습니다. 지금은 작지만 조작 가능한 로봇 정책 런타임에 가까워졌습니다.
다음 질문
남은 질문은 둘입니다. 하나는 더 거친 지형입니다. 지금 정책들은 flat terrain에서 잘 걷습니다. 진짜 로봇다움은 방향 전환과 옆걸음, 불균일한 바닥에서 드러납니다. 다른 하나는 실물입니다. 시뮬레이터가 아무리 좋아도 현실의 마찰과 지연, 케이블과 나사 풀림은 따로 옵니다.
그래도 여기까지 온 것만으로 배운 점은 분명합니다. 피지컬 AI에서 "모델을 돌렸다"는 말은 너무 넓습니다. 진짜 질문은 이것입니다. 그 모델이 본 세상을 내가 재현했는가. 관측값 하나하나를 같은 세계로 맞췄는가. 그 과정을 다시 실행할 수 있게 남겼는가.
로봇이 브라우저에서 걷는 장면은 작습니다. 그 작은 장면이 성립하려면 학습과 물리, 웹 런타임과 자동 검증이 한 줄로 이어져야 합니다. 저는 그 줄을 만드는 일이 피지컬 AI를 배우는 가장 빠른 길이라고 생각합니다. 읽은 개념이 몸을 얻는 순간도 대개 그 줄 위에서 생깁니다.
- MuJoCo Playground, Google DeepMind
- MuJoCo WebAssembly와 mujoco-js
- onnxruntime-web
- Unitree Go1, Unitree G1, Boston Dynamics Spot 모델
- physical-ai 실험 04, 05, 06



