bitterharvest’s diary

A Bitter Harvestは小説の題名。作者は豪州のPeter Yeldham。苦闘の末に勝ちえた偏見からの解放は命との引換になったという悲しい物語

ボールの衝突をFunctional Reactive Programmingで表現する(3)

4.追突するボールをプログラミングするために準備

先の記事で、一直線上を走る二つのボールでの追突後の速度を求めた。即ち、二つのボールの質量をそれぞれ\(m_1\),\(m_2\)、追突前の速度をそれぞれ\(v_1\), \(v_1\)とすると、追突後の速度はそれぞれ
\(v'_1 = u'_1 + V_0 = -u_1 + V_0 = -v_1 + 2 \times V_0 = \frac{(m_1 - m_2) \times v_1+2 \times m_2 \times v_2}{m_1+m_2}\),
\( v_2' = \frac{(m_2 - m_1) \times v_2+ 2 \times m_1 \times v_1}{m_1+m_2}\)
となる。

ここではプログラムを簡単にするために、両方の質量は同じとする。そうすると、都合のよいことに、\(v'_1 =v_2\), \(v'_2 =v_1\)となる。即ち、衝突後には、相手の速度が自分の速度となり、自分の速度が空いての速度となる。従って、速度がお互いに入れ替わる。

ところで、プログラムではある程度の時間間隔でボールの状態を計算するので、二つのボールが衝突する瞬間に計算することはまれで、計算する時間の間に衝突が殆どの場合生じる。これを図で表すと次のようになる。
f:id:bitterharvest:20150930112725p:plain

今、プログラムは、微小な時間間隔\(dt\)でボールの位置を計算していたとする。一番上のイラストが、衝突直前のボールの様子である。この後、\(dt\)が経ち、再びボールの位置を計算したとする。この時、衝突を考慮に入れずにそのまま計算すると、真ん中のイラストのように二つのボールは一部で重なった状態になる。しかし、実際には衝突が生じるので、一番下のイラストの状態を得る必要がある

衝突後のそれぞれのボールの位置を求めてみる。すべては、ボールの中心を結んだ\(x\)軸上だけで考えることができるので、以下は、\(x\)座標だけで考える。

衝突後に食い込んだ状態(真ん中のイラスト)での先行するボールと後続するボールの中心の位置を\(x'_1\), \(x'_2\)とすると、重なっているところの(\(x\)軸上での)長さは\(r_1+r_2-(x'_1-x'_2)\)である。また、衝突後に経過した時間(からこのイラストの状態になるまでの時間)を\(dt'\)とすると、ボールの相対速度\(v_2-v_1\)にこの時間をかけたもの\((v_2-v_1) \times dt'\)が、重なっている長さ\(r_1+r_2-(x'_1-x'_2)\)と等しくなる。

ところで、ボールが衝突したことを考慮する(一番下のイラスト)。先行するボールの速度が\(v_2\)となり、後続する行するボールの速度が\(v_1\)となるため、ボールが離れる距離はこの相対速度に衝突後の時間をかけたもの、即ち、\((v_2-v_1) \times dt'\)となる。これは先の重なった部分と同じ長さであり、衝突後には、二つのボールは重なっていた部分の長さだけ離れることになる。

先行するボールの正しい位置は次のようになる。衝突を考慮しなかったために、食い込んでしまった部分の長さは\(v_1 \times dt\)である。また、衝突後に実際に進んだ長さは、速度が入れ替わるので、\(v_2 \times dt\)である。前者をキャンセルし後者を追加すればよいので、衝突を考慮にしないで得た(真ん中のイラストの)ボールの中心\(x'_1\)に\((v_2-v_1) \times dt'\)だけ加えれば正しい位置を得ることができる。\((v_2-v_1) \times dt'\)が\(r_1+r_2-(x'_1-x'_2)\)であったことを用いれば、衝突後の正しい位置は、\(x'_2+(r_1+r_2)\)となる。

後続するボールについても同じように求めることができ、\(x'_1-(r_1+r_2)\)となる。

いま、右方向に進んでいる二つのボールの追突を考えたが、左側に進んでいる場合でも、また、正面から衝突する場合でも、この式は成り立つ。興味のある人は下の図を参考に解くとよい。
f:id:bitterharvest:20150930133342p:plain