PythonThompsonVPythonSeries

From Wiki

Jump to: navigation, search

This is the support page for Erik Thompson's VPython tutorials.


Contents

Code for Episode 1 (VPython: Projectile Motion 1)

from visual import *

scene.width = 800
scene.height = 600

scene.autoscale = 0
scene.range = (100,100,100)
scene.center = (0,40,0)

ball = sphere(pos=(0,100,0),radius=2)
ground = box(pos=(0,-1,0),size=(10,2,10))

gravity = 9.8   # m/s**2
seconds = 0 
dt = .01

finished = False           
while not finished:
    rate(100)   # go thru the loop no more than 100 times/s
    seconds += dt

    # position equation: y(t) = y0 + v0*t + .5 * a * t**2
    ballHeight = 100 - .5 * gravity * seconds**2

    ball.pos = vector(0,ballHeight,0)

    if ballHeight - 2 < 0:
        finished = True
        print "seconds to fall: " + str(seconds)

Code for Episode 2 (VPython: Projectile Motion 2)

from visual import *

scene.width = 800
scene.height = 600

scene.autoscale = 0
scene.range = (100,100,100)
scene.center = (0,40,0)

ball = sphere(pos=(0,102,0),radius=2)
ground = box(pos=(0,-1,0),size=(100,2,10))
building = box(size=(6,100,6),pos=(0,50,0),color=color.blue)

gravity = 9.8   # m/s**2
velocityX = 6   # m/s
seconds = 0
dt = .01

finished = False
while not finished:
    rate(100) # go thru the loop no more than 100 times/s
    seconds += dt

    # position equation: y(t) = y0 + v0*t + .5 * a * t**2
    ballY = 102 - .5 * gravity * seconds**2
    ballX = velocityX * seconds

    ball.pos = vector(ballX,ballY,0)

    if ballY - 2 <= 0:
        finished = True
        print "seconds to drop: " + str(seconds)
        print "distance in the x direction: " + str(ballX)

Code for Episode 3 (VPython: Projectile Motion 3)

from visual import *

scene.width = 800
scene.height = 600

scene.autoscale = 0
scene.range = (100,100,100)
scene.center = (50,40,0)

ball = sphere(pos=(0,2,0),radius=2, color=color.green)
ground = box(pos=(50,-1,0),size=(100,2,10))


gravity = 9.8  # m/s**2
velocity = 25   # m/s
angle = 45     # degrees
angle = angle * (pi/180) # converted to radians

# sin = opp / hyp
# cos = adj / hyp

# therefore

# opp = hyp * sin
# adj = hyp * cos

VelocityY = velocity * sin(angle)
VelocityX = velocity * cos(angle)

seconds = 0
dt = .01

finished = False
while not finished:
    rate(100) # go thru the loop no more than 100 times/s
    seconds += dt

    # position equation: y(t) = y0 + v0*t + .5 * a * t**2
    ballY = 2 + VelocityY * seconds - .5 * gravity * seconds**2
    ballX = VelocityX * seconds

    ball.pos = vector(ballX,ballY,0)

    if ballY - 2 <= 0:
        finished = True
        print "initial velocity: " + str(velocity)
        print "angle thrown: " + str(angle)
        print "seconds in flight: " + str(seconds)
        print "distance in the x direction: " + str(ballX)


Code for Episode 4 (VPython: Projectile Motion 4)

from visual import *

scene.width = 800
scene.height = 600

scene.autoscale = 0
scene.range = (100,100,100)
scene.center = (50,40,0)

ball = sphere(pos=(0,2,0),radius=2, color=color.green)
ground = box(pos=(50,-1,0),size=(100,2,50))


gravity = 9.8  # m/s**2
velocity = 25   # m/s
angle = 45     # degrees
angle = angle * (pi/180) # converted to radians

# sin = opp / hyp
# cos = adj / hyp

# therefore

# opp = hyp * sin
# adj = hyp * cos

VelocityY = velocity * sin(angle)
VelocityX = velocity * cos(angle)
VelocityZ = 0

VelocityThrown = vector(VelocityX,VelocityY,0)

VelocityWind = vector(2,1,-5)

TotalVelocity = VelocityThrown + VelocityWind

