LeRobot documentation

Unitree G1

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Unitree G1

Unitree G1 휴머노이드는 LeRobot에서 지원됩니다. 원격 조작, locomanipulation 정책 학습, 시뮬레이션 내 테스트 등을 수행할 수 있습니다. 29 DoF 및 23 DoF 변형 모델 모두 지원됩니다.

구현 선택

UnitreeG1 클래스는 UnitreeG1Config.embodiment를 통해 관절 정의를 선택합니다. 기본값은 g1_29이며, 따라서 기존 구성은 G1-29 동작을 유지합니다. --robot.embodiment=g1_23 또는 Python에서 23-DoF 레이아웃을 선택합니다:

from lerobot.robots.unitree_g1 import UnitreeG1Config

config = UnitreeG1Config(embodiment="g1_23", is_simulation=False)
기능G1-29G1-23
조인트 구성 및 액션/관측 특징29개의 몸체 관절, 14개의 팔 관절23개의 몸체 관절, 10개의 팔 관절
DDS 명령/피드백 레이아웃29개의 활성 슬롯29개의 슬롯에서 부재한 조인트를 비활성 상태로 유지
MuJoCo 시뮬레이션지원아직 지원되지 않으며, 네이티브 모델이 계획되어 있습니다
Locomotion controllersGR00T 및 HolosomaGR00T 및 Holosoma
SONIC 전신 컨트롤러지원지원되지 않습니다. 정책은 29 DoF를 요구합니다
중력 보상지원되며, 기본적으로 비활성화되어 있습니다아직 지원되지 않으며, 네이티브 키네틱스는 계획 중입니다

두 변형 모두 동일한 29슬롯 DDS 메시지 레이아웃을 사용합니다. G1-29는 29개 슬롯을 모두 사용하는 반면, G1-23은 23개를 사용하고 존재하지 않는 조인트에 해당하는 6개 슬롯을 비활성 상태로 둡니다. 따라서 kp, kd, default_positions 벡터는 여전히 29개 요소의 길이를 유지하며 DDS 슬롯을 인덱스로 사용합니다. G1-23의 활성 팔 슬롯은 15..19와 22..26입니다. 13, 14, 20, 21, 27, 28 슬롯에는 활성 조인트가 없으며, 해당 설정 값은 0이어야 합니다. 이러한 슬롯은 액션/관측 특징에서 제외되며 다시 번호를 매기지 않습니다. G1-23 메시지를 게시하기 전에 비활성 및 예약된 커맨드 항목은 초기화됩니다. 명시적인 게인 오버라이드는 유한하고, 음이 아니어야 하며, 동일한 희소 레이아웃을 사용해야 합니다. 기본 게인은 두 변형 모두에서 조인트 이름으로 공유되므로, 동일한 물리적 조인트는 동일한 게인을 사용하고 G1-23에 없는 슬롯은 0을 유지합니다.

Native G1-23 MuJoCo 시뮬레이션은 아직 지원되지 않습니다. 시뮬레이션이 활성화된 상태로 G1-23 embodiment를 선택하면 transport 초기화 전에 실패합니다. Native G1-23 MuJoCo 모델은 향후 버전에서 계획되어 있습니다.


Part 1: 시작하기

Unitree SDK 설치

unitree_sdk2_python 설치 가이드를 따르세요. unitree_sdk2py==1.0.1 및 cyclonedds==0.10.2로 테스트했습니다:

conda create -y -n lerobot python=3.12
conda activate lerobot
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
cd unitree_sdk2_python
pip install -e .
cd ..

LeRobot 설치

conda install ffmpeg -c conda-forge
conda install -c conda-forge "pinocchio>=3.0.0,<4.0.0"
git clone https://github.com/huggingface/lerobot.git
cd lerobot
pip install -e '.[unitree_g1]'
For now, pinocchio must be installed from conda-forge (not pip) to include the CasADi bindings needed for arm IK.

설치 테스트(시뮬레이션)

시뮬레이션 환경에는 자체적인 종속성이 있습니다. 시뮬레이션 환경의 종속성을 확인하세요: Unitree G1 Mujoco EnvHub.

