top = vector(0, 2, 0) # where top of spring is held precess = vector(0, 0, 0) # initial momentum of center of mass Fgrav = vector(0, -M*9.81, 0) gaxis = vector(0, 0, 1) # initial orientation of gyroscope gaxis = norm(gaxis) I = 1/2*M*R**2 # moment of inertia of gyroscope Lrot = I*omega*gaxis # angular momentum cm = gpos + 0.5*Ls*gaxis # center of mass of shaft # ############################################################ the scene vp = Plotter(verbose=0, axes=3, interactive=0) shaft = vp.cylinder([[0,0,0], Ls*gaxis], r=0.03, c='dg') rotor = vp.cylinder([(Ls-0.55)*gaxis, (Ls-0.45)*gaxis], r=R, c='t') bar = vp.cylinder([Ls*gaxis/2-R*vector(0,1,0), Ls*gaxis/2+R*vector(0,1,0)], r=R/6, c='r') gyro = vp.makeAssembly([shaft, rotor, bar]) # group actors into a single one spring= vp.helix(top, gpos, r=0.06, thickness=0.01, c='gray') box = vp.box(top, length=0.2, width=0.02, height=0.2, c='gray') # ############################################################ the physics pb = ProgressBar(0, 5, dt, c='b') for t in pb.range(): Fspring = -ks*norm(gpos-top)*(mag(gpos-top)-Lrest) torque = cross(-1/2*Ls*norm(Lrot), Fspring) # torque about center of mass Lrot += torque*dt precess += (Fgrav+Fspring)*dt # momentum of center of mass cm += (precess/M)*dt gpos = cm - 1/2*Ls*norm(Lrot) # set orientation along gaxis and rotate it around its axis by omega*t degrees
# ############################################################ g, r = 9.81, Lshaft/2 I3 = 1/2*M*R**2 # moment of inertia, I, of gyroscope about its own axis I1 = M*r**2 + 1/2*I3 # I about a line through the support, perpendicular to axis phi = psi = thetadot = 0 x = vector(theta, phi, psi) # Lagrangian coordinates v = vector(thetadot, phidot, psidot) # ############################################################ the scene vp = Plotter(verbose=0, axes=3, interactive=0) shaft = vp.cylinder([[0,0,0], [Lshaft,0,0]], r=.03, c='dg') rotor = vp.cylinder([[Lshaft/2.2,0,0],[Lshaft/1.8,0,0]], r=R, texture='marble') base = vp.sphere([ 0, 0, 0], c='dg', r=.03) tip = vp.sphere([Lshaft, 0, 0], c='dg', r=.03) gyro = vp.makeAssembly([shaft, rotor, base, tip]) # group relevant actors pedestal = vp.box([0,-0.63,0], height=.1, length=.1, width=1, texture='wood5') pedbase = vp.box([0,-1.13,0], height=.5, length=.5, width=.05, texture='wood5') pedpin = vp.pyramid([0,-.08,0], axis=[0,1,0], s=.05, height=.12, texture='wood5') formulas = vp.load('data/images/gyro_formulas.png', alpha=.9).scale(.003).pos([-1,-1,-1.1]) # ############################################################ the physics pb = ProgressBar(0, 4, dt, c='b') for i, t in enumerate(pb.range()): st, ct, sp, cp = sin(x[0]), cos(x[0]), sin(x[1]), cos(x[1]) thetadot, phidot, psidot = v # unpack atheta = st*ct*phidot**2 + (M*g*r*st-I3*(psidot+phidot*ct)*phidot*st)/I1 aphi = (I3/I1)*(psidot+phidot*ct)*thetadot/st - 2*ct*thetadot*phidot/st apsi = phidot*thetadot*st - aphi*ct
# Make a icon actor to indicate orientation or for comparison # and place it in one of the 4 corners within the same renderer # from vtkplotter import Plotter vp = Plotter(axes=5) # type 5 builds an annotated orientation cube act = vp.load('data/270.vtk', c='blue', bc='v') vp.render() a1 = vp.load('data/250.vtk', c=2) a2 = vp.load('data/290.vtk', alpha=.4) icon = vp.makeAssembly([a1, a2]) vp.addIcon(icon, pos=4) # 4=bottom-right lg = vp.load('data/images/embl_logo.jpg') vp.addIcon(lg, pos=1) vp.show(act)