2015-03-19 17 views
5

我有一個程序,其中的圓圈可以互相反彈。我跟着從這裏的指示用於旋轉向量以及基於所述碰撞角度縮放幅度:http://www.vobarian.com/collisions/2dcollisions2.pdf我無法找到python中的此圓圈反彈計算有什麼問題

我在python寫這個代碼(0索引指示的x座標):

norm_vect = [(object2.pos[0] - object1.pos[0]), (object2.pos[1] - object1.pos[1])] 
unit = sqrt((norm_vect[0]**2) + (norm_vect[1]**2)) 
unit_vect = [float(norm_vect[0])/unit, float(norm_vect[1]) /unit] 
tan_vect = [-unit_vect[1], unit_vect[0]] 
vel1 = object1.vel 
vel2 = object2.vel 
vel1_norm = vel1[0] * unit_vect[0] + vel1[1] * unit_vect[1] 
vel1_tan = vel1[0] * tan_vect[0] + vel1[1] * tan_vect[1] 
vel2_norm = vel2[0] * unit_vect[0] + vel2[1] * unit_vect[1] 
vel2_tan = vel2[0] * tan_vect[0] + vel2[1] * tan_vect[1] 
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) + 2 * object2.mass * vel2_norm)/(object1.mass + object2.mass) 
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) + 2 * object1.mass * vel1_norm)/(object1.mass + object2.mass) 
new_norm_vect1 = [new_vel1_norm * float(unit_vect[0]), new_vel1_norm * float(unit_vect[1])] 
new_norm_vect2 = [new_vel2_norm * float(unit_vect[0]), new_vel2_norm * float(unit_vect[1])] 
new_tan_vect1 = [new_vel1_norm * float(tan_vect[0]), new_vel1_norm * float(tan_vect[1])] 
new_tan_vect2 = [new_vel2_norm * float(tan_vect[0]), new_vel2_norm * float(tan_vect[1])] 

# Now update the object's velocity 
object1.vel = [new_norm_vect1[0] + new_tan_vect1[0], + new_norm_vect1[1] + new_tan_vect1[1]] 
object2.vel = [new_norm_vect2[0] + new_tan_vect2[0], + new_norm_vect2[1] + new_tan_vect2[1]] 

問題有時它有效,但不適合其他時間。誰能告訴我爲什麼?看起來好像球是以正確的角度相撞,然後他們的出口軌跡交換了什麼。我在codekulptor瀏覽器中寫道:http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_2.py

任何人都可以指出我出錯的地方嗎?

編輯:它可能是我處理碰撞的方式嗎?這裏是步驟:

1) Draw the balls on the screen 
    2) Create set of unique pairs of collidable objects 
    3) For each ball, move the ball's position 1 frame forward according to the velocity: 
     ->1) Check to see if the ball is hitting a wall 
     ->2) For each pairset, if the ball in question is a member of the pair: 
      -->1) If distance between centers is less than sum of radii: 
        -->1) Calculate rebound trajectories 
        ---2) Find N such that position + rebound trajectory *N is out of collision zone 
+1

你最後一行的object2.2是什麼? – 2015-03-19 04:04:16

+0

一個錯字:)我有實際的代碼有點不同於與我的類互動,所以我不得不在這裏重寫一些。錯過了那一個! – Apc0243 2015-03-19 04:40:24

+0

如果你只是想解決這個問題,不關心從第一原理解決它,那麼你可以使用物理引擎來代替。 – 2015-03-19 04:47:39

回答

2

在線模擬真的很酷!我沒有詳細研究完整的代碼,只是您在問題中發佈的片段。從快速瀏覽中,您可以正確計算切向和法向單位矢量,舊法向速度和切向速度,以及新的法向速度。但在此之後,你似乎迷失了一下。正如關於碰撞的文件中所解釋的那樣,在碰撞期間切向速度不會改變,所以不需要計算new_tan_vect1/2。我也不明白你爲什麼計算new_norm_vect1,法向量在碰撞期間不會改變。