pip install mujoco loguru msgpack msgpack-numpy
lerobot-teleoperate \
  --robot.type=unitree_g1 \
  --robot.is_simulation=true \
  --teleop.type=unitree_g1 \
  --teleop.id=wbc_unitree \
  --robot.cameras='{"global_view": {"type": "zmq", "server_address": "localhost", "port": 5555, "camera_name": "head_camera", "width": 640, "height": 480, "fps": 30, "warmup_s": 5}}' \
  --display_data=true \
  --robot.controller=GrootLocomotionController

이 명령을 실행하면 G1에 대한 MuJoCo sim instance가 시작됩니다. 시뮬레이션에서 로봇의 이동 운동을 제어하려면 실행 전에 게임패드를 머신에 연결할 수 있습니다. --robot.controller를 통해 HolosomaLocomotionController와 GrootLocomotionController를 모두 지원합니다.

  • 9를 눌러 로봇을 해제합니다
  • 7 / 8 키를 눌러 허리 높이를 증가 / 감소

엔드 이펙터 선택

--robot.end_effector는 팔이 무엇을 장착하는지 지정합니다: dex1은 병렬 그립퍼(기본값), dex3는 세 손가락 손, dummy는 맨 손목입니다. 시뮬레이션에서는 MuJoCo 모델을 선택하며, 이는 손가락 액추에이터와 장면이 포함하는 카메라를 결정합니다. 손목 카메라는 엔드 이펙터에 장착되므로 dummy에는 head_camera만 있습니다.

lerobot-teleoperate \
  --robot.type=unitree_g1 \
  --robot.is_simulation=true \
  --robot.end_effector=dex3 \
  --teleop.id=wbc_unitree \
  --robot.controller=GrootLocomotionController

sim은 모델의 카메라를 --robot.sim_camera_port(기본값 5555) 포트의 ZMQ를 통해 게시하며, --robot.cameras의 zmq 카메라는 이 포트에서 이를 읽습니다. MuJoCo의 인터랙티브 창을 대신 열려면 --robot.sim_publish_images=false를 전달하세요. sim은 카메라 또는 창 중 하나만 렌더링하며, 둘 다 렌더링하지 않습니다. 오프스크린 컨텍스트는 뷰어가 아닌 해당 컨텍스트를 생성한 스레드에 속하기 때문입니다. --robot.sim_onscreen는 카메라에 위임하는 대신 이 선택을 명시적으로 지정하며, 둘 다 요청하는 것은 거부됩니다. 디스플레이가 없는 머신에서 수행할 수 있는 작업인 둘 다 렌더링하지 않으려면, 이 옵션과 --robot.sim_publish_images를 모두 false로 설정하세요.

물리적 로봇에 연결

G1의 Ethernet IP는 192.168.123.164로 고정되어 있습니다. 사용자의 머신은 동일한 서브넷의 정적 IP, 즉 x ≠ 164인 192.168.123.x를 가져야 합니다.

# Replace 'enp131s0' with your ethernet interface name (check with `ip a`)
sudo ip addr flush dev enp131s0
sudo ip addr add 192.168.123.200/24 dev enp131s0
sudo ip link set enp131s0 up

로봇에 SSH로 접속

ssh unitree@192.168.123.164
# Password: 123

이더넷으로 인터넷 공유

G1은 저장소를 클론하고 패키지를 설치하기 위해 인터넷 접속이 필요합니다. 노트북의 연결을 이더넷으로 공유하세요:

노트북에서:

sudo sysctl -w net.ipv4.ip_forward=1

# Replace wlp132s0f0 with your WiFi interface name
sudo iptables -t nat -A POSTROUTING -o wlp132s0f0 -s 192.168.123.0/24 -j MASQUERADE
sudo iptables -A FORWARD -i wlp132s0f0 -o enp131s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i enp131s0 -o wlp132s0f0 -j ACCEPT

G1에서:

sudo ip route del default 2>/dev/null || true
sudo ip route add default via 192.168.123.200 dev eth0
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

# Verify
ping -c 3 8.8.8.8

