Volver a Learn

Cómo calibrar las cámaras en Unitree G1

Calibración de cámara intrínseca y extrínseca basada en ChArUco para las cámaras de cabeza Unitree G1. Guarde en YAML, valida y integra con su pila de políticas.

Cada manipulación seria o la locomoción del humanoide Unitree G1 comienza con una buena calibración de la cámara. Este tutorial recorre la calibración intrínseca y extrínseca de la matriz de la cámara de la cabeza G1 utilizando una tabla ChArUco y OpenCV, guardando los resultados a YAML y validando con una verificación de la cordura de error de reproyección.

Humanoid Tiempo total: aproximadamente 90 minutos Dificultad: Intermedio Actualizado abril 2026

Lo que lograrás

Al final de este tutorial tendrá intrínsecas por cámara (matriz de cámara y coeficientes de distorsión) para cada una de las cámaras de cabeza G1, extrínsecas entre cámaras en el equipo de cabeza, y opcionalmente la extrínseca desde el marco de la cámara de cabeza hasta el enlace de base G1. Todo guardado en YAML en un formato que su pila de ROS 2 / LeRobot / OpenVLA puede consumir directamente.

La mala calibración es una de las causas raíces más comunes de "la política funcionó en sim pero falla en el robot real" corrompe todo a la baja: coordinación ojo a mano, estimación de profundidad, detección de objetos y políticas de cámara a acción.

Pre-requisitos

  • Unitree G1 con la matriz de cámara de la cabeza alimentada y en streaming (las variantes EDU / Desarrollador exponen las cámaras sobre el SDK).
  • Tabla de ChArUco. Imprimir una tabla A2 8x11 con cuadros de 40 mm y marcadores de 30 mm ArUco en papel mate y montarla en una superficie rígida, plana y no deformable (tabla de espuma o acrílico).
  • Estación de trabajo con Ubuntu 22.04, Python 3.10, OpenCV 4.8+, y el SDK Unitree G1 instalado.
  • Evite el sol directo o los reflejos especulares en la tabla.

Los pasos

  1. Imprimir y montar la tabla de ChArUco

Generar la tabla PDF:

```
python -c "
import cv2
aruco = cv2.aruco
d = aruco.getPredefinedDictionary(aruco.DICT_5X5_100)
board = aruco.CharucoBoard((8, 11), 0.040, 0.030, d)
img = board.generateImage((1500, 2100), marginSize=40)
cv2.imwrite('charuco_a2.png', img)
"
```

Imprimir en tamaño real (sin escalar) en papel mate A2, verificar que los cuadros impresos miden exactamente 40,0 mm, y montar en un respaldo rígido y plano.

  1. Configure el G1 y transmita las cámaras

Inicie el proceso de conexión de la cámara de cabeza a través del SDK Unitree. La unión exacta de Python está en el [unitreerobotics] T15) GitHub el patrón general es un suscriptor que produce marcos numpy sincronizados por cámara. Verifique que puede leer los marcos de todas las cámaras de cabeza en Python simultáneamente. Si cae una cámara, arregla eso antes de empezar a capturar.

  1. Captura 40 a 60 cuadros de tablero

Mover la cabeza (o la placa) de G1 a través de una amplia gama de poses: inclinada a la izquierda, inclinada a la derecha, cercana, lejos, fuera del eje. La calibración de OpenCV es tan buena como la diversidad de puntos de vista que le da. Para la estereo extrínseca, captura marcos sincronizados en ambas cámaras para cada pose.

```
import cv2

for i in range(60):
    frame_left, frame_right = camera.grab_sync()
    cv2.imwrite(f'calib/left_{i:03d}.png', frame_left)
    cv2.imwrite(f'calib/right_{i:03d}.png', frame_right)
    input("move board, press enter")
```

Punta: la tabla debe llenar al menos el 30% del marco, y los marcadores más detectados en las esquinas deben abarcar toda la región de la imagen.

  1. Computa las intrínsecas por cámara