其他一些小備註:

  • 爲什麼要使用float()在你的代碼?這通常是不需要的。如果原因是爲了得到正確的除法結果,那麼您應該在代碼頂部添加一個from __future__ import division,因爲您似乎在使用Python2。有關更多信息,請參閱this old question

  • 你所說的norm_vect實際上是非歸一化的法線向量,而你所謂的unit_vect實際上是歸一化的法向量單位向量。我只會調用norm_vect,以使正常和切線之間的區別更加清晰。單位矢量是長度爲1的任何矢量,因此使用該矢量對於法向矢量有點誤導。

  • 如果你打算做更多這樣的模擬,你應該考慮學習numpy。這允許您編寫矢量化計算,而不是手動編寫所有xy的等式。例如。 norm_vect = pos2 - pos1; norm_vect /= np.linalg.norm(norm_vect)object1.vel = norm_vect * new_vel1_norm + tang_vect * vel1_tang

我會寫你的代碼段應該或多或少像這樣(未測試的代碼):

from __future__ import division # move this to the top of your program 

# calculate normal and tangential unit vectors 
norm_vect = [(object2.pos[0] - object1.pos[0]), 
      (object2.pos[1] - object1.pos[1])] # stil un-normalized! 
norm_length = sqrt((norm_vect[0]**2) + (norm_vect[1]**2)) 
norm_vect = [norm_vect[0]/norm_length, 
      norm_vect[1]/norm_length] # do normalization 
tang_vect = [-norm_vect[1], norm_vect[0]] # rotate norm_vect by 90 degrees 

# normal and tangential velocities before collision 
vel1 = object1.vel 
vel2 = object2.vel 
vel1_norm = vel1[0] * norm_vect[0] + vel1[1] * norm_vect[1] 
vel1_tang = vel1[0] * tang_vect[0] + vel1[1] * tang_vect[1] 
vel2_norm = vel2[0] * norm_vect[0] + vel2[1] * norm_vect[1] 
vel2_tang = vel2[0] * tang_vect[0] + vel2[1] * tang_vect[1] 

# calculate velocities after collision 
new_vel1_norm = (vel1_norm * (object1.mass - object2.mass) 
    + 2 * object2.mass * vel2_norm)/(object1.mass + object2.mass) 
new_vel2_norm = (vel2_norm * (object2.mass - object1.mass) 
    + 2 * object1.mass * vel1_norm)/(object1.mass + object2.mass) 
# no need to calculate new_vel_tang, since it does not change 

# Now update the object's velocity 
object1.vel = [norm_vect[0] * new_vel1_norm + tang_vect[0] * vel1_tang, 
       norm_vect[1] * new_vel1_norm + tang_vect[1] * vel1_tang] 
object2.vel = [norm_vect[0] * new_vel2_norm + tang_vect[0] * vel2_tang, 
       norm_vect[1] * new_vel2_norm + tang_vect[1] * vel2_tang] 

我改名一些變量,使之更加清晰。

+0

現在我覺得我在Python中搞了一些東西,因爲速度會改變,但由於某種原因,全局類的狀態並沒有改變。請看這裏:http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_3.py難道是因爲我無法從'__future__'導入,因爲codeskulptor是一個非常有限的Python實現,所以人們可以學習交互的基礎知識simpleGUI模塊由Coursera Class的教授和codeskulptor創建) – Apc0243 2015-03-19 18:30:41

+0

http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_4.py < - 一個更清潔,但問題仍然存在,我不知道爲什麼。我認爲這是因爲我的collision()函數是由類方法調用的。我不確定如何在班級內部執行成對碰撞檢查,這就是爲什麼我把它拉出來的原因 – Apc0243 2015-03-19 18:44:18

+1

看着你在碰撞函數中打印的速度,看起來當一個輕球碰到一個重球時,速度正在翻轉,但是之後直接翻轉到相反的方向,所以沒有發生任何事情。錯誤發生在你的'match_objects'函數中,你添加每一對兩次,一次向前,一次向後。然後每次碰撞檢測兩次,從object1和object2中,這兩個相互抵消。這似乎工作(球有時會卡住):http://www.codeskulptor.org/#user39_sV5TmqJSlAYGeOG.py – 2015-03-19 20:29:50