2015-03-19 12 views
5

Tôi có một chương trình mà các vòng kết nối có thể bị trả lại thành một vòng kết nối khác. Tôi làm theo các hướng dẫn từ đây để quay các vectơ và rộng độ lớn dựa trên góc độ va chạm: http://www.vobarian.com/collisions/2dcollisions2.pdfTôi không thể tìm thấy điều gì sai với tính toán trả về vòng kết nối này trong python

tôi đã viết mã này trong python (chỉ số 0 chỉ ra tọa độ 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]] 

Vấn đề là nó hoạt động đôi khi, nhưng không phải lúc khác. bất cứ ai đó có thể trả lời tôi tại sao? Có vẻ như nếu các quả bóng va chạm ở góc bên phải thì quỹ đạo thoát của chúng hoán đổi hay gì đó. Tôi đã viết điều này trong trình duyệt codeskulptor: http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_2.py

Có ai có thể chỉ ra nơi tôi đã đi sai?

EDIT: Có thể đó là cách tôi xử lý xung đột không? Đây là các bước:

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

đối tượng2.2 trên dòng cuối cùng của bạn ở đó là gì? –

+0

một lỗi đánh máy :) Tôi có mã thực tế khác một chút để tương tác với các lớp của tôi vì vậy tôi phải viết lại một số ở đây. Bỏ lỡ cái đó! – Apc0243

+0

Nếu bạn chỉ muốn giải quyết vấn đề và không quan tâm đến việc giải quyết nó từ nguyên tắc đầu tiên, sau đó bạn chỉ có thể sử dụng một công cụ vật lý để thay thế. –

Trả lời

2

Mô phỏng trực tuyến thực sự tuyệt vời! Tôi đã không nghiên cứu chi tiết mã hoàn chỉnh của bạn, chỉ là đoạn trích bạn đã đăng trong câu hỏi của mình. Từ một cái nhìn nhanh chóng, bạn tính toán một cách chính xác các vectơ đơn vị tiếp tuyến và bình thường, vận tốc bình thường và tiếp tuyến cũ, và vận tốc bình thường mới. Nhưng sau đó, bạn dường như bị lạc một chút. Như đã giải thích trong tài liệu về va chạm, vận tốc tiếp tuyến không thay đổi trong khi va chạm, do đó không cần tính toán new_tan_vect1/2. Tôi cũng không hiểu tại sao bạn tính toán new_norm_vect1, vectơ bình thường không thay đổi trong khi va chạm.

Một số nhận xét nhỏ khác:

  • tại sao bạn sử dụng float() trên tất cả các mã của bạn? Điều này là bình thường không cần thiết. Nếu lý do cho điều này là để có được kết quả chính xác cho phân chia, bạn thực sự cần thêm một from __future__ import division ở đầu mã của bạn, vì bạn dường như đang sử dụng Python2. Xem this old question để biết thêm thông tin.

  • Những gì bạn gọi là norm_vect thực sự là véc tơ bình thường chưa được chuẩn hóa và những gì bạn gọi là unit_vect thực sự là vector đơn vị chuẩn hóa bình thường. Tôi sẽ chỉ gọi cả hai norm_vect, để làm cho sự khác biệt giữa bình thường và tiếp tuyến rõ ràng hơn. Một vector đơn vị là bất kỳ vectơ nào có độ dài 1, do đó việc sử dụng vectơ cho vectơ thông thường là một chút sai lệch.

  • Nếu bạn định làm nhiều loại mô phỏng hơn, bạn nên cân nhắc tìm hiểu về numpy. Điều này cho phép bạn viết các phép tính được vector hóa, thay vì viết ra tất cả các phương trình cho xy bằng tay. Ví dụ. norm_vect = pos2 - pos1; norm_vect /= np.linalg.norm(norm_vect) hoặc object1.vel = norm_vect * new_vel1_norm + tang_vect * vel1_tang.

Tôi sẽ viết đoạn mã của bạn nên ít nhiều như thế này (mã chưa được kiểm tra):

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] 

tôi đổi tên một số biến để làm cho nó rõ ràng hơn.

+0

Bây giờ tôi cảm thấy như tôi đang vặn vẹo thứ gì đó trong python vì vận tốc thay đổi nhưng vì lý do nào đó, trạng thái lớp toàn cầu không bị thay đổi. Xem ở đây: http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_3.py Có thể là tôi không thể nhập từ '__future__' bởi vì codeskulptor là một triển khai rất hạn chế của Python chỉ để mọi người có thể tìm hiểu những điều cơ bản về tương tác (mô-đun simpleGUI được tạo bởi các giáo sư của Lớp Coursera cùng với người viết mã) – Apc0243

+0

http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_4.py <- cái đó sạch hơn nhưng vấn đề vẫn còn đó và tôi không biết tại sao. Tôi nghĩ rằng đó là vì hàm collision() của tôi được gọi bởi một phương thức lớp. Tôi không chắc chắn làm thế nào để thực hiện kiểm tra va chạm cặp đôi bên trong của lớp đó là lý do tại sao tôi kéo nó ra – Apc0243

+1

Nhìn vào vận tốc bạn in trong chức năng va chạm, có vẻ như khi một quả bóng ánh sáng va chạm với một quả bóng nặng, vận tốc đã được lật như nó cần, nhưng sau đó trực tiếp sau đó nó đã được lật một lần nữa theo hướng ngược lại để có hiệu quả không có gì đã xảy ra. Lỗi này nằm trong hàm 'match_objects' của bạn, bạn thêm mỗi cặp hai lần, một lần tiến lên và một lần ngược lại. Mỗi va chạm sau đó được phát hiện hai lần, từ object1 và cho object2, hai cái này hủy lẫn nhau. Điều này dường như làm việc (quả bóng đôi khi bị mắc kẹt): http://www.codeskulptor.org/#user39_sV5TmqJSlAYGeOG.py –

Các vấn đề liên quan