def find_launch_sequence(maxiter = 5): intercept = cept - t_launch_indx host = 1 time2 = full_time[t_launch_indx:] planet_x = xx[t_launch_indx:] planet_v = vv[t_launch_indx:] dvv = dv[t_launch_indx:] x0_sat = planet_x[0, host] + vars.radius[0]*1000/vars.AU_tall*nt.unit_vector(planet_v[0, host]) v0_sat = planet_v[0, host] xv = ot.vis_viva(mass[0], nt.norm(x0_sat), semimajor[-1]) deviation = np.pi/2-nt.angle_between(v0_sat, x0_sat) dvv[0] = nt.rotate(dvv[0], deviation) v00_sat = xv*nt.rotate(nt.unit_vector(v0_sat), deviation) acc_optimal = lambda r, t: ot.gravity(mass[0], m_sat, r)/m_sat opt_orb, opt_vel = ot.orbit(x0_sat, v00_sat, acc_optimal, time2) opt_vel = opt_vel.transpose() opt_orb = opt_orb.transpose() '' x_sat, v_sat, dv_used = ot.n_body_sat(planet_x, mass, time2, dvv, x0_sat, v0_sat, m_sat) print(v_sat) print('Closest approach:', min(nt.norm(planet_x[:, 2] - x_sat, ax = 1))) opt_dev = nt.norm(x_sat - opt_orb.transpose(), ax = 1) boost_thresh = ot.grav_influence(mass[0], mass[1], x_sat, 1) dist_to_host = nt.norm(planet_x[:, 1] - x_sat, ax = 1) boost_time = np.where(dist_to_host > boost_thresh)[0][0] print('Time of boost:', time2[boost_time]) x_sat, v_sat, dv_used = ot.n_body_sat(planet_x, mass, time2, dvv, x0_sat, v0_sat, m_sat, opt_vel, opt_orb, time2[boost_time], True) print('Closest approach:',min(nt.norm(planet_x[:, 2] - x_sat, ax = 1))) print('Optimal closest approach:', ot.grav_influence(mass[0], mass[2], x_sat)[intercept]) closest = np.argmin(nt.norm(planet_x[:,2]- x_sat, ax=1)) print('total dv:', np.sum(nt.norm(dv_used))) dv_used[closest-3000:] = dv_used[closest-3000:]*0 x_sat, v_sat, dv_used = ot.n_body_sat(planet_x, mass, time2, dv_used, x0_sat, v0_sat, m_sat, opt_vel, opt_orb, time2[boost_time], False) print('Closest approach:',min(nt.norm(planet_x[:, 2] - x_sat, ax = 1))) print('total dv:', np.sum(nt.norm(dv_used))) closest = np.argmin(nt.norm(planet_x[:,2]- x_sat, ax=1)) return x_sat, v_sat, dvv, opt_orb, closest, dv_used
def get_dev(t_orient, optx, optv, x_sat, v_sat, nums, topt): # Find deviation from optimal orbit with optimal position optx, optimal velocity optv devx = np.zeros((nums-1)) devv = np.copy(devx) dv = np.zeros((nums-1, 2)) vec_between = np.copy(dv) for ii in range(nums-1): arg1 = np.argmin(np.abs(topt - t_orient[ii])) arg2 = np.argmin(np.abs(topt - t_orient[ii + 1])) devx[ii] = nt.norm(x_sat[ii]-optx[arg1]) devv[ii] = nt.norm(v_sat[ii]-optv[arg1]) dv[ii] = -v_sat[ii] + optv[arg1] vec_between[ii] = nt.unit_vector(-x_sat[ii] + optx[arg1]) return devx, devv, dv, vec_between
def launch_sat(): m_star = vars.m_star m_planets = vars.m a = vars.a radius = vars.radius * 1000 / vars.AU_tall # Planet radii given in AUs m_sat = vars.satellite / vars.solar_mass x0 = np.array([[x0, y0] for x0, y0 in zip(vars.x0, vars.y0)]) v0 = np.array([[vx0, vy0] for vx0, vy0 in zip(vars.vx0, vars.vy0)]) x0 = np.concatenate((np.zeros((1, 2)), x0)) # Set sun initial conditions v0 = np.concatenate((np.zeros((1, 2)), v0)) mass = np.append(m_star, m_planets) host = 1 target = 2 t0 = 0 t1 = 0.6 period = ot.kepler3(m_star, m_planets, a)[0] orbits = t1 / period stepsperorbit = 10000 steps = stepsperorbit * orbits print('Steps:', steps) time = np.linspace(t0, t1, steps) x, v = ot.patched_conic_orbits(time, mass, x0, v0) tol = 5e-5 t_launch_est, t_cept = find_launch_time(time, tol, x, v, mass, m_sat, target, host) t_launch = t_launch_est[0] t_intercept = t_cept[0] launch_indx = np.argmin(np.abs(t_launch - time)) intercept_indx = np.argmin((np.abs(t_intercept - time))) print('Launch window selected at t =', t_launch) t2 = time[launch_indx] time2 = np.linspace(t2, t1, steps) x0_sat = x[launch_indx, host] v0_sat = v[launch_indx, host] semimajor = (nt.norm(x0_sat) + nt.norm(x[intercept_indx, target])) / 2 x, v = ot.patched_conic_orbits(time2, mass, x[launch_indx], v[launch_indx]) # Find planetary orbits dv = np.zeros((len(time2), 2)) launch_indx = 0 intercept_indx = np.argmin(np.abs(t_intercept - time2)) dv_opt = ot.vis_viva(mass[0], nt.norm(x0_sat), semimajor) deviation = np.pi / 2 - nt.angle_between( v0_sat, x0_sat) # Angular deviation for Hohmann transfer print('Angular deviation for optimal orbit', deviation) v0_opt = dv_opt * nt.rotate(nt.unit_vector(v0_sat), deviation) acc = lambda r, t: ot.gravity(m_sat, m_star, r) / m_sat opt_orb, opt_vel = ot.orbit(x0_sat, v0_opt, acc, time2) # Optimal transfer orbit opt_orb = opt_orb.transpose() opt_vel = opt_vel.transpose() dvv = np.zeros((len(time2), 2)) v_escape = ot.vis_viva(m_planets[0], radius[0], 1e20) # Escape velocity print('Escape velocity', v_escape) dvv[0] = v_escape * nt.unit_vector(v0_sat) - v0_sat x0_sat = x0_sat + nt.unit_vector(v0_sat) * radius[0] x_sat, v_sat, dv_used = ot.n_body_sat(x, mass, time2, dvv, x0_sat, v0_sat, m_sat) print('Closest approach:', min(nt.norm(x[:, 2] - x_sat, ax=1))) opt_dev = nt.norm(x_sat - opt_orb, ax=1) boost_thresh = ot.grav_influence(m_star, m_planets[0], x_sat, 1) dist_to_host = nt.norm(x[:, 1] - x_sat, ax=1) print('Safe to boost for dist to host:', dist_to_host[0]) boost_time = np.where(dist_to_host > boost_thresh)[0][0] print('Time of boost:', time2[boost_time]) x_sat, v_sat, dv_used = ot.n_body_sat(x, mass, time2, dvv, x0_sat, v0_sat, m_sat, opt_vel, opt_orb, 0, True) closest = np.argmin(nt.norm(x[:, 2] - x_sat, ax=1)) print('Closest approach:', min(nt.norm(x[:, 2] - x_sat, ax=1))) print('Time of closest approach:', time2[closest]) print('Predicted time of intercept:', t_intercept) print('Total dv required:', np.sum(np.abs(dv_used))) plt.plot(x_sat[:, 0], x_sat[:, 1], '--k', opt_orb[:, 0], opt_orb[:, 1], '-.k', linewidth=0.8) plt.plot(x[:, 2, 0], x[:, 2, 1], 'k', x[:, 1, 0], x[:, 1, 1], 'b', linewidth=0.8) plt.xlabel('x [AU]', size=12) plt.ylabel('y [AU]', size=12) plt.legend([ 'Satellite Orbit', 'Optimal Orbit', 'Target Planet Orbit', 'Home Planet Orbit' ], frameon=False) plt.scatter(x0_sat[0], x0_sat[1], c='k') plt.scatter(x[intercept_indx, 2, 0], x[intercept_indx, 2, 1], c='k') plt.scatter(x_sat[intercept_indx, 0], x_sat[intercept_indx, 1], c='k') plt.scatter(x_sat[closest, 0], x_sat[closest, 1], c='k') plt.scatter(x[closest, 2, 0], x[closest, 2, 1], c='k') plt.axis('equal') plt.show()
for i in range(n): acc = lambda r: ot.system_acceleration(masses, r, i, n) x[i] = xx[i] + vv[i]*dt + 0.5*acc(xx)*dt**2 for i in range(n): acc = lambda r: ot.system_acceleration(masses, r, i, n) v[i] = vv[i] + 0.5*(acc(xx)+ acc(x))*dt cm = ot.center_of_mass(masses, x) xx = x vv = v tcount += dt if tcount > t_boost and not_launched: dt = dt/1000 print(dt) xx[0] = np.copy(xx[2]) + vars.radius[0]*1000/vars.AU_tall*nt.unit_vector(vv[2]) vv[0] = np.copy(vv[2]) + nt.unit_vector(vv[2])*dv_boost not_launched = False print('LAUNCHED!') elif not_launched: xx[0] = np.copy(xx[2]) + vars.radius[0]*1000/vars.AU_tall*nt.unit_vector([vv[2]]) vv[0] = np.copy(vv[2]) small = nt.norm(xx[0]- xx[3]) if small < closest: closest = small print('Closest Approach: ', closest)
def landing(pos, vel, boost_angle, boost, plot = False): #Where pos and vel is given relative to the planet, not relative to the sun #plt.figure() period = vars.period[1]*24*60*60 radius = vars.radius_normal_unit[1] print('RADIUS[1]', radius) A = vars.area_lander #cross sectional area A_parachute = 25 M_planet = vars.m_normal_unit[1] m = vars.mass_lander G = vars.G_SI polar_vec = np.array([0,1]) dt = 0.1 t = 0 count = 0 boost_time = 1000 parachute_time = 1001 angle1 = 0 boost_velocity = 0 time_force = np.linspace(0, 30000, 300001) force = np.zeros(300001) print('forceShapes', time_force.shape, force.shape) boosted = False parachuted = False angle_less = False #theta is not really theta, but the tangent given in meters print('NORM', nt.norm(pos)) while abs(boost_angle) > np.pi: if boost_angle > 0: boost_angle = boost_angle - 2*np.pi elif boost_angle < 0: boost_angle = boost_angle + 2*np.pi while nt.norm(pos) > radius: #while count < 240000: wel = p2c_vel(c2p_pos(pos), 2*np.pi/period * polar_vec) vel_drag = vel - wel rho = part6.density(nt.norm(pos)) acc = -1/2*rho*A*nt.norm(vel_drag)*vel_drag/m - (M_planet*G/(nt.norm(pos)**2))*nt.unit_vector(pos) vel = vel + acc*dt pos = pos + vel*dt t += dt force[count] = nt.norm(acc*m) count += 1 if np.arctan2(pos[1],pos[0]) >= boost_angle and angle_less: #a check that should trigger when the desired angle is reached, and not before this #without the 'and angle_less' it would not work because angles are stupid 0->2pi->0 if not boosted: if plot: plt.scatter(pos[0]/1000, pos[1]/1000, c = 'b') print('boosted at angle', np.arctan2(pos[1],pos[0])) print('boost angle is ', boost_angle) boosted = True boost_time = t print('boost_time', boost_time) angle1 = np.arctan2(pos[1],pos[0]) boost_velocity = -vel*(1-boost) vel = vel*boost elif np.arctan2(pos[1],pos[0]) <= boost_angle: angle_less = True if nt.norm(vel_drag) < 30 and not parachuted: #parachute will be launched when the drag velocity is below 30m/s #could have included a check to see if the new force will be above #some threshold, though this should not happen at 30m/s parachute_time = t parachuted = True print('paratime', parachute_time) A = A_parachute acc = -1/2*rho*A*nt.norm(vel_drag)*vel_drag/m - (M_planet*G/(nt.norm(pos)**2))*nt.unit_vector(pos) F = m*acc force[count] = nt.norm(acc*m) print('Force', nt.norm(F), 'N') if count % int(50) == 0 and plot: plt.scatter(pos[0]/1000, pos[1]/1000, 1, 'r') angle2 = np.arctan2(pos[1],pos[0]) if plot: print('time', t) plt.scatter(pos[0]/1000, pos[1]/1000, c = 'b') print('DRAG: You reached the surface with a velocity of %.3f m/s after %.2f seconds' %(nt.norm(vel_drag), (t-boost_time))) vel_drag_radial = nt.norm(vel_drag*nt.unit_vector(-pos)) vel_drag_tangential = nt.norm(vel_drag*nt.rotate(nt.unit_vector(-pos), np.pi/2)) print('DRAG: Radial velocity was %.3f m/s and tangential velocity was %.3f m/s' %(vel_drag_radial, vel_drag_tangential)) print('Angle', angle2-angle1) plt.axis('equal') plt.xlabel('X-position [km]') plt.ylabel('Y-position [km]') pi_vec = np.linspace(0, 2*np.pi, 1000) for theta in pi_vec: circle = p2c_pos(np.array([radius, theta])) #circle2 = circle * 1.27 plt.scatter(circle[0]/1000, circle[1]/1000, 0.1, 'k') #plt.scatter(circle2[0], circle2[1], 0.1, 'k') plt.show() #plt.plot(time_force, force, '-k') #plt.xlabel('Time [s]') #plt.ylabel('Force [N]') #plt.show() print('BOOST TIME ', boost_time) return angle2, angle2-angle1, parachute_time, boost_time, boost_velocity, t
phase1 = np.linspace(0, t1, steps) phase2 = np.linspace(t_launch - launch_duration, t2 - (t2-t_launch)/steps2, steps2) phase3 = np.linspace(t2, t3, steps) full_time = np.concatenate((phase1, phase2, phase3)) xx, vv = sol.find_two_body_orbits(full_time, mass, x0, v0) #np.save('saved/saved_params/xx_sol2.npy', xx) #np.save('saved/saved_params/vv_sol2.npy', vv) #xx = np.load('saved/saved_params/xx_sol2.npy') #vv = np.load('saved/saved_params/vv_sol2.npy') dv = np.zeros((len(full_time), 2)) t_launch_indx = len(phase1) cept = np.argmin(np.abs(full_time - t_cept[-1])) dv[t_launch_indx] = dw[-1]*nt.unit_vector(vv[t_launch_indx, 1]) print('Go for launch') tol2 = 1e-3 dw, tw, t_cept, semimajor = ot.trajectory(m_t, xx, vv, 1, -1, 2, 0, full_time, False, tol2) import launch launch.test(testing = True) xx = xx.transpose() vv = vv.transpose() xx = xx.transpose() vv = vv.transpose() print(xx.shape) print(dw[-1], tw, t_cept[-1]) print('Initial launch index:', t_launch_indx) t_launch_indx = np.argmin(abs(full_time - tw[-1]))
def launch(time_vector, planet_position, planet_velocity, t0, theta = 1/2*np.pi, testing = False): #print('angle = ', theta) #print('angle = ', theta * 180/np.pi) radius = vars.radius_normal_unit[0] planet_mass = vars.m_normal_unit[0] grav_const = vars.gravitational_constant satellite_mass = vars.satellite period = vars.period[0] #unit is 24h force_box = np.load('saved/engine/force_box.npy') fuel_consumed_box_per_sec = np.load('saved/engine/fuel_consumed_box_per_sec.npy') part_consumed_box = fuel_consumed_box_per_sec/vars.molecule_mass position = radius DDt = time_vector[1]- time_vector[0] indd = int(t0/DDt) home_planet_position = planet_position[:,1] - planet_position[:,0] home_planet_velocity = planet_velocity[:,1] - planet_velocity[:,0] x_interp = nt.interp_xin(time_vector, home_planet_position) v_interp = nt.interp_xin(time_vector, home_planet_velocity) planet_position_t0 = np.array([x_interp[0](t0), x_interp[1](t0)]) planet_velocity_t0 = np.array([v_interp[0](t0), v_interp[1](t0)]) #print(planet_position_t0) #planet_position_t0 = np.array([home_planet_position[0,indd], home_planet_position[1,indd]]) #planet_velocity_t0 = np.array([home_planet_velocity[0,indd], home_planet_velocity[1,indd]]) #print(planet_position_t0) force = 35000e3 #input? kraft for hele raketten fuel_mass = 3000e3-satellite_mass #input? total fuelmasse for raketten boxes = force/force_box #antall bokser regnes utifra ønsket kraft fuel_consumption = boxes * fuel_consumed_box_per_sec #drivstofforbruk regnes ut for samlet motor mass = satellite_mass + fuel_mass initial_mass = mass initial_fuel_mass = fuel_mass #print('PARTICLES PER BOX PER SEC', part_consumed_box) #print('FUEL CONSUMED PER SEC', fuel_consumption) #print('BOXES', boxes) dt = 0.01 t = t0*vars.year escape_velocity = (2*grav_const*planet_mass/position)**0.5 velocity = 0; count = 0; has_fuel = 1 tangential_velocity = 2*np.pi*radius/(period*24*60*60) while (velocity**2 + tangential_velocity**2)**(1/2) < escape_velocity: #1Dimensional acceleration = force/mass*has_fuel - grav_const*planet_mass/(position**2) velocity = velocity + acceleration*dt position = position + velocity*dt mass = mass - fuel_consumption*dt fuel_mass = fuel_mass - fuel_consumption*dt escape_velocity = (2*grav_const*planet_mass/position)**0.5 if fuel_mass < 0: has_fuel = 0 print('NO ORBIT') break t = t + dt count += 1 ''' print('\n\n') print('Velocity in planet reference frame', velocity) print('Duration', t) print('Fuel percentage', fuel_mass / initial_fuel_mass*100) print('Initial Fuel', initial_fuel_mass) print('Fuel', fuel_mass) print('height', position-radius) print('\n\n') ''' tangential_velocity = tangential_velocity/vars.AU_tall*vars.year position = position/vars.AU_tall velocity = velocity/vars.AU_tall*vars.year t_AU = t/vars.year planet_position_t1 = np.array([x_interp[0](t_AU), x_interp[1](t_AU)]) planet_velocity_t1 = np.array([v_interp[0](t_AU), v_interp[1](t_AU)]) unitvector = nt.unit_vector(planet_position_t1) position_before_rotation = position * unitvector + nt.rotate(unitvector, np.pi/2) * (t_AU - t0) * tangential_velocity #radiallyish outwards from sun/cm velocity_before_rotation = velocity * unitvector + nt.rotate(unitvector, np.pi/2) * tangential_velocity position_after_rotation = nt.rotate(position_before_rotation, theta) #returns array with [x, y] velocity_after_rotation = nt.rotate(velocity_before_rotation, theta) final_position = planet_position_t1 + position_after_rotation final_velocity = planet_velocity_t1 + velocity_after_rotation phi = nt.angle_between(planet_velocity_t1, velocity_after_rotation) print('PHI', phi) print('THETA', theta) print('Duration:', t-t0*vars.year) if testing == True: vars.solar_system.engine_settings(force_box, boxes, part_consumed_box, initial_fuel_mass, \ t-t0*vars.year, planet_position_t0 + nt.rotate(vars.radius_AU[0]*unitvector, theta), t0) vars.solar_system.mass_needed_launch(final_position, test = False) launch_pos = planet_position_t0 + nt.rotate(vars.radius_AU[0]*unitvector, theta) #new_mass, dvv = boost(force, fuel_consumption, mass, satellite_mass, 1000000, 0.00001) #print('DELTA V', dvv*vars.year/vars.AU_tall) #print('MASS', new_mass) return t_AU, final_position, final_velocity, mass/vars.solmasse, fuel_mass/vars.solmasse, phi, launch_pos
semimajor = (nt.norm(x0_sat) + nt.norm(x[intercept_indx, target]))/2 #x, v = ot.patched_conic_orbits(time2, mass, x[launched_indx], v[launched_indx]) #np.save('saved/saved_params/xx_sol4.npy', x) #np.save('saved/saved_params/vv_sol4.npy', v) x = np.load('saved/saved_params/xx_sol4.npy') v = np.load('saved/saved_params/vv_sol4.npy') dv = np.zeros((len(time2), 2)) launch_indx = 0 launched_indx = 0 intercept_indx = np.argmin(np.abs(t_intercept-time2)) dv_opt = ot.vis_viva(mass[0], nt.norm(x0_sat), semimajor) deviation = np.pi/2 - nt.angle_between(v0_sat, x0_sat) v0_opt = dv_opt*nt.rotate(nt.unit_vector(v0_sat), deviation) acc = lambda r, t: ot.gravity(m_sat, m_star, r)/m_sat t_optvec = np.linspace(topt, t2, 1000) #a, b = ot.orbit(x0_sat, v0_opt, acc, t_optvec) # This only makes sure that the optimal orbit and the launch with mcast actually align. #a = a.transpose(); b = b.transpose() #opt_orb, opt_vel = ot.orbit(a[-1], b[-1], acc, time2) # Calculate optimal orbit #np.save('saved/saved_params/xopt1.npy', opt_orb) #np.save('saved/saved_params/vopt1.npy', opt_vel) opt_orb = np.load('saved/saved_params/xopt1.npy') opt_vel = np.load('saved/saved_params/vopt1.npy') opt_orb = opt_orb.transpose() opt_vel = opt_vel.transpose() min_dist_res() # Minimum resolution distance