Ejecutar la calibración intrínseca de ChArUco por cámara:

```
import cv2, glob, numpy as np

aruco = cv2.aruco
d = aruco.getPredefinedDictionary(aruco.DICT_5X5_100)
board = aruco.CharucoBoard((8, 11), 0.040, 0.030, d)
detector = aruco.CharucoDetector(board)

all_corners, all_ids, img_size = [], [], None
for fn in sorted(glob.glob('calib/left_*.png')):
    img = cv2.imread(fn, cv2.IMREAD_GRAYSCALE)
    img_size = img.shape[::-1]
    corners, ids, _, _ = detector.detectBoard(img)
    if ids is not None and len(ids) > 6:
        all_corners.append(corners)
        all_ids.append(ids)

ret, K, dist, rvecs, tvecs = aruco.calibrateCameraCharuco(
    all_corners, all_ids, board, img_size, None, None)
print('RMS reprojection error:', ret)
```

RMS objetivo por debajo de 0,5 píxeles. Por encima de 1 px indica mala planitud de la tabla, insuficiente diversidad de posturas o marcos fuera de enfoque.

  1. Computa las estereotipos extrínsecas

Para pares de cámaras (por ejemplo, cámaras de cabeza izquierda + derecha en una plataforma G1 binocular), ejecuta T5 utilizando las observaciones intrínsecas ya calculadas y de la tabla sincronizada.

```
ret, K1, D1, K2, D2, R, T, E, F = cv2.stereoCalibrate(
    object_points, left_img_points, right_img_points,
    K_left, D_left, K_right, D_right, img_size,
    flags=cv2.CALIB_FIX_INTRINSIC)
```
  1. Computa extrínsecas de cabeza a base (opcional)

Si su política de aguas abajo necesita posiciones de cámara en el enlace base o marco mundial G1, recorra a través de la kinemática de la cabeza conocida: lea el estado de la cabeza en el SDK, compón con el extrínseco de la cámara a la cabeza (desde la URDF o una calibración de ojo de mano única) y publique un ROS 2 T7.

  1. Ahorrar para YAML

Guarde en un formato YAML compatible con ROS para que funcionen los cargadores estándar T8:

```
import yaml

out = {
    'image_width': 1280,
    'image_height': 720,
    'camera_name': 'g1_head_left',
    'camera_matrix': {'rows': 3, 'cols': 3, 'data': K.flatten().tolist()},
    'distortion_model': 'plumb_bob',
    'distortion_coefficients': {'rows': 1, 'cols': 5, 'data': dist.flatten().tolist()},
}
with open('g1_head_left.yaml', 'w') as f:
    yaml.safe_dump(out, f)
```
  1. Valida en una escena de prueba

Captura un nuevo marco ChArUco que no estaba en el conjunto de calibración. Detecta esquinas, reproyecta usando tus intrínsecas guardadas, y superpone la imagen. El error medio de reproyección debe permanecer por debajo de 0,5 píxeles. También pasear el robot a través de algunas poses diferentes de la cabeza y ver la disparidad estéreo en un objeto de distancia conocida si está de acuerdo con la distancia medida en cinta a dentro de 1 a 2 cm a un rango de 1 m, sus extrínsecas son buenas.

¿Qué hacer ahora?

Incluye sus intrínsecas calibradas en cualquier pila de políticas de aguas abajo: OpenVLA fine-tuning utiliza imágenes rectificadas, LeRobot recording almacena las T9 junto a los episodios, y Isaac Lab necesita las mismas intrínsecas para la transferencia sim-a-real. Si está ejecutando SLAM o profundidad densa, una buena calibración es las apuestas de mesa.

Modo de falla común

Esto es un error de re-proyección: tablero deformado, diversidad de postura insuficiente o marcos fuera de enfoque.

Extrínsecas equivocadas en unos pocos cm: generalmente un insecto unidad tamaño cuadrado en metros vs milímetros.

