Inelastic collision in Python

Viewed 262

This is my first post in here. I'm trying to learn python code. I made a program using turtle module that simulates a bouncing ball suffering an inelastic collision in order to make the maximum height of the bounce less each time. It works well until a time when the ball is bouncing in a very short height and it stops bouncing to make the ball just move downwards at a constant (small) speed - which obviously isn't the expected.

The "floor" is a line at the y = -100 coordinate.

My iteration code is this:

while t < 5000:
    vy += g
    h += vy
    corpo.goto(0, h)

    if h <= -100 and g == 0:
        vy = 0
        h = -100
        g = 0
    if abs(vy) <= 0.000000000000000000001 and h <= -100:
        vy = 0
        g = 0
        h = -100
    elif h <= -100 and vy < 0:
        vy = -vy * 0.75

    print(vy)

    t += dt 
1 Answers

The problem is your completion condition is never satisfied, probably because you are adding an acceleration to a velocity (assuming g refers to gravity, if it doesn't you really should consider giving it a different name). The other issue is that, even with that correction, your completion condition of abs(vy) <= 0.000000000000000000001 would only be met if g * dt is less than 0.000000000000000000001 / 0.75, otherwise vy will not ever be small enough.

There are two ways to fix the latter issue, you can scale your completion condition to g * dt, i.e.

if abs(vy) <= abs(g * dt) and h <= -100:
    # ...

or you can turn gravity off when h <= -100 and raise the threshold slightly, i.e.

t = 0
dt = 0.0001
vy = 0
h = 0
g = -5
while t < 500:
    if h <= -100 and g == 0:
        vy = 0
        h = -100
        g = 0
        break
    if abs(vy) <= 0.0001 and h <= -100:
        vy = 0
        g = 0
        h = -100
    elif h <= -100 and vy < 0:
        vy = -vy * 0.75
    elif h > -100:
        vy += g * dt

    h += vy
    print(h, vy)

    t += dt 

In the former case, convergence is guaranteed (the ball will stop), in the latter it is not (it may oscillate ad infinitum). Since the former guarantees convergence, it is generally preferable - but not entirely realistic.

The most realistic solution though is to combine both, i.e.

t = 0
dt = 0.001
vy = 0
h = 0
g = -9.81
while t < 500:
    if h <= -100 and g == 0:
        vy = 0
        h = -100
        g = 0
        break
    if abs(vy) <= abs(g * dt)*2 and h <= -100:
        vy = 0
        g = 0
        h = -100
    elif h <= -100 and vy < 0:
        vy = -vy * 0.75
    elif h > -100:
        vy += g * dt

    h += vy
    print(h, vy)

    t += dt 

Do note that there are certain values of the time step, dt, for which convergence will not occur - if such a case is encountered, either the scaling of the completion condition or the time step should be adjusted.

Related