wandres.dev
MATEMÁTICAS DEL 3D III · Rotaciones y cuaterniones

Gimbal lock: la demostración, no la anécdota

Por qué en ciertas orientaciones los ángulos de Euler pierden un grado de libertad, demostrado sobre la matriz que construye Three.js, y qué consecuencias tiene en la práctica.

⏱ 18 min

El gimbal lock se cuenta casi siempre con una animación de tres anillos que se alinean y una referencia al programa Apolo. Está bien como intuición y es inútil como herramienta: no permite predecir cuándo va a ocurrir, ni reconocer el síntoma, ni decidir qué hacer. Esta lección lo demuestra sobre la matriz concreta que Three.js construye, con lo que la condición exacta queda a la vista y el diagnóstico deja de depender de la memoria visual.

🎯 Al terminar esta lección sabrás
  • Demostrar algebraicamente la pérdida de un grado de libertad en el ángulo central.
  • Identificar qué orientación concreta produce el bloqueo según el orden elegido.
  • Distinguir el bloqueo de la representación de un problema del objeto.
  • Reconocer los tres síntomas que produce en una aplicación real.

La demostración sobre la matriz

Three.js construye la matriz de rotación de un Euler con orden XYZ a partir de seis valores: el seno y el coseno de cada uno de los tres ángulos. Llamemos a y b al coseno y al seno del ángulo en X, c y d a los del ángulo en Y, y e y f a los del ángulo en Z.

Las nueve entradas de la matriz quedan así:

fila 1:   c·e            -c·f            d
fila 2:   a·f + b·e·d    a·e - b·f·d    -b·c
fila 3:   b·f - a·e·d    b·e + a·f·d     a·c

Ahora impón la condición del bloqueo: el ángulo central, el de Y, vale noventa grados. Entonces su coseno c vale cero y su seno d vale uno. Sustituye:

fila 1:   0              0               1
fila 2:   a·f + b·e      a·e - b·f       0
fila 3:   b·f - a·e      b·e + a·f       0

Y ahora reconoce las fórmulas del seno y el coseno de una suma. a·f + b·e es el seno de la suma de los ángulos en X y en Z. a·e - b·f es el coseno de esa misma suma. La matriz completa queda reducida a:

fila 1:   0              0               1
fila 2:   sen(x+z)       cos(x+z)        0
fila 3:  -cos(x+z)       sen(x+z)        0

La matriz solo depende de la suma de los ángulos primero y tercero. Los dos parámetros se han fusionado en uno. Puedes cambiar el ángulo en X y el ángulo en Z todo lo que quieras: mientras su suma no cambie, la orientación es exactamente la misma. Y para cualquier orientación alcanzable en esa configuración, hay infinitas parejas de ángulos que la producen.

Eso es el gimbal lock, dicho con precisión: en el conjunto de orientaciones donde el ángulo central vale más o menos noventa grados, la aplicación de tres ángulos a orientaciones deja de ser localmente invertible y pierde un grado de libertad. No es que la orientación sea imposible; es que las tres perillas ya no controlan tres cosas independientes.

import * as THREE from 'three';

const grados = THREE.MathUtils.degToRad;

// Angulo central en 90 grados: solo importa la suma del primero y el tercero.
const p = new THREE.Quaternion().setFromEuler(new THREE.Euler(grados(20), grados(90), grados(50), 'XYZ'));
const q = new THREE.Quaternion().setFromEuler(new THREE.Euler(grados(60), grados(90), grados(10), 'XYZ'));
const r = new THREE.Quaternion().setFromEuler(new THREE.Euler(grados(0),  grados(90), grados(70), 'XYZ'));

console.log('p igual a q:', p.angleTo(q) < 1e-6);   // true, ambas suman 70
console.log('p igual a r:', p.angleTo(r) < 1e-6);   // true, tambien suma 70

// Fuera del bloqueo, las mismas ternas dan orientaciones distintas.
const s = new THREE.Quaternion().setFromEuler(new THREE.Euler(grados(20), grados(80), grados(50), 'XYZ'));
const t = new THREE.Quaternion().setFromEuler(new THREE.Euler(grados(60), grados(80), grados(10), 'XYZ'));
console.log('con Y a 80 grados difieren:', THREE.MathUtils.radToDeg(s.angleTo(t)).toFixed(2));

Dónde está la singularidad según el orden

El eje que provoca el bloqueo es siempre el del medio, y la condición es siempre que su ángulo valga más o menos noventa grados. Cambiar el orden no elimina la singularidad: la mueve a otras orientaciones.

