몇 가지 일이있을 수 있습니다. 당신은 그 쿼터니온을 다시 정규화하는 것에 대해서는 언급하지 않았습니다. 네가 그렇게하지 않으면 나쁜 일은 분명히 일어날 것이다. 델타 - 쿼터니온 구성 요소를 원래의 쿼터니언에 추가하기 전에 dt
이 경과 한 시간만큼 곱하면된다는 말도 아닙니다. 각속도가 초당 라디안인데 단 몇 초 만에 앞으로 나아갈 경우 지나치게 멀리 나아갑니다. 그러나, 그렇다고하더라도, 당신은 이산적인 양의 시간을 밟아서 극소수 인 것처럼하려고 시도하기 때문에, 특히 당신의 타임 스텝이나 각속도가 큰 경우, 이상한 일이 일어날 것입니다.
물리 엔진 ODE는 몸체의 회전을 각속도에서 미소 한 단계를 취하는 것처럼 업데이트하거나 유한 크기의 단계를 사용하여 업데이트하는 옵션을 제공합니다. 유한 단계는 훨씬 정확하지만 일부 삼각 함수가 필요합니다. 함수와 너무 조금 느립니다. 관련 ODE 소스 코드는 here, lines 300-321이며 델타 - 쿼터니언 코드는 here, line 310입니다. 이 분할 0으로 문제를 방지 할 수 있으며 여전히 매우 정확
if (fabs(x) < 1.0e-4) return (1.0) - x*x*(0.166666666666666666667);
else return sin(x)/x;
: sinc(x)
가
float wMag = sqrt(wx*wx + wy*wy + wz*wz);
float theta = 0.5f*wMag*dt;
q[0] = cos(theta); // Scalar component
float s = sinc(theta)*0.5f*dt;
q[1] = wx * s;
q[2] = wy * s;
q[3] = wz * s;
.
쿼터니언 q
은 신체의 방향의 기존 쿼터니언 표현에 미리 곱해진다. 그런 다음 다시 정규화하십시오. -
편집이 공식에서 오는 경우 :
초기 사원 수 q0
시간의 dt
금액에 대한 각속도 w
으로 회전 한 후 결과 최종 쿼터니언 q1
을 고려하십시오. 여기서 우리가하는 것은 각속도 벡터를 쿼터니언으로 바꾸고 그 쿼터니온에 의해 첫 번째 방향을 회전시키는 것입니다. 쿼터니온과 각속도는 축각 표현의 변형입니다. 인 몸체는 단위 축 주위로 theta
에 의해 정준 방향에서 으로 회전되고 방향은 다음과 같은 쿼터니언 표현을 갖습니다. q0 = [cos(theta/2) sin(theta/2)x sin(theta/2)y sin(theta/2)z]
. 단위 축 [x,y,z]
주위에 인 몸체theta/s
은 각속도가 w=[theta*x theta*y theta*z]
입니다. 따라서 dt
초 동안 회전이 얼마나 발생할지 결정하려면 먼저 각속도 크기 인 theta/s = sqrt(w[0]^2 + w[1]^2 + w[2]^2)
을 추출합니다. 그런 다음 우리는 dt
을 곱하여 실제 각도를 찾습니다 (그리고 이것을 4 원으로 바꾸는 데 편의를 위해 동시에 2로 나눕니다).[x y z]
축을 정규화해야하므로 theta
으로 나눕니다. 그것이 sinc(theta)
부분의 출처입니다. (theta
에는 크기가 작기 때문에 0.5*dt
이 추가로 있으므로이 값을 배수합니다.) sinc(x)
함수는 숫자가 안정되고 정확하기 때문에 x
이 작을 때 함수의 테일러 급수 근사법을 사용하고 있습니다. 이 편리한 기능을 사용할 수있는 능력은 실제 크기 인 wMag
으로 나누지 않은 이유입니다. 매우 빠르게 회전하지 않는 물체는 매우 작은 각속도를 갖습니다. 우리가 이것을 매우 일반적으로 기대하기 때문에 안정적인 솔루션이 필요합니다. 우리가 끝내는 것은 회전의 단일 단계 시간 단계 dt
을 나타내는 쿼터니언입니다. 벡터는 속도와 방법에 증가 회전 상태를 나타내는 quaterniom (즉, 회전 운동의 미분 방정식을 통합) 각 dphi
(작은 벡터 증가 정확도 사이에 아주 좋은 트레이드 오프와 metod이 있습니다
예상되는 결과를 얻지 못했다고합니다. 뭐가 잘못 될 것 같니? – JCooper
추적에 모델을 사용하고 있는데 안정적이지 않습니다. –
"w"벡터에 "델타 시간"이 이미 곱해져 있습니까? 이 방정식은 "델타 시간"이 작은 경우에만 제대로 작동합니다. – minorlogic