2012-03-19 12 views
5

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: X

Y: Y

Z: Z

kết hợp, như Rz (psi) Ry (phi) Rx (theta) = Rxyz (theta, phi, psi); họ đưa ra:

Rxyz: Rxyz

Và ma trận xoay quy ước cụ thể của Góc Euler tôi muốn; là thế này:

Euler: 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):

Code

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:

Euler Angles Gif

Đó là, xoay quanh Z, sau đó xung quanh mới trục X (X') sau đó xung quanh mới Z '' trục.

+0

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. –

+0

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

Trả lời

1

Tôi chưa hoàn toàn tìm ra điều này, nhưng có một điều tôi đã chú ý: Bạn sử dụng các hàm arccos/arcsin như thể cos/sin là bijective, chỉ lấy nghịch đảo của chúng. Tuy nhiên, khi chụp các arccos, hãy xem xét general solutions đối với các hàm vòng cung. Ví dụ, khi cos y = x, sau đó có hai (tốt, vô cùng nhiều) giải pháp:

  • y = arccos x + 2kPI, nơi k element Z
  • y = 2PI - arccos x + 2kPI, k như trên

Với k=-1, phương trình cuối cùng giảm tới

  • y = -arccos x

Tổng cộng, y = +- arccos x. Về cơ bản, điều này thực tế là cos là đối xứng trục với x=0. Đối số tương tự áp dụng cho arcsin, dẫn đến y = PI - asin x (với k=0 trong giải pháp chung của sin y = x)

Điều này tức là áp dụng cho mã của bạn. Tuyên bố γ = Math.acos(r(c3)); bằng cách nào đó phải tính đến đăng nhập. Tôi đấu tranh với điều này, phải có một tiêu chí để phân loại giải pháp "không chính xác".

+0

Tôi cũng nhận thấy điều này, rắc rối của việc loại bỏ các câu trả lời sai mỗi khi acos/asin được sử dụng mặc dù có vẻ khó khăn - tôi tưởng tượng nó cần chạy một bộ thử nghiệm nhỏ trên 4 câu trả lời có thể có +/- sự mơ hồ sẽ gây ra, và sau đó chọn câu trả lời đã hoạt động. Chạy một bộ thử nghiệm mỗi lần sẽ làm hỏng sự gọn gàng của giải pháp quá, mà tôi không phải là quá nhiều một fan hâm mộ của. – will

+0

Tôi cũng đã đặt câu hỏi tại đây, http://math.stackexchange.com/questions/122162/convert-from-fixed-axis-xyz-rotations-to-euler-zxz-rotations và chỉ quyết định sử dụng ZXZ phép quay thay vì Z''X'Z của euler. Tuy nhiên không phải là lý tưởng. – will

+0

Vì vậy, cuối cùng tôi đã đọc một số về tất cả những điều này nastiness. Tìm hiểu cách thực hiện và trả lời [tại đây] (http://math.stackexchange.com/a/637534/27211). – will