Проблема, которую я имею, заключается в том, что мне нужно преобразовать из вращения неподвижной оси XYZ, к вращениям Эйлера вокруг Z, затем X ', затем Z' '.Преобразование из вращения Euler ZXZ, вращения неподвижной оси XYZ
Вот соответствующие матрицы:
X:
Y:
Z:
Совмещенный, а Rz (фунтов на квадратный дюйм) Ry (фи) Rx (тета) = Rxyz (theta, phi, psi); они дают:
Rxyz:
и матрица вращения для конкретной конвенции углов Эйлера я хочу; это:
Эйлер:
Так что мой первоначальный план был для сравнения матричных элементов, и извлекать углы я хотел таким образом; Я пришел с этим (фактическим текущим кодом в конце):
Но это не работает в нескольких случаях. Наиболее очевидное существо, когда Cos (theta) Cos (phi) == 1; с тех пор Cos (beta) = 1, и поэтому Sin [beta] = 0. Если Sin (бета) является s2 в коде. Это происходит только тогда, когда Cos (theta) и cos (phi) = +/- 1.
Так что я сразу могу исключить возможные ситуации;
Когда тета или phi = 0, 180, 360, 540, ..., затем Cos (тета) и Cos (phi) равны +/- 1;
поэтому мне нужно только сделать это по-разному для этих случаев;
И я закончил с этим кодом:
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(γ)};
}
Где г и эк лишь две простые функции;
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);
}
эк просто сравнить цифры для испытаний, а г предотвратить с плавающей запятой ошибки маневрового числа вне диапазона Math.acos/Math.asin и давая мне результаты NaN;
(т.е. каждый сейчас и потом я бы в конечном итоге с Math.acos (1.000000000000000004) или что-то.)
который учитывает 4 случая наличия вращения вокруг х и у, которые оставляют с2 == 1 ,
Но теперь возникает проблема;
Все, что я сделал выше, имеет смысл для меня, но оно не дает правильных углов;
Вот несколько выходных данных в каждой паре, первые - тета phi psi, а вторая из каждой пары - соответствующие альфа-бета-гамма-линии.Не обращая внимания на ошибки округления, это, кажется, получить некоторые из углов от примерно
[0.0, 0.0, 0.0] - correct!
[0.0, 0.0, 0.0]
[0.0, 0.0, 45.0] - correct!
[0.0, 0.0, 45.0]
[0.0, 0.0, 90.0] - correct!
[0.0, 0.0, 90.0]
[0.0, 0.0, 135.0] - correct!
[0.0, 0.0, 135.0]
[0.0, 0.0, 180.0] - correct
[0.0, 0.0, 180.0]
[0.0, 0.0, 225.0] - correct
[0.0, 0.0, 225.0]
[0.0, 0.0, 270.0] - correct
[0.0, 0.0, 270.0]
[0.0, 0.0, 315.0] - correct
[0.0, 0.0, 315.0]
[0.0, 45.0, 0.0] - incorrect: should be [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]
я думаю, что это связано с тем, как Math.acos и Math.asin работа, Может кто-нибудь придумать решение?
EDIT: math.asin и math.acos возвращают значения между -pi/2 и pi/2 и 0 и pi соответственно. Это не двусмысленно, поэтому я не думаю, что проблема здесь. Похоже, что я, возможно, математика неправильно где-то, но я не могу видеть дыру в моем рассуждении ...
EDIT2: Для тех, кто, как не знает, как работать Эйлер вращение, это так:
то есть, вращается вокруг Z, а затем вокруг новых Х осей (Х»), а затем вокруг нового Z '' оси.
У углов Эйлера есть двусмысленности в 90-е годы - я думаю, 0/45/0 эквивалентен 90/45/-90, если я правильно понимаю ваши оси. –
углы Эйлера вращаются вокруг Z, тогда X ', затем Z' ', поэтому 0/45/0 составляет 45 относительно оси X, а 90/45/-90 вращает оси так, что ось X' такая же, как ось Y. 90/45/-90 - это поворот 45 по сравнению с Y. – will