Discrete time으로 어떤 "물체"의 운동을 표현할 때 흔히 사용되는 방법 ((컴퓨터 공학의 여러 시뮬레이션이나 애니메이션, 게임 류에서 많이 쓰이게 된다)) 이, 시간 자체의 간격 dt에 대해서, "점"의 운동을 표현하기 위한 세 가지 벡터
- 가속도 = a(t) = (어떤 함수)
- 속도 = v(t + dt) = v(t) + dt * a(t)
- 위치 = p(t + dt) = p(t) + dt * v(t)
를 쓰는 방식인데, 이걸로 표현 못하는 아주 기본적인 운동이 있다.
심지어 a(t)의 크기가 상수인 어떤 함수다. 그런데도 연속 시간;continuous time이랑 봤을 때 상당히 다른 움직임을 보이는 운동은 뭐가 있을까 :$ ((dt가 0이 아니라서 생기는 문제이기도 하다))
연속일 때의 적분과, 이산에서의 차분합이 같지 않아서 생기는 문젠데, 가장 극적으로 그런 현상이 드러나는 것 중 하나가 등속 원운동이다.
등속원운동이 특이(?)한게, 속도의 크기(=속력)은 일정한데, 등가속도 운동이라는 것. 그래서 적분식 자체도 상당히 단순(…)하게 나타나게 되는데, 이걸 차분식(difference equation)에서 합을 구해보면 점점 원의 지름(…)이 커지는 현상이 일어난다.
위에서 사용한 dt를 이용한 위치 계산식 자체가, 수치 해석에서 미분 방정식을 풀 때 말하는 Euler method인데, 이 밑에 깔린 가정이,
짧은 시간 dt에서 a(t)가 일정하다
라는 것인데, |a(t)|는 일정하지만 a(t)의 방향 ((a(t)는 벡터다)) 이 계속해서 바뀌고, dt가 0이 아니라서 오차 항이 누적이 된다. 비슷하게, 좀 더 안정적(=stable)한 다른 방법들, Runge-Kutta method 같은 것을 써서 좀 더 늘어나는 반지름이 작게(…)만들 수는 있지만 일정하게 유지되게 만들기는 힘들다 — 다만 운동 자체의 일종의 damping을 둬서 그런 일이 없는 것 처럼 만들 수는 있다.
그런데 위와 같은 방법들을 쓰면 컴퓨터 애니메이션이나 시뮬레이션 쪽 입장에서 봤을 때, dt를 작게하면 시간이 많이 걸리고, 그렇다고 크게 유지하면 시스템 자체가 발산(divergence)해서 시뮬레이션 자체가 망가지는 경우를 겪게된다. 그래서 쓰는 방법이 implicit Euler method (혹은 backward Euler method) 라고 부르는 방법인데, 이건 내재적으로(…) 일종의 damping term이 들어가 있어서 운동을 기술하는데 사용하면 반지름이 줄어든다(………..). 실제 시스템에서 저렇게 모든 여러 요소가 고정되어있는 경우는 적기 때문에, 약간의 damping이 있어도 눈치 채이지 않는 경우가 허다하긴 하다;
다만 damping이 있기 때문에 시뮬레이션 / 애니메이션에서는 좀 더 큰 dt를 써도되고, 시스템 자체가 발산하는 위험도 없어서 더 좋은 방법이긴하다… 다만 컴퓨터 게임에서 쓰기엔 어느 쪽도 편하지는 않다는 것.
일단 Euler method 자체는 dt가 작아야하기도 하고, 하나하나의 계산은 걸리는 시간이 짧아서 좋긴하지만 계산 오차는 알려진 방법 중에 제일 크다. 반대로 implicit Euler method의 경우에는 dt 자체를 너무 크게한 경우에 dead-reckoning 결과와 실제 진행 결과의 차이가 클 수도 있다는 문제 + 한 번의 스텝동안을 구하는 시간이 길다는 문제 Orz
역시 세상에 쉬운 것은 없나보다(…)
크기에 주목하지 않고, 뭐 그런게 어딨어! 라고 생각했는데
실로 원운동…..
|a(t)| 는 상수지 후후후(…)
implicit method를 제대로 구현하는 건 너무 어려워서 약간 쉬운 문제로 바꾼 semi-implicit method를 쓰는데 (explicit method에 비하면 안정적이지만) 발산 잘 하더군요 orz
게임 엔진에서 이런 방식을 쓰기도 한다는군요. (제대로 읽어 보지는 않았는데 발산이 불가능한 시스템이라는데 ..)
http://www.gamasutra.com/resource_guide/20030121/jacobson_pfv.htm
implicit이 SVD를 쓰던가 해야하니 한스텝 오버헤드가 크긴하지 -_-a
하지만 그런 방법을 안 쓰면 스텝 크기가 특정 문턱값을 넘어서면(먼산)
저건 한 번 읽어봐야겠구나…