seconds = 0
dt = .01

finished = False
while not finished:
    rate(100) # go thru the loop no more than 100 times/s
    seconds += dt

    # position equation: y(t) = y0 + v0*t + .5 * a * t**2
    ballY = 2 + TotalVelocity.y * seconds - .5 * gravity * seconds**2
    ballX = TotalVelocity.x * seconds
    ballZ = TotalVelocity.z * seconds

    ball.pos = vector(ballX,ballY,ballZ)

    if ballY - 2 <= 0:
        finished = True
        print "initial velocity: " + str(velocity)
        print "angle thrown: " + str(angle)
        print "seconds in flight: " + str(seconds)
        print "distance in the x direction: " + str(ballX)
        mylabel = label(pos=(50,60,0),text="seconds in flight: " + str(seconds),height=10)

Code for Episode 5 (VPython: Friction)

from visual import *

scene.width = 800
scene.height = 600

scene.autoscale = 0
scene.range = (100,100,100)
scene.center = (50,40,0)

puck = cylinder(pos=(0,0,0),axis=(0,2,0), radius=2, color=color.green)
puck.mass = 1 # kg
ground = box(pos=(50,-1,0),size=(100,2,50))

mylabel = label(pos=(50,60,0),text="velocity x: ",height=10)

gravity = 9.8  # m/s**2
velocity = 25   # m/s
angle = 45     # degrees
angle = angle * (pi/180) # converted to radians

# sin = opp / hyp
# cos = adj / hyp

# therefore

# opp = hyp * sin
# adj = hyp * cos

VelocityY = velocity * sin(angle)
VelocityX = velocity * cos(angle)
VelocityZ = 0

VelocityThrown = vector(VelocityX,VelocityY,0)

VelocityWind = vector(0,0,0)

TotalVelocity = VelocityThrown + VelocityWind
puckVelocityY = TotalVelocity.y

seconds = 0
dt = .01

finished = False
while not finished:
    rate(100) # go thru the loop no more than 100 times/s
    seconds += dt

    puckY = TotalVelocity.y * seconds - .5 * gravity * seconds**2

    if puckY <= 0:
        puckY = 0
        
        # Force Due To Kinetic Friction = Normal Force * CoefficientKinetic
        CoefficientOfKineticFriction = .45

        # Newton's second law: Force = mass * acceleration
        ForceDown = puck.mass * gravity

        # Newton's third law: forces come in pairs, and these two
        # forces are equal in magnitude and opposite in direction
        ForceNormal = ForceDown

        ForceKineticFriction = ForceNormal * CoefficientOfKineticFriction

        AccelerationDueToKineticForce = ForceKineticFriction / puck.mass

        # velocity = initial velocity * acceleration * time
        TotalVelocity.x += -AccelerationDueToKineticForce * dt

        puckX = puck.pos.x + TotalVelocity.x * dt

    else:
        puckX = TotalVelocity.x * seconds        
    

    # position equation: y(t) = y0 + v0*t + .5 * a * t**2


    puckZ = TotalVelocity.z * seconds

    puckVelocityY += -gravity * dt
    
    mylabel.text = "velocity x: " + str(TotalVelocity.x) + "\nvelocity y: " + str(puckVelocityY)
    puck.pos = vector(puckX,puckY,puckZ)

    if TotalVelocity.x <= 0:
        finished = True

Code for Episode 6 (VPython: Force, Motion & Vectors)

from visual import *

print"""
Converted everything we can to vectors.
Eliminated excess variables.

Important points:

A vector is something with an x,y, and z componenet.

The following are always vectors:
position
velocity
acceleration
force

The magnitude of a vector gives us it's total length.
Magnitude is not a vector and it is always positive.

The norm of a vector gives us a vector in the same direction with a
magnitude of one.

A vector is equal to it's magnitude multiplied by it's norm:
aVector == mag(aVector) * norm(aVector)

A vector in the opposite direction of the same length would be the
same thing multiplied by negative one:
oppositeVector = -1 * aVector
or
oppositeVector = -1 * mag(aVector) * norm(bVector)
"""

# SET UP THE WINDOW
scene.width = 800
scene.height = 600

