Rotaciones, orientación y cuaterniones
Este ejemplo revisa conceptos de rotaciones tridimensionales y cómo se utilizan los cuaterniones para describir la orientación y las rotaciones. Los cuaterniones son un campo sesgado de números hipercomplejos. Han encontrado aplicaciones en la industria aeroespacial, gráficos por computadora y realidad virtual. En MATLAB®, las matemáticas de cuaterniones se pueden representar manipulando la clase quaternion
.
La clase HelperDrawRotation
se utiliza para ilustrar varias partes de este ejemplo.
dr = HelperDrawRotation;
Rotaciones en tres dimensiones
Todas las rotaciones en 3-D se pueden definir mediante un eje de rotación y un ángulo de rotación alrededor de ese eje. Considere la imagen tridimensional de una tetera en el gráfico más a la izquierda. La tetera se gira 45 grados alrededor del eje Z en el segundo gráfico. En el tercer gráfico se muestra una rotación más compleja de 15 grados alrededor del eje [1 0 1]. Los cuaterniones encapsulan el eje y el ángulo de rotación y tienen un álgebra para manipular estas rotaciones. La clase quaternion
y este ejemplo utilizan la convención de "regla de la mano derecha" para definir rotaciones. Es decir, las rotaciones positivas son en el sentido de las agujas del reloj alrededor del eje de rotación cuando se ven desde el origen.
dr.drawTeapotRotations;
Rotación de puntos
Los vértices de la tetera se rotaron alrededor del eje de rotación en el sistema de referencia. Considere un punto (0,7, 0,5) girado 30 grados alrededor del eje Z.
figure; dr.draw2DPointRotation(gca);
Rotación de marco
La rotación de cuadros es, en cierto sentido, lo opuesto a la rotación de puntos. En la rotación de marco, los puntos del objeto permanecen fijos, pero el marco de referencia gira. De nuevo, considere el punto (0,7, 0,5). Ahora el marco de referencia se gira 30 grados alrededor del eje Z. Tenga en cuenta que si bien el punto (0,7, 0,5) permanece fijo, tiene coordenadas diferentes en el nuevo marco de referencia rotado.
figure; dr.draw2DFrameRotation(gca);
Orientación
La orientación se refiere al desplazamiento angular de un objeto con respecto a un marco de referencia. Normalmente, la orientación se describe mediante la rotación que provoca este desplazamiento angular desde una orientación inicial. En este ejemplo, la orientación se define como la rotación que lleva una cantidad en un sistema de referencia principal a un sistema de referencia secundario. La orientación suele darse como un cuaternión, una matriz de rotación, un conjunto de ángulos de Euler o un vector de rotación. Es útil pensar en la orientación como una rotación del marco: el marco de referencia secundario se gira en relación con el marco principal.
Considere un ejemplo en el que el sistema de referencia secundario se gira 30 grados alrededor del vector [1/3 2/3 2/3].
figure; dr.draw3DOrientation(gca, [1/3 2/3 2/3], 30);
Cuaterniones
Los cuaterniones son números de la forma
dónde
y y
son números reales. En el resto de este ejemplo, los cuatro números
y
se denominan "partes" del cuaternión.
Cuaterniones para rotaciones y orientación.
El eje y el ángulo de rotación están encapsulados en las partes del cuaternión. Para un eje de rotación de vector unitario [ x, y, z] y un ángulo de rotación , el cuaternión que describe esta rotación es
Tenga en cuenta que para describir una rotación utilizando un cuaternión, el cuaternión debe ser un cuaternión unitario. Un cuaternión unitario tiene una norma de 1, donde la norma se define como
Hay varias formas de construir un cuaternión en MATLAB, por ejemplo:
q1 = quaternion(1,2,3,4)
q1 = quaternion 1 + 2i + 3j + 4k
Los arreglos de cuaterniones se pueden hacer de la misma manera:
quaternion([1 10; -1 1], [2 20; -2 2], [3 30; -3 3], [4 40; -4 4])
ans = 2x2 quaternion array 1 + 2i + 3j + 4k 10 + 20i + 30j + 40k -1 - 2i - 3j - 4k 1 + 2i + 3j + 4k
También se pueden usar arreglos con cuatro columnas para construir cuaterniones, donde cada columna representa una parte de cuaternión:
qmgk = quaternion(magic(4))
qmgk = 4x1 quaternion array 16 + 2i + 3j + 13k 5 + 11i + 10j + 8k 9 + 7i + 6j + 12k 4 + 14i + 15j + 1k
Los cuaterniones se pueden indexar y manipular como cualquier otra arreglo:
qmgk(3)
ans = quaternion 9 + 7i + 6j + 12k
reshape(qmgk,2,2)
ans = 2x2 quaternion array 16 + 2i + 3j + 13k 9 + 7i + 6j + 12k 5 + 11i + 10j + 8k 4 + 14i + 15j + 1k
[q1; q1]
ans = 2x1 quaternion array 1 + 2i + 3j + 4k 1 + 2i + 3j + 4k
Matemáticas del cuaternión
Los cuaterniones tienen operaciones aritméticas bien definidas. La suma y la resta son similares a los números complejos: las partes se suman y restan de forma independiente. La multiplicación es más complicada debido a la ecuación anterior:
Esto significa que la multiplicación de cuaterniones no es conmutativa. Es decir, para cuaterniones
y
. Sin embargo, cada cuaternión tiene un inverso multiplicativo, por lo que los cuaterniones se pueden dividir. Los arreglos de la clase
quaternion
se pueden sumar, restar, multiplicar y dividir en MATLAB.
q = quaternion(1,2,3,4); p = quaternion(-5,6,-7,8);
Suma
p + q
ans = quaternion -4 + 8i - 4j + 12k
Sustracción
p - q
ans = quaternion -6 + 4i - 10j + 4k
Multiplicación
p*q
ans = quaternion -28 - 56i - 30j + 20k
Multiplicación en orden inverso (tenga en cuenta el resultado diferente)
q*p
ans = quaternion -28 + 48i - 14j - 44k
La división derecha de p
por q
equivale a .
p./q
ans = quaternion 0.6 + 2.2667i + 0.53333j - 0.13333k
La división izquierda de q
por p
equivale a .
p.\q
ans = quaternion 0.10345 + 0.2069i + 0j - 0.34483k
El conjugado de un cuaternión se forma negando cada una de las partes no reales, similar a la conjugación de un número complejo:
conj(p)
ans = quaternion -5 - 6i + 7j - 8k
Los cuaterniones se pueden normalizar en MATLAB:
pnormed = normalize(p)
pnormed = quaternion -0.37905 + 0.45486i - 0.53067j + 0.60648k
norm(pnormed)
ans = 1
Rotaciones de puntos y cuadros con cuaterniones
Los cuaterniones se pueden utilizar para rotar puntos en un marco de referencia estático o para rotar el propio marco de referencia. La función rotatepoint
rota un punto usando un cuaternión
mediante la siguiente ecuación:
donde es
y indica conjugación de cuaterniones. Tenga en cuenta que la multiplicación de cuaterniones anterior da como resultado un cuaternión con la parte real,
, igual a 0. Las
,
y
del resultado forman el punto rotado (
,
,
).
Considere el ejemplo de rotación de puntos desde arriba. El punto (0,7, 0,5) se giró 30 grados alrededor del eje Z. En tres dimensiones este punto tiene una coordenada Z 0. Usando la formulación eje-ángulo, se puede construir un cuaternión usando [0 0 1] como eje de rotación.
ang = deg2rad(30);
q = quaternion(cos(ang/2), 0, 0, sin(ang/2));
pt = [0.7, 0.5, 0]; % Z-coordinate is 0 in the X-Y plane
ptrot = rotatepoint(q, pt)
ptrot = 0.3562 0.7830 0
De manera similar, la función rotateframe
toma un cuaternión y el punto
para calcular
Nuevamente, la multiplicación de cuaterniones anterior da como resultado un cuaternión con 0 parte real. Las (,
,
) partes del resultado forman la coordenada del punto
en el nuevo marco de referencia rotado. Usando la clase
quaternion
:
ptframerot = rotateframe(q, pt)
ptframerot = 0.8562 0.0830 0
Un cuaternión y su conjugado tienen efectos opuestos debido a la simetría en las ecuaciones de rotación de puntos y marcos. Girar por el conjugado "deshace" la rotación.
rotateframe(conj(q), ptframerot)
ans = 0.7000 0.5000 0
Debido a la simetría de las ecuaciones, este código realiza la misma rotación.
rotatepoint(q, ptframerot)
ans = 0.7000 0.5000 0
Otras representaciones de rotación
A menudo, las rotaciones y orientaciones se describen utilizando medios alternativos: Ángulos de Euler, matrices de rotación y/o vectores de rotación. Todos estos interoperan con cuaterniones en MATLAB.
Los ángulos de Euler se utilizan con frecuencia porque son fáciles de interpretar. Considere un marco de referencia girado 30 grados alrededor del eje Z, luego 20 grados alrededor del eje Y y luego -50 grados alrededor del eje X. Tenga en cuenta que aquí, y en todo momento, las rotaciones alrededor de cada eje son intrínsecas: cada rotación posterior se realiza alrededor del conjunto de ejes recién creado. En otras palabras, la segunda rotación es alrededor del "nuevo" eje Y creado por la primera rotación, no alrededor del eje Y original.
figure; euld = [30 20 -50]; dr.drawEulerRotation(gca, euld);
Para construir un cuaternión a partir de estos ángulos de Euler con el fin de rotar el marco, use el constructor quaternion
. Dado que el orden de las rotaciones es primero alrededor del eje Z, luego alrededor del nuevo eje Y y finalmente alrededor del nuevo eje X, use el indicador 'ZYX'
.
qeul = quaternion(deg2rad(euld), 'euler', 'ZYX', 'frame')
qeul = quaternion 0.84313 - 0.44275i + 0.044296j + 0.30189k
El indicador 'euler'
indica que el primer argumento está en radianes. Si el argumento está en grados, utilice el indicador 'eulerd'
.
qeuld = quaternion(euld, 'eulerd', 'ZYX', 'frame')
qeuld = quaternion 0.84313 - 0.44275i + 0.044296j + 0.30189k
Para volver a convertir a ángulos de Euler:
rad2deg(euler(qeul, 'ZYX', 'frame'))
ans = 30.0000 20.0000 -50.0000
De manera equivalente, se puede utilizar el método eulerd
.
eulerd(qeul, 'ZYX', 'frame')
ans = 30.0000 20.0000 -50.0000
Alternativamente, esta misma rotación se puede representar como una matriz de rotación:
rmat = rotmat(qeul, 'frame')
rmat = 0.8138 0.4698 -0.3420 -0.5483 0.4257 -0.7198 -0.1926 0.7733 0.6040
La conversión a cuaterniones es similar:
quaternion(rmat, 'rotmat', 'frame')
ans = quaternion 0.84313 - 0.44275i + 0.044296j + 0.30189k
Así como un cuaternión se puede usar para rotación de punto o marco, se puede convertir en una matriz de rotación (o conjunto de ángulos de Euler) específicamente para rotación de punto o marco. La matriz de rotación para la rotación de puntos es la transpuesta de la matriz para la rotación de cuadros. Para convertir entre representaciones de rotación, es necesario especificar 'point'
o 'frame'
.
La matriz de rotación para la sección de rotación de puntos de este ejemplo es:
rotmatPoint = rotmat(q, 'point')
rotmatPoint = 0.8660 -0.5000 0 0.5000 0.8660 0 0 0 1.0000
Para encontrar la ubicación del punto rotado, multiplique por la derecha rotmatPoint
por el arreglo transpuesta pt
.
rotmatPoint * (pt')
ans = 0.3562 0.7830 0
La matriz de rotación para la sección de rotación del marco de este ejemplo es:
rotmatFrame = rotmat(q, 'frame')
rotmatFrame = 0.8660 0.5000 0 -0.5000 0.8660 0 0 0 1.0000
Para encontrar la ubicación del punto en el marco de referencia rotado, multiplique a la derecha rotmatFrame
por el arreglo transpuesta pt
.
rotmatFrame * (pt')
ans = 0.8562 0.0830 0
Un vector de rotación es una encapsulación de rotación compacta y alternativa. Un vector de rotación es simplemente un vector de tres elementos que representa el eje de rotación de longitud unitaria ampliado por el ángulo de rotación en radianes. No hay ningún marco ni punto asociado con un vector de rotación. Para convertir a un vector de rotación:
rv = rotvec(qeul)
rv = -0.9349 0.0935 0.6375
Para convertir a un cuaternión:
quaternion(rv, 'rotvec')
ans = quaternion 0.84313 - 0.44275i + 0.044296j + 0.30189k
Distancia
Una ventaja de los cuaterniones sobre los ángulos de Euler es la falta de discontinuidades. Los ángulos de Euler tienen discontinuidades que varían según la convención que se utilice. La función dist
compara el efecto de rotación de dos cuaterniones diferentes. El resultado es un número en el rango de 0 a pi
. Considere dos cuaterniones construidos a partir de ángulos de Euler:
eul1 = [0, 10, 0]; eul2 = [0, 15, 0]; qdist1 = quaternion(deg2rad(eul1), 'euler', 'ZYX', 'frame'); qdist2 = quaternion(deg2rad(eul2), 'euler', 'ZYX', 'frame');
Restando los ángulos de Euler, se puede ver que no hay rotación alrededor del eje Z o del eje X.
eul2 - eul1
ans = 0 5 0
La diferencia entre estas dos rotaciones es de cinco grados alrededor del eje Y. El dist
también muestra la diferencia.
rad2deg(dist(qdist1, qdist2))
ans = 5.0000
Para ángulos de Euler como eul1
y eul2
, calcular la distancia angular es trivial. Un ejemplo más complejo, que abarca una discontinuidad del ángulo de Euler, es:
eul3 = [0, 89, 0]; eul4 = [180, 89, 180]; qdist3 = quaternion(deg2rad(eul3), 'euler', 'ZYX', 'frame'); qdist4 = quaternion(deg2rad(eul4), 'euler', 'ZYX', 'frame');
Aunque eul3
y eul4
representan casi la misma orientación, la simple resta de ángulos de Euler da la impresión de que estas dos orientaciones están muy separadas.
euldiff = eul4 - eul3
euldiff = 180 0 180
El uso de la función dist
en los cuaterniones muestra que solo hay una diferencia de dos grados en estas rotaciones:
euldist = rad2deg(dist(qdist3, qdist4))
euldist = 2.0000
Un cuaternión y su negativo representan la misma rotación. Esto no es obvio al restar cuaterniones, pero la función dist
lo deja claro.
qpos = quaternion(-cos(pi/4), 0 ,0, sin(pi/4))
qpos = quaternion -0.70711 + 0i + 0j + 0.70711k
qneg = -qpos
qneg = quaternion 0.70711 + 0i + 0j - 0.70711k
qdiff = qpos - qneg
qdiff = quaternion -1.4142 + 0i + 0j + 1.4142k
dist(qpos, qneg)
ans = 0
Funciones admitidas
La clase quaternion
le permite describir efectivamente rotaciones y orientaciones en MATLAB. La lista completa de funciones compatibles con cuaterniones se puede encontrar con la función methods
:
methods('quaternion')
Methods for class quaternion: angvel ismatrix prod cat isnan quaternion classUnderlying isrow rdivide compact isscalar reshape conj isvector rotateframe ctranspose ldivide rotatepoint disp length rotmat dist log rotvec double meanrot rotvecd eq minus single euler mtimes size eulerd ndims slerp exp ne times horzcat norm transpose iscolumn normalize uminus isempty numel underlyingType isequal parts validateattributes isequaln permute vertcat isfinite plus isinf power Static methods: ones zeros