Ahora que tengo la matriz de coordenadas de una marca con respecto a otra lo que necesito es obtener los ángulos de rotación con respecto a cada uno de los ejes. El problema es que en la escasa documentación que ofrece Artoolkit lo que dice es que la última columna de la matriz indica la distancia en los distintos ejes X, Y, y Z. Y efectivamente al acercar o alejar las marcas se puede apreciar.
Pero no dice nada acerca de las otras 3 columnas que después descubrí que indican la rotación que yo buscaba.
Matriz de rotación
r [0,0] r [0,1] r [0,2]
r [1,0] r [1,1] r [1,2]
r [2,0] r [2,1] r [2,2]
Así que empiezo a hacer pruebas primero coloco una marca base y debajo de ella coloco otra. Como se puede apreciar están sobre la mesa sin giro alguno


Sin figura 3D
Con figura 3D
La tetera roja está colocada en la marca base.
Y la matriz resultado es la siguiente:
| [R] = |
| 0,9988 |
0,0060 |
-0,0496 |
0,1213 |
| -0,0064 |
0,9999 |
-0,0091 |
-130,7769 |
| 0,0495 |
0,0094 |
0,9987 |
5,0256 |
|
| Cuya matriz de rotación se parece bastante a:
|
Efectivamente la última columna cumple su cometido de indicar la distancia, ya que para dx y dz su valor es cercano a 0 pero para dy nos da un valor d -130 es decir la marca secundaria está por debajo de la marca base. Y el resto de la matriz (la matriz de rotación) se parece a la matriz identidad.
Después hice pruebas con distintas marcas colocándolas en ángulos reconocibles de 90 grados con respecto a una marca base (la de la tetera rosa) que será respecto a la que calcule las matrices de coordenadas.


Como se puede observar cada una de las marcas 1, 2, y 3 están giradas 90 grados en un sentido u otro con respecto a uno delos ejes de la marca 0.
La marca 1 está girada con respecto al eje X.
La marca 2 está girada con respecto al eje Y.
La marca 3 está girada con respecto al eje Z.
Y las matrices de coordenadas respecto a la marca base 0 (tetera rosa) obtenidas para cada un una de las otras marcas son las siguientes:
Matriz de la marca 1.
| [R] = |
| 0,9984 |
0,0036 |
0,0557 |
-3,8267 |
| 0,0556 |
-0,1288 |
-0,990 |
53,1803 |
| 0,0036 |
0,9917 |
-0,1288 |
67,2298 |
|
| Cuya matriz de rotación se parece bastante a:
|
Matriz de la marca 2.
| [R] = |
| 0,0168 |
-0,0193 |
-0,9997 |
74,2620 |
| -0,0366 |
0,9991 |
-0,0199 |
10,7033 |
| 0,9992 |
0,0370 |
0,0161 |
57,7545 |
|
| Cuya matriz de rotación se parece bastante a:
|
Matriz de la marca 3.
| [R] = |
| -0,0356 |
0,9993 |
-0,0067 |
8,1143 |
| -0,9970 |
-0,0351 |
0,0685 |
-115,7258 |
| 0,0682 |
0,0092 |
0,9976 |
-11,3858 |
|
| Cuya matriz de rotación se parece bastante a:
|
Estos valores tan poco aleatorios tienen su explicación, la cual encontré en los apuntes de la asignatura SIO, Síntesis de imágenes por Ordenador (José Cortés Parejo).

Seno de 90º es 1 y de -90º es -1 y el coseno 90 es 0. Así que lo que nos dicen las matrices es que la marca 1 está girada 90 grados alrededor del eje X, y las marcas 2 y 3 -90 grados alrededor de los ejes Y y Z respectivamente.
Así que la conclusión es que la matriz de rotación general es la multiplicación de las matrices de rotación con respecto a cada eje. Si consideramos α, β y γ los ángulos de giro alrededor de los ejes X, Y y Z respectivamente tenemos que multiplicando las matrices de rotación obtenemos lo siguiente.
| [R] = |
Rotación en eje Z
| cos γ |
-sen β |
0 |
| sen γ |
cos γ |
0 |
| 0 |
0 |
1 |
|
* ( |
Rotación en eje Y
| cos β |
0 |
senβ |
| 0 |
1 |
0 |
| -sen β |
0 |
cos β |
|
* |
Rotación en eje X
| 1 |
0 |
0 |
| 0 |
cos α |
-senα |
| 0 |
senα |
cos α |
|
) |
[R] =
| cos β * cos γ |
sen α * sen β * cos γ – cos α * sen γ |
cos α * sen β * cos γ + sen α * sen γ |
| cos β * sen γ |
sen α * sen β * sen γ + cos α * cos γ |
cos α * sen β * sen γ – sen α * cos γ |
| -sen β |
sen α * cos β |
cos α * cos β |
Se corresponde con:
Matriz de rotación
r [0,0] r [0,1] r [0,2]
r [1,0] r [1,1] r [1,2]
r [2,0] r [2,1] r [2,2]
Esta sería entonces la matriz de rotación compacta para los 3 ejes que obtenemos como resultado de la función arGetTransMat junto con el último vector que ya comentamos que era el de la distancia.
Para obtener entonces los ángulos α , β y γ simplemente tenemos que despejar operando sobre los componentes apropiados de la matriz.
(sen α * cos β)/(cos α * cos β) = sen α /cos α = tan α → α = atan (tan α)
Sustituyendo por los componentes de la matriz : α = atan ( r [2,1] / r [2,2])
β = asen -(-sen β) = asen -(r [2,0])
(cos β * sen γ)/(cos β * cos γ) = sen γ /cos γ = tan γ → γ = atan (tan γ)
Sustituyendo por los componentes de la matriz : γ = atan ( r [1,0] / r [0,0])
Estos ángulos estarán expresados en radianes. Para expresarlos en grados sistema más reconocible por nosotros solo tenemos que multiplicar por 180 y dividir por Pi.
El código podría ser algo así:
#define PI 3.14159265358979323846
Ángulo de giro en X → α = (atan (matriz[2][1] / matriz[2][2]) * 180) / PI;
Ángulo de giro en Y → β = (asin (-matriz[2][0]) * 180) / PI;
Ángulo de giro en Z → γ = (atan (matriz[1][0] / matriz[0][0]) * 180) / PI;
Que bonito sería el mundo si esto fuera tan fácil, pero no lo es, y este código después de probarlo un poco se aprecia un error en la estimación de los ángulos con respecto a X y Z esto es debido a que produce Gimball lock. Este error se produce cuando hay giros de 90 con respecto al eje Y (cos 90º = 0) segundo en la multiplicación de matrices y es un error intrínseco a este tipo de uso de los ángulos de euler.
Estoy estudiando distintas opciones para solucionarlo, parece que una buena opción es el uso de quaternion para la representación de la rotación, aunque después para el paso a archivos de movimiento de esqueleto formato bvh necesitaría los ángulos de euler, lo que supondría una nueva conversión.
En principio voy a seguir estudiando opciones, y empezando a tocar archivos bvh, para su mejor compresión de este modo espero encontrar la solución más adecuada al desarrollo de la siguiente fase, la escritura automática de un archivo bvh a partir de las coordenadas obtenidas por las marcas.
Saludos.
0,9999