He escrito un código para convertir un cuaternión en ángulos de Euler, suponiendo una secuencia de Euler ZYX. Siguiendo las convenciones detalladas en este documento https://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/19770019231.pdf
m11=qin(:,1).^2+qin(:,2).^2-qin(:,3).^2-qin(:,4).^2;
m12=2.*(qin(:,2).*qin(:,3)-qin(:,1).*qin(:,4));
m13=2.*(qin(:,2).*qin(:,4)+qin(:,1).*qin(:,3));
m21=2.*(qin(:,2).*qin(:,3)+qin(:,1).*qin(:,4));
m22=qin(:,1).^2-qin(:,2).^2+qin(:,3).^2-qin(:,4).^2;
m31=2.*(qin(:,2).*qin(:,4)-qin(:,1).*qin(:,3));
m32=2.*(qin(:,3).*qin(:,4)+qin(:,1).*qin(:,2));
m33=qin(:,1).^2-qin(:,2).^2-qin(:,3).^2+qin(:,4).^2;
rz=atan2(m21,m11);
ry=zeros(length(m31),1);
idx=m31.^2<1;
ry(idx)=atan(-m31(idx)./sqrt(1-m31(idx).^2));
ry(~idx)=-atan2(m31(~idx),0);
rx=atan(m32./m33);
Sin embargo, cuando implemento el código anterior en un microprocesador el ángulo de balanceo (rx) se vuelve erróneo a ~ 85 grados. Creo que este es un problema común conocido como 'gimbal lock', que resulta de las singularidades debido a una rotación en el tono que está cerca de 90 grados (creo que esto ocurre cerca de 85 grados debido a los valores de precisión única utilizados por el micro).
He estado investigando cómo se suele tratar el problema y he encontrado el siguiente documento https://pdfs.semanticscholar.org/6681/37fa4b875d890f446e689eea1e334bcf6bf6.pdf . Este documento defiende las ventajas de esta metodología cuando se utilizan operaciones de precisión única, frente a otras técnicas de tratamiento del problema, como la metodología detallada por Ken Shoemake. El autor maneja la conversión cerca de las singularidades calculando los dos primeros ángulos y luego calculando el tercer ángulo usando los otros ángulos.
He intentado aplicar la misma metodología para extraer una secuencia ZYX Euler.
Matriz de rotación Z:
[c3s30−s3c30001]
Matriz de rotación Y:
[c20−s2010s20c2]
Multiplicando los dos juntos obtengo
[c3c2s3−s2c3−s3c2c3s2s2s20c2]
Tomando la transposición de lo anterior obtengo:
[c3c2−s3c2s2s3c30−s2c3s2s2c2]
Multiplicando esto con una matriz de rotación arbitraria obtengo:
[c3c2m11−s3c2m21+s2m31c3c2m01−s3c2m22+s2m32c3c2m13−s3c2m23+s2m31s3m11+c3m21s3m12+c3m22s3m13+c3m22−s2c3m11+s2s2m21+c2m31−s2c3m12+s2s2m22+c2m32−s2c3m13+s2s2m23+c2m33]
La rotación final es en este caso sobre el eje X:
Matriz de rotación X:
[1000c1s10−s1c1]
De esto obtengo el siguiente código:
rz=atan2(m21,m11);
c2=sqrt((m11.^2)+(m21.^2));
ry=atan2(-m31,c2);
s3=sin(rz);
c3=cos(rz);
rx=atan2(s3.*m13+c3.*m12, c3.*m22+s3.*m23);
Por desgracia, esto no parece dar el mismo resultado que el primer conjunto de ecuaciones. ¿Podría alguien indicarme mi error, o un método alternativo mejor para hacer esto? ¿Hay algún problema con este método? Idealmente, se agradecerían algunos ejemplos de código.