Hi all!
"The bouncing ball" consists basically in a simple red ball bouncing up and down. Also I've added a graphing function to plot the position over time where you can see the lost energy at every bounce.
Picture:
Description:
Involved physics: 1D kinematics, differential equations (without solving them).
Needed python libraries: visual and visual.graph
Parameters: you can change the initial velocity, high, gravity, the elasticity of the bounce and friction with air.
Explaining the code:
#PROGRAM DEPENDENCES:
from visual import *
from visual.graph import *
from visual import *
from visual.graph import *

Next step is the display were you can set up the size of the window, the title, if you want python to autoscale the scene among others.
#SCENE DISPLAY (FROM VPYTHON)
scene.width = 700
scene.height = 600
scene.title = 'BOUNCING BALL'
scene.autoscale=False
scene.fullscreen = False
scene.center = vector(0, 10, 10)
scene.height = 600
scene.title = 'BOUNCING BALL'
scene.autoscale=False
scene.fullscreen = False
scene.center = vector(0, 10, 10)

The variables' values can be changed because the equations are written as a function of them.
#VARIABLES
t_max = 20 #program timeout
g = 9.81 #aceleration of gravity
y = 10 #initial high of the ball
v = 10 #initial velocity of the ball
dt = 0.006 #increase of time for each iteration
e = 0.9 #coef. lost of energy in each bounce
k = 0 #friction with air
t = 0 #initial time
g = 9.81 #aceleration of gravity
y = 10 #initial high of the ball
v = 10 #initial velocity of the ball
dt = 0.006 #increase of time for each iteration
e = 0.9 #coef. lost of energy in each bounce
k = 0 #friction with air
t = 0 #initial time

Here defining floor as a box and ball as a sphere (a vpython's function) for drawing them
in the scene. Next step, the position of the ball is updated within a while loop.
#DRAWING THE OBJECTS
floor = box(height = 0.2, width = 30, length = 30, color =
color.white, material = materials.wood)
ball = sphere(pos = vector(0, y, 0), radius = 1, color =
color.red)

Before entering the while, we define the display of the curve and the plot's interface.
#GRAPH
f1 = gdisplay(x=0, y=0, width=600, height=600,
title='MOVEMENT (y vs. t)', xtitle="t", ytitle='y',
foreground=color.black, background=color.white,
xmax=t_max, xmin=0, ymax=15, ymin=0)
f1 = gcurve(color=color.black) #The graphics curve
f1 = gdisplay(x=0, y=0, width=600, height=600,
title='MOVEMENT (y vs. t)', xtitle="t", ytitle='y',
foreground=color.black, background=color.white,
xmax=t_max, xmin=0, ymax=15, ymin=0)
f1 = gcurve(color=color.black) #The graphics curve

The next step is to create a loop for updating the position of the ball. Here are used differential equations to update incrementally the position.
The idea is to start the loop with a value of dt, that causes a sequence of small increments in velocity and position. Doing that, you are drawing successive pictures of the ball, floor that produces a movement effect.
while t < t_max: #main loop
rate (200) #loops/sec
#DIFERENTIAL EQUATIONS
dv = g*dt  k*v*dt
v = v + dv
dy = v*dt
y = y + dy
t = t + dt
rate (200) #loops/sec
#DIFERENTIAL EQUATIONS
dv = g*dt  k*v*dt
v = v + dv
dy = v*dt
y = y + dy
t = t + dt

Now comes a crutial part, the bounce. It's obvius that the ball has to bounce when it has the floor's position, then the idea is to invert the velocity upwards. The problem is that our program has an error in position given by the magnitude of dt. This small error forbids us to put a simple if like: "if y == ball.radius:", because it's not sure that the ball will reach this exact point. So we are forced to put the next condition: "if y < ball.radius:" . But now we have another problem, the ball renters the if at the next iteration because it haven't yet reached the needed high to be upper than ball.radius. That's because if you apply some lose of energy the bounce isn't symmetric. This produces a "bug" where the ball inverts his velocity several times and can bounce downwards. The solution is to set up the ball's position to the ball.radius high after entering the if function, so avoiding this "bug".
#Bounce conditions
if y < ball.radius:
v = v*e
y = ball.radius
#Scene updating
ball.y = y

Finally you have to update the ball.y and draw this point into the graph:
#Drawing in the plot
f1.plot(pos = (t , y))
print "...FINISH!"
print "www.pythonforphysics.blogspot.com"
That's all! Don't forget to comment if you enjoyed! :)
*You can download the program from the library or from on this link
I am new to Python and am being "forced" to use it because of a course I am taking plus the text is Chabay & Sherwood. I learn best by example and problems.
ReplyDeleteThank you for doing this blog. The code and your explanation is very helpful.
Jim
Nice!
DeleteI think that learning by examples is a good way of doing it.
I will be adding more codes but if you have a suggestion just comment it here!
Thanks and good luck with the course!
I am a beginer to VIDLE. This code and comments have helped me very much. Although, I am having trouble getting the ball to bounce, if you could help me out it would be greatly appreciated.
ReplyDeleteThanks again.
I am teaching myself Python using a bouncing ball program, but the ball loses energy with each bounce even if I don't program any loss of energy. I think it probably occurs because of approximation at the time of bouncing, but I'm not sure. Like you, I reset the location of the ball to the border (4 borders in my case) when it is within one radius of the border. Any suggestions?
ReplyDeleteI should have mentioned that I enjoy your programs. This is a nice service to all of us trying to learn Python or those interested in bouncing balls!
ReplyDeleteThis comment has been removed by the author.
ReplyDelete