scene.autoscale = 0 # stop vpython from zooming in and out on its own
scene.range = (100,100,100) 
scene.center = (50,40,0) # center in on this point

# CREATE OUR PUCK OBJECT AND SET IT'S INITIAL VALUES
puck = cylinder(pos=(0,0,0),axis=(0,2,0), radius=2, color=color.green)
puck.velocity = vector(0,0,0)
puck.acceleration = vector(0,0,0)
puck.mass = 1 # kg

# CREATE A GROUND FOR THE PUCK
ground = box(pos=(50,-1,1),size=(100,2,50))

# CREATE A LABEL FOR US TO PUT INFO IN
mylabel = label(pos=(50,60,0),height=10,box=0)

# THESE ARE ALL THE ACCELERATION VECTORS THAT WILL BE
# ACTING ON OUR PUCK (IGNORE THE COLLISION FORCE AND ACCELERATION)
accelerationGravity = vector(0,-9.8,0)  # m/s**2
accelerationNormal = vector(0,0,0) # m/s**2, none until hits the ground
accelerationKineticFriction = vector(0,0,0) # m/s**2, none until hits ground

# SET UP SOME INITIAL CONDITIONS FOR THROWNING THE PUCK
velocityThrownMagnitude = 25   # m/s
angleThrown = 45     # degrees
angleThrown = angleThrown * (pi/180) # converted to radians

# CONVERTING THE VELOCITY THROWN ANGLE AND MAGNITUDE
# INTO A VECTOR
velocityThrown = vector(0,0,0)
velocityThrown.y = velocityThrownMagnitude * sin(angleThrown)
velocityThrown.x = velocityThrownMagnitude * cos(angleThrown)
velocityThrown.z = 0

# SET THE WIND VELOCITY AS A VECTOR
velocityWind = vector(0,0,-3)

# SET THE PUCK'S INITAL VELOCITY AND ACCELERATION
puck.velocity = velocityThrown + velocityWind
puck.acceleration = accelerationGravity + accelerationNormal + accelerationKineticFriction

seconds = 0 #  total time starts out at zero
dt = .01    # .01 seconds (difference in time)

finished = False
while not finished:
    rate(100) # go thru the loop no more than 100 times/s
    seconds += dt  # total time (we don't use it anymore)

    # we update the position and velocity incrementally
    # based on the last calculated acceration and its previous
    # velocity and accleration (.01 seconds ago).
    
    # velocity equation: vel = vel0 + accel * time
    # position equation: pos = pos0 + vel0*time + .5 * accel * time**2
    puck.velocity += puck.acceleration * dt
    puck.pos += puck.velocity * dt + .5 * puck.acceleration * dt**2

    # if we've hit the ground we deal with friction
    if puck.pos.y <= 0:
        # We're ignoring in the force of the collision but we'll say
        # the end result of the collision will make the velocity
        # in the y direction equal to zero
        puck.velocity.y = 0
        puck.pos.y = 0
        
        # Force Magnitude Due To Kinetic Friction = Normal Force * CoefficientKinetic
        CoefficientOfKineticFriction = .45

        # Newton's second law: Force = Mass * Acceleration
        forceGravity = puck.mass * accelerationGravity

        # Newton's third law: forces come in pairs, and these two
        # forces are equal in magnitude and opposite in direction
        forceNormal = -forceGravity

        # Newton's second law written as Acceleration = Force / Mass
        accelerationNormal = forceNormal / puck.mass

        # Figure out the magnitude of the frictional force
        forceKineticFrictionMagnitude = mag(forceNormal * CoefficientOfKineticFriction)

        # Figure out the direction of the frictional force
        forceKineticFrictionDirection = norm(puck.velocity) * -1

        # Multiply them to get the frictional force vector
        forceKineticFriction = forceKineticFrictionMagnitude * forceKineticFrictionDirection

        # Use the Force to find Acceleration: Acceleration = Force / Mass        
        accelerationKineticFriction = forceKineticFriction / puck.mass

        # Update the pucks acceleration
        puck.acceleration = accelerationNormal + accelerationGravity + accelerationKineticFriction
    
    # End the loop when the puck stops moving
    # magnitude is always positive unless it's zero
    # but due to imprecision in our program it will likely
    # never be zero so stop it when the velocity is close to zero
    if mag(puck.velocity) <= .02:
        finished = True
        puck.velocity = (0,0,0)

    # show some info as we go through the loop
    message =  "VPython Video Tutorial: Vectors (Force,Acceleration,Velocity,Position) & Kinetic Friction\n"
    message += "Puck Info:\n"
    message += "position is: " + str(puck.pos) + "\n"
    message += "velocity is: " + str(puck.velocity) + "\n"
    message += "acceleration is: " + str(puck.acceleration) + "\n"
    message += "magnitude of velocity vector is: " + str(mag(puck.velocity)) + " m/s" + "\n"
    message += "norm of velocity vector is: " + str(norm(puck.velocity))
    mylabel.text = message