G1에 Unitree SDK 설치

unitree_sdk2_python 설치 가이드를 따르세요:

conda create -y -n lerobot python=3.12
conda activate lerobot
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
cd unitree_sdk2_python
python -m pip install -e .
cd ..

G1에 LeRobot 설치

git clone https://github.com/huggingface/lerobot.git
cd lerobot
conda install -c conda-forge "pinocchio>=3.0.0,<4.0.0"
python -m pip install -e '.[unitree_g1]'
For now, pinocchio must be installed from conda-forge (not pip) to include the CasADi bindings needed for arm IK.

(선택 사항) 로봇에서 WiFi 활성화

무선 SSH 액세스를 위해 G1에서 WiFi를 활성화할 수 있습니다(기본적으로 차단됨):

sudo rfkill unblock all
sudo ip link set wlan0 up
sudo nmcli radio wifi on
sudo nmcli device set wlan0 managed yes
sudo systemctl restart NetworkManager

WiFi 네트워크에 연결:

nmcli device wifi list

sudo nmcli connection add type wifi ifname wlan0 con-name "YourNetwork" ssid "YourNetwork"
sudo nmcli connection modify "YourNetwork" wifi-sec.key-mgmt wpa-psk
sudo nmcli connection modify "YourNetwork" wifi-sec.psk "YourPassword"
sudo nmcli connection modify "YourNetwork" connection.autoconnect yes
sudo nmcli connection up "YourNetwork"

ip a show wlan0

이후에는 이더넷 대신 WiFi를 통해 SSH로 연결할 수 있습니다:

ssh unitree@<ROBOT_WIFI_IP>
# Password: 123

Part 2: 원격 조작 & 이동

로봇 서버 실행

로봇에서(~/lerobot에서):

cd ~/lerobot
python src/lerobot/robots/unitree_g1/run_g1_server.py --camera

Locomotion Policy 실행

Ethernet, WiFi(실험적), 또는 로봇 자체에서 teleoperation 클라이언트를 실행할 수 있습니다. 네트워크로 인해 발생할 수 있는 지연(latency)에 유의하세요.

노트북에서:

lerobot-teleoperate \
  --robot.type=unitree_g1 \
  --robot.is_simulation=false \
  --robot.robot_ip=<ROBOT_IP> \
  --teleop.type=unitree_g1 \
  --teleop.id=wbc_unitree \
  --robot.cameras='{"global_view": {"type": "zmq", "server_address": "<ROBOT_IP>", "port": 5555, "camera_name": "head_camera", "width": 640, "height": 480, "fps": 30}}' \
  --display_data=true \
  --robot.controller=HolosomaLocomotionController

--robot.controller를 통해 GrootLocomotionController와 HolosomaLocomotionController를 모두 지원합니다.


Part 3: Homunculus Exoskeleton를 이용한 Loco-Manipulation

Homunculus Exoskeleton를 통해 loco-manipulation 솔루션을 제공합니다. 이는 전체 신체를 제어하기 위한 오픈소스 7 DoF 엑소스켈레톤입니다. 여기에서 확인해 보세요.

교정

lerobot-calibrate \
  --teleop.type=unitree_g1 \
  --teleop.left_arm_config.port=/dev/ttyACM1 \
  --teleop.right_arm_config.port=/dev/ttyACM0 \
  --teleop.id=exo

교정 중에 각 관절을 전체 범위로 이동합니다. 조정이 완료되면 관절을 중립 위치로 이동한 후 n을 눌러 다음으로 진행합니다.

Dataset 기록

lerobot-record \
  --robot.type=unitree_g1 \
  --robot.is_simulation=true \
  --robot.cameras='{"global_view": {"type": "zmq", "server_address": "localhost", "port": 5555, "camera_name": "head_camera", "width": 640, "height": 480, "fps": 30}}' \
  --teleop.type=unitree_g1 \
  --teleop.left_arm_config.port=/dev/ttyACM1 \
  --teleop.right_arm_config.port=/dev/ttyACM0 \
  --teleop.id=exo \
  --dataset.repo_id=your-username/dataset-name \
  --dataset.single_task="Test" \
  --dataset.num_episodes=2 \
  --dataset.episode_time_s=5 \
  --dataset.reset_time_s=5 \
  --dataset.push_to_hub=true \
  --dataset.streaming_encoding=true \
  --dataset.encoder_threads=2

