SO-101은 Hugging Face LeRobot 문서가 대표 예제로 쓰는 저가형 6축 로봇팔로, 사람이 리더 팔을 움직이면 팔로워 팔이 따라 하는 방식으로 시연 데이터를 모읍니다. 이 글은 LeRobot을 처음 쓰는 엔지니어가 모터 설정부터 데이터셋 녹화, ACT 정책 학습, 실제 로봇에서의 실행까지 한 흐름으로 따라 할 수 있도록 공식 문서의 명령어를 순서대로 정리합니다. 다 읽고 나면 각 단계에서 무엇을 확인해야 다음 단계로 넘어갈 수 있는지 판단할 수 있습니다.
모방학습과 행동 생성 모델이 Physical AI 전체에서 어디에 놓이는지는 피지컬 AI와 월드 모델 개요에서 먼저 볼 수 있습니다.
시작 전에 준비할 하드웨어와 소프트웨어
SO-101 조립 문서에 따르면 팔로워 팔은 6개 관절 모두 Feetech STS3215 모터(1/345 감속)를 씁니다. 리더 팔은 자기 무게를 버티면서도 손으로 가볍게 움직일 수 있도록 관절마다 감속비가 다른 모터를 섞습니다.
| 리더 팔 관절 | 모터 번호 | 감속비 |
|---|---|---|
| Base / Shoulder Pan | 1 | 1/191 |
| Shoulder Lift | 2 | 1/345 |
| Elbow Flex | 3 | 1/191 |
| Wrist Flex | 4 | 1/147 |
| Wrist Roll | 5 | 1/147 |
| Gripper | 6 | 1/147 |
부품 목록(BOM)과 3D 프린트 파일은 TheRobotStudio의 SO-ARM100 저장소 README에서 안내합니다. 소프트웨어 쪽은 설치 문서 기준으로 다음 조건이 필요합니다.
| 항목 | 요구 사항 |
|---|---|
| Python | 3.12 (conda 또는 uv 가상환경) |
| PyTorch | 2.10 이상 지원 |
| 영상 디코딩 | TorchCodec + ffmpeg (macOS Intel, Linux ARM 등 미지원 플랫폼은 pyav로 자동 대체) |
| 모터 SDK | feetech extra |
| 학습 장비 | NVIDIA GPU(cuda) 또는 Apple silicon(mps) |
1단계: LeRobot과 Feetech SDK 설치
녹화·재생·캘리브레이션에는 core_scripts, 학습에는 training, SO-101 모터 통신에는 feetech extra가 필요합니다. 한 PC에서 녹화와 학습을 모두 한다면 세 가지를 함께 설치합니다.
conda create -y -n lerobot python=3.12
conda activate lerobot
conda install ffmpeg -c conda-forge
git clone https://github.com/huggingface/lerobot.git
cd lerobot
pip install -e ".[core_scripts,training,feetech]"
WSL에서 설치한다면 evdev를 추가로 설치하라는 안내가 설치 문서에 있습니다. 빌드 오류가 나면 cmake, build-essential, ffmpeg 개발 라이브러리를 먼저 설치합니다.
2단계: 모터 ID 설정과 캘리브레이션
새 모터는 대부분 기본 ID가 1이어서, 같은 버스에 여러 개를 연결하면 컨트롤러가 구분하지 못합니다. 그래서 ID와 통신 속도(baudrate)를 모터 내부 EEPROM에 한 번씩 써 넣어야 합니다.
- 포트 찾기: 컨트롤러 보드를 USB와 전원에 연결하고
lerobot-find-port를 실행합니다. 안내에 따라 USB를 뽑았다 꽂으면 해당 팔의 포트(예:/dev/ttyACM0)가 출력됩니다. Linux에서는sudo chmod 666 /dev/ttyACM0으로 접근 권한을 줘야 할 수 있습니다. - 팔로워 모터 설정: 아래 명령을 실행하면 그리퍼부터 한 모터씩 연결하라는 안내가 나옵니다. 보드에는 항상 한 모터만 연결된 상태여야 합니다.
- 리더 모터 설정: 같은 방식으로
--teleop.type=so101_leader로 반복합니다. - 캘리브레이션: 모든 관절을 가동 범위의 가운데에 놓고 Enter를 누른 뒤, 각 관절을 끝에서 끝까지 움직입니다. 리더와 팔로워를 각각 한 번씩 합니다.
lerobot-setup-motors \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0
lerobot-setup-motors \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1
lerobot-calibrate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_follower_arm
lerobot-calibrate \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_leader_arm
실제 로봇 모방학습 문서는 id 값이 캘리브레이션 파일을 저장하는 키라고 설명합니다. 여기서 정한 my_follower_arm, my_leader_arm을 이후 모든 명령에 그대로 써야 합니다. Waveshare 컨트롤러 보드를 쓴다면 두 점퍼가 USB 쪽인 B 채널에 꽂혀 있는지도 확인합니다.
3단계: 원격조작으로 동작 확인
녹화 전에 리더를 움직였을 때 팔로워가 같은 자세로 따라오는지 확인합니다. 카메라를 함께 연결하고 --display_data=true를 주면 rerun 화면에서 영상과 관절 값을 같이 볼 수 있습니다.
lerobot-teleoperate \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_follower_arm \
--robot.cameras="{front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_leader_arm \
--display_data=true
캘리브레이션이 빠진 장치가 있으면 이 명령이 캘리브레이션 절차를 먼저 시작합니다. 특정 관절만 반대로 움직이거나 끝에서 튄다면 해당 팔의 캘리브레이션을 다시 하는 것이 가장 빠른 확인 방법입니다.
4단계: 데이터셋 녹화
녹화한 데이터는 LeRobotDataset 형식으로 ~/.cache/huggingface/lerobot/{repo-id}에 저장되고, 기본 설정에서는 녹화가 끝나면 Hugging Face Hub에 업로드됩니다. 먼저 쓰기 권한 토큰으로 로그인합니다.
hf auth login --token ${HUGGINGFACE_TOKEN} --add-to-git-credential
HF_USER=$(NO_COLOR=1 hf auth whoami | awk -F': *' 'NR==1 {print $2}')
lerobot-record \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_follower_arm \
--robot.cameras="{front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--teleop.type=so101_leader \
--teleop.port=/dev/ttyACM1 \
--teleop.id=my_leader_arm \
--display_data=true \
--dataset.repo_id=${HF_USER}/so101_pick_place \
--dataset.num_episodes=50 \
--dataset.single_task="Pick up the cube and place it in the bin"
녹화 흐름은 키보드로 제어합니다. n·r·q 문자 키는 Wayland나 SSH 같은 헤드리스 환경에서도 터미널이 포커스된 상태면 동작합니다.
| 키 | 동작 |
|---|---|
→ 또는 n | 현재 에피소드(또는 리셋 시간)를 일찍 끝내고 다음으로 |
← 또는 r | 현재 에피소드를 취소하고 다시 녹화 |
ESC 또는 q | 세션 종료, 영상 인코딩, 업로드 |
에피소드 길이는 --dataset.episode_time_s, 리셋 시간은 --dataset.reset_time_s로 바꾸며 둘 다 기본값은 60초입니다. 공식 문서는 첫 과제로 여러 위치의 물체를 집어 상자에 넣는 작업을 권하고, 위치당 10개씩 최소 50개 에피소드를 녹화하라고 안내합니다. 카메라는 고정하고 잡는 방식을 일정하게 유지하며, 카메라 화면만 보고도 사람이 과제를 할 수 있는 구도인지 확인합니다. 녹화가 중간에 끊겼다면 같은 명령에 --resume=true와 --dataset.root를 붙이고, num_episodes에는 추가로 녹화할 개수를 넣습니다.
5단계: ACT 정책 학습
ACT(Action Chunking with Transformers)는 Zhao 등의 2023년 논문에서 제안된 방법입니다. 한 스텝의 행동이 아니라 행동 시퀀스(청크)를 한 번에 예측해, 오차가 시간에 따라 누적되는 문제를 줄이는 것이 핵심입니다. 논문 초록은 저가 하드웨어로 10분 분량의 시연만으로 6개 실제 과제에서 80~90% 성공률을 보고합니다. LeRobot은 같은 명령 구조에서 Diffusion Policy, SmolVLA, Pi0 계열도 policy.type만 바꿔 학습할 수 있으므로, ACT로 데이터 파이프라인을 먼저 검증해 두면 이후 모델을 바꿔 비교하기 쉽습니다.
LeRobot의 ACT 기본 설정에서 결과에 직접 영향을 주는 값은 다음과 같습니다.
| 파라미터 | 기본값 | 의미 |
|---|---|---|
chunk_size | 100 | 한 번에 예측하는 행동 스텝 수 |
n_action_steps | 100 | 예측한 청크 중 실제로 실행하는 스텝 수 (chunk_size 이하) |
vision_backbone | resnet18 | ImageNet 사전학습 가중치로 시작 |
use_vae | True | 시연의 다양성을 잠재 변수(latent_dim 32)로 모델링 |
temporal_ensemble_coeff | None | 켜면 매 스텝 추론해 청크를 평균하며, 이때 n_action_steps는 1이어야 함 |
optimizer_lr | 1e-5 | 백본 학습률도 1e-5 |
학습 명령은 데이터셋과 정책 종류만 주면 데이터셋에 저장된 관절 수와 카메라 구성에 맞춰 모델 입출력이 자동으로 맞춰집니다.
lerobot-train \
--dataset.repo_id=${HF_USER}/so101_pick_place \
--policy.type=act \
--output_dir=outputs/train/act_so101_pick_place \
--job_name=act_so101_pick_place \
--policy.device=cuda \
--wandb.enable=true \
--policy.repo_id=${HF_USER}/act_so101_pick_place
Apple silicon이라면 --policy.device=mps로 바꿉니다. 공식 문서는 학습에 몇 시간이 걸린다고 안내하며, 체크포인트는 outputs/train/act_so101_pick_place/checkpoints에 쌓입니다. 중단됐다면 --config_path=.../checkpoints/last/pretrained_model/train_config.json --resume=true로 이어서 학습합니다. 로컬 GPU가 부족하면 --job.target=a10g-small처럼 Hugging Face Jobs의 클라우드 GPU를 지정할 수 있습니다.
6단계: 학습한 정책을 로봇에서 실행
실행은 lerobot-rollout으로 합니다. base 전략은 녹화 없이 정책만 돌리고, sentry 전략은 실행 결과를 평가용 데이터셋으로 계속 녹화해 업로드합니다. 카메라 이름과 구성은 학습 데이터와 같아야 합니다.
lerobot-rollout \
--strategy.type=base \
--policy.path=${HF_USER}/act_so101_pick_place \
--robot.type=so101_follower \
--robot.port=/dev/ttyACM0 \
--robot.id=my_follower_arm \
--robot.cameras="{front: {type: opencv, index_or_path: 0, width: 640, height: 480, fps: 30}}" \
--task="Pick up the cube and place it in the bin" \
--duration=60
정책을 엣지 보드에서 상시 실행할 계획이라면, ACT보다 큰 VLA 정책으로 넘어갈 때 메모리 요구량이 크게 달라집니다. 이 차이는 온디바이스 VLA를 위한 엣지 GPU VRAM 산정 가이드와 VLA VRAM 계산기로 미리 가늠할 수 있습니다.
성공률이 낮을 때 데이터부터 확인할 네 가지
정책이 물체 근처에서 머뭇거리거나 엉뚱한 위치로 가면, 하이퍼파라미터보다 데이터셋을 먼저 의심하는 것이 순서입니다.
- 카메라 구도: 녹화 때와 실행 때 카메라 위치·각도가 같은지 확인합니다. 공식 문서도 녹화 중 카메라 고정을 첫째 조건으로 듭니다.
- 변화의 양: 잡는 위치, 조명, 물체를 한꺼번에 바꿨다면 한 가지 조건으로 줄여 다시 학습합니다. 공식 문서는 안정적으로 잡기 시작한 뒤에 변화를 조금씩 늘리라고 권합니다.
- 에피소드 품질:
lerobot-replay --dataset.episode=0으로 녹화한 에피소드를 로봇에서 재생해 보면, 시연 자체가 흔들렸는지 로봇 반복 정밀도의 문제인지 구분할 수 있습니다. - 동작의 부드러움: 청크 경계에서 동작이 끊기면
n_action_steps를chunk_size보다 작게 두거나, 시간 앙상블(temporal_ensemble_coeff, 이때n_action_steps=1)을 시험해 볼 수 있습니다. 시간 앙상블은 매 스텝 추론하므로 추론 장비의 연산 여유도 함께 확인합니다.