Code for Episode 7 (VPython: Tension)

from __future__ import division # so 3/2 equals 1.5 instead of 1
from visual import *

print"""
A look at tension, static and kinetic friction.

This is a model of an experiment in which a book is placed on a flat table.
The book has a string tied to it with the other hand hanging off the side
of the table.  We will be adding weights to the string hanging off the edge
until the book starts sliding.

In this experiment the program will already know the coefficient of static
friction and the coefficient of kinetic friction.  When the user has added
enough mass to overcome static friction the book will slide accordingly.

The use of a pulley (not shown) helps negate friction on the string as well
as change the direction of force transmitted thru the string.  We are
approximating the the mass and friction of the string and pulley to be zero.
"""

# SET UP THE WINDOW
scene.width = 800
scene.height = 600

scene.autoscale = 1 # let vpython pick the range this time
scene.center = (1.5,.50,0) # center up and a little to the right of the origin

##########################################################################################
#
# CREATE THE OBJECTS ON OUR INITIAL SCENE
#
##########################################################################################

# CREATE A TABLE TO WORK ON
table = frame() # we want to make a table object that is built from a table top and leg.
tabletop = box(frame=table,pos=(0,1,0),size=(3,.2,1))
tableleg = cylinder(frame=table,pos=(0,0,0),axis=(0,1,0),radius=.3) # big round leg in the middle              

# CREATE THE GROUND
ground = box(size=(4,.2,1),pos=(0,-.1,0),color=color.yellow)

# CREATE OUR BOOK TO SLIDE
book = box(pos=(0,1.15,0),size=(.3,.1,.2), color=color.green)
book.mass = .1        # .1 kg
book.velocity = vector(0,0,0)
book.acceleration = vector(0,0,0)
book.force = vector(0,0,0)
book.moving = False     # it starts out at rest on the table

# ADD A STARTING MASS TO THE END OF THE STRING CREATED BELOW
weight = box(pos=(1.55,.5,0),size=(.1,.1,.1),color=color.green)
weight.mass = .02      # 20 grams = .020 kg
# we want the size of the mass to be roughly proportional to its mass
weight.size = vector(.1,weight.mass * 3,.1)  
# we want all of the increased size to be placed on top istead of
# half on top and half on the bottom so we adjust the position
weight.pos.y = .5 + (weight.size.y / 2)     
weight.velocity = vector(0,0,0)
weight.acceleration = vector(0,0,0)
weight.force = vector(0,0,0)

# TIE A STRING TO THE BOOK AND HANG THE STRING OVER THE TABLE TIED TO THE WEIGHT
string = curve(pos=[book.pos, (1.55,1.1,0)], color=color.red ) # string goes from book to slightly over edge
string.append( weight.pos ) # string goes straight down

# CREATE MASS OBJECTS TO CLICK AND LABEL DESCRIPTION
mass1 = sphere(pos=(3,2.3,.2),radius=.1,color=color.red)
mass1.mass = .001        # kg
message = "Click to add 1.0 grams."
mass1Label = label(pos=mass1.pos, text=message,yoffset=20)

mass2 = sphere(pos=(3,1.5,.2),radius=.13,color=color.blue)
mass2.mass = .005         # kg
message = "Click to add 5.0 grams."
mass2Label = label(pos=mass2.pos, text=message,yoffset=20)

# CREATE A LABEL FOR MESSAGES TO USER
mylabel = label(pos=(3.5,-1,0))