참고: 조이스틱만 사용하는 경우 --teleop.left_arm_config.port와 --teleop.right_arm_config.port를 생략하세요.

예시 데이터셋: nepyope/unitree_box_move_blue_full


Part 4: 학습 및 추론

학습

python src/lerobot/scripts/lerobot_train.py \
  --dataset.repo_id=your-username/dataset-name  \
  --policy.type=pi05 \
  --output_dir=./outputs/pi05_training \
  --job_name=pi05_training \
  --policy.repo_id=your-username/your-repo-id \
  --policy.pretrained_path=lerobot/pi05_base \
  --policy.compile_model=true \
  --policy.gradient_checkpointing=true \
  --trackio.enable=true \
  --policy.dtype=bfloat16 \
  --policy.freeze_vision_encoder=false \
  --policy.train_expert_only=false \
  --steps=3000 \
  --policy.device=cuda \
  --batch_size=32

RTC를 사용한 추론

호환되는 학습된 정책은 로컬 추론 시 RTC를 사용할 수 있습니다:

lerobot-rollout \
  --strategy.type=base \
  --policy.path=your-username/your-repo-id \
  --policy.device=cuda \
  --robot.type=unitree_g1 \
  --robot.is_simulation=false \
  --robot.controller=HolosomaLocomotionController \
  --robot.cameras='{"global_view": {"type": "zmq", "server_address": "<ROBOT_IP>", "port": 5555, "camera_name": "head_camera", "width": 640, "height": 480, "fps": 30}}' \
  --task="task_description" \
  --duration=1000 \
  --fps=30 \
  --inference.type=rtc

G1 locomotion 컨트롤러는 rollout의 recoverable waiting에서 사용하는 retained-target 계약을 선언하지 않습니다. 동작이 시작된 후, action buffer가 소진되면 grace-period 대기 대신 terminal fault가 발생합니다. 요청 마감 시간과 observation-age 제한도 적용됩니다. 이 레시피를 사용하기 전에 정책의 사용 가능한 chunk가 추론 지연을 커버하는지 검증하십시오. 로컬 RTC 대기 및 예산을 참조하십시오. SONIC에는 아래에 설명된 별도의 retained-token 계약이 있습니다.


Part 5: SONIC 전신 제어(잠재 토큰 정책)

LeRobot는 이제 NVIDIA의 SONIC 전체 본체 배포 스택의 decoder 부분을 SonicWholeBodyController로 이식했습니다. 관절을 직접 명령하는 대신, 정책은 각 틱마다 64차원 latent motion token(motion_token.{i}.pos)을 출력합니다. SONIC decoder는 해당 토큰과 최근 고유수용감각(proprioception) 히스토리를 받아 잔차(residual) 동작을 생성하며, 이 동작은 스케일링된 후 서 있는 자세에 더해져 29개 자유도(DoF) 전체에 대한 50 Hz 관절 위치 목표를 산출합니다.

컨트롤러는 ONNX 디코더와 모든 배포 상수(PD 이득, default_angles, action_scale, 그리고 중립 토큰)를 lerobot/sonic_decoder에서 로드합니다. 저장소에는 컨트롤러의 policy_type="low_latency" 인수로 선택할 수 있는 증류된 저지연 디코더도 함께 제공됩니다(기본값은 "default").

시뮬레이션에서 테스트

SONIC 모션 토큰으로 학습된 모든 토큰 출력 정책(예: nepyope/sonic_walk)이 이를 구동할 수 있습니다:

lerobot-rollout \
  --strategy.type=base \
  --policy.path=nepyope/sonic_walk \
  --policy.device=cuda \
  --robot.type=unitree_g1 \
  --robot.is_simulation=true \
  --robot.controller=SonicWholeBodyController \
  --robot.cameras='{"ego_view": {"type": "zmq", "server_address": "localhost", "port": 5555, "camera_name": "head_camera", "width": 640, "height": 480, "fps": 30, "warmup_s": 15}}'

