- Introducción =====
Este documento sirve como referencia técnica para comprender los parámetros del código de H2O. El propósito es facilitar el aprendizaje autónomo y la colaboración con la comunidad. Cualquier corrección es bienvenida en los comentarios.
- Proyectos y Publicaciones ============
Enlace del proyecto: https://omni.human2humanoid.com/Resumen del artículo: https://www.cnblogs.com/myleaf/p/18727733Título del artículo: OmniH2O: Universal and Dexterous Human-to-Humanoid Whole-Body Teleoperation and Learning
2.2 Conjuntos de Datos
2.2.1 Descripción de los datasets
El artículo requiere dos conjuntos de datos: SMPL y AMASS. SMPL es un conjunto de datos que contiene puntos del esqueleto humano y parámetros de mallado (mesh), representando individuos estáticos sin movimiento.
AMASS amplía SMPL incluyendo secuencias de movimiento humano.
- Características: SMPL es un modelo generativo de人体网格 3D, mientras que AMASS es un dataset de captura de movimiento con parámetros SMPL.
- Funcionalidad: SMPL se usa para modelado, AMASS para proporcionar datos de movimiento.
- Aplicaciones: SMPL genera modelos humanos estáticos o dinámicos, AMASS para aálisis y síntesis de movimiento humano.
AMASS es una base de datos de movimiento humano grande que unifica diferentes conjuntos de datos de captura de movimiento óptico bajo un marco común y parametrización¹. Contiene más de 40 horas de datos de movimiento, abarcando más de 300 sujetos y más de 11000 movimientos¹. Utiliza el modelo humano SMPL², que es un modelo humano generativo basado en espacios de formas mixtas y poses, capaz de describir la forma y pose humanas con pocos parámetros².
AMASS emplea un nuevo método llamado MoSh++⁴ que convierte datos de captura de movimiento en mallas humanas 3D realistas representadas por modelos de cuerpo rígido⁴. Este método funciona con conjuntos de marcadores arbitrarios mientras recupera dinámica de tejido blando y movimientos realistas de manos⁴. El dataset AMASS está estrictamente filtrado y controlado качества, proporcionando muestras ricas y diversas de movimiento humano para entrenar y evaluar métodos de estimación de pose y forma humana.
La base de datos AMASS es un archivo JSON que almacena metadatos de cada conjunto de datos de captura de movimiento y parámetros del modelo humano SMPL. Los nombres de archivo consisten en el nombre del dataset, número de sujeto y número de movimiento, por ejemplo CMU_01_01.json¹.
2.2.2 Código de los Datasets
SMPL: Requiere registro https://smpl.is.tue.mpg.de/login.phpDespués de descargar y extraer, modificar nombres según sea necesario.
AMASS: También requiere registro Formato del modelo:
https://amass.is.tue.mpg.de/register.phpMás detalles en: https://blog.csdn.net/qq_53930200/article/details/137646272
2.2.3 PHC
Perpetual Humanoid Control for Real-time Simulated Avatars Es uno de los trabajos preparatorios de H2O para retargeting humano. Proyecto: https://github.com/ZhengyiLuo/PHC/
- Código del Artículo =======
En el archivo principal xxx_teleop_env.py hay múltiples procesamientos de observaciones:
Resumen de relaciones entre variables:
local_ref_body_poses la diferencia entreref_body_posyroot_posdiff_local_body_poses la diferencia entreref_body_posybody_posbody_pos[:,0,:]representaroot_pos
Las observaciones implican principalmente transformaciones de coordenadas, como convertir del sistema de coordenadas global al sistema de coordenadas de la pelvis (parte superior del cuerpo).
-----Actualización 2025.3.1: Confirmado - las observaciones transforman del sistema de coordenadas parental al sistema de coordenadas raíz (pelvis). Los valores multiplicados por
root_rotation_basese mapean al sistema de coordenadas correspondiente.
Nota del autor: Aquí se realizan transformaciones de coordenadas porque los movimientos de referencia están en coordenadas del mundo. Para el robot, ciertos datos parecen anómalos, por lo que se convierten al sistema de coordenadas del cuerpo. Esto permite que las coordenadas relativas no se vean afectadas por el desplazamiento del robot.
2.1 compute_imitation_observations:
# Cálculo de diferencias locales para posiciones corporales
obs.append(diff_local_body_pos_flat.view(B, time_steps, -1))
# Transformación de cuaterniones a representación tangente-normal
obs.append(torch_utils.quat_to_tan_norm(diff_local_body_rot_flat).view(B, time_steps, -1))
# Velocidades locales del raíz
obs.append(diff_local_root_vel.view(B, time_steps, -1))
obs.append(diff_local_root_ang_vel.view(B, time_steps, -1))
# Posiciones y rotaciones de referencia en espacio local
obs.append(local_ref_body_pos.view(B, time_steps, -1))
obs.append(local_ref_body_rot.view(B, time_steps, -1))
# Diferencias en grados de libertad
obs.append(dof_diff.view(B, time_steps, -1))
obs.append(dof_vel_diff.view(B, time_steps, -1))
2.2 compute_imitation_observations_teleop:
# Solo posición de referencia local para teleoperación
obs.append(local_ref_body_pos.view(B, time_steps, -1))
2.3 compute_imitation_observations_teleop_max:
# Máximo de posiciones corporales y referencias
obs.append(diff_local_body_pos_flat.view(B, time_steps, -1))
obs.append(local_ref_body_pos.view(B, time_steps, -1))
2.4 compute_imitation_observations_teleop_max_heading:
# Incluye orientación heading
obs.append(diff_local_body_pos_flat.view(B, time_steps, -1))
obs.append(local_ref_body_pos.view(B, time_steps, -1))
obs.append(diff_local_heading_rot_flat.view(B, time_steps, -1))
2.5 compute_imitation_observations_max_full:
# Observaciones completas con velocidades
obs.append(diff_local_body_pos_flat.view(B, time_steps, -1))
obs.append(torch_utils.quat_to_tan_norm(diff_local_body_rot_flat).view(B, time_steps, -1))
obs.append(diff_local_vel.view(B, time_steps, -1))
obs.append(diff_local_ang_vel.view(B, time_steps, -1))
obs.append(local_ref_body_pos.view(B, time_steps, -1))
obs.append(local_ref_body_rot.view(B, time_steps, -1))
2.6 compute_humanoid_observations:
# Observaciones completas del robot
obs_list += [local_body_pos, local_body_rot_obs, local_body_vel, local_body_ang_vel, dof_pos, dof_vel]
2.7 compute_humanoid_observations_max_full:
# Observaciones sin DOF
obs_list += [local_body_pos, local_body_rot_obs, local_body_vel, local_body_ang_vel]
- Sección Principal =====
La función compute_self_and_task_obs() gestiona diferentes variaciones de observaciones. A continuación se muestra la comparación entre versiones.
3.1 Versión 1
self_obs = compute_humanoid_observations(
body_pos, body_rot, root_vel, root_ang_vel,
dof_pos, dof_vel, True, True
)
task_obs = compute_imitation_observations(
root_pos, root_rot, body_pos, body_rot,
root_vel, root_ang_vel, dof_pos, dof_vel,
ref_body_pos, ref_body_rot, ref_root_vel,
ref_root_ang_vel, ref_joint_pos, ref_joint_vel, 1
)
obs = torch.cat([self_obs, task_obs, self.projected_gravity, self.actions], dim=-1)
3.2 Versión Mínima
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel,
base_gravity, delta_base_pos, delta_heading,
ref_dof_pos, ref_dof_vel, ref_base_vel,
ref_base_ang_vel, ref_base_gravity,
self.actions
], dim=-1)
3.3 Versión Mínima 2
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel,
base_gravity, delta_base_pos, delta_heading,
ref_dof_pos, self.actions
], dim=-1)
3.4 Versión Teleoperación
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel,
base_gravity, delta_base_pos, delta_heading,
task_obs, # 18 dimensiones
self.actions # 19 dimensiones
], dim=-1)
3.5 Versión Teleoperación Limpia
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.6 Versión Teleoperación Superlimpia
obs = torch.cat([
dof_pos, dof_vel,
task_obs,
self.actions
], dim=-1)
3.7 Versión Teleoperación Extendida
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.8 Versión Teleoperación Extendida sin Velocidad Lineal
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs, # 24 dimensiones
self.actions
], dim=-1)
3.9 Versión Teleoperación Extendida Máxima
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.10 Versión Teleoperación Extendida Máxima sin Velocidad
# Con historial
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs,
self.actions,
history_to_be_append
], dim=-1)
# Sin historial
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.11 Versión Teleoperación Extendida VR Máxima
# Con historial
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel, base_gravity,
task_obs,
self.actions,
history_to_be_append
], dim=-1)
# Sin historial
obs = torch.cat([
dof_pos, dof_vel, base_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.12 Versión Teleoperación Extendida VR Máxima sin Velocidad Lineal
# Con historial
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs,
self.actions,
history_to_be_append
], dim=-1)
# Sin historial
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.13 Versión Teleoperación Extendida VR Máxima sin Velocidad Lineal con Heading
# Configuración similar a la versión anterior
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs,
self.actions,
history_to_be_append
], dim=-1)
3.14 Versión Teleoperación Extendida Máxima Completa
obs = torch.cat([
self_obs,
task_obs,
self.actions
], dim=-1) # 342 + 552 + 19 = 913 dimensiones
3.15 Versión Teleoperación Extendida Máxima sin Velocidad Lineal
obs = torch.cat([
dof_pos, dof_vel, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.16 Versión Teleoperación Extendida Máxima con Aceleración
obs = torch.cat([
dof_pos, dof_vel, base_acc, base_ang_vel, base_gravity,
task_obs,
self.actions
], dim=-1)
3.17 Observaciones Privilegiadas
if self.cfg.env.num_privileged_obs is not None:
# Observaciones privilegiadas (77 dimensiones totales)
self.privileged_info = torch.cat([
self._base_com_bias, # 3
self._ground_friction_values[:, self.feet_indices], # 2
self._link_mass_scale, # 8
self._kp_scale, # 19
self._kd_scale, # 19
self._rfi_lim_scale, # 19
self.contact_forces[:, self.feet_indices, :].reshape(self.num_envs, 6), # 6
torch.clamp_max(self._recovery_counter.unsqueeze(1), 1), # 1
], dim=1)
# Total: 913 + 77 = 990 dimensiones
privileged_obs_buf = torch.cat([obs_buf_denoise, self.privileged_info], dim=1)
- Problemas Técnicos y Soluciones ====================
4.1
Comparación de articulaciones entre robot G1 y robot H1 por defecto.
Es necesario modificar las articulaciones predeterminadas porque el robot G1 tiene una configuración diferente.
4.2
SMPL solo mapea piernas, brazos y pelvis, no torso, manos ni cabeza.
Después del entrenamiento se observa cierta discrepancia en la correspondencia de puntos clave.
La pelvis (pelvis) es compartida entre H1 y G1, por lo que no es necesario modificar torso_link a waist_yaw_link.
4.3
Después de ajustar la altura y la longitud de los brazos, las vibraciones mejoraron significativamente.
4.4 Datos de Movimiento
Valores principales de motion en el archivo motion_lib_g1.py:
root_pos: posición del pelvisroot_rot: rotación del pelvis (cuaternión)dof_pos: posiciones de los grados de libertadroot_vel: velocidad lineal del pelvisroot_ang_vel: velocidad angular del pelvisdof_vel: velocidades de los grados de libertadmotion_aa: representación axis-anglerg_pos: posiciones de todos los cuerpos rígidosrb_rot: rotaciones de todos los cuerpos rígidosbody_vel: velocidades de todos los cuerposbody_ang_vel: velocidades angulares de todos los cuerpos
4.5
Verificación de información de altura desde archivos AMASS.
4.6
Obtención de vértices humanos y ángulos articulares.
Total de 72 poses: 3 para ángulo global de posición, 69 para 23 articulaciones en formato axis-angle.
4.7
Prolbema principal: Unificación de puntos clave entre retargeting y RL. El retargeting permite puntos flotando en el aire mientras que RL tiene física con gravedad, causando que el robot caiga o levante piernas. Es un problema complejo de resolver.
4.8
El valor cfg.env.test controla el tiempo de muestreo. La longitud de motion se maneja appendeando current_motions.
4.9
Lógica de reproducción: se entrena un modelo grande con datos AMASS. Para reproducir un motion específico:
# Especificar archivo de motion
motion.motion_file = "resources/motions/g1/g1_test.pkl"
# Cargar modelo entrenado
load_run = "25_02_26_12-36-51_g1_ACCAD_10000_TEACHER"
4.10
El módulo de estimación humana parece usar procesamiento de visión por computadora. La implementación real podría no estar completa en el código.
4.11
Extracción de puntos clave de cámara RGB. HybrIK es el método mencionado para RGB a SMPL pero presenta problemas de ejecución.
4.12
El dataset de movimientos está filtrado pero el criterio específico no está documentado en el código.
4.13
Transformaciones de coordenadas en URDF: cada articulación tiene posición relativa al padre. Aquí se aplica la rotación del padre al hijo y se suma a la posición del padre.
4.14 Detalles de Rewards y Observaciones
4.14.1 Función de Recompensa
En la recompensa de articulaciones:
# Rewards tracking de puntos clave
joint_reward = ... # para student network
4.14.2 Motion
teleop_selected_keypoints_names = [] # Vacío en student
4.14.3 Configuración de Distilación
# En train.distill_model_config
teleop_selected_keypoints_names = ...
# Se asigna a motion.teleop_selected_keypoints_names
4.14.4 _track_bodies_extend_id y selected_keypoints_idx
_track_bodies_extend_id: incluye articulaciones extendidasselected_keypoints_idx: índice de puntos clave seleccionados
4.14.5 Observaciones
- Estudiante: menos links observados, sin información privilegiada
- Teacher: todos los links observados con información privilegiada
4.15
Heading se refiere al ángulo de orientación en radianes.
4.16
Diferencias en comandos demo entre modos.
4.17 Sim2Sim
La integración con SDK de Unitree G1 requiere adaptación de interfaces.
4.18
Análisis de curvas de datos para对齐 datos de simulación. Comparación de rangos de valores entre Issac Gym y MuJoCo.
4.19
Frecuencias de control:
- Issac Gym: PD controller 200Hz, bucle externo 50Hz
- MuJoCo: bucle externo 200Hz, bucle interno 20Hz
4.20
Uso de projected_gravity como observación.
4.21 Alineación de Entornos Virtuales
4.21.1 ref_pos
Comparación de ref_pos entre Issac Gym y MuJoCo - diferían en 2 frames.
4.21.2 ref_vel
Igual diferencia de 2 frames.
4.21.3 root_rot
Verificación importante - los valores iniciales diferían significativamente entre entornos.
4.22 Solución Final
El problema principle era la desalineación de observaciones entre MuJoCo e Issac Gym. Cuando hay comportamiento anómalo como movimientos erráticos, lo primero a verificar es la对齐 de observaciones.
- Extensiones y Herramientas ==================
5.1 Temas
Formato de código recomendado.
5.2 Extensiones VSCode
- urdf-preview: visualización en tiempo real de archivos URDF
- Rainbow Indent: indentación coloreada
- Temas de sidebar: Numary, One Monokai
- Plugin para archivos .npz de NumPy y visor de PDF
- Modelos de lenguaje locally: Qwen (limitaciones en red local)