Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

VPython Sphere Velocity Problem

  1. Nov 30, 2008 #1
    Hi there, I'd like to preface my question with a few things. First off, I'm not great at physics, but I don't think the following is a hard question for any of you to answer. Also, I'm not too great with VPython, mostly because I know I'm only going to be using Python in general for another 2 weeks and never again (more of C++ and VB kinda guy), but my logic is usually pretty sound.

    I'm working on a project where there's a box, with two spheres inside of it. One sphere is stationary while the other is moving. Well, one of the requirements is that the moving sphere must change direction upon impact with both the walls and the stationary sphere. I've got the answer to that problem, but the "velocity" of the moving sphere is not static and for the life of me I can't figure out how to have it change direction correctly and keep the same relative velocity. It seems to be move faster after the impact with the middle ball. I'm hoping this is an easy answer that's going to make me look silly, because I've looked and thought about it but probably not in the right frame of mind.

    Below is the code for the whole thing:
    Code (Text):
    from visual import *

    side = 4.0
    thick = .03
    Height = 2*side - thick
    Width = 2*side + thick
    RightWall = box(pos =(side,0,0),length=thick,height=Height,width=Width,color=color.red)
    LeftWall = box(pos=(-side,0,0),length=thick,height=Height,width=Width,color=color.blue)
    BottomWall = box(pos=(0,-side,0),length=Width,height=thick,width=Width,color=color.green)
    TopWall = box(pos=(0,side,0),length=Width,height=thick,width=Width,color=color.orange)
    BackWall = box(pos=(0,0,-side),length=Height,height=Height,width=thick,color=color.white)

    CenterSphere = sphere(pos=(0,0,0),radius = 1,color=color.black)

    ball = sphere(color=color.yellow,raidus=1,pos=(0,side-1,0))
    ball.mass = 1.0

    ball.velocity = vector(-0.15,-0.23,+0.27)

    side = side-thick*0.5-ball.radius

    dt = 0.5
    t = 0.0

    ball.trail = curve(color=color.white)

    while 1:
        t = t+dt
        ball.pos = ball.pos + (ball.velocity/ball.mass)*dt
        if not (side > ball.x >-side):
            ball.velocity.x = -ball.velocity.x
        if not (side > ball.y >-side):
            ball.velocity.y = -ball.velocity.y
        if not (side > ball.z > -side):
            ball.velocity.z = -ball.velocity.z
        if distance<(ball.radius + CenterSphere.radius):
            direction=norm(CenterSphere.pos - ball.pos) #<-- Here is where I'm calculating incorrectly
            print "direction: "+str(direction)
            print "ball.velocity before: " + str(ball.velocity)
            print "ball.velocity after: "+ str(ball.velocity)
            ball.pos = ball.pos + (ball.velocity/ball.mass)*dt
            print "ball.pos after: "+str(ball.pos)
    Also, if there's a preferred forum for this type of message, I apologize, this seemed most appropriate. Please move accordingly.
  2. jcsd
  3. Nov 30, 2008 #2
    I will give my few pennies worth, and I apologize if I don't understand your problem or your code correctly. Here are a few question marks that I have.

    1. If everything else is stationary, would the mass of the ball be relevant?
    2. Would you consider reducing dt, because at a speed of 0.385 m/s, the ball can penetrate up to 0.2m into the wall. I understand that this can be refined later, and does not yet contribute to your current problems.
    3. boucing off sphere
    I see a potential problem here because ball.velocity is the real velocity, direction is normalized. So the subtraction will not be meaningful.
    "direction" is the unit vector of the rebound direction, similar to the perpendicular direction to the wall. For the wall, the new direction is simply v.x=-v.x, or the like.
    For the sphere, the moving ball is not always moving towards the centre of the stationary ball, it could graze it at an angle, so you may want to do something like
    velocity = velocity + 2 * velocity .dot. direction
    where .dot. is the dot product opertor, the factor 2 is to cancel the component towards the sphere and put on "reverse".
  4. Nov 30, 2008 #3
    1. I was told that's how I needed to increment the position.
    2. I was told that's what the time interval is.
    3b. So I should have it say:
    Code (Text):
    ball.velocity = ball.velocity+2*(vector(dot(ball.velocity.x,direction).x,dot(ball.velocity.y,direction).y,dot(ball.velocity.z,direction).z))
    Code (Text):
    ball.velocity =ball.velocity - 2*(dot(ball.velocity,direction))*direction
    Because the first one flips out and goes outside of the box, but it seems to stick with you example. I apologize about my ignorance, but I'm unaware of the usage of the written usage of the dot product operator. I'm assuming you meant dot(velocity, direction). In which case I can't add it to the velocity because it returns a float not a vector. Thus the multiplication against the direction (which multiplies each item in the direction vector against the return of the dot product) or breaking it all down into the x,y,z coordinates (which moves the ball outside of the box). I have to assume that because I visually can't see it speeding up too greatly and the printed results don't go about .50 or below .05 that the "speed" of the ball is relatively stable with the second code snippet, right?
  5. Dec 1, 2008 #4
    Sorry, my bad.
    What I meant was (correct the syntax, because I have never programmed in vPython)
    ball.velocity =ball.velocity + 2*norm(ball.velocity)*direction
    The idea was to have the component of the velocity in the direction joining the two centres of the spheres to be reversed only, irrespective of the velocity of the movement of the ball.
  6. Dec 1, 2008 #5

    So VPython doesn't seem to like that. Don't know why it's not working the way it should, but I've multipled each vector by each vector and it just goes nuts.

    Is there another route to take? Sin,Cosin and Tan functions show up a lot in my searches, would using those lead me to greener pastures? If it would, how would I implement them? Also, the one that seemed to work the best would be:
    Code (Text):

    ball.velocity = ball.velocity-2*(dot(ball.velocity,direction)*direction)
    but the speed seemed to not stay the same, is that a problem I'm going to run into no matter what?

    Thanks again for some more input, I swear I'm not trying to be difficult.
  7. Dec 1, 2008 #6
    Can you check (by printing some data) if direction is a unit vector?
    Also can you print the following vectors and figure out what went wrong by performing the calculations manually (at least for one impact)?

    ball velocity (before and after impact)
  8. Dec 1, 2008 #7

    I know this is going to sound really silly of me, but I wouldn't know how to start performing the calculations manually. :-(

    I'm more of a procedural programmer, not a physics guy. *shrug* I also have no formal education (although I'm going to be working on one starting next month) and the last time I took physics was 2001.

    But I have attached a file with the print out of the ball velocity (before and after), the direction, as well as formula used to create the new velocity. I ran each attempt for a maximum of 20 contacts with the sphere and only two of them made it that far. The others I had to quit because they went outside of the box and just bounced around in limbo.

    There is one variable in the equations that is not mentioned in my previous code and that's:
    Code (Text):

    xchange = norm(ball.velocity)
    I really do appreciate all the help, I'm sorry I'm so naive/ignorant/idiot on this subject. I'm trying to learn it the best I can, but it's a little overwhelming.

    Attached Files:

  9. Dec 1, 2008 #8
    No problem at all.
    I will take a look at the numbers and get back to you.
  10. Dec 2, 2008 #9
    Code (Text):
    I have looked at it, the problem should be solved by changing the above line with
    Code (Text):
    I have checked that the speed is conserved.
    Basically, what we are doing is to get the magnitude using the dot-product, and multiplied by the direction to get the vector, and multiplied by two to reverse the component perpendicular to the impact surface.
  11. Dec 2, 2008 #10
    I really to appreciate the help you've been able to give me, but apparently, the professor wants this to work all the time. Even with the size of the centersphere at least twice as large as the moving sphere, the moving sphere wraps around the centersphere.

    So, what I'm going to need is the actual formulas for each vectors directional change. If that makes any sense.

    Basically, I need to use the actual physics of the ball bouncing. If you can you can give me the formulas like = Ballx = Ballx-Centerx or whatever. The V(x,y,z) = (v1x-v2yz-d1jkl;adfjasd) confuses the piss out of me. :redface:
  12. Dec 3, 2008 #11
    I do not see anything wrong with your code, it should work as expected.

    On the other hand, what I can see coming is that there would be more than one ball of different sizes going into the equations, hence the question about mass. Very similar to what we see in the early video games.

    Here is a summary/confirmation of what your code does:

    Code (Text):
    [QUOTE]    distance=mag(CenterSphere.pos-ball.pos)
        if distance<(ball.radius + CenterSphere.radius):[/QUOTE]
    These two lines in your code should take care of the differing radii of the spheres.

    I believe the lastest code that I posted is independent of the radii of the spheres.

    I will write out the formula in vector form, all single capital letters are vectors.
    D=unit vector of the direction from the centre of the moving sphere to the centre of the stationary sphere (as defined in your code)
    V=vector representing the velocity of the moving sphere before impact
    V'=vector representing the velocity of the moving sphere after impact with stationary sphere

    Code (Text):
    V' = V-2D(V.D)
    where V.D is the dot product between V and D.

    The condition of impact is as you have coded, namely
    Distance between spheres = DISTANCE = |CentreSphere.pos-Ball.pos|
    and condition of impact is
    DISTANCE <=CentreSphere.radius+Ball.radius

    Can you confirm if the code is working as it should after the latest change? If not, could you post the problem you find?
  13. Dec 3, 2008 #12
    Well, when I sat down to look at this tonight, I noticed where I had made mistake. I had mis-typed radius as raidus, so when my professor changed the sizes of the spheres, the moving sphere wasn't changing size. Also, when he increased the center sphere, he didn't take into account that the distance between the exterior of the center sphere and the walls has to be at least 1 1/2 times the size of the moving sphere. Otherwise, the ball wont bounce correctly because it will never get around unless moving along the seam.

    But, it's a good thing I'm determined.

    Also, I reorganized the velocity to view it as yours:
    Code (Text):
    ball.velocity = ball.velocity-2*distance*dot(ball.velocity,direction)

    Tomorrow evening, I'll be putting my findings in front of him again. I'll let ya know what he decides is wrong with it this time. Thanks again!
  14. Dec 3, 2008 #13
    FYI, this is a sort of homework, but not really. The teacher while lecturing said that he'd been working on something like this for at least 6 months and challenged anyone to work on it to figure it out. And since I'm bored with my class I figured I'd give it a shot.
  15. Dec 4, 2008 #14
    This is great!
    In fact, you question has stimulated me into eventually working on a similar problem in more general terms, possibly with multiple spheres of different diameters. I'll let you know if I get anywhere with it.
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook