Last week, Rhett did a post on animating a bouncing ball in VPython. This was mostly making a point about the distinction between real simulation and animation, along the lines of yesterday’s post on social construction of videogame reality. But, of course, my immediate reaction was, “That’s not how a bouncing ball looks…” This is how a bouncing ball looks:
(As you can see from the watermark, I’m trying out a new video editor…)
This is footage of four different types of balls bouncing on a lab cart in our stockroom, shot in gratuitous slow motion (240 fps) because I’m still playing around with my new camera. These are what I happened to have lying around: a black rubber “happy” ball from a lab set, a hard plastic projectile from a PASCO launcher, a ping-pong ball, and a racquetball. There are some significant differences between them– the projectile ball stops really quickly, while the ping-pong ball goes on forever– but they all have one thing in common: the bounce height decreases rapidly as the bouncing goes on.
So, if you want to really animate a bouncing ball, you need to capture that. And, of course, being a great big nerd, I’m far more interested in simulation than animation, so let’s think about the physics, here, and how to code it up in VPython.
First and foremost, we need to think about how to handle the bouncing behavior. But, of course, that’s pretty easy and obvious, given all the previous futzing around with VPython simulation we’ve done here: we just treat the ball as a spring. I assigned a fairly arbitrary spring constant to the ball, and put in an if-then statement to apply a spring force if the center of the ball was within a radius of the “floor.” Then I fiddled with the spring constant to give reasonable behavior, namely keeping the center of the ball from getting all the way to the floor. That gives you a bouncing behavior that looks just like Rhett’s constant acceleration animation:
So, you know, physics works.
Of course, the more interesting question is how to handle the decay of the bounce. To put that in, we need to think about the physics of why it decays. This is easiest to understand in terms of energy: the falling ball has some kinetic energy, and when it hits the table, some of that energy is converted into thermal energy, heating up the ball and the table by a tiny amount. That thermal energy can’t be recovered and turned back into energy of motion, so when the ball heads back up, it has less kinetic energy than when it started. That means that when it reaches the peak of its flight, turning all of the kinetic energy into gravitational potential energy, it’s not as high as it was on the previous bounce.
So, how to model this? Well, the cheap and easy thing to do would be to just insert a line that automatically decreases the energy when it bounces. But we didn’t explicitly calculate the energy of the ball at any point in the simulation above, just the forces that act on in. Besides, we’re trying to do physics here.
So, how do you lose energy? Well, introductory Newtonian mechanics tells us that energy is converted to thermal energy through the action of “non-conservative” forces (a term that causes no end of confusion, but we’re kind of stuck with it…), which are easiest to understand by considering their opposite.. A “conservative” force is one where the work done as you move between two points is independent of the path you take from one point to the other, and those give you potential energy– gravity is a good example. As you lift something up, gravity resists your motion, but if you lower it, gravity helps you move it. The total work done by gravity thus depends only on the difference in heights– if you lift something up above the final position, then lower it back down, gravity resists the motion for part of that, and helps for another part, and those bits cancel each other out.
A non-conservative force, on the other hand, is one where the work done depends on the path that you follow– a short path means little work, and a longer path requires more work. Friction and air resistance are the classic examples: because friction is always in the direction opposite the direction of motion, it never helps you, and only hurts. A long path means more work against friction, which is why people moving furniture always follow the most direct route they can when sliding stuff across the floor.
So, to lose energy, we want to add a force that is always in the direction opposite the ball’s motion. There are two classic, simple mathematical forms for this kind of thing if you’re thinking about drag forces on a particle moving in a fluid: For thick fluids, there’s a viscous drag force that depends on the velocity, and for thinner ones, there’s a drag force that depends on the square of the velocity. Since the VPython simulation tracks velocity directly, as a vector, both of these are easy to implement with an extra line in the if-then statement where I calculate the spring force. Of course, I’m not sure which of these to prefer, so I coded both of them up.
But then, it’s not clear why either of those models would apply; they’re just convenient and familiar things to add in. The actual dissipation comes about through the motion of the atoms and molecules making up the ball and the table, which aren’t necessarily like particles in a fluid. But those are also the very things that give rise to the spring force, so maybe a more appropriate method would be to add a drag force that’s a fixed fraction of the spring force (but still always in the direction opposing the motion). That’s also pretty easy to do, so I added a third calculation to the loop.
So, what’s the end result? Well, here are three traces showing the three different models, for a fairly arbitrary choice of parameters that give 50 bounces before the height of the bounce is less than 5% of the radius of the ball. (This is an unrealistic set of values, but it highlights the difference between the models, and we’re just playing at the moment).
On the left is the linear-in-velocity drag force, in the middle is the velocity-squared drag force, and on the right is the fraction-of-the-spring-force drag. You can see that there’s a big difference between the linear and quadratic models– the quadratic version dies down much faster, but looks like it sort of levels out and continues at a lower amplitude for a long time. If you can see a difference between the linear and fraction-of-drag models, you’ve got better eyes than me. In fact, they’re nearly identical. Don’t believe me? Here are some graphs:
The top graph shows the time of the nth bounce– defined as the time when VPython noticed that the velocity has changed from down to up– and the bottom graph shows the height of the nth bounce– defined as the time when VPython noticed that the velocity has changed from up to down. These are closely related, of course– the time between bounces is the time to go up to a given height and come back down– but they’re two easy things to measure and graph. And the important thing to notice from these is that there’s basically no difference between the linear-drag and fraction-of-spring models. Why is that? I have no idea. If you know, please enlighten me.
So, how do these compare to the real bouncing balls from the video at the top of this post? Well, this is where the gratuitous sow motion kind of bites me in the ass– analyzing these with Tracker takes frickin’ forever because of the high frame rate. I do have numbers for one of the clips, though, but this post is kind of long already, so we’ll save that for tomorrow…
In the meantime, if you’d like to play with the simulation yourself, play “find the stupid coding error,” or just point and laugh at my rudimentary VPython, the code for this is on Gist. Have fun.