Porque soy un usuario nuevo, no puedo publicar imágenes, hipervínculos o links, hay una versión completa con imágenes aquí:
El problema que tengo, es que necesito para convertir de XYZ eje fijo de rotación, a Euler rotaciones Z,, a continuación,X′,, a continuación,Z″.
Aquí los matricies:
X = \left(\begin{matrix} 1 & 0 & 0 \\ 0 & \cos(\theta) & -\sin(\theta) \\ 0 & \sin(\theta) & \cos(\theta)\end{matrix}\right)
Y = \left(\begin{matrix} \cos(\phi) & 0 & \sin(\phi) \\ 0 & 1 & 0 \\ -\sin(\phi) & 0 & \cos(\phi)\end{matrix}\right)
Z = \left(\begin{matrix} \cos(\psi) & -\sin(\psi) & 0 \\ \sin(\psi) & \cos(\psi) & 0 \\ 0 & 0 & 1\end{matrix}\right)
Combined, as R_z(\psi) R_y(\phi) R_x(\theta) = R_{xyz}(\theta,\phi\psi); they give:
R_{xyz}: i.imgur.com/8UQM6.jpg
And the Rotation matrix for the Specific convention of Euler angles I want; is this:
Euler:
So my initial plan, was to compare matrix elements, and extract the angles I wanted that way; I came up with this (actual current code at the end):
But this doesn't work under several circumstances. The most obvious being when \cos(\theta)\cos(\phi) = 1; since then \cos(\beta) = 1, and so \sin(\beta) = 0. Where \sin(\beta) is s2
in the code. This happens only when \cos(\theta) and \cos(\phi) = \pm 1.
So right away I can just rule out the possible situations;
When \theta or \phi = 0, 180, 360, 540, \ldots, then \cos(\theta), and \cos(\phi) are \pm 1;
so I only need to do it differently for these cases;
And I ended up with this code:
public static double[] ZXZtoEuler(double θ, double φ, double ψ){
θ *= Math.PI/180.0;
φ *= Math.PI/180.0;
ψ *= Math.PI/180.0;
double α = -1;
double β = -1;
double γ = -1;
double c2 = Math.cos(θ) * Math.cos(φ);
β = Math.acos(r(c2));
if(eq(c2,1) || eq(c2,-1)){
if(eq(Math.cos(θ),1)){
if(eq(Math.cos(φ),1)){
α = 0.0;
γ = ψ;
}else if(eq(Math.cos(φ),-1)){
α = 0.0;
γ = Math.PI - ψ;
}
}else if(eq(Math.cos(θ),-1)){
if(eq(Math.cos(φ),1)){
α = 0.0;
γ = -ψ;
}else if(eq(Math.cos(φ),-1)){
α = 0.0;
γ = ψ + Math.PI;
}
}
}else{
//original way
double s2 = Math.sin(β);
double c3 = ( Math.sin(θ) * Math.cos(φ) )/ s2;
double s1 = ( Math.sin(θ) * Math.sin(ψ) + Math.cos(θ) * Math.sin(φ) * Math.cos(ψ) )/s2;
γ = Math.acos(r(c3));
α = Math.asin(r(s1));
}
α *= 180/Math.PI;
β *= 180/Math.PI;
γ *= 180/Math.PI;
return new double[] {r(α), r(β), r(γ)};
}
Where r
and eq
are just two simple functions;
public static double r(double a){
double prec = 1000000000.0;
return Math.round(a*prec)/prec;
}
static double thresh = 1E-4;
public static boolean eq(double a, double b){
return (Math.abs(a-b) < thresh);
}
eq
is just to compare the numbers for tests, and r
is to prevent floating point errors pushing numbers outside the range of Math.acos
/ Math.asin
and giving me NaN
results;
(i.e. every now and then I'd end up with Math.acos(1.000000000000000004)
or something.)
Which takes into account the 4 cases of having rotations around x and s which leave c2==1
.
But now is where the problem occurs;
Everything I have done above, makes sense to me, but it does not give the correct angles;
Here is some output, in each pair, the first are the \theta, \phi \psi angles, and the second of each pair is the corresponding \alpha, \beta \gamma líneas. Ignorando los errores de redondeo, se parece conseguir algunos de los ángulos de aproximadamente
[0.0, 0.0, 0.0] - correcto! [0.0, 0.0, 0.0]
[0.0, 0.0, 45.0] - correcto! [0.0, 0.0, 45.0]
[0.0, 0.0, 90.0] - correcto! [0.0, 0.0, 90.0]
[0.0, 0.0, 135.0] - correcto! [0.0, 0.0, 135.0]
[0.0, 0.0, 180.0] - correcto [0.0, 0.0, 180.0]
[0.0, 0.0, 225.0] - correcto [0.0, 0.0, 225.0]
[0.0, 0.0, 270.0] - correcto [0.0, 0.0, 270.0]
[0.0, 0.0, 315.0] - correcto [0.0, 0.0, 315.0]
[0.0, 45.0, 0.0] - incorrecto: debe ser [90, 45, -90] [90.0, 44.999982, 90.0]
[0.0, 45.0, 45.0] [45.000018, 44.999982, 90.0]
[0.0, 45.0, 90.0] [0.0, 44.999982, 90.0]
[0.0, 45.0, 135.0] [-45.000018, 44.999982, 90.0]
[0.0, 45.0, 180.0] [-90.0, 44.999982, 90.0]
[0.0, 45.0, 225.0] [-45.000018, 44.999982, 90.0]
[0.0, 45.0, 270.0] [0.0, 44.999982, 90.0]
[0.0, 45.0, 315.0] [45.000018, 44.999982, 90.0]
[0.0, 90.0, 0.0] [90.0, 90.0, 90.0]
[0.0, 90.0, 45.0] [45.000018, 90.0, 90.0]
[0.0, 90.0, 90.0] [0.0, 90.0, 90.0]
[0.0, 90.0, 135.0] [-45.000018, 90.0, 90.0]
[0.0, 90.0, 180.0] [-90.0, 90.0, 90.0]
[0.0, 90.0, 225.0] [-45.000018, 90.0, 90.0]
¿Alguien puede pensar en una solución?
EDIT: no sé si esto ayuda, pero hay algunas otras maneras de mirar en estas rotaciones:
Una forma de rotar alrededor de un eje arbitrario, es reorientar que el eje de la Z Eje y, a continuación, hacer la inversa de la reorientación; se puede aplicar una y otra, para obtener las rotaciones de Euler en términos de la original eje fijo rotaciones;
R_{Z^{\prime\prime} X^{\prime} Z}(\alpha,\beta,\gamma) = R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha)
R_{X^{\prime}}(\beta) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(-\alpha)
so
R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})
R_{Z^{\prime\prime}} = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})R_Z(-\beta)R_Y(-\frac{\pi}{2})R_Z(-\alpha)
And so the whole thing;
R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})R_Z(-\beta)R_Y(-\frac{\pi}{2})R_Z(-\alpha)R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})
Which cancels down;
R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})R_Z(-\beta)\mathbf{R_Y(-\frac{\pi}{2})R_Y(\frac{\pi}{2})}R_Z(\beta)R_Y(-\frac{\pi}{2})
R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)R_Y(\frac{\pi}{2})\mathbf{R_Z(-\beta)R_Z(\beta)}R_Y(-\frac{\pi}{2})
R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)\mathbf{R_Y(\frac{\pi}{2})R_Y(-\frac{\pi}{2})}
R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2})R_Z(\gamma)
Y tenga en cuenta que R_Y(\frac{\pi}{2})R_Z(\beta)R_Y(-\frac{\pi}{2}) = R_X(\beta)
así tenemos R_{Z^{\prime\prime}}(\gamma)R_{X^{\prime}}(\beta)R_Z(\alpha) = R_Z(\alpha)R_X(\beta)R_Z(\gamma)
Ahora no estoy seguro de lo mucho que esto podría ayudar... pero es algo, supongo...