Runs inconsistentes: comprobar que el estado de la articulación de la cabeza está bloqueado mientras se captura cada marco; movimiento durante la captura de interrupciones de calibración.

** Política sigue fallido después de la calibración:** verifique el orden de imagen (BGR vs RGB) y el orden de tamaño (recorte luego recorte vs recorte luego recorte) coincide con el procesamiento preliminar de la política.

Inmersión profunda: por qué ChArUco sobre tablero de ajedrez simple

Un tablero de ajedrez simple es el objetivo de calibración del libro de texto, pero tiene un modo de falla bien conocido: si alguna parte del tablero está oculta, toda la detección falla. ChArUco (un tablero de ajedrez con fiduciarios ArUco incrustados en los cuadros blancos) resuelve esto dando a cada rincón una identidad única. El calibrador puede usar observaciones parciales, por lo que puede mover la tabla de manera agresiva a través de diversas poses sin perder tiempo de captura en marcos inutilizables. Evite las funciones obsoletas en los tutoriales antiguos; el refinamiento de la esquina de subpixel es mucho mejor en la nueva API.

En particular, para las cámaras de cabeza humanoides, ChArUco también ayuda con una sutileza: la cabeza se inclina durante la captura, por lo que sus marcos alternan entre "la tabla toma toda la imagen" y "la tabla se desvía a un lado".

¿Qué tan bueno es lo suficientemente bueno?

El error de reproyección es el número de título, pero no toda la historia.

  • ** Formación en políticas de RGB:** 0,5 a 1,0 px está bien. Las políticas son algo tolerantes a los pequeños errores intrínsecos, especialmente si se entrenan y se despliegan con la misma calibración.
  • ** Profundidad de estereo o SLAM:** inferior a 0,3 px. Compuestos de error externo a través de la triangulación.
  • Manipulamiento de ojos de mano: menos de 0,5 px en el interior y menos de 2 mm en el exterior del factor de cámara a la extremidad.

Inmersión profunda: desencadenantes de recalibración

Un G1 no necesita una recalibración semanal, pero algunos eventos lo justifican: (1) cualquier impacto físico en la cabeza o montaje de la cámara, (2) el intercambio de una cámara, (3) la deriva térmica en un nuevo sitio de despliegue (laboratorio frío al suelo de producción caliente), y (4) si se ven errores de re-proyección creciendo durante semanas de uso. Automatice una rápida verificación de la cordura de ChArUco como parte de su mantenimiento semanal 5 cuadros y una verificación de re-rejección capta el 90% de la deriva de calibración.

Profundidad: integración con la formación política

Una vez que se guarde la calibración YAML, cablearla en su pila aguas abajo en tres lugares: (1) la tubería de grabación guarda la calibración junto a cada episodio para que pueda rectificarlo más tarde si es necesario, (2) la preprocesamiento de políticas opcionalmente no desvía o cultiva según lo intrínseco, y (3) la preprocesamiento de tiempo de inferencia utiliza los mismos parámetros como la formación. Las discrepancias entre la formación y el preprocesamiento de la inferencia son la causa raíz más común de los fallos de "trabajo en portátil, fracaso en robot".

Preguntas frecuentes

** ¿Puedo omitir la calibración si estoy haciendo solo teleop? ** Sí, teleop no requiere calibración. Pero pierdes la capacidad de entrenar una política de pixel-to-action más tarde en los datos grabados.

¿Cuánto tiempo es válida una calibración? Meses, sin impacto físico en la cabeza.

¿La calibración de G1 URDF es lo suficientemente precisa como para salir de la caja? Por lo general, dentro de unos pocos milímetros es suficiente para las políticas RGB, límite para la manipulación.

¿Qué hay de las cámaras de ojo de pez? Utilice los módulos T11 o T12 en OpenCV el modelo T13 asumido en este tutorial no maneja la distorsión del ojo de pez.

Tutoriales y recursos relacionados