Vấn đề tôi có, là tôi cần chuyển đổi từ phép quay trục cố định XYZ, sang phép xoay Euler về Z, rồi X ', rồi Z' '.Chuyển đổi từ xoay ZXZ Euler, để xoay trục XYZ cố định
Dưới đây là các ma trận có liên quan:
X:
Y:
Z:
kết hợp, như Rz (psi) Ry (phi) Rx (theta) = Rxyz (theta, phi, psi); họ đưa ra:
Rxyz:
Và ma trận xoay quy ước cụ thể của Góc Euler tôi muốn; là thế này:
Euler:
Vì vậy, kế hoạch ban đầu của tôi, là để so sánh các yếu tố ma trận, và trích xuất các góc độ tôi muốn như vậy; Tôi đến với điều này (mã hiện tại thực tế ở cuối):
Nhưng điều này không làm việc dưới nhiều hoàn cảnh. Sự rõ ràng nhất khi Cos (theta) Cos (phi) == 1; kể từ đó Cos (beta) = 1, và vì vậy Sin [beta] = 0. Trong đó Sin (beta) là s2 trong mã. Điều này chỉ xảy ra khi Cos (theta) và cos (phi) = +/- 1.
Vì vậy, ngay lập tức tôi chỉ có thể loại trừ các tình huống có thể xảy ra;
Khi theta hoặc phi = 0, 180, 360, 540, ..., sau đó là Cos (theta) và Cos (phi) là +/- 1;
vì vậy tôi chỉ cần thực hiện điều đó một cách khác nhau đối với những trường hợp này;
Và tôi đã kết thúc với mã này:
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(γ)};
}
đâu r và eq chỉ là hai chức năng đơn giản;
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 chỉ để so sánh các số cho thử nghiệm và r là để ngăn các lỗi dấu phẩy động đẩy số ngoài phạm vi Math.acos/Math.asin và cho tôi kết quả NaN;
(tức là tất cả bây giờ và sau đó tôi muốn kết thúc với Math.acos (1,000000000000000004) hoặc một cái gì đó.)
nào sẽ đưa vào tài khoản trong 4 trường hợp có phép quay xung quanh x và y mà rời c2 == 1 .
Nhưng bây giờ là nơi xảy ra sự cố;
Mọi thứ tôi đã làm ở trên, có ý nghĩa với tôi, nhưng nó không đưa ra các góc chính xác;
Đây là một số đầu ra, trong mỗi cặp, đầu tiên là các góc psi phi psi, và thứ hai của mỗi cặp là các dòng gamma alpha beta tương ứng.Bỏ qua những lỗi làm tròn, nó dường như nhận được một số góc độ tắt khoảng
[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]
tôi nghĩ rằng đó là do cách Math.acos và Math.asin công việc, bất cứ ai có thể nghĩ ra một giải pháp?
EDIT: math.asin và math.acos trả về giá trị giữa -pi/2 và pi/2 và 0 và pi tương ứng. Đây không phải là mơ hồ, vì vậy tôi không nghĩ rằng vấn đề là ở đây. Nó có vẻ như tôi có thể có các toán sai ở đâu đó, nhưng tôi không thể nhìn thấy một lỗ trong lập luận của tôi ...
EDIT2: Để ai như thế nào không biết làm thế nào Euler quay làm việc, nó như thế này:
Đó là, xoay quanh Z, sau đó xung quanh mới trục X (X') sau đó xung quanh mới Z '' trục.
Góc Euler có sự mơ hồ ở độ tuổi 90 - Tôi nghĩ 0/45/0 tương đương với 90/45/-90 nếu tôi hiểu chính xác trục của bạn. –
Góc Euler xoay quanh Z, rồi X ', rồi Z' ', vì vậy 0/45/0 là 45 về trục X, trong khi 90/45/-90 xoay trục sao cho trục X giống như trục Y. 90/45/-90 là vòng quay 45 về Y. – will