실제 로봇에서 실행

GPU 머신에서 remote inference 정책 서버를 실행하고, 로봇 브리지, SONIC 디코더 및 rollout 클라이언트는 G1 Jetson에 유지합니다. 네트워크를 통해 오가는 것은 64-D 토큰 청크뿐이며, 디코더와 50 Hz rt/lowcmd 루프는 온보드에서 유지됩니다.

두 컴퓨터 모두에 remote extra를 설치하세요. G1에는 Unitree extra를 유지하세요:

# GPU machine
python -m pip install -e '.[remote]'

# G1 Jetson
python -m pip install -e '.[unitree_g1,remote]'

GPU 머신에서 저장소 루트에서 정책 서버를 시작합니다. 유지 관리되는 프로필은 nepyope/sonic_walk와 일치합니다. 다른 정책을 사용하려면 해당 체크포인트와 기능 계약을 함께 복사하고 업데이트하세요.

lerobot-policy-server \
  --config_path=examples/remote_inference/unitree_g1_sonic.yaml

G1에서는 브리지와 카메라를 계속 실행 상태로 유지하세요:

python src/lerobot/robots/unitree_g1/run_g1_server.py --camera

그 다음 두 번째 G1 터미널에서 rollout 클라이언트를 시작하고 <GPU_MACHINE_IP>를 대체합니다:

lerobot-rollout \
  --strategy.type=base \
  --inference.type=remote \
  --inference.endpoint=tcp/<GPU_MACHINE_IP>:7447 \
  --inference.deployment=g1-sonic \
  --inference.semantics=unitree-g1-sonic-motion-token-v1 \
  --inference.encoding=jpeg \
  --inference.action_starvation_grace_s=1.0 \
  --robot.type=unitree_g1 \
  --robot.is_simulation=false \
  --robot.robot_ip=127.0.0.1 \
  --robot.controller=SonicWholeBodyController \
  --robot.cameras='{"ego_view": {"type": "zmq", "server_address": "127.0.0.1", "port": 5555, "camera_name": "head_camera", "width": 640, "height": 480, "fps": 30, "warmup_s": 5}}' \
  --task='walk forward' \
  --fps=30 \
  --return_to_initial_position=false \
  --interactive=true

G1의 이동이 명확해졌을 때에만 /start를 입력하십시오. SONIC는 마지막 완전한 토큰을 재전송하면 온보드 디코더의 밸런싱이 유지되므로 대기 지원을 선언합니다. 첫 번째 정책 결과가 나오기 전에 rollout은 디코더의 중립 토큰을 전송합니다. 액션 버퍼가 소진되면, 마지막에 적용된 토큰을 최대 action_starvation_grace_s(위에서 1초) 동안 반복합니다. 새로운 예측이 도착하지 않으면 rollout이 장애를 일으키며 구성된 종료/연결 해제 경로를 따릅니다. 조이스틱 속도를 이 방식으로 유지할 수 없으므로 G1 로코모션 컨트롤러는 여전히 지원되지 않습니다.

이 레시피는 초기 위치 복귀를 비활성화합니다. SONIC의 잠재 토큰 공간을 보간하는 것은 검증된 물리적 복귀 궤적이 아니기 때문입니다. 토큰을 연결 시 값으로 되돌리는 결과를 초래하므로 같은 이유로 /reset도 피해야 합니다. /stop은 여전히 원격 세션을 종료하고 표준 컨트롤러 종료 경로를 통해 로봇을 연결 해제합니다.

SonicWholeBodyController를 사용하면 관찰 상태는 29개의 관절 위치가 아니라 64차원 토큰 에코이므로, 해당 상태에 대해 학습된 호환 가능한 체크포인트가 필요합니다. 연결 시 로봇은 컨트롤러가 제어권을 넘겨받기 전에 관절을 디코더의 default_angles으로 부드럽게 이동시킵니다.


추가 자료


마지막 업데이트: 2026년 7월

Update on GitHub