2012-12-20 2 views
0

개체 회전에 대한 간단한 쿼터니언 구현이 있습니다. 같은 축 정렬 벡터 (즉, X, Y 또는 Z 축을 따라)에 대해 회전을 나타내는 두 쿼터니언을 만들면 결과는 크기의 합계에 의한 단일 회전과 같습니다 (즉, PI/2 회전 후 PI/2는 다시 PI로 회전하는 것과 같습니다). 좋습니다.쿼터니언 연결은 축 정렬시에만 작동합니다.

회전 축이 축 정렬되지 않은 경우 연결이 예상대로 (PI/2로 회전하면 PI/2가 다시 이 아니며이 PI로 회전하는 것과 동일 함) 분기됩니다. 그 좋지 않다.

며칠 동안 내 코드를 보면서, 나는 틀린 것을 보지 못했기 때문에 지금 물어 보도록하겠습니다. 나는 쿼터니언이 어떻게 작동하는지 근본적으로 오해하고 있습니까? 솔직히 저는 쿼터니언을 완전히 이해하지 못하기 때문에 쿼터니언에 대해 축 각 회전의 관점에서 추론하고 있습니다.

그렇지 않으면 내 코드를 살펴볼 수 있습니까? :-) 방금 Java로 작성된 모든 것을 Android 용 GitHub로 푸시했습니다. https://github.com/wtracy/quaternions Quaternions 디렉토리 아래에는 Eclipse 프로젝트가 있습니다. (이클립스가 무엇이든 읽을 필요는 없지만 편리하다.) 쿼터니언 클래스는 src/폴더 아래있다. 테스트/폴더에는 JUnit 테스트와 Quaternion 클래스를 실행하는 데 필요한 클래스의 스텁이 있습니다.

나는 코드와 테스트를 쉽게 수행 할 수 있도록 최선을 다했습니다. 내 코드에서 버그를 찾기 위해 인터넷에 질문하는 바보 같은 생각이 들지만, 나는 아이디어가 깨끗합니다. :-P

답변

3

쿼터니온 곱셈에 기호 오류가 있습니다. 하지 것이다 - 당신은 xz에 대한 방정식의 마이너스 잘못된 용어를

(w1 + x1*i + y1*j + z1*k)*(w2 + x2*i + y2*j + z2*k) 
= w1*w2 - x1*x2 - y1*y2 - z1*z2 
+ (w1*x2 + x1*w2 + y1*z2 - z1*y2)*i 
+ (w1*y2 - x1*z2 + y1*w2 + z1*x2)*j 
+ (w1*z2 + x1*y2 - y1*x2 + z1*w2)*k 

i*j = k j*i = -k 
j*k = i k*j = -i 
k*i = j i*k = -j 

이후

public Quaternion times(Quaternion q2) { 
    Quaternion q1 = this; 
    float w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; 
    float x = q1.x*q2.w + q1.w*q2.x + q1.z*q2.y - q1.y*q2.z; 
    float y = q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x; 
    float z = q1.w*q2.z - q2.x*q2.y + q1.y*q2.x + q1.z*q2.w; 
    return new Quaternion(w, x, y, z); 
} 

기입이 제품은이다 두 축이 같은 경우 차이점, 하나도 쓸 수 있기 때문에 (속기로)

(r + v)*(s + w) = r*s - <v|w> + r*w + s*v + v×w 

v×w = 0은 동일 직선 벡터이지만 축이 다르면 표시됩니다.

또한, z의 방정식,

float z = q1.w*q2.z - q2.x*q2.y + q1.y*q2.x + q1.z*q2.w; 
          ^^^^^^^^^ 

에 한 번 두 요인 q2를 사용, 오타가 있습니다.

이 있어야

public Quaternion times(Quaternion q2) { 
    Quaternion q1 = this; 
    float w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; 
    float x = q1.x*q2.w + q1.w*q2.x - q1.z*q2.y + q1.y*q2.z; 
    float y = q1.w*q2.y - q1.x*q2.z + q1.y*q2.w + q1.z*q2.x; 
    float z = q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w; 
    return new Quaternion(w, x, y, z); 
} 
+0

올바른 트랙에 나를 붙여 주셔서 감사합니다. 나는 여전히 w에 이상한 값을 얻고 있지만, 적어도 나는 올바른 길을 가고 있다는 것을 알고있다. – wtracy

0

즉시 회전축이 축 배향 아니므로, 그 연접은 기대 (/ 2 다음 PI/2를 다시 아니다 PI 의해 회전 발산 PI로 회전하는 것과 동일). 그 좋지 않다.

수학 능력을 확보 한 후에도 여전히 그렇지 않을 수 있습니다. 일반적으로 3 차원 공간에서의 회전은 교환 가능하지 않습니다.회전 A와 회전 B를 수행하는 경우 일반적으로 처음으로 회전 B를 수행하고 회전 A를 수행 한 결과와 다른 방향으로 끝납니다.