## simulate a coin flip - from visual import * scene.autoscale = 0 # updates position, velocity, angle, spin rate of coin (first arg.) # falling in a gravitational field (vector, 2nd argument), over a # time dt (number, 3rd argument), with damping (air resistance, 4th # argument). def coinspinfall(obj, g, dt, damping): obj.pos += obj.vel * dt obj.vel += g * dt obj.theta += obj.omega * dt obj.rotate(angle=obj.omega*dt, axis = (0,0,1)) # very simple model for air resistance, if needed obj.omega -= damping * dt * obj.omega obj.vel -= dt * abs(cos(obj.theta)) * damping * obj.vel # computes new velocity and spin rate, when coin bounces # takes 2 arguments. def coinbounce(coin, damp): # conserve energy, act with vertical force. # change in angular momentum is - r * cos(theta) * impulse # energy = 0.5 I om^2 + 0.5 m v^2 # delta(omega) = +/- impulse/I * cos(theta) # delta(v) = impulse/m # take I = 0.3, m = 1 # delta(E) = 0.5 I (+/-2 om * impulse *cos+ impulse^2*cos*cos) + 0.5 (2*v * impulse + impulse^2) # 2 delta(E) = impulse * (+/- 2 (om*I*cos)+(2*v) + (I*cos^2+1)*impulse) # set equal to zero, get impulse = -2*(+/- I*om*cos + v)/(I*cos^2+1) I = 0.3 ## moment of inertia, in units of m * r**2 # debug E = 0.5 * I * coin.omega*coin.omega + 0.5 * coin.vel.y * coin.vel.y co = cos(coin.theta) ## handy variable to have # debug print coin.y,coin.vel.y,coin.omega,cos(coin.theta),E if coin.y+sin(coin.theta) < 0: impulse = -2.0 * (coin.omega * co + coin.vel.y)/(co*co/I+1) coin.vel.y += impulse coin.omega += impulse/I * co coin.y = -sin(coin.theta)+0.0001 else: impulse = -2.0 * (-coin.omega * co + coin.vel.y)/(co*co/I+1) coin.vel.y += impulse coin.omega += -impulse/I* co coin.y = sin(coin.theta)+0.0001 # simple model for loss of energy during bounce coin.omega -= coin.omega * damp coin.vel -= coin.vel * damp #E = 0.5 * I * coin.omega*coin.omega + 0.5 * coin.vel.y * coin.vel.y #print impulse,cos(coin.theta),E #coinreport(coin) # Updates coin (1st arg) over time dt (third arg), # with fractional loss of speed each bounce # given by the 2nd argument. # Using zero air resistance, magnitude of gravity = 1. def coinupdate(coin, loss, dt): if coin.y+sin(coin.theta) > 0 and coin.y-sin(coin.theta)>0: damping = 0.0 coinspinfall(coin, vector(0,-1, 0), dt, damping) else: coinbounce(coin, loss) #print coin.vel.y, coin.omega, coin.y # makes a coin at position initialx along the x-axis and rotated # by an initial angle initialtheta (first and second arguments) def makecoin(initialx, initialtheta): coin = frame(pos=(initialx,10,0)) coin.vel = vector(0,0,0) coin.theta = initialtheta coin.rotate(axis=(0,0,1),angle=coin.theta) coin.omega = 0.0 cyl1 = cylinder(frame=coin,axis=(0,0.1,0),color=color.green) cyl2 = cylinder(frame=coin,axis=(0,-0.1,0),color=color.red) return coin # returns true if the coin is still moving; if very slow, returns false. def coinmoving(coin): return abs(coin.vel.y) > 0.1 or abs(coin.y) > 0.02 # reports which side is facing up def coinreport(coin): print "Report on coin at position",coin.x, if cos(coin.theta) >0: print " Facing green up - Heads" else: print " Facing red up - Tails"