In [ ]:
from vpython import *
# Gyroscope hanging from a spring
# Bruce Sherwood
scene.title = 'Gyroscope'
scene.background = color.gray(0.9)
top = vector(0,1,0) # where top of spring is held
ks = 100 # spring stiffness
Lspring = 1 # unstretched length of spring
Rspring = 0.03 # radius of spring
Dspring = 0.03 # thickness of spring wire
Lshaft = 1 # length of gyroscope shaft
Rshaft = 0.03 # radius of gyroscope shaft
M = 1 # mass of gyroscope (massless shaft)
Rrotor = 0.4 # radius of gyroscope rotor
Drotor = 0.1 # thickness of gyroscope rotor
omega = 40 # angular speed of rotor around axis
Dsquare = 1.4*Drotor # thickness of square that turns with rotor
I = 0.5*M*Rrotor**2 # moment of inertia of gyroscope
g = 9.8
Fgrav = vector(0,-M*g,0)
precession = M*g*(Lshaft/2)/(I*abs(omega)) # exact precession angular velocity
phi = atan(precession**2*(Lshaft/2)/g) # approximate angle of spring to vertical
s = M*g/(ks*cos(phi)) # approximate stretch of spring
# Refine estimate of angle of spring to vertical:
phi = 1/( ((I*abs(omega))/(M*Lshaft/2))**2/(g*Lshaft/2)-(Lspring+s)/(Lshaft/2) )
# Refine again:
s = M*g/(ks*cos(phi))
phi = 1/( ((I*abs(omega))/(M*Lshaft/2))**2/(g*Lshaft/2)-(Lspring+s)/(Lshaft/2) )
pprecess = vector(0,-1,M*precession*(Lshaft/2+(Lspring+s)*sin(phi)))
# Momentum required for completely smooth precession:
##pprecess = vector(0,0,M*precession*(Lshaft/2+(Lspring+s)*sin(phi)))
if omega < 0:
pprecess = -pprecess
support = box(pos=top+vector(0,0.01,0), size=vector(0.2,0.02,0.2), color=color.green)
spring = helix(pos=top, axis=vector(-(Lspring+s)*sin(phi),
-(Lspring+s)*cos(phi),0), coils=10, radius=Rspring,
thickness=Dspring, color=vector(1,0.7,0.2))
gyropos = top+spring.axis
gyroaxis = vector(1,0,0)
shaft = cylinder(pos=vector(0,0,0), axis=Lshaft*gyroaxis,
radius=Rshaft, color=color.gray(0.8))
rotor = cylinder(pos=0.5*gyroaxis*(Lshaft-Drotor),
axis=gyroaxis*Drotor, radius=Rrotor, color=color.gray(0.8))
stripe1 = box(color=color.black, size=vector(.01,2*Rrotor,.01),
pos=rotor.pos+1.02*rotor.axis)
stripe2 = box(color=color.black, size=vector(.01,2*Rrotor,.01),
pos=rotor.pos-0.02*rotor.axis)
gyro = compound([shaft,rotor,stripe1,stripe2],
pos=gyropos, axis=gyroaxis)
gyro.texture = textures.metal
gyro.rotate(axis=vector(0,1,0), angle=pi)
# center of mass of shaft
cm = gyro.pos+0.5*Lshaft*gyro.axis
Lrot = I*omega*gyro.axis
p = pprecess
dt = 0.01
t = 0
while True:
rate(50)
Fspring = -ks*norm(spring.axis)*(mag(spring.axis)-Lspring)
# Calculate torque about center of mass:
torque = cross(-0.5*Lshaft*gyro.axis,Fspring)
Lrot = Lrot+torque*dt
p = p+(Fgrav+Fspring)*dt
cm = cm+(p/M)*dt
# Update positions of shaft, rotor, spring, stripes
if omega > 0:
gyro.axis = norm(Lrot)
else:
gyro.axis = -norm(Lrot)
gyro.pos = cm-0.5*Lshaft*gyro.axis # shaft rotated, adjust connection to spring
spring.axis = gyro.pos - top
gyro.rotate(angle=omega*dt/4, axis=gyro.axis) # spin easier to see if slower than actual omega
In [ ]: