Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2D Elastic Ball Collision Physics

I am making a program that involves elastic ball physics. I have worked out all of the maths for collision against walls and stationary objects, but I cannot figure out what happens when two moving balls collide. I have mass and velocity (x and y velocity to be exact, but velocity of each ball and their direction will do) and would like the formulae for those. Remember - this is a perfectly elastic collision - so no spinning balls, etc.

like image 591
0WJYxW9FMN Avatar asked Feb 04 '16 20:02

0WJYxW9FMN


2 Answers

This wikipedia article provides a formula to compute velocities after collision between two particles :

There are many reasons to use this formula :

  • you just need the velocity vectors of your balls before collision, their mass and their position,
  • you don't need to define angles of deviation,
  • the operations are simple (just dot product required),
  • the vectors can be expressed in any coordinates system.

There is no proof in the wikipedia article so I provide it below.


Definition of the problem

enter image description here

For each ball we define :

  • mi the mass
  • vi the vector of velocity before collision
  • v'i the vector of velocity after collision
  • Oi the point of center
  • xi the vector of Oi position

The unit vector n is normal to the surfaces of balls at the point of contact.

The unit vector t is tangent to the surfaces of balls at the point of contact.


Physics law to use

The conservation of the total momentum is expressed by :

The conservation of total kinetic energy is expressed by :

As there is no force applied in the tangential direction, the tangential components of velocities are unchanged after collision :


Proof

The tangential components of velocities are unchanged. So we can rewrite the conservation laws with normal components and we have a 1D problem now :

The conservation of kinetic energy can be factorized then simplified with the conservation of momentum :

We combine this last expression with the conservation of momentum and we get the normal component of v'1 :

Finally, we find the formula of the wikipedia article for v'1 :

The formula of v'2 is symmetrical.

like image 151
cromod Avatar answered Sep 18 '22 21:09

cromod


Since I'm doing a remake on blobby, the the bodies are not necessarily balls - hit angles are not related to distance between X1,X2. So I was using the equations from this: https://williamecraver.wixsite.com/elastic-equations enter image description here

below is the code that computes vector angle from dx dy velocities: Further below are the equations (that require the converted vector input). code is in python 3.8x. Tuples are input and output to the functions.

def angle_ofdxdy(dxdy):  # returns angle, z
  dx, dy = dxdy[0], dxdy[1]
  if abs(dy) < 0.01: #prevent div by zero
    dy = 0.01
  # https://math.stackexchange.com/questions/1327253/how-do-we-find-out-angle-from-x-y-coordinates
  z = (dx ** 2 + dy ** 2) ** 0.5
  angle = 2 * atan(dy / (dx + z))
  return (round(angle, 4), z)

below is a prep function that uses the above before calling the equations:

def calc_impulse_xy1xy2(xy1_xy2, ball_mass=1, wall_mass=10000000, gamma=0):
  xy1, xy2 = xy1_xy2
  a1, z = angle_ofdxdy(xy1)
  a2, z2 = angle_ofdxdy(xy2)
  # print(f'xy xy translator called for xy={xy1}, xy2{xy2}, angles {degrees(a1):.0f},  {degrees(a2):.0f}')
  return cv1v2(z, a1, z2, a2, ball_mass, wall_mass, gamma)

below are the actual equasions:

def cv1v2(ball_velocity=5, ball_theta=0, wall_velocity=0, wall_theta=0, ball_mass=1, wall_mass=10000000, gamma=0):
  g = gamma  # 0 needs further explainig. ba
  t1,t2 = ball_theta, wall_theta
  v1,v2 = ball_velocity, wall_velocity  # a scalar.
  m1,m2 = ball_mass, wall_mass

  # print('pi/2 is',pi/2)
  vx = (v1 * cos(t1 - g) * (m1 - m2) + 2 * m2 * v2 * cos(t2 - g)) * cos(g) / (m1 + m2) + v1 * sin(t1 - g) * cos(g + pi / 2)
  vy = (v1 * cos(t1 - g) * (m1 - m2) + 2 * m2 * v2 * cos(t2 - g)) * sin(g) / (m1 + m2) + v1 * sin(t1 - g) * sin(g + pi / 2)
  v2x = (v2 * cos(t2 - g) * (m2 - m1) + 2 * m1 * v1 * cos(t1 - g)) * cos(g) / (m1 + m2) + v2 * sin(t2 - g) * cos(g + pi / 2)
  v2y = (v2 * cos(t2 - g) * (m2 - m1) + 2 * m1 * v1 * cos(t1 - g)) * sin(g) / (m1 + m2) + v2 * sin(t2 - g) * sin(g + pi / 2)
  xyxy = ((round(vx, 2), round(vy, 2)), (round(v2x, 2), round(v2y, 2)))
  print(f'Ball: {v1:.1f}({degrees(t1):.0f}\u2070)\t Player:{v2:.1f}({degrees(t2):.0f}\u2070),  impact angle:{degrees(g):.0f}\u2070 masses:{m1},{m2} \nresult:{xyxy}')
  return xyxy

The function is referring to ball and wall. This is just a hint in case you want to test wall bouncing using the same equations (there's default heavy weight assigned to the second object). You can put identical masses of course in function call. Tested. Working


This approach assumes you calculated Gamma - the angle of contact. It is faily easy if you have full info of the collision point and shape of your objects. Especially if at least one is a ball

like image 23
Guy Avatar answered Sep 21 '22 21:09

Guy