top_direction.pos = -sys[:,2] * top_direction.height / 2.0 - offset top_axis.axis = sys[:,1] * top_axis.height top_body.axis = sys[:,1] * top_body.height top_direction.axis = sys[:,2] * top_direction.height top_trail.append(pos = -offset * 2) display(width = 800, height = 600) theta = pi / 12.0 dt = 0.002 sys = np.matrix(np.identity(3)) omega_p = uy * 20 sys = sys.rotate(theta * -uz) omega_p = omega_p.rotate(theta, -uz) top = cylinder(radius = 5, height = 0.5, mass = 5) top_axis = cylinder(radius = 0.25, height = 10) top_direction = cylinder(radius = 0.27, height = 11, color = color.red) top_trail = curve(color = color.red) axes = cylinder_principal_axes(top.mass, 2.5, 5) # Optional code to provide initial angular velocity to cancel out nutations omega_precession = top.mass * 9.8 * (top_axis.height / 2) / (axes[1] * mag(omega_p)) * uy # omega_p += omega_precession arrow_offset = vector(-12, 0, 0) omega_axis = arrow(pos = arrow_offset + uy * 4, shaftwidth = 0, color = color.yellow, opacity = 1)
omega_axis = arrow(pos = vector(-8, -8, -8), shaftwidth = 0, color = color.yellow, opacity = 1) l_axis = arrow(pos = vector(-8, -10, -8), shaftwidth = 0, color = color.green, opacity = 1) while True: # Convert omega-prime to omega omega = (sys.I * omega_p.mat()).vec() # Update omega from Euler's equations torque = vector() omega += delta_omega(axes, omega, torque) * dt # Calculate l-prime from omega and compensate angular velocity l = (sys * (inertia_tensor(axes) * omega.mat())).vec() # Convert omega back to omega-prime omega_p = (sys * omega.mat()).vec() # Rotate coordinate system by omega-prime sys = sys.rotate(omega_p * dt) # Rotate object to match coordinate system orient_top(top, top_axis, top_direction, sys) # Update diagnostics omega_axis.axis = norm(omega_p) * 3 l_axis.axis = norm(l) * 3 rate(300)