def _update_anim(self): import vpython as vp g = self.domain_param['g'] m_ball = self.domain_param['m_ball'] r_ball = self.domain_param['r_ball'] m_beam = self.domain_param['m_beam'] l_beam = self.domain_param['l_beam'] d_beam = self.domain_param['d_beam'] ang_offset = self.domain_param['ang_offset'] c_frict = self.domain_param['c_frict'] x = float(self.state[0]) # ball position along the beam axis [m] a = float(self.state[1]) # angle [rad] # Update the animation self._anim['ball'].radius = r_ball self._anim['ball'].pos = vp.vec( vp.cos(a)*x - vp.sin(a)*(d_beam/2. + r_ball), vp.sin(a)*x + vp.cos(a)*(d_beam/2. + r_ball), 0 ) self._anim['beam'].size = vp.vec(l_beam, d_beam, 2*d_beam) self._anim['beam'].rotate( angle=float(self.state[3])*self._dt, axis=vp.vec(0, 0, 1), origin=vp.vec(0, 0, 0) ) # Set caption text self._anim['canvas'].caption = f"""
def init_stars(radius,size,num_star): ''' Generate background stars ''' for i in range(int(num_star)): theta = rd.uniform(0,2*np.pi) phi = rd.uniform(0,np.pi) vp.sphere(pos=radius*model_scale*vp.vector(vp.sin(theta)*vp.cos(phi),vp.sin(theta)*vp.sin(phi),vp.cos(theta)), radius=model_scale*size,color=vp.color.white)
def main(): ''' Set up Stationary scene ''' scene = vp.canvas(title='Solar system',width=1300,height=600,center=vp.vector(0,0,0)) scene.autoscale = False scene.range = star_radius*model_scale scene.camera.pos = vp.vector(0,100000,star_radius*model_scale) # nice view # scene.camera.pos = vp.vector(100000,0,0) # side view # scene.camera.pos = vp.vector(0,100000,0) # top down view scene.camera.axis = vp.vector(vp.vector(0,0,0) - scene.camera.pos) # Background stars if show_backgound_stars == True: init_stars(star_radius, star_size, num_star) ''' Set up Animated objects ''' # Intialize Asteroid belt if show_asteroid_belt == True: print('Generating asteroid belt') ast_list, ast_radius_list, ast_theta0_list = init_belt(ast_belt_radius, ast_size, num_ast) # Initialize Kuiper belt if show_kuiper_belt == True: print('Generating kuiper belt') kui_list, kui_radius_list, kui_theta0_list = init_belt(kui_belt_radius, kui_size, num_kui) # Initialize planet system object_list = init_system(filename) ''' Animation ''' print('Begin animation') dt = 100 i = 0 # Counter for moving the belts while True: vp.rate(500000) # update planet position for body in object_list: body.motion(dt, i) # rotate asteroid belt and kuiper belt if rotate_belt == True and show_asteroid_belt == True: # shift theta of all belt objects for ast, ast_radius, ast_theta0 in zip(ast_list, ast_radius_list, ast_theta0_list): ast_theta = ast_theta0 + i * 2*np.pi/ast_belt_period # change in theta per unit time = omega = 2pi/T ast.pos = model_scale*ast_radius*vp.vector(vp.cos(ast_theta),0,vp.sin(ast_theta)) if rotate_belt == True and show_kuiper_belt == True: for kui, kui_radius, kui_theta0 in zip(kui_list, kui_radius_list, kui_theta0_list): kui_theta = kui_theta0 + i * 2*np.pi/kui_belt_period kui.pos = model_scale*kui_radius*vp.vector(vp.cos(kui_theta),0,vp.sin(kui_theta)) if i%int(print_step) == 0: print('Celestial object positions update completed - Running next iteration') i += 1
def _init_anim(self): import vpython as vp l_pole = float(self.domain_param['l_pole']) r_pole = 0.05 th, _ = self.state # Init render objects on first call self._anim['canvas'] = vp.canvas(width=1000, height=600, title="Pendulum") # Joint self._anim['joint'] = vp.sphere( pos=vp.vec(0, 0, r_pole), radius=r_pole, color=vp.color.white, ) # Pole self._anim['pole'] = vp.cylinder(pos=vp.vec(0, 0, r_pole), axis=vp.vec(2 * l_pole * vp.sin(th), -2 * l_pole * vp.cos(th), 0), radius=r_pole, length=2 * l_pole, color=vp.color.blue, canvas=self._anim['canvas'])
def init_belt(belt_radius, size_range, num_rock): ''' Generate the ring-like belts ''' rock_list = [] radius_list = [] theta0_list = [] # Create objects in a belt at random positions following a normal distribution radius_mean = np.mean(belt_radius) # radius range of belt radius_std = (belt_radius[1] - belt_radius[0]) / 4. # estimated std for i in range(int(num_rock)): loading = (i + 1) / num_rock * 100 if loading % 10 == 0: print('loading... ', int(loading), '%') radius = np.random.normal(radius_mean, radius_std) size = rd.uniform(size_range[0], size_range[1]) / 2. # radius theta0 = rd.uniform(0, 2 * np.pi) rock = vp.sphere( pos=model_scale * vp.vector(radius * vp.cos(theta0), 0, radius * vp.sin(theta0)), radius=model_scale * size, color=vp.color.white) rock_list.append(rock) radius_list.append(radius) theta0_list.append(theta0) return rock_list, radius_list, theta0_list
def _init_anim(self): import vpython as vp r_ball = self.domain_param['r_ball'] l_beam = self.domain_param['l_beam'] d_beam = self.domain_param['d_beam'] x = float(self.state[0]) # ball position along the beam axis [m] a = float(self.state[1]) # angle [rad] self._anim['canvas'] = vp.canvas(width=800, height=600, title="Ball on Beam") self._anim['ball'] = vp.sphere( pos=vp.vec(x, d_beam/2. + r_ball, 0), radius=r_ball, color=vp.color.red, canvas=self._anim['canvas'] ) self._anim['beam'] = vp.box( pos=vp.vec(0, 0, 0), axis=vp.vec(vp.cos(a), vp.sin(a), 0), length=l_beam, height=d_beam, width=2*d_beam, color=vp.color.green, canvas=self._anim['canvas'] )
def __init__(self, pos, ori, rad, thi, I, no_of_seg, turns=1): self.pos = pos self.ori = ori self.rad = rad self.thi = thi self.I = I self.no_of_seg = no_of_seg self.turns = turns self.ring = vp.ring(pos=self.pos, axis=self.ori, radius=self.rad, thickness=self.thi) element_length = (2 * np.pi * self.rad) / self.no_of_seg segments = [0] * (self.no_of_seg) for i in range(self.no_of_seg): theta = i * (2 * np.pi / self.no_of_seg) y = self.rad * np.cos(theta) z = self.rad * np.sin(theta) segments[i] = vp.cylinder( pos=vp.vec(self.pos.x, self.pos.y + y, self.pos.z + z), axis=element_length * vp.vec(0, -vp.sin(theta), vp.cos(theta)), radius=self.thi) segments[i].visible = False self.segments = segments print('done')
def _update_anim(self): import vpython as vp g = self.domain_param['g'] l_plate = self.domain_param['l_plate'] m_ball = self.domain_param['m_ball'] r_ball = self.domain_param['r_ball'] eta_g = self.domain_param['eta_g'] eta_m = self.domain_param['eta_m'] K_g = self.domain_param['K_g'] J_m = self.domain_param['J_m'] J_l = self.domain_param['J_l'] r_arm = self.domain_param['r_arm'] k_m = self.domain_param['k_m'] R_m = self.domain_param['R_m'] B_eq = self.domain_param['B_eq'] c_frict = self.domain_param['c_frict'] V_thold_x_neg = self.domain_param['V_thold_x_neg'] V_thold_x_pos = self.domain_param['V_thold_x_pos'] V_thold_y_neg = self.domain_param['V_thold_y_neg'] V_thold_y_pos = self.domain_param['V_thold_y_pos'] offset_th_x = self.domain_param['offset_th_x'] offset_th_y = self.domain_param['offset_th_y'] d_plate = 0.01 # only for animation # Compute plate orientation a_vp = -self.plate_angs[0] # plate's angle around the y axis (alpha) b_vp = self.plate_angs[1] # plate's angle around the x axis (beta) # Axis runs along the x direction self._anim['plate'].size = vp.vec(l_plate, l_plate, d_plate) self._anim['plate'].axis = vp.vec(vp.cos(a_vp), 0, vp.sin(a_vp)) * float(l_plate) # Up runs along the y direction (vpython coordinate system) self._anim['plate'].up = vp.vec(0, vp.cos(b_vp), vp.sin(b_vp)) # Get ball position x = self.state[2] # along the x axis y = self.state[3] # along the y axis self._anim['ball'].pos = vp.vec( x * vp.cos(a_vp), y * vp.cos(b_vp), r_ball + x * vp.sin(a_vp) + y * vp.sin(b_vp) + vp.cos(a_vp) * d_plate / 2.) self._anim['ball'].radius = r_ball # Set caption text self._anim['canvas'].caption = f"""
def motion(self, dt): ''' Rotate rod in SHM ''' self.dt = dt # Update position, omega and alpha self.theta += self.omega*dt self.alpha = - kappa / self.inertia * self.theta self.omega += self.alpha*dt # Update rod position and axis self.rod.pos = vp.vector(self.length/2.*vp.cos(self.theta),self.y_location,-self.length/2.*vp.sin(self.theta)) self.rod.axis = vp.vector(-self.length*vp.cos(self.theta),0,self.length*vp.sin(self.theta))
def _reset_anim(self): import vpython as vp r_ball = self.domain_param['r_ball'] l_beam = self.domain_param['l_beam'] d_beam = self.domain_param['d_beam'] self._anim['ball'].pos = vp.vec( float(self.state[0]), vp.sin(self.state[1]) * float(self.state[0]) + vp.cos(self.state[1]) * d_beam / 2. + r_ball, 0) self._anim['beam'].visible = False self._anim['beam'] = vp.box(pos=vp.vec(0, 0, 0), axis=vp.vec(vp.cos(float(self.state[1])), vp.sin(float(self.state[1])), 0), length=l_beam, height=d_beam, width=2 * d_beam, color=vp.color.green, canvas=self._anim['canvas'])
def _init_anim(self): import vpython as vp l_pole = float(self.domain_param['l_pole']) l_rail = float(self.domain_param['l_rail']) # Only for animation l_cart, h_cart = 0.08, 0.08 r_pole, r_rail = 0.01, 0.005 # Get positions x, th, _, _ = self.state self._anim['canvas'] = vp.canvas(width=1000, height=600, title="Quanser Cartpole") # Rail self._anim['rail'] = vp.cylinder( pos=vp.vec(-l_rail / 2, -h_cart / 2 - r_rail, 0), # a VPython's cylinder origin is at the bottom radius=r_rail, length=l_rail, color=vp.color.white, canvas=self._anim['canvas']) # Cart self._anim['cart'] = vp.box(pos=vp.vec(x, 0, 0), length=l_cart, height=h_cart, width=h_cart / 2, color=vp.color.green, canvas=self._anim['canvas']) self._anim['joint'] = vp.sphere( pos=vp.vec(x, 0, r_pole + h_cart / 4), radius=r_pole, color=vp.color.white, ) # Pole self._anim['pole'] = vp.cylinder(pos=vp.vec(x, 0, r_pole + h_cart / 4), axis=vp.vec(2 * l_pole * vp.sin(th), -2 * l_pole * vp.cos(th), 0), radius=r_pole, length=2 * l_pole, color=vp.color.blue, canvas=self._anim['canvas'])
def motion(self, dt, other_objects, i): ''' Update object positions as a function of timestep ''' self.other_objects = other_objects # Verlocity verlet method # Update body position, velocity and acceleration relative to all other objects self.position, self.velocity, self.acceleration = velocity_verlet( self.centr_body, self.other_objects, self.position, self.velocity, self.acceleration, dt) # Update vpython sphere location self.sphere.pos = self.position * model_scale if self.is_moon == False: # Update text position self.label.pos = model_scale * vp.vector( self.position.x, self.position.y + 5e9 * model_scale, self.position.z) # Update trojan belt position to follow jupiter if self.name == 'Jupiter' and show_trojan_belt == True: for tro_rock, radius, theta0 in zip(self.tro_rock_list, self.tro_radius_list, self.tro_theta0_list): # Change in theta, from original position to updated self.position updated_theta = np.arctan(self.position.x / self.position.z) if self.position.z < 0: updated_theta += np.pi j_del_theta = updated_theta - self.init_j_theta # new theta = starting angle of rock relative to original theta + jupiter's moved theta theta = theta0 + j_del_theta tro_rock.pos = model_scale * vp.vector( radius * vp.sin(theta), 0, radius * vp.cos(theta)) if show_arrows == True: self.arrow.pos = model_scale * self.position self.arrow.axis = self.velocity # Print planet's updated position if i % int(print_step) == 0 and self.is_moon == False: print(self.name, 'at location', self.position)
def _update_anim(self): import vpython as vp g = self.domain_param['g'] m_pole = self.domain_param['m_pole'] l_pole = float(self.domain_param['l_pole']) d_pole = self.domain_param['d_pole'] tau_max = self.domain_param['tau_max'] r_pole = 0.05 th, _ = self.state # Cart self._anim['joint'].pos = vp.vec(0, 0, r_pole) # Pole self._anim['pole'].pos = vp.vec(0, 0, r_pole) self._anim['pole'].axis = vp.vec(2 * l_pole * vp.sin(th), -2 * l_pole * vp.cos(th), 0) # Set caption text self._anim['canvas'].caption = f"""
def _update_anim(self): import vpython as vp g = self.domain_param['g'] m_cart = self.domain_param['m_cart'] m_pole = self.domain_param['m_pole'] l_pole = float(self.domain_param['l_pole']) l_rail = float(self.domain_param['l_rail']) eta_m = self.domain_param['eta_m'] eta_g = self.domain_param['eta_g'] K_g = self.domain_param['K_g'] J_m = self.domain_param['J_m'] R_m = self.domain_param['R_m'] k_m = self.domain_param['k_m'] r_mp = self.domain_param['r_mp'] B_eq = self.domain_param['B_eq'] B_pole = self.domain_param['B_pole'] # Only for animation l_cart, h_cart = 0.08, 0.08 r_pole, r_rail = 0.01, 0.005 # Get positions x, th, _, _ = self.state # Rail self._anim['rail'].pos = vp.vec(-l_rail / 2, -h_cart / 2 - r_rail, 0) self._anim['rail'].length = l_rail # Cart self._anim['cart'].pos = vp.vec(x, 0, 0) self._anim['joint'].pos = vp.vec(x, 0, r_pole + h_cart / 4) # Pole self._anim['pole'].pos = vp.vec(x, 0, r_pole + h_cart / 4) self._anim['pole'].axis = vp.vec(2 * l_pole * vp.sin(th), -2 * l_pole * vp.cos(th), 0) # Set caption text self._anim['canvas'].caption = f"""
def reset(): global theta, thetadot, psi, psidot, phi, phidot theta = 0.3*vp.pi # initial polar angle of shaft (from vertical) thetadot = 0 # initial rate of change of polar angle psi = 0 # initial spin angle psidot = 30 # initial rate of change of spin angle (spin ang. velocity) phi = -vp.pi/2 # initial azimuthal angle phidot = 0 # initial rate of change of azimuthal angle if pureprecession: # Set to True if you want pure precession, without nutation a = (1-I3/I1)*vp.sin(theta)*vp.cos(theta) b = -(I3/I1)*psidot*vp.sin(theta) c = M*g*r*vp.sin(theta)/I1 phidot = (-b+vp.sqrt(b**2-4*a*c))/(2*a) gyro.axis = gyro.length * \ vp.vector(vp.sin(theta)*vp.sin(phi), vp.cos(theta), vp.sin(theta)*vp.cos(phi)) A = vp.norm(gyro.axis) gyro.pos = 0.5*Lshaft*A tip.pos = Lshaft*A tip.clear_trail()
from vpython import sphere, vector, sin, cos, rate, pi s = sphere() t = 0 # seconds dt = 0.001 # seconds R = 10 # meters omega = 3.14 # radians/second s.pos = vector(R * cos(omega * t), R * sin(omega * t), 0) s.velocity = omega * R * vector(-sin(t * omega), cos(t * omega), 0) while t < 2 * 2 * pi / omega: s.velocity = omega * R * vector(-sin(t * omega), cos(t * omega), 0) s.pos = s.pos + s.velocity * dt t = t + dt rate(1 / dt)
def in_strikezone(): return in_boundary(strikezone.pos.x, strikezone.size.x, ball.pos.x) and \ in_boundary(strikezone.pos.y, strikezone.size.y, ball.pos.y) and \ in_boundary(strikezone.pos.z, strikezone.size.z, ball.pos.z) gravity = 0.447 * vec(0, -9.8, 0) ball = sphere() ball.pos = 0.305 * vec(0, 5 + (10 / 12), 0) ball.radius = 0.305 * 1.45 / 12 angle = atan( (strikezone.pos.y - ball.pos.y) / (strikezone.pos.x - ball.pos.x)) + 0.03 ball.velocity = 0.447 * 120 * vec(cos(angle), sin(angle), 0) trail = curve(color=color.blue, pos=ball.pos) t = 0 dt = 0.0001 C = 1.0 A = ball.radius**2 * pi p = 1.2 wind = vec(0, 0, 40) def drag(v, C, p, A): return 0.5 * C * p * A * v.mag * v
t = 0 dt = 0.01 # s s = sphere() spring = helix(radius=0.6, thickness=0.3) s.velocity = vector(-10, 0, 0) s.pos = vector(10, 0, 0) * dt # m s.prev_pos = s.pos - s.velocity * dt # m thermal_energy = 0 while t < 12.0 * pi: kinetic_energy = 0.5 * m * dot(s.velocity, s.velocity) potential_energy = 0.5 * k * dot(s.prev_pos, s.prev_pos) thermal_energy += d * dot(s.velocity, s.velocity) * dt s.force = -k * s.pos - d * s.velocity + 3.0 * sin(1.0 * t) * vector( 1, 0, 0) temp = copy(s.prev_pos) s.pos, s.prev_pos = 2 * s.pos - s.prev_pos + s.force * dt**2 / m, 1 * s.pos s.velocity = (s.pos - temp) / (2 * dt) spring.axis = s.pos - spring.pos t += dt rate(1 / dt) kinetic.plot(pos=(t, kinetic_energy)) potential.plot(pos=(t, potential_energy)) thermal.plot(pos=(t, thermal_energy)) energy.plot(pos=(t, kinetic_energy + potential_energy + thermal_energy))
thickness=.1) angle = 0 da = .01 trail = vp.curve(color=vp.color.magenta, radius=.02) trail.append(vp.vector(1, 0, 0)) trail.append(vp.vector(1, 0, 2)) trail.append(vp.vector(2, 0, 2)) while angle < 3 * vp.pi / 4: vp.rate(100) ptr.rotate(angle=da, axis=vp.vector(0, 0, 1), origin=ptr.pos) trail.append(ptr.pos + ptr.axis) angle += da vp.sleep(1) # sleep for 1 second vp.scene.autoscale = False vp.scene.append_to_caption("""Drag the mouse and you'll drag a sphere. On a touch screen, press and hold, then drag.""") t = 0 dt = .01 y0 = gslabel.pos.y ball_yo = ball.pos.y while t < 10: vp.rate(1 / dt) ball.pos.y = ball_yo + 0.5 * vp.sin(-4 * t) spring.length = ball.pos.y - spring.pos.y - ball.radius + 0.15 gslabel.yoffset = 28 * vp.sin(-4 * t) t += dt
bar2.rotate(angle=-vp.pi / 2, axis=vp.vec(0, 0, 1), origin=vp.vec(axle2.pos.x, axle2.pos.y, bar2.pos.z)) bar2.rotate(angle=theta2, axis=vp.vec(0, 0, 1), origin=vp.vec(axle2.pos.x, axle2.pos.y, bar2.pos.z)) dt = 0.0002 t = 0 while True: vp.rate(1 / dt) # Calculate accelerations of the Lagrangian coordinates= atheta1 = ( (E * C / B) * vp.sin(theta1) - F * vp.sin(theta2)) / (D - E * A / B) atheta2 = -(A * atheta1 + C * vp.sin(theta1)) / B # Update velocities of the Lagrangian coordinates= theta1dot = theta1dot + atheta1 * dt theta2dot = theta2dot + atheta2 * dt # Update Lagrangian coordinates= dtheta1 = theta1dot * dt dtheta2 = theta2dot * dt theta1 = theta1 + dtheta1 theta2 = theta2 + dtheta2 bar1.rotate(angle=dtheta1, axis=vp.vec(0, 0, 1), origin=pivot1) bar1b.rotate(angle=dtheta1, axis=vp.vec(0, 0, 1), origin=pivot1) pivot2 = vp.vec(axle2.pos.x, axle2.pos.y, pivot1.z) axle2.rotate(angle=dtheta1, axis=vp.vec(0, 0, 1), origin=pivot1) bar2.rotate(angle=dtheta2, axis=vp.vec(0, 0, 1), origin=pivot2)
def f(x, y): # Return the value of the function of x and y: return 0.7+0.2*vp.sin(10*x)*vp.cos(10*y)*vp.sin(5*t)
def justOne(func, x0, tEnd=10, deltat=0.005): """ Double pendulum simulation via VPython given an R^4 -> R^4 differential equation (allows the testing of various such ODEs) Adapted from https://trinket.io/glowscript/9bdab2cf88 Arguments func: python function, R^4 -> R^4 system of ODEs x0: list with 4 elements, initial condition to integrate from in the form [theta1, omega1, theta2, omega2] tEnd: time to integrate until deltat: spacing between sampled functional values (note: not the step the integrator uses) """ # constants t = 0 theta1, omega1, theta2, omega2 = x0 L1 = 1 L2 = 1 vp.canvas(width=1400, height=750, background=vp.color.white, range=1.75, autoscale=False, userpan=False, userspin=False, userzoom=False) # create the ceiling, masses, and strings ceiling = vp.box(pos=vec(0, 1, 0), size=vec(0.1, 0.05, 0.1), color=vp.color.gray(0.5)) rball1 = vp.sphere(pos=vec(ceiling.pos.x + L1 * vp.sin(theta1), ceiling.pos.y - L1 * vp.cos(theta1), 0), radius=0.05, color=vp.color.orange) rball1.color = vp.color.black rball1.radius = 0.05 rball2 = vp.sphere(pos=vec( ceiling.pos.x + L1 * vp.sin(theta1) + L2 * vp.sin(theta2), ceiling.pos.y - L1 * vp.cos(theta1) - L2 * vp.cos(theta2), 0), radius=0.05, color=vp.color.black, make_trail=True, interval=10, retain=15) rball2.color = vp.color.black rball2.radius = 0.05 rstring1 = vp.cylinder(pos=ceiling.pos, axis=rball1.pos - ceiling.pos, color=vp.color.gray(0.5), radius=0.008) rstring2 = vp.cylinder(pos=rball1.pos, axis=rball2.pos - rball1.pos, color=vp.color.gray(0.5), radius=0.008) # generating simulation data actualSol = solve_ivp(func, [0, tEnd], x0, t_eval=np.linspace(0, tEnd, int(tEnd / deltat))) # calculation loop while t < tEnd / deltat: vp.rate(1 / deltat) rball1.pos = vec(vp.sin(actualSol.y[0][t]), -vp.cos(actualSol.y[0][t]), 0) + ceiling.pos rstring1.axis = rball1.pos - ceiling.pos rball2.pos = rball1.pos + vec(vp.sin(actualSol.y[2][t]), -vp.cos(actualSol.y[2][t]), 0) rstring2.axis = rball2.pos - rball1.pos rstring2.pos = rball1.pos t = t + 1 stop_server()
z = L * vp.random() - L / 2 if i == 0: Atoms.append( vp.sphere(pos=vp.vector(x, y, z), radius=Ratom, color=vp.color.cyan, make_trail=True, retain=100, trail_radius=0.3 * Ratom)) else: Atoms.append( vp.sphere(pos=vp.vector(x, y, z), radius=Ratom, color=gray)) apos.append(vp.vector(x, y, z)) theta = vp.pi * vp.random() phi = 2 * vp.pi * vp.random() px = pavg * vp.sin(theta) * vp.cos(phi) py = pavg * vp.sin(theta) * vp.sin(phi) pz = pavg * vp.cos(theta) p.append(vp.vector(px, py, pz)) deltav = 100 # binning for v histogram def barx(v): return int(v / deltav) # index into bars array nhisto = int(4500 / deltav) histo = [] for i in range(nhisto): histo.append(0.0)
body = sphere(radius = 0.05) body.color = color.orange R = 1 body.pos = vector(1,0,0) attach_trail(body) omega = 5 # rad/s # modulo della velocità angolare time = 0 dt = 0.001 axis_x = arrow(pos=vector(0,0,0), axis=vector(1,0,0), shaftwidth=0.01) axis_y = arrow(pos=vector(0,0,0), axis=vector(0,1,0), shaftwidth=0.01) while True: rate(100) time = time + dt body.pos.x = R* cos(omega*time) # coordinata x in un moto circolare uniforme body.pos.y = R* sin(omega*time)
import vpython as vp from robot_imu import RobotImu from delta_timer import DeltaTimer import imu_settings imu = RobotImu(mag_offsets=imu_settings.mag_offsets) vp.cylinder(radius=1, axis=vp.vector(0, 0, 1), pos=vp.vector(0, 0, -1)) needle = vp.arrow(axis=vp.vector(1, 0, 0), color=vp.color.red) vp.graph(xmin=0, xmax=60, scroll=True) graph_yaw = vp.gcurve(color=vp.color.blue) timer = DeltaTimer() while True: vp.rate(100) dt, elapsed = timer.update() mag = imu.read_magnetometer() yaw = -vp.atan2(mag.y, mag.x) graph_yaw.plot(elapsed, vp.degrees(yaw)) needle.axis = vp.vector(vp.sin(yaw), vp.cos(yaw), 0)
tip.pos = Lshaft*A tip.clear_trail() reset() vp.scene.waitfor('textures') dt = 0.0001 t = 0 Nsteps = 20 # number of calculational steps between graphics updates while True: vp.rate(200) for step in range(Nsteps): # multiple calculation steps for accuracy # Calculate accelerations of the Lagrangian coordinates: atheta = vp.sin(theta)*vp.cos(theta)*phidot**2+(M*g*r*vp.sin(theta) - I3*(psidot+phidot*vp.cos(theta))*phidot*vp.sin(theta))/I1 aphi = (I3/I1)*(psidot+phidot*vp.cos(theta))*thetadot / \ vp.sin(theta)-2*vp.cos(theta)*thetadot*phidot/vp.sin(theta) apsi = phidot*thetadot*vp.sin(theta)-aphi*vp.cos(theta) # Update velocities of the Lagrangian coordinates: thetadot += atheta*dt phidot += aphi*dt psidot += apsi*dt # Update Lagrangian coordinates: theta += thetadot*dt phi += phidot*dt psi += psidot*dt gyro.axis = gyro.length * \ vp.vector(vp.sin(theta)*vp.sin(phi),
def render(self, mode, render_step=10): assert isinstance(self._dyn, BallBalancerDynamics ), "Missing dynamics properties for simulation!" # Cheap printing to console if self._step_count % render_step == 0: print( "time step: {:3} | in bounds: {:1} | state: {} | action: {}" .format(self._step_count, self.state_space.contains(self._state), self._state, self._curr_action)) if not self.state_space.contains(self._state): # State is out of bounds np.set_printoptions(precision=3) print("min state : ", self.state_space.low) print("last state: ", self._state) print("max state : ", self.state_space.high) # Render using VPython import vpython as vp vp.rate(30) d_plate = 0.01 # only for animation # Init render objects on first call if self._anim_canvas is None: self._anim_canvas = vp.canvas(width=800, height=600, title="Quanser Ball Balancer") self._anim_ball = vp.sphere( pos=vp.vector(self._state[2], self._state[3], self._dyn.r_ball + d_plate / 2.), radius=self._dyn.r_ball, mass=self._dyn.m_ball, color=vp.color.red, canvas=self._anim_canvas, ) self._anim_plate = vp.box( pos=vp.vector(0, 0, 0), size=vp.vector(self._dyn.l_plate, self._dyn.l_plate, d_plate), color=vp.color.green, canvas=self._anim_canvas, ) # Compute plate orientation a = -self._plate_angs[0] # plate's angle around the y axis (alpha) b = self._plate_angs[1] # plate's angle around the x axis (beta) # Axis runs along the x direction self._anim_plate.axis = vp.vec( vp.cos(a), 0, vp.sin(a), ) * self._dyn.l_plate # Up runs along the y direction (vpython coordinate system is weird) self._anim_plate.up = vp.vec( 0, vp.cos(b), vp.sin(b), ) # Compute ball position x = self._state[2] # ball position along the x axis y = self._state[3] # ball position along the y axis self._anim_ball.pos = vp.vec( x * vp.cos(a), y * vp.cos(b), self._dyn.r_ball + x * vp.sin(a) + y * vp.sin(b) + vp.cos(a) * d_plate / 2., ) # Set caption text self._anim_canvas.caption = f"""
model = virtual_robot.make_robot() virtual_robot.robot_view() compass = vp.canvas(width=400, height=400) vp.cylinder(radius=1, axis=vp.vector(0, 0, 1), pos=vp.vector(0, 0, -1)) needle = vp.arrow(axis=vp.vector(1, 0, 0), color=vp.color.red) vp.graph(xmin=0, xmax=60, scroll=True) graph_roll = vp.gcurve(color=vp.color.red) graph_pitch = vp.gcurve(color=vp.color.green) graph_yaw = vp.gcurve(color=vp.color.blue) timer = DeltaTimer() while True: vp.rate(100) dt, elapsed = timer.update() fusion.update(dt) # reset the model model.up = vp.vector(0, 1, 0) model.axis = vp.vector(1, 0, 0) # Reposition it model.rotate(angle=vp.radians(fusion.roll), axis=vp.vector(1, 0, 0)) model.rotate(angle=vp.radians(fusion.pitch), axis=vp.vector(0, 1, 0)) model.rotate(angle=vp.radians(fusion.yaw), axis=vp.vector(0, 0, 1)) needle.axis = vp.vector(vp.sin(vp.radians(fusion.yaw)), vp.cos(vp.radians(fusion.yaw)), 0) graph_roll.plot(elapsed, fusion.roll) graph_pitch.plot(elapsed, fusion.pitch) graph_yaw.plot(elapsed, fusion.yaw)
def simulateDoublePendula(models, func, x0, tEnd=10, deltat=0.005): """ Multiple double pendulum simulation via VPython given an R^4 -> R^4 differential equation (true double pendulum ODEs) and set of trained models Adapted from https://trinket.io/glowscript/9bdab2cf88 Arguments models: list of trained EQL/EQL-div models func: python function, R^4 -> R^4 system of ODEs x0: list with 4 elements, initial condition to integrate from in the form [theta1, omega1, theta2, omega2] tEnd: time to integrate until deltat: spacing between sampled functional values (note: not the step the integrator uses) """ t = 0 theta1, omega1, theta2, omega2 = x0 L1 = 1 L2 = 1 vp.canvas(width=1400, height=750, background=vp.color.white, range=1.75, autoscale=False, userpan=False, userspin=False, userzoom=False) # create the ceiling, masses, and strings ceiling = vp.box(pos=vec(0, 1, 0), size=vec(0.1, 0.05, 0.1), color=vp.color.gray(0.5)) # real double pendulum rball1 = vp.sphere(pos=vec(ceiling.pos.x + L1 * vp.sin(theta1), ceiling.pos.y - L1 * vp.cos(theta1), 0), radius=0.05, color=vp.color.orange) rball1.color = vp.color.black rball1.radius = 0.05 rball2 = vp.sphere(pos=vec( ceiling.pos.x + L1 * vp.sin(theta1) + L2 * vp.sin(theta2), ceiling.pos.y - L1 * vp.cos(theta1) - L2 * vp.cos(theta2), 0), radius=0.05, color=vp.color.black, make_trail=True, interval=10, retain=15) rball2.color = vp.color.black rball2.radius = 0.05 rstring1 = vp.cylinder(pos=ceiling.pos, axis=rball1.pos - ceiling.pos, color=vp.color.gray(0.5), radius=0.008) rstring2 = vp.cylinder(pos=rball1.pos, axis=rball2.pos - rball1.pos, color=vp.color.gray(0.5), radius=0.008) # double pendulums based on learned equations balls = [None for i in range(len(models) * 2)] strings = [None for i in range(len(models) * 2)] colors = [ vec(240 / 255, 133 / 255, 33 / 255), vec(110 / 255, 0, 95 / 255), vec(0, 129 / 255, 131 / 255) ] for i in range(0, len(balls), 2): balls[i] = vp.sphere(pos=vec(ceiling.pos.x + L1 * vp.sin(theta1), ceiling.pos.y - L1 * vp.cos(theta1), 0), radius=0.05, color=colors[int(i / 2)]) balls[i].color = colors[int(i / 2)] balls[i].radius = 0.05 balls[i + 1] = vp.sphere(pos=vec( ceiling.pos.x + L1 * vp.sin(theta1) + L2 * vp.sin(theta2), ceiling.pos.y - L1 * vp.cos(theta1) - L2 * vp.cos(theta2), 0), radius=0.05, color=colors[int(i / 2)], make_trail=True, interval=10, retain=15) balls[i + 1].color = colors[int(i / 2)] balls[i + 1].radius = 0.05 strings[i] = vp.cylinder(pos=ceiling.pos, axis=balls[i].pos - ceiling.pos, color=vp.color.gray(0.5), radius=0.008) strings[i + 1] = vp.cylinder(pos=balls[i].pos, axis=balls[i + 1].pos - balls[i].pos, color=vp.color.gray(0.5), radius=0.008) # generating simulation data actualSol, modelsSol = ode.odeSolve(models, func, x0, [0, tEnd], deltat) # calculation loop while t < tEnd / deltat: vp.rate(1 / deltat) rball1.pos = vec(vp.sin(actualSol.y[0][t]), -vp.cos(actualSol.y[0][t]), 0) + ceiling.pos rstring1.axis = rball1.pos - ceiling.pos rball2.pos = rball1.pos + vec(vp.sin(actualSol.y[2][t]), -vp.cos(actualSol.y[2][t]), 0) rstring2.axis = rball2.pos - rball1.pos rstring2.pos = rball1.pos for i in range(0, len(balls), 2): balls[i].pos = vec(vp.sin(modelsSol[int( i / 2)].y[0][t]), -vp.cos(modelsSol[int(i / 2)].y[0][t]), 0) + ceiling.pos strings[i].axis = balls[i].pos - ceiling.pos balls[i + 1].pos = (balls[i].pos + vec(vp.sin(modelsSol[int(i / 2)].y[2][t]), -vp.cos(modelsSol[int(i / 2)].y[2][t]), 0)) strings[i + 1].axis = balls[i + 1].pos - balls[i].pos strings[i + 1].pos = balls[i].pos t = t + 1 stop_server()
from vpython import sphere, vector, sin, cos, rate, pi s = sphere() t = 0 # seconds dt = 0.001 # seconds R = 10 # meters omega = 3.14 # radians/second s.pos = vector(R * cos(t * omega), R * sin(t * omega * 2), 0) s.velocity = omega * R * vector(-sin(t * omega), cos(t * 2 * omega) * 2, 0) while t < 100 * 2 * pi / omega: s.velocity = omega * R * vector(-sin(t * omega), cos(t * 2 * omega) * 2, 0) s.pos += s.velocity * dt t += dt rate(1 / dt)