LeRobot documentation
Unitree G1
Unitree G1
El humanoide Unitree G1 es compatible con LeRobot. Puedes teleoperarlo, entrenar políticas de locomanipulación, probarlo en simulación y mucho más. Se admiten las variantes de 29 y 23 grados de libertad.
Selección de encarnación
La clase UnitreeG1 selecciona sus definiciones de articulaciones a través de UnitreeG1Config.embodiment.
El valor predeterminado es g1_29; por lo tanto, las configuraciones existentes conservan el comportamiento de G1-29. Seleccione
el diseño de 23-DoF con --robot.embodiment=g1_23 o en Python:
from lerobot.robots.unitree_g1 import UnitreeG1Config
config = UnitreeG1Config(embodiment="g1_23", is_simulation=False)| Capacidad | G1-29 | G1-23 |
|---|---|---|
| Configuración conjunta y características de acción/observación | 29 articulaciones del cuerpo, 14 articulaciones de los brazos | 23 articulaciones del cuerpo, 10 articulaciones de los brazos |
| Distribución de comandos/retroalimentación de DDS | 29 slots activos | 29 ranuras con articulaciones ausentes dejadas inactivas |
| Simulación de MuJoCo | Soportado | Aún no compatible; se planea un modelo nativo |
| Controladores de locomoción | GR00T y Holosoma | GR00T y Holosoma |
| Controlador de cuerpo completo SONIC | Soportado | No compatible; la política requiere 29 GDL |
| Compensación de la gravedad | Soportado, desactivado por defecto | Aún no compatible; cinemática nativa planificada |
Ambas variantes utilizan el mismo diseño de mensaje DDS de 29 ranuras. G1-29 utiliza las 29 ranuras, mientras que G1-23 utiliza 23 y deja inactivas las seis ranuras de articulaciones inexistentes. Por lo tanto, los vectores kp, kd y default_positions siguen teniendo 29 elementos y se indexan por ranura DDS.
Las ranuras de brazo activas de G1-23 son 15..19 y 22..26. Las ranuras 13, 14, 20, 21, 27, 28 no tienen
articulación activa; sus valores de configuración deben ser cero. Se omiten de las características de acción/observación, no se renumeran.
Las entradas de comando inactivas y reservadas se limpian antes de publicar un mensaje G1-23.
Las sobrescripciones explícitas de ganancias deben ser finitas, no negativas y utilizar el mismo diseño disperso.
Las ganancias predeterminadas se comparten por nombre de articulación entre ambas variantes, por lo que las articulaciones físicas idénticas
utilizan ganancias idénticas, mientras que las ranuras ausentes de G1-23 permanecen en cero.
La simulación nativa de G1-23 en MuJoCo aún no está soportada. Seleccionar la encarnación G1-23 con la simulación habilitada falla antes de la inicialización del transporte. Se planea un modelo nativo de G1-23 en MuJoCo para una versión futura.
Parte 1: Primeros pasos
Instale el SDK de Unitree
Siga la guía de instalación de unitree_sdk2_python. Probado con unitree_sdk2py==1.0.1 y 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 ..Instalar 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.
Probar la instalación (simulación)
El entorno de simulación tiene sus propias dependencias. Consulta las dependencias del entorno de simulación: 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=GrootLocomotionControllerEsto iniciará una instancia de simulación de MuJoCo para el G1. Puedes conectar un mando de juego a tu máquina antes de iniciar para controlar la locomoción del robot en la simulación. Admitimos tanto HolosomaLocomotionController como GrootLocomotionController mediante --robot.controller.
- Pulsa
9para soltar el robot - Pulsa
7/8para aumentar / disminuir la altura de la cintura
Elegir el efector final
--robot.end_effector indica qué llevan los brazos: dex1 para las pinzas paralelas (el valor predeterminado), dex3 para las manos de tres dedos, o dummy para muñecas desnudas. En la simulación, selecciona el modelo de MuJoCo, que determina los actuadores de los dedos y las cámaras que incluye la escena: las cámaras de muñeca están montadas en el efector final, por lo que dummy solo tiene head_camera.
lerobot-teleoperate \
--robot.type=unitree_g1 \
--robot.is_simulation=true \
--robot.end_effector=dex3 \
--teleop.id=wbc_unitree \
--robot.controller=GrootLocomotionControllerEl simulador publica las cámaras del modelo a través de ZMQ en --robot.sim_camera_port (5555 por defecto), que es de donde las cámaras zmq en --robot.cameras las leen. Pasa --robot.sim_publish_images=false para abrir la ventana interactiva de MuJoCo en su lugar: el simulador renderiza ya sea sus cámaras o su ventana, nunca ambas, ya que los contextos fuera de pantalla pertenecen al hilo que los crea y no al visor. --robot.sim_onscreen nombra esa elección explícitamente en lugar de dejarla a las cámaras, y pedir ambas se rechaza; establécela y --robot.sim_publish_images ambas en falso para no renderizar ninguna, que es lo que puede hacer una máquina sin pantalla.
Conectar al robot físico
La IP de Ethernet del G1 está fija en 192.168.123.164. Su máquina debe tener una IP estática en la misma subred: 192.168.123.x donde x ≠ 164.
# 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 upConectarse al robot mediante SSH
ssh unitree@192.168.123.164
# Password: 123Compartir Internet a través de Ethernet
El G1 necesita acceso a internet para clonar repositorios e instalar paquetes. Comparta la conexión de su laptop a través de Ethernet:
En tu portátil:
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 ACCEPTEn el 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.8Instale el SDK de Unitree en el G1
Siga la guía de instalación de 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 ..Instalar LeRobot en el G1
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.
(Opcional) Activar el WiFi en el robot
Para el acceso SSH inalámbrico, puede habilitar el WiFi en el G1 (está bloqueado de forma predeterminada):
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 NetworkManagerConectar a una red 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 wlan0A continuación, puede usar SSH a través de WiFi en lugar de Ethernet:
ssh unitree@<ROBOT_WIFI_IP>
# Password: 123Parte 2: Teleoperación y locomoción
Ejecutar el servidor de Robot
En el robot (desde ~/lerobot):
cd ~/lerobot
python src/lerobot/robots/unitree_g1/run_g1_server.py --cameraEjecutar la política de locomoción
Puede ejecutar el cliente de teleoperación desde su portátil a través de Ethernet, a través de WiFi (experimental) o directamente en el propio robot. Tenga en cuenta la latencia potencial introducida por su red.
Desde tu portátil:
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=HolosomaLocomotionControllerAdmitimos tanto GrootLocomotionController como HolosomaLocomotionController mediante --robot.controller.
Parte 3: Manipulación con el exoesqueleto Homunculus
Ofrecemos una solución de loco-manipulación mediante el Exoesqueleto Homunculus, un exoesqueleto de 7 DoF de código abierto para el control de todo el cuerpo. Puedes verlo aquí.
Calibrar
lerobot-calibrate \ --teleop.type=unitree_g1 \ --teleop.left_arm_config.port=/dev/ttyACM1 \ --teleop.right_arm_config.port=/dev/ttyACM0 \ --teleop.id=exo
Durante la calibración, mueva cada articulación a través de su rango completo. Después de ajustar, coloque la articulación en una posición neutra y presione n para avanzar.
Registrar un 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=2Nota: Omita
--teleop.left_arm_config.porty--teleop.right_arm_config.portsi solo está usando el joystick.
Conjunto de datos de ejemplo: nepyope/unitree_box_move_blue_full
Parte 4: Entrenamiento e inferencia
Entrenar
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=32Inferencia con RTC
Una política entrenada compatible puede usar RTC de inferencia local:
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=rtcLos controladores de locomoción G1 no declaran el contrato de objetivo retenido utilizado por la espera recuperable de rollout. Por lo tanto, una vez que comienza el movimiento, agotar su búfer de acciones provoca una falla terminal en lugar de una espera de período de gracia. También se aplican los plazos de solicitud y los límites de antigüedad de la observación. Valide que el chunk utilizable de la política cubra la latencia de inferencia antes de usar esta receta; consulte espera y presupuestos de RTC local. SONIC tiene un contrato de token retenido separado, descrito a continuación.
Parte 5: Control de cuerpo completo de SONIC (Políticas de tokens latentes)
LeRobot ahora incorpora la mitad decoder del stack de despliegue de cuerpo completo SONIC de NVIDIA como SonicWholeBodyController. En lugar de comandar articulaciones, la política emite un token latente de movimiento de 64 dimensiones (motion_token.{i}.pos) en cada tick; el decodificador SONIC mapea ese token junto con el historial reciente de propiocepción a una acción residual que se escala y se suma a la pose de pie, generando objetivos de posición de articulaciones a 50 Hz para los 29 DoF.
El controlador carga su decodificador ONNX y todas las constantes de despliegue (ganancias PD, default_angles, action_scale y el token neutro) desde lerobot/sonic_decoder. El repositorio también incluye un decodificador destilado de baja latencia, seleccionable con el argumento policy_type="low_latency" del controlador (el valor predeterminado es "default").
Prueba en simulación
Cualquier política de salida de tokens entrenada con tokens de movimiento SONIC (p. ej. nepyope/sonic_walk) puede controlarla:
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}}'Ejecutar en el robot físico
Ejecute el servidor de políticas de inferencia remota en la máquina con GPU y mantenga el puente del robot, el decodificador SONIC y el cliente de rollout en el Jetson G1. Solo los fragmentos de tokens de 64 dimensiones cruzan la red; el decodificador y el bucle de rt/lowcmd a 50 Hz permanecen a bordo.
Instale el extra remoto en ambas máquinas. Mantenga el extra de Unitree en el G1:
# GPU machine
python -m pip install -e '.[remote]'
# G1 Jetson
python -m pip install -e '.[unitree_g1,remote]'En la máquina con GPU, inicie el servidor de política desde la raíz del repositorio. El perfil mantenido coincide con nepyope/sonic_walk; para otra política, copie y actualice su checkpoint y su contrato de características juntos.
lerobot-policy-server \ --config_path=examples/remote_inference/unitree_g1_sonic.yaml
En el G1, mantén el puente y la cámara en funcionamiento:
python src/lerobot/robots/unitree_g1/run_g1_server.py --camera
Luego, inicie el cliente de rollout en un segundo terminal de G1, reemplazando <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=trueEscriba /start solo después de que G1 esté listo para moverse. SONIC declara soporte de espera porque reenviar el último token completo mantiene el equilibrio del decodificador a bordo. Antes del primer resultado de la política, rollout envía el token neutro del decodificador. Si el búfer de acciones se agota, repite el último token aplicado durante un máximo de action_starvation_grace_s (un segundo en el ejemplo anterior); si no llega una predicción nueva, rollout falla y sigue su ruta de apagado/desconexión configurada. Los controladores de locomoción de G1 no son compatibles porque sus velocidades de joystick no pueden conservarse de esta manera.
La receta desactiva el retorno a la posición inicial: interpolar a través del espacio de tokens latentes de SONIC no es una trayectoria de retorno físico validada. Evite /reset por la misma razón, ya que devolvería el token a su valor de conexión. /stop sigue cerrando la sesión remota y desconectando el robot a través de la ruta normal de apagado del controlador.
Con SonicWholeBodyController, el estado de observación es el eco de tokens de 64 dimensiones en lugar de las 29 posiciones articulares, por lo que un checkpoint compatible debe entrenarse contra ese estado. Al conectar, el robot lleva las articulaciones suavemente a los default_angles del decodificador antes de que el controlador tome el control.
Recursos adicionales
- Documentación del SDK de Unitree
- GR00T-WholeBodyControl
- Holosoma
- Documentación de LeRobot
- Unitree IL LeRobot
Última actualización: julio de 2026
Update on GitHub