I can't find what is wrong with this calculation of circle rebound in python

I have a program in which circles can bounce off of each other. I followed directions from here to rotate vectors and scale values ​​based on the angle of collision: http://www.vobarian.com/collisions/2dcollisions2.pdf

I wrote this code in python (index 0 indicates x coordinate):

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 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]] 

The problem is that it works sometimes, but not at another time. Can someone tell me why? It seems that if the balls collide at right angles, then their output paths change or something like that. I wrote this in a browser browser: http://www.codeskulptor.org/#user39_8q0Xdp3Y4s_2.py

Can someone point out where I made a mistake?

EDIT: Could I handle the collision? Here are the steps:

  1) Draw the balls on the screen 2) Create set of unique pairs of collidable objects 3) For each ball, move the ball 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 
+5
source share
1 answer

The online simulation is really cool! I have not studied your complete code in detail, just a snippet that you posted in your question. With a quick glance, you correctly calculate the tangential and normal unit vectors, the old normal and tangential velocities, and the new normal speed. But after that you seem a little lost. As explained in the collision document, the tangential velocities do not change during the collision, so there is no need to calculate new_tan_vect1/2 . I also do not understand why you are calculating new_norm_vect1 , the normal vector does not change during the collision.

Some other small notes:

  • why do you use float() throughout your code? This is usually not required. If the reason for this is to get the correct division results, you really should add from __future__ import division to the top of your code, since you seem to be using Python2. See this old question for more information.

  • What you call norm_vect is actually a non-normalized normal vector, and what you call unit_vect is actually a normalized normal unit vector. I would just call norm_vect to make the difference between normal and tangential more clear. A single vector is any vector with a length of 1, so using this for a normal vector is a bit wrong.

  • If you plan on doing more of these simulations, you should consider learning about numpy . This allows you to write vectorized calculations instead of manually writing all the equations for x and y . For instance. norm_vect = pos2 - pos1; norm_vect /= np.linalg.norm(norm_vect) norm_vect = pos2 - pos1; norm_vect /= np.linalg.norm(norm_vect) or object1.vel = norm_vect * new_vel1_norm + tang_vect * vel1_tang .

I would write that your fragment should be more or less similar (unverified code):

 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 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] 

I renamed some of the variables to make them more understandable.

+2
source

Source: https://habr.com/ru/post/1215641/


All Articles