##########################################################################################
#
# CREATE VARIABLES FOR THE FORCES ACTING IN OUR PROGRAM
#
##########################################################################################

accelerationGravity = vector(0.0,-9.8,0.0)

gravityForceOnWeight = weight.mass * accelerationGravity
weight.force = gravityForceOnWeight

gravityForceOnBook = book.mass * accelerationGravity
normalForceOnBook = -1 * gravityForceOnBook

# The string pulls with the same force on both the book and weight.
# If the weight isn't moving, then the string tension (force) is equal to the
# force pulling the weight down (mass * gravity)
string.forceTensionMagnitude = mag(weight.force)

coefficientOfKineticFriction = .20      # constant for calculating kinetic friction between book and table
coefficientOfStaticFriction = .60       # constant for calculating static friction between book and table

directionBookIsBeingPulled = vector(1,0,0)

# FORMULA: magnitude of frictional force = coefficient * normal force
#          direction of frictional force = the direction opposing motion

# static frictional force acts on book when it isn't moving
# this is a maxiumum value.  It is the force that needs to be overcome
forceStaticFrictionOnBook = coefficientOfStaticFriction * mag(normalForceOnBook) * directionBookIsBeingPulled * -1
# kinetic frictional force acts on book when it is moving
forceKineticFrictionOnBook = coefficientOfKineticFriction * mag(normalForceOnBook) * directionBookIsBeingPulled * -1

##########################################################################################
#
# INITITIALIZE SOME MORE VARIABLES AND GO INTO OUR LOOP
#
##########################################################################################

book.startXpos = book.pos.x     # just to keep track of some stats
weight.startYpos = weight.pos.y # just to keep track of some stats
distanceBookTraveled = 0        # just to keep track of some stats
distanceWeightTraveled = 0      # just to keep track of some stats
dt = .01    # seconds
Finished = False
while not Finished:
    rate(100) # go thru loop no more than 100 times/sec
    if scene.mouse.events: # detect mouse events
        mouse = scene.mouse.getclick()
        if mouse.pick == mass1 or mouse.pick==mass2: # was a mass clicked?
            weight.mass += mouse.pick.mass  # add clicked mass to total mass
            weight.size = vector(.1,weight.mass * 3,.1) # same code as above
            weight.pos.y = .5 + (weight.size.y / 2)     # same code as above      

    # do we have enough force to move the book?
    if not book.moving:
        string.forceTensionMagnitude = mag(weight.mass * accelerationGravity)
        if string.forceTensionMagnitude > mag(forceStaticFrictionOnBook):
            book.moving = True # we have enough pulling force to overcome static friction

    if book.moving: # if so, we need to move everything
        # how fast are the weight and mass accelerating
        if weight.pos.y - weight.size.y/2 > 0: # if the weight hasn't landed
            # Let's write the equations that we know
            # 1. force on the weight = force pulling down - force pulling up
            # 2. force on the book = force pulling right - force holding back
            # otherwise written:
            # 1. mass of the weight * acceleration = mass of the weight * gravity - tension 
            # 2. mass of the book * acceleration = tension - frictional force on book 
            # There are two unknowns (acceleration and tension)
            # Using a bunch of algebra we get the acceleration

            # from equation 2: tension = mass of the book * acceleration + frictional force on book
            # substitute that into equation 1:
            # mass of the weight * gravity - (mass of the book * acceleration + frictional force on book) = mass of the weight * acceleration
            # use algebra to isolate acceleration variable
            # mass of the weight * acceleration + mass of the book * acceleration = mass of the weight * gravity - frictional force on book
            # acceleration (mass of the weight + mass of the book) = mass of the weight * gravity - frictional force on book
            # acceleration = (mass of the weight * gravity - frictional force on book) / (mass of the weight + mass of the book)
            accelerationMagnitude = (weight.mass * 9.8 - mag(forceKineticFrictionOnBook)) / (weight.mass + book.mass)
            weight.acceleration = accelerationMagnitude * vector(0,-1,0)
            book.acceleration = accelerationMagnitude * vector(1,0,0)            
        else: # weight has landed
            book.acceleration = forceKineticFrictionOnBook / book.mass
            string.forceTensionMagnitude = 0
            
        # move the book and weight according to their acceleration
        book.velocity += book.acceleration * dt
        book.pos += (book.velocity * dt + .5 * book.acceleration * dt**2) 
        distanceBookTraveled = book.pos.x - book.startXpos

        if weight.pos.y - weight.size.y/2 > 0: # if weight hasn't landed
            weight.velocity += weight.acceleration * dt
            weight.pos += (weight.velocity * dt + .5 * weight.acceleration * dt**2) 
            distanceWeightTraveled = weight.startYpos - weight.pos.y
       
        # keep string attached to end of book and weight
        string.pos = [ book.pos, (1.55,1.1,0), weight.pos ]

        if book.velocity.x < 0:
            Finished = True

    message = "String Tension: " + str(string.forceTensionMagnitude)
    message += "\nMax Static Frictional Force: " + str(forceStaticFrictionOnBook)
    message += "\nMax Kinetic Frictional Force: " + str(forceKineticFrictionOnBook)
    message += "\nTotal mass on string: " + str(weight.mass*1000) + " grams."
    message += "\nAcceleration of Book: " + str(book.acceleration)
    message += "\nAcceleration of Weight: " + str(weight.acceleration)
    message += "\nDistance Book Traveled: %.2f meters" % distanceBookTraveled
    message += "\nDistance Weight Traveled: %.2f meters" % distanceWeightTraveled

    mylabel.text =  message