Orden Eje central Orientación que bloquea
XYZ Y Cuando el eje Z local queda alineado con el eje X del mundo
YXZ X Cuando el objeto mira recto hacia arriba o hacia abajo
ZXY X La misma que la anterior
ZYX Y Análoga a la del primero, con los ejes intercambiados

De ahí sale el criterio de elección de orden que ya apareció en la lección anterior: pon en el centro el eje sobre el que el objeto no va a girar mucho. Para una cámara en primera persona el orden YXZ deja la singularidad en el cenit y el nadir, que son dos orientaciones que el control puede limitar sin que nadie lo note; con el orden por defecto, el bloqueo caería en una orientación horizontal perfectamente normal.

Esta es también la razón de que casi todos los sistemas de cámara con Euler tengan una línea que recorta la elevación a un valor ligeramente inferior a noventa grados. No es una restricción estética: es evitar la singularidad.

El bloqueo no está en el objeto, está en las coordenadas, y por eso ningún ajuste lo arregla

La confusión más extendida sobre el gimbal lock es creer que hay orientaciones prohibidas o que el objeto «se atasca». No hay nada atascado. El objeto puede alcanzar cualquier orientación y girar libremente desde ella; lo que falla es el sistema de coordenadas con el que la estás describiendo. Es exactamente el mismo fenómeno que la longitud geográfica en el polo norte: el punto existe, no tiene nada de especial, y sin embargo todas las longitudes se juntan ahí y la coordenada deja de significar nada. Nadie diría que el polo norte está roto. Esta distinción no es filosófica, tiene tres consecuencias operativas. La primera: no busques el bug en la lógica de rotación, porque no está ahí; si el objeto se comporta raro solo al acercarse a una orientación concreta, el problema es la parametrización. La segunda: cambiar el orden de los ejes no soluciona nada, solo traslada el problema a otro sitio, y si el objeto necesita girar libremente en las tres direcciones no hay ningún orden bueno. La tercera, y la que de verdad importa: la solución no es un parche sino un cambio de representación. Existe además un resultado matemático que cierra la puerta a cualquier apaño: el espacio de las rotaciones tridimensionales no admite ninguna descripción con tres parámetros que sea suave y sin singularidades en todas partes. Con tres números, siempre habrá un polo. Por eso la respuesta es usar cuatro.

Los tres síntomas en una aplicación real

Saber la teoría sirve si te permite reconocer el problema cuando aparece disfrazado. Aparece de tres formas.

El giro brusco al cruzar el cenit. Una cámara orbital a la que se le permite llegar exactamente arriba pega un latigazo lateral al pasar por el punto más alto. La orientación de destino es correcta, pero el camino que toma la interpolación pasa por la zona donde una variación mínima de orientación exige una variación enorme de ángulos. El síntoma es un tirón, no un fallo.

La animación que da una vuelta de más. Dos fotogramas clave con ternas de Euler que describen orientaciones cercanas pero con números lejanos —por la no unicidad— producen al interpolar un giro completo espectacular donde debería haber un movimiento de diez grados. Es el fallo clásico de las animaciones exportadas con curvas de Euler, y es la razón de que los formatos modernos guarden cuaterniones.

El control que se vuelve hipersensible. Cerca de la singularidad, la relación entre mover el ratón y cambiar la orientación se dispara. El usuario lo describe como que «se descontrola» en una zona concreta.

Los tres tienen el mismo diagnóstico y la misma solución. Diagnóstico: comprueba si el fenómeno ocurre siempre en torno a la misma orientación y si esa orientación corresponde al eje central del orden que estás usando. Solución: si la rotación es de un solo eje, no hay problema que resolver; si hay dos ejes con recorrido limitado, limita el central; si hay libertad completa en tres ejes, pasa a cuaterniones.

Un apunte histórico, ahora que sirve de algo

La expresión viene de los sistemas inerciales de navegación, que montaban una plataforma estabilizada sobre tres anillos articulados. Cuando dos de los ejes de esos anillos se alineaban, la plataforma perdía la capacidad de girar en una dirección y el sistema dejaba de poder seguir la orientación de la nave.

En las misiones Apolo, la unidad de medida inercial tenía tres anillos y el bloqueo era una preocupación operativa real: había que evitar activamente ciertas actitudes, y el ordenador de a bordo avisaba al acercarse a la zona peligrosa. Se estudió añadir un cuarto anillo, que habría eliminado el problema, y se descartó por peso y complejidad.

Lo relevante del episodio para quien programa gráficos no es la anécdota, sino la analogía exacta: el cuarto anillo del hardware cumple el mismo papel que la cuarta componente de un cuaternión. En ambos casos, la manera de eliminar una singularidad es añadir una dimensión redundante y aceptar una restricción.