Code for Episode 8 (VPython: Gravity)

from __future__ import division
from visual import *

print"""
In this model we will attempt to figure out the speed of the moon orbiting the
earth using Newton's Law of Universal Gravitation.

The earths mass is 5.98 * 10**24 kg
The earths radius is 6,380 km

The moons mass is 7.36 * 10**22 kg
The moons radius is 1,740 km

The center of the moon is 384000 km from the center of the earth.
The hubble space telescope orbits 600 km from the earth surface.
The international space station orbits about 360 km from the earth surface.
Geostationary orbit is 35,786 km above the earth's surface (equator).
GPS satellites orbit 20,000 km above the earth's surface.

In this episode we'll pretend the earth is stationary and ignore the satellites gravitational
pool on the earth.

To use this program:

1.  It is recommended that you uncomment the lines that
    increase the radius of the earth and satellite.

2.  Ajust the initial speed of the satellite to different speeds.  Try
    to figure out what speed gives a circular orbit by adjusting the speed
    and rerunning the program.

3.  You may need to decrease the value of dt to smaller values if you are
    trying to model satellites close to the earth.
"""

##########################################################################################
#
# FUNCTIONS
#
##########################################################################################

# this converts totalseconds to a nice string (days, hours, minutes and seconds)
def make_time_string(t):
    "Accept a number of seconds, return a relative string."
    if t < 60: return "%02i seconds"%t
    mins,secs = divmod(t, 60)
    if mins < 60: return "%02i minutes %02i seconds"%(mins,secs)
    hours, mins = divmod(mins,60)
    if hours < 24: return "%02i hours %02i minutes"%(hours,mins)
    days,hours = divmod(hours,24)
    return "%02i days %02i hours"%(days,hours)


##########################################################################################
#
# INITIALIZE WINDOW & DECLARATIONS
#
##########################################################################################

scene.center = (0,0,0)
scene.width = 800
scene.height = 600

scene.range = (1.0e9,1.0e9,1.0e9)

# some approximate data from the internet in scientific notation
# note: the following are three different ways of writing the same number
# 123000
# 1.23 * 10**5
# 1.23e5
massOfEarth = 5.98e24   # kg
massOfSatellite = 7.36e22    # kg
radiusOfEarth = 6.38e6  # m
radiusOfSatellite = 1.74e6   # m
distanceEarthToSatellite = 3.84e8  # m - the moon
#distanceEarthToSatellite = radiusOfEarth + 

# if we want to model satellites close to earth we may
# need to lower the difference in time (dt) which will
# decrease the error in our calculations but will take
# longer to run.
dt = 100 # seconds (try 100 for the moon, 1 to 10 for lower satellites)
totalseconds = 0 

# Univsal Law of Gravitation
# Gravitational Force = G * (mass1 * mass2) / r**2
# G is the univasal gravitaion constant which is about 6.67 * 10**(-11)
# r is the distance between the centers of the two masses
G = 6.67e-11


##########################################################################################
#
# CREATE EARTH AND SATELLITE OBJECTS
#
##########################################################################################

earth = sphere(pos=(0,0,0),radius=radiusOfEarth,color=color.blue)
earth.mass = massOfEarth

satellite = sphere(pos=(0,distanceEarthToSatellite,0),radius=radiusOfSatellite,color=color.white)
satellite.mass = massOfSatellite

mylabel = label(pos=(0,distanceEarthToSatellite + 100000000,0))

# when we draw things to scale as above the moon is a little hard to see
# lets pretend the moon has a much larger radius so we can see it
#satellite.radius = satellite.radius * 3
#earth.radius = earth.radius * 3 # be careful with this one as low satellites will be hidden

##########################################################################################
#
# SET INITIAL MOTION OF SATELLITE
#
##########################################################################################

# the moon will have a starting velocity that we will provide
# the direction will be left to right
speedOfSatellite = 500 # change this to how fast we think the satellite is going in m/s

# Instead of guessing we could cheat and calculate what the speed instead
# Satellites's Acceleration = Gravitational Force / Mass
# This equation is often simplified by cancelling mass2 (the saellite.mass in this case)
#initialAcceleration = (G * earth.mass * satellite.mass / distanceEarthToSatellite**2) / satellite.mass  # UNCOMMENT TO CHEAT

# Uniform Circular Motion: a = v**2/R (a is centripetal acceleration, R is the distance from the center of the circle)
# v**2 = a * R
# v = (a * R)**.5

#calculatedVelocity = (initialAcceleration * distanceEarthToSatellite)**.5 # UNCOMMENT TO CHEAT
#speedOfSatellite = calculatedVelocity # UNCOMMENT TO CHEAT

satellite.velocity = speedOfSatellite * vector(1,0,0) # m/s from left to right  


##########################################################################################
#
# GO THRU OUR LOOP
#
##########################################################################################
finished = False # it's always false so an it's an infitite loop
while not finished:
    totalseconds += dt
    rate(10000) # a high number pretty much means go as fast as our computer can
    
    # the magnitude of a vector subtracted from another is 
    # the distance between the two vectors
    distEarthToSatellite = mag(earth.pos - satellite.pos)

    # the norm of a vector subtracted from another is a
    # one unit vector in the direction of the other vector
    # See diagram of vector subtraction on wikipedia:
    # http://en.wikipedia.org/wiki/Vector_(spatial)#Vector_addition_and_subtraction
    ForceGravityOnTheSatelliteDir = norm(earth.pos - satellite.pos)    

    # calculate force magnitude from Newton's Law of Universal Gravitation
    ForceGravityOnTheSatelliteMag = G * (earth.mass * satellite.mass) / distEarthToSatellite**2

    # point that force magnitude in the direction of Earth
    ForceGravityOnTheSatellite = ForceGravityOnTheSatelliteMag * ForceGravityOnTheSatelliteDir

    # move the satellite using the force, Newton's 2nd Law, and the position equations
    satellite.acceleration = ForceGravityOnTheSatellite / satellite.mass
    satellite.velocity += satellite.acceleration * dt
    satellite.pos += satellite.velocity * dt + .5 * satellite.acceleration * dt**2

    # Display info to the user
    message = "Satellite's distance from earth's surface: %3.f kilometers" % ((distEarthToSatellite-radiusOfEarth)/1000)
    message += "\nSatellite's speed: %.0f m/s" % mag(satellite.velocity)
    message += "\nSatellite's acceleration magnitude: %.4f m/s**2" % mag(satellite.acceleration)
    message += "\nTime: " + make_time_string(totalseconds)
    mylabel.text = message

Code for Episode 9 (VPython: Spring Force)

from __future__ import division
from visual import *

print"""
Spring Force:  Hooke's Law
Force = -Spring Constant * Spring Displacement
F = -kx

The program models the motion of weight attached to a spring
after the weight is pulled (stretching the spring) and released.
Friction is ignored in this model so once started the system
never stops oscillating back and forth.
"""

##########################################################################################
#
# INITIALIZE WINDOW & DECLARATIONS
#
##########################################################################################

scene.range = vector(1,1,1)
scene.center = vector(0,0,0)
scene.width = 800
scene.height = 600


##########################################################################################
#
# CREATE SPRING, WEIGHT & LABEL OBJECTS
#
##########################################################################################

relaxedlength = vector(.60,0,0) # length of spring when it isn't stretched or compressed
spring = helix(pos=(-.75,0,0),axis=relaxedlength, radius=.1,coils=8,thickness=.01,color=color.green)
spring.constant = 2 # k

weight = box(pos=(0,0,0),size=(.3,.3,.3),color=color.yellow)
weight.mass = 10 # kg
weight.velocity = vector(0,0,0)
weight.acceleration = vector(0,0,0)
weight.force = vector(0,0,0)

frictionlessSurface = box(size=(2,.02,.5),pos=(0,-.16,0))
wall = box(size=(.04,.5,.3),pos=(-.77,.1,0),color=color.red)

mylabel = label(pos=(0,.4,0))
mylabel.text = "DRAG WEIGHT TO\nSTART"                


##########################################################################################
#
# WAIT FOR USER TO DRAG THE WEIGHT
#
##########################################################################################

pick = 0
weightmoved = False
while not weightmoved:
    if scene.mouse.events:
        mouse = scene.mouse.getevent() # obtain drag or drop event
        if mouse.drag and mouse.pick == weight: # if clicked on the weight
            drag_pos = mouse.pickpos # where on the ball the mouse was
            pick = mouse.pick # pick is now the weight object (nonzero)
            scene.cursor.visible = 0 # make cursor invisible
        elif mouse.drop: # released the mouse button at end of drag
            pick = None # end dragging (None is False)
            scene.cursor.visible = 1 # cursor visible again
            weightmoved = True
    if pick:
        new_pos = scene.mouse.project(normal=(0,0,1)) # project onto xy plane
        if new_pos != drag_pos: # if the mouse has moved since last position
            pick.pos.x += new_pos.x - drag_pos.x # offset for where the weight was clicked
            # uncomment next 2 lines to limit range spring can be pulled or compressed
            #if pick.pos.x < -.35: pick.pos.x = -.35
            #if pick.pos.x > .35:  pick.pos.x = .35                
            spring.displacement = pick.pos
            spring.axis = relaxedlength + spring.displacement 
            drag_pos = new_pos # update drag position
            message = "Springs behave according to Hooke's Law only if"
            message += "\nthey aren't stretched or compressed too far."
            message += "\nTry no more than about 35 centimeters for realistic results."
            message += "\ndisplacement: %.2f meters" % spring.displacement.x 
            mylabel.text = message

##########################################################################################
#
# PULL AND RELEASE THE WEIGHT, THEN GO THRU THE LOOP
#
##########################################################################################

spring.displacement = weight.pos # the weight starts at (0,0,0) and is attached to spring
spring.axis = relaxedlength + spring.displacement

finished = False # this will always be false so it's an infinite loop
dt = .01    # seconds
seconds = 0 # total time
while not finished:
    rate(100)
    seconds += dt
    
    # Calculate the spring force using Hooke's Law
    SpringForce = -spring.constant * spring.displacement

    # The spring force acts on the weight
    weight.force = SpringForce

    # move the weight from the applied force using 
    # Newton's 2nd law and the position equations
    weight.acceleration = weight.force/weight.mass
    weight.velocity += weight.acceleration * dt
    weight.pos += weight.velocity + .5 * weight.acceleration * dt**2

    # calculate the new spring displacement
    spring.displacement = weight.pos

    # update the length of the spring
    spring.axis = relaxedlength + spring.displacement

    # message to the user
    message = "VPython Video Tutorial: Spring Force"
    message += "\ndisplacement: %.1f" % spring.displacement.x 
    message += "\nvelocity: %.3f" % weight.velocity.x  
    message += "\nacceleration: %.2f" % weight.acceleration.x 
    message += "\nforce: % .1f" % weight.force.x
    mylabel.text = message
Personal tools