def plot(self, x, ax=None): """ ax = prob.plot(x, ax=None) - x: encoded trajectory - ax: matplotlib axis where to plot. If None figure and axis will be created - [out] ax: matplotlib axis where to plot Plots the trajectory represented by a decision vector x on the 3d axis ax Example:: ax = prob.plot(x) """ import matplotlib as mpl from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from PyKEP import epoch, AU from PyKEP.sims_flanagan import sc_state from PyKEP.orbit_plots import plot_planet, plot_sf_leg # Creating the axis if necessary if ax is None: mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() axis = fig.gca(projection='3d') else: axis = ax # Plotting the Sun ........ axis.scatter([0], [0], [0], color='y') # Plotting the legs ....... # 1 - We decode the chromosome extracting the time of flights T = list([0] * (self.__n_legs)) for i in range(self.__n_legs): T[i] = x[1 + i * 8] # 2 - We compute the epochs and ephemerides of the planetary encounters t_P = list([None] * (self.__n_legs + 1)) r_P = list([None] * (self.__n_legs + 1)) v_P = list([None] * (self.__n_legs + 1)) for i, planet in enumerate(self.seq): t_P[i] = epoch(x[0] + sum(T[0:i])) r_P[i], v_P[i] = self.seq[i].eph(t_P[i]) # 3 - We iterate through legs to compute mismatches and throttles constraints ceq = list() cineq = list() m0 = self.__sc.mass for i in range(self.__n_legs): # First Leg v = [a + b for a, b in zip(v_P[i], x[(3 + i * 8):(6 + i * 8)])] x0 = sc_state(r_P[i], v, m0) v = [ a + b for a, b in zip(v_P[i + 1], x[(6 + i * 8):(11 + i * 8)]) ] xe = sc_state(r_P[i + 1], v, x[2 + i * 8]) throttles = x[(1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):( 1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i], x0, throttles, t_P[i + 1], xe) # update mass! m0 = x[2 + 8 * i] plot_sf_leg(self.__leg, units=AU, N=10, ax=axis) # Plotting planets for i, planet in enumerate(self.seq): plot_planet(planet, t_P[i], units=AU, legend=True, color=(0.7, 0.7, 1), ax=axis) plt.show() return axis
def _compute_constraints_impl(self, x): # 1 - We decode the chromosome extracting the time of flights T = list([0] * (self.__n_legs)) for i in range(self.__n_legs): T[i] = x[1 + i * 8] # 2 - We compute the epochs and ephemerides of the planetary encounters t_P = list([None] * (self.__n_legs + 1)) r_P = list([None] * (self.__n_legs + 1)) v_P = list([None] * (self.__n_legs + 1)) for i, planet in enumerate(self.seq): t_P[i] = epoch(x[0] + sum(T[0:i])) r_P[i], v_P[i] = self.seq[i].eph(t_P[i]) # 3 - We iterate through legs to compute mismatches and throttles constraints ceq = list() cineq = list() m0 = self.__sc.mass for i in range(self.__n_legs): # First Leg v = [a + b for a, b in zip(v_P[i], x[(3 + i * 8):(6 + i * 8)])] x0 = sc_state(r_P[i], v, m0) v = [a + b for a, b in zip(v_P[i + 1], x[(6 + i * 8):(9 + i * 8)])] xe = sc_state(r_P[i + 1], v, x[2 + i * 8]) throttles = x[(1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):( 1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i], x0, throttles, t_P[i + 1], xe) # update mass! m0 = x[2 + 8 * i] ceq.extend(self.__leg.mismatch_constraints()) cineq.extend(self.__leg.throttles_constraints()) # Adding the boundary constraints # departure v_dep_con = (x[3]**2 + x[4]**2 + x[5]**2 - self.__vinf_dep**2) / (EARTH_VELOCITY**2) # arrival v_arr_con = (x[6 + (self.__n_legs - 1) * 8]**2 + x[7 + (self.__n_legs - 1) * 8] **2 + x[8 + (self.__n_legs - 1) * 8]**2 - self.__vinf_arr**2) / (EARTH_VELOCITY**2) cineq.append(v_dep_con * 100) cineq.append(v_arr_con * 100) # We add the fly-by constraints for i in range(self.__n_legs - 1): DV_eq, alpha_ineq = fb_con(x[6 + i * 8:9 + i * 8], x[11 + i * 8:14 + i * 8], self.seq[i + 1]) ceq.append(DV_eq / (EARTH_VELOCITY**2)) cineq.append(alpha_ineq) # Making the mismatches non dimensional for i in range(self.__n_legs): ceq[0 + i * 7] /= AU ceq[1 + i * 7] /= AU ceq[2 + i * 7] /= AU ceq[3 + i * 7] /= EARTH_VELOCITY ceq[4 + i * 7] /= EARTH_VELOCITY ceq[5 + i * 7] /= EARTH_VELOCITY ceq[6 + i * 7] /= self.__sc.mass # We assemble the constraint vector retval = list() retval.extend(ceq) retval.extend(cineq) return retval
def plot(self, x, ax=None): """ ax = prob.plot(x, ax=None) - x: encoded trajectory - ax: matplotlib axis where to plot. If None figure and axis will be created - [out] ax: matplotlib axis where to plot Plots the trajectory represented by a decision vector x on the 3d axis ax Example:: ax = prob.plot(x) """ import matplotlib as mpl from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from PyKEP import epoch, AU from PyKEP.sims_flanagan import sc_state from PyKEP.orbit_plots import plot_planet, plot_sf_leg # Creating the axis if necessary if ax is None: mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() axis = fig.gca(projection='3d') else: axis = ax # Plotting the Sun ........ axis.scatter([0], [0], [0], color='y') # Plotting the legs ....... # 1 - We decode the chromosome extracting the time of flights T = list([0] * (self.__n_legs)) for i in range(self.__n_legs): T[i] = x[1 + i * 8] # 2 - We compute the epochs and ephemerides of the planetary encounters t_P = list([None] * (self.__n_legs + 1)) r_P = list([None] * (self.__n_legs + 1)) v_P = list([None] * (self.__n_legs + 1)) for i, planet in enumerate(self.seq): t_P[i] = epoch(x[0] + sum(T[0:i])) r_P[i], v_P[i] = self.seq[i].eph(t_P[i]) # 3 - We iterate through legs to compute mismatches and throttles constraints ceq = list() cineq = list() m0 = self.__sc.mass for i in range(self.__n_legs): # First Leg v = [a + b for a, b in zip(v_P[i], x[(3 + i * 8):(6 + i * 8)])] x0 = sc_state(r_P[i], v, m0) v = [a + b for a, b in zip(v_P[i + 1], x[(6 + i * 8):(11 + i * 8)])] xe = sc_state(r_P[i + 1], v, x[2 + i * 8]) throttles = x[(1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):(1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i], x0, throttles, t_P[i + 1], xe) # update mass! m0 = x[2 + 8 * i] plot_sf_leg(self.__leg, units=AU, N=10, ax=axis) # Plotting planets for i, planet in enumerate(self.seq): plot_planet(planet, t_P[i], units=AU, legend=True, color=(0.7, 0.7, 1), ax = axis) plt.show() return axis
def _compute_constraints_impl(self, x): # 1 - We decode the chromosome extracting the time of flights T = list([0] * (self.__n_legs)) for i in range(self.__n_legs): T[i] = x[1 + i * 8] # 2 - We compute the epochs and ephemerides of the planetary encounters t_P = list([None] * (self.__n_legs + 1)) r_P = list([None] * (self.__n_legs + 1)) v_P = list([None] * (self.__n_legs + 1)) for i, planet in enumerate(self.seq): t_P[i] = epoch(x[0] + sum(T[0:i])) r_P[i], v_P[i] = self.seq[i].eph(t_P[i]) # 3 - We iterate through legs to compute mismatches and throttles constraints ceq = list() cineq = list() m0 = self.__sc.mass for i in range(self.__n_legs): # First Leg v = [a + b for a, b in zip(v_P[i], x[(3 + i * 8):(6 + i * 8)])] x0 = sc_state(r_P[i], v, m0) v = [a + b for a, b in zip(v_P[i + 1], x[(6 + i * 8):(9 + i * 8)])] xe = sc_state(r_P[i + 1], v, x[2 + i * 8]) throttles = x[(1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):(1 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i], x0, throttles, t_P[i + 1], xe) # update mass! m0 = x[2 + 8 * i] ceq.extend(self.__leg.mismatch_constraints()) cineq.extend(self.__leg.throttles_constraints()) # Adding the boundary constraints # departure v_dep_con = (x[3] ** 2 + x[4] ** 2 + x[5] ** 2 - self.__vinf_dep ** 2) / (EARTH_VELOCITY ** 2) # arrival v_arr_con = (x[6 + (self.__n_legs - 1) * 8] ** 2 + x[7 + (self.__n_legs - 1) * 8] ** 2 + x[8 + (self.__n_legs - 1) * 8] ** 2 - self.__vinf_arr ** 2) / (EARTH_VELOCITY ** 2) cineq.append(v_dep_con * 100) cineq.append(v_arr_con * 100) # We add the fly-by constraints for i in range(self.__n_legs - 1): DV_eq, alpha_ineq = fb_con(x[6 + i * 8:9 + i * 8], x[11 + i * 8:14 + i * 8], self.seq[i + 1]) ceq.append(DV_eq / (EARTH_VELOCITY ** 2)) cineq.append(alpha_ineq) # Making the mismatches non dimensional for i in range(self.__n_legs): ceq[0 + i * 7] /= AU ceq[1 + i * 7] /= AU ceq[2 + i * 7] /= AU ceq[3 + i * 7] /= EARTH_VELOCITY ceq[4 + i * 7] /= EARTH_VELOCITY ceq[5 + i * 7] /= EARTH_VELOCITY ceq[6 + i * 7] /= self.__sc.mass # We assemble the constraint vector retval = list() retval.extend(ceq) retval.extend(cineq) return retval
def point(self, x, filename): """ prob.point(decision_vector, filename) This method will save all the relevant simulation data for the trajectory described by decision_vector in json form in the file 'filename.json'. The data generated can then be used by the postprocessing toolbox (from this fork of PyKEP : PyKEP/postProcessingToolbox/), without having to re-create a prob abject. Indeed, if the problem definition is changed, the decision_vector will not mean anything: it only encode a trajectory for a very specific problem. When tens or hundreds of trajectories are generated, and then compared, keeping only the decision vector is not a good idea, if the parameters of the problems have been tweaked to realize those tens or hundreds of different simulations. The data stored in the file can be imported using import.json from the json package. The description of the stored data has still to be described in detail // TODO : description of the content of the .json file Those files are to be given as parameters for the postprocessing toolbox. """ from PyKEP import epoch, AU from PyKEP.sims_flanagan import sc_state from PyKEP.orbit_plots import plot_planet, plot_sf_leg from PyKEP.orbit_plots import point_sf_leg, point_kepler, point_taylor, point_planet from scipy.linalg import norm from math import sqrt import csv import pprint from PyKEP.trajopt.motor import getObjectMotor from PyKEP.trajopt.spacecraft import getObjectSpacecraft XYZ = [] xx = [] yy = [] zz = [] tt = [] mm = [] x_bounds = [] y_bounds = [] z_bounds = [] seq1 = self.seq1 seq2 = self.seq2 data = {} # Plotting the legs ....... # 1 - We decode the chromosome extracting the time of flights T = list([0] * (self.__n_legs)) for i in range(self.__n_legs): T[i] = x[3 + i * 8] # 2 - We compute the epochs and ephemerides of the planetary encounters t_P = list([None] * (self.__n_legs + 2)) r_P = list([None] * (self.__n_legs + 2)) v_P = list([None] * (self.__n_legs + 2)) for i, planet in enumerate(self.seq1): t_P[i] = epoch(x[0] + sum(T[0:i])) r_P[i], v_P[i] = self.seq1[i].eph(t_P[i]) for i, planet in enumerate(self.seq2): t_P[i + len(seq1)] = epoch(x[0] + sum(T[0:i + len(seq1) - 1]) + x[1]) r_P[i + len(seq1)], v_P[i + len(seq1)] = self.seq2[i].eph( t_P[i + len(seq1)]) # 3 - We iterate through legs to compute mismatches and throttles constraints ceq = list() cineq = list() m0 = x[2] data['legs'] = [] massesAlongTheWay = [m0] self.__leg.set_spacecraft(self.__spacecrafts[0]) sc = self.__spacecrafts[0] for i in range(len(self.seq1) - 1): # First Leg v = [a + b for a, b in zip(v_P[i], x[(5 + i * 8):(8 + i * 8)])] x0 = sc_state(r_P[i], v, m0) v = [ a + b for a, b in zip(v_P[i + 1], x[(8 + i * 8):(11 + i * 8)]) ] xe = sc_state(r_P[i + 1], v, x[4 + i * 8]) throttles = x[(3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):( 3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i], x0, throttles, t_P[i + 1], xe) # update mass! minit = m0 m0 = x[4 + 8 * i] massesAlongTheWay = massesAlongTheWay + [m0] xi, yi, zi, mi, ti, Txi, Tyi, Tzi, Tmaxi, x_boundsi, y_boundsi, z_boundsi = point_sf_leg( self.__leg, units=AU, N=10) xx = xx + xi yy = yy + yi zz = zz + zi ti = [e + t_P[i].jd for e in ti] #for k in range(len(Txi)): # print norm([Tyi[k],Txi[k],Tzi[k]]) data['legs'] = data['legs'] + [{ 'x': [e for e in xi], 'y': [e for e in yi], 'z': [e for e in zi], 'm': [e for e in mi], 't': [e for e in ti], 'P_tot': [sc.get_totalPower(norm(e)) for e in zip(xi, yi, zi)], 'P_engine': [ sc.DutyCycle * sc.get_powerThrust(norm(e[0:3]) * e[3] / sc.DutyCycle) for e in zip(Txi, Tyi, Tzi, Tmaxi) ], 'Tx': [e for e in Txi], 'Ty': [e for e in Tyi], 'Tz': [e for e in Tzi], 'Tmax': [e for e in Tmaxi], 'mi': minit, 'mf': m0, 'planet1': { 'name': seq1[i].name, 'date': t_P[i].jd }, 'planet2': { 'name': seq1[i + 1].name, 'date': t_P[i + 1].jd } }] XYZ = XYZ + [xi] + [yi] + [zi] x_bounds = x_bounds + x_boundsi y_bounds = y_bounds + y_boundsi z_bounds = z_bounds + z_boundsi #outbound m0 = m0 - self.__dm # mass lost around ceres massesAlongTheWay = massesAlongTheWay + [m0] self.__leg.set_spacecraft(self.__spacecrafts[1]) sc = self.__spacecrafts[1] for i in range( len(self.seq1) - 1, len(self.seq1) + len(self.seq2) - 2): # First Leg v = [a + b for a, b in zip(v_P[i + 1], x[(5 + i * 8):(8 + i * 8)])] x0 = sc_state(r_P[i + 1], v, m0) v = [ a + b for a, b in zip(v_P[i + 2], x[(8 + i * 8):(11 + i * 8)]) ] xe = sc_state(r_P[i + 2], v, x[4 + i * 8]) throttles = x[(3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):( 3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i + 1], x0, throttles, t_P[i + 2], xe) # update mass! minit = m0 m0 = x[4 + 8 * i] massesAlongTheWay = massesAlongTheWay + [m0] xi, yi, zi, mi, ti, Txi, Tyi, Tzi, Tmaxi, x_boundsi, y_boundsi, z_boundsi = point_sf_leg( self.__leg, units=AU, N=10) xx = xx + xi yy = yy + yi zz = zz + zi ti = [e + t_P[i + 1].jd for e in ti] #for k in range(len(Txi)): # print norm([Tyi[k],Txi[k],Tzi[k]]) data['legs'] = data['legs'] + [{ 'x': [e for e in xi], 'y': [e for e in yi], 'z': [e for e in zi], 'm': [e for e in mi], 't': [e for e in ti], 'P_tot': [sc.get_totalPower(norm(e)) for e in zip(xi, yi, zi)], 'P_engine': [ sc.DutyCycle * sc.get_powerThrust(norm(e[0:3]) * e[3] / sc.DutyCycle) for e in zip(Txi, Tyi, Tzi, Tmaxi) ], 'Tx': [e for e in Txi], 'Ty': [e for e in Tyi], 'Tz': [e for e in Tzi], 'Tmax': [e for e in Tmaxi], 'mi': minit, 'mf': m0, 'planet1': { 'name': seq2[i - len(seq1) - 2].name, 'date': t_P[i + 1].jd }, 'planet2': { 'name': seq2[i + 1 - len(seq1) - 2].name, 'date': t_P[i + 2].jd } }] XYZ = XYZ + [xi] + [yi] + [zi] x_bounds = x_bounds + x_boundsi y_bounds = y_bounds + y_boundsi z_bounds = z_bounds + z_boundsi XYZplanet = [] data['planetOrbits'] = [] data['planetPosition'] = [] listAlreadySaved = [] for i, planet in enumerate(self.seq1): xp, yp, zp = point_planet(planet, t_P[i], units=AU) #Save orbit if it has not been done already if (seq1[i].name not in listAlreadySaved): listAlreadySaved.append(seq1[i].name) data['planetOrbits'].append({ 'name': seq1[i].name, 'x': [e for e in xp], 'y': [e for e in yp], 'z': [e for e in zp] }) data['planetPosition'].append({ 'name': seq1[i].name, 'x': xp[0], 'y': yp[0], 'z': zp[0], 'dateS': pprint.pformat(t_P[i])[0:20], 'date': t_P[i].jd, 'scmass': massesAlongTheWay[i] }) for i, planet in enumerate(self.seq2): xp, yp, zp = point_planet(planet, t_P[i + len(seq1)], units=AU) #Save orbit if it has not been done already if (seq2[i].name not in listAlreadySaved): listAlreadySaved.append(seq2[i].name) data['planetOrbits'].append({ 'name': seq2[i].name, 'x': [e for e in xp], 'y': [e for e in yp], 'z': [e for e in zp] }) data['planetPosition'].append({ 'name': seq2[i].name, 'x': xp[0], 'y': yp[0], 'z': zp[0], 'dateS': pprint.pformat(t_P[i + len(seq1)])[0:20], 'date': t_P[i + len(seq1)].jd, 'scmass': massesAlongTheWay[i + 3] }) #Calculate vinf velocities v_dep_1 = sqrt(x[5]**2 + x[6]**2 + x[7]**2) v_arr_1 = sqrt(x[8 + (len(seq1) - 2) * 8]**2 + x[9 + (len(seq1) - 2) * 8]**2 + x[10 + (len(seq1) - 2) * 8]**2) v_dep_2 = sqrt(x[5 + (len(seq1) - 1) * 8]**2 + x[6 + (len(seq1) - 1) * 8]**2 + x[7 + (len(seq1) - 1) * 8]**2) v_arr_2 = sqrt(x[8 + (len(seq1) - 1 + len(seq2) - 2) * 8]**2 + x[9 + (len(seq1) - 1 + len(seq2) - 2)]**2 + x[10 * (len(seq1) - 1 + len(seq2) - 2)]**2) #Logging all trajectory parameters data['traj'] = {} data['traj']['high_fidelity'] = self.__leg.high_fidelity data['traj']['solar_powered'] = self.__leg.solar_powered data['traj']['outbound'] = [[seq1[i].name, t_P[i].jd] for i in range(len(seq1))] data['traj']['inbound'] = [[seq2[i].name, t_P[i + len(seq1)].jd] for i in range(len(seq2))] data['traj']['vinf'] = { 'v_dep1': v_dep_1, 'v_dep2': v_dep_2, 'v_arr1': v_arr_1, 'v_arr2': v_arr_2 } data['traj']['spacecrafts'] = [ getObjectSpacecraft(self.__spacecrafts[0]), getObjectSpacecraft(self.__spacecrafts[1]) ] data['traj']['duty_cycle'] = [ self.__spacecrafts[0].DutyCycle, self.__spacecrafts[1].DutyCycle, ] data['traj']['dm'] = self.__dm data['traj']['mi'] = x[2] data['traj']['mf'] = self.__mf data['traj']['decision_vector'] = x data['traj']['dt'] = x[1] data['traj']['t_launch'] = t_P[0].jd data['traj']['t_launchS'] = pprint.pformat(t_P[0])[0:20] data['traj']['t_return'] = t_P[-1].jd data['traj']['t_returnS'] = pprint.pformat(t_P[-1])[0:20] data['traj']['duration'] = t_P[-1].jd - t_P[0].jd import json with open(filename, 'w') as outfile: json.dump(data, outfile) # File structure: # Number of legs, length points, number of planets to plot, length points # Legs trajectories # Planets trajectories # Planets names #with open('test1.csv', 'w') as csvfile: # writer = csv.writer(csvfile) # #writer.writerow([self.__n_legs, len(XYZ[0]), len(list_planet),len(XYZplanet[0])]) # for i in range(len(XYZ)): # writer.writerow(XYZ[i]) # for i in range(len(XYZplanet)): # writer.writerow(XYZplanet[i]) # #writer.writerow(list_planet) return xx, yy, zz, x_bounds, y_bounds, z_bounds, data
def _compute_constraints_impl(self, x): seq1 = self.seq1 seq2 = self.seq2 # 1 - We decode the chromosome extracting the time of flights T = list([0] * (self.__n_legs)) for i in range(self.__n_legs): T[i] = x[3 + i * 8] # 2 - We compute the epochs and ephemerides of the planetary encounters t_P = list([None] * (self.__n_legs + 2)) r_P = list([None] * (self.__n_legs + 2)) v_P = list([None] * (self.__n_legs + 2)) for i, planet in enumerate(self.seq1): t_P[i] = epoch(x[0] + sum(T[0:i])) r_P[i], v_P[i] = self.seq1[i].eph(t_P[i]) for i, planet in enumerate(self.seq2): t_P[i + len(seq1)] = epoch(x[0] + sum(T[0:i + len(seq1) - 1]) + x[1]) r_P[i + len(seq1)], v_P[i + len(seq1)] = self.seq2[i].eph( t_P[i + len(seq1)]) # 3 - We iterate through legs to compute mismatches and throttles constraints ceq = list() cineq = list() m0 = x[2] #inbound self.__leg.set_spacecraft(self.__spacecrafts[0]) for i in range(len(self.seq1) - 1): # First Leg v = [a + b for a, b in zip(v_P[i], x[(5 + i * 8):(8 + i * 8)])] x0 = sc_state(r_P[i], v, m0) v = [ a + b for a, b in zip(v_P[i + 1], x[(8 + i * 8):(11 + i * 8)]) ] xe = sc_state(r_P[i + 1], v, x[4 + i * 8]) throttles = x[(3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):( 3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i], x0, throttles, t_P[i + 1], xe) # update mass! m0 = x[4 + 8 * i] ceq.extend(self.__leg.mismatch_constraints()) cineq.extend(self.__leg.throttles_constraints()) #outbound self.__leg.set_spacecraft(self.__spacecrafts[1]) m0 = m0 - self.__dm # mass lost around ceres for i in range( len(self.seq1) - 1, len(self.seq1) + len(self.seq2) - 2): # First Leg v = [a + b for a, b in zip(v_P[i + 1], x[(5 + i * 8):(8 + i * 8)])] x0 = sc_state(r_P[i + 1], v, m0) v = [ a + b for a, b in zip(v_P[i + 2], x[(8 + i * 8):(11 + i * 8)]) ] xe = sc_state(r_P[i + 2], v, x[4 + i * 8]) throttles = x[(3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i])):( 3 + 8 * self.__n_legs + 3 * sum(self.__n_seg[:i]) + 3 * self.__n_seg[i])] self.__leg.set(t_P[i + 1], x0, throttles, t_P[i + 2], xe) # update mass! m0 = x[4 + 8 * i] ceq.extend(self.__leg.mismatch_constraints()) cineq.extend(self.__leg.throttles_constraints()) # Adding the boundary constraints # departure1 v_dep_con1 = (x[5]**2 + x[6]**2 + x[7]**2 - self.__vinf_dep1**2) / (EARTH_VELOCITY**2) # arrival1 v_arr_con1 = (x[8 + (len(seq1) - 2) * 8]**2 + x[9 + (len(seq1) - 2) * 8]**2 + x[10 + (len(seq1) - 2) * 8]**2 - self.__vinf_arr1**2) / (EARTH_VELOCITY**2) # departure2 v_dep_con2 = (x[5 + (len(seq1) - 1) * 8]**2 + x[6 + (len(seq1) - 1) * 8]**2 + x[7 + (len(seq1) - 1) * 8]**2 - self.__vinf_dep2**2) / (EARTH_VELOCITY**2) # arrival2 v_arr_con2 = (x[8 + (len(seq1) - 1 + len(seq2) - 2) * 8]**2 + x[9 + (len(seq1) - 1 + len(seq2) - 2)]**2 + x[10 * (len(seq1) - 1 + len(seq2) - 2)]**2 - self.__vinf_arr2**2) / (EARTH_VELOCITY**2) cineq.append(v_dep_con1 * 100) cineq.append(v_arr_con1 * 100) cineq.append(v_dep_con2 * 100) cineq.append(v_arr_con2 * 100) # We add the fly-by constraints for i in range(len(seq1) - 2): DV_eq, alpha_ineq = fb_con(x[8 + i * 8:11 + i * 8], x[13 + i * 8:16 + i * 8], self.seq1[i + 1]) ceq.append(DV_eq / (EARTH_VELOCITY**2)) cineq.append(alpha_ineq) for i in range(len(seq2) - 2): DV_eq, alpha_ineq = fb_con( x[8 + (i + len(seq1) - 1) * 8:11 + (i + len(seq1) - 1) * 8], x[13 + (i + len(seq1) - 1) * 8:16 + (i + len(seq1) - 1) * 8], self.seq2[i + 1]) ceq.append(DV_eq / (EARTH_VELOCITY**2)) cineq.append(alpha_ineq) #Adding the mass constraint mass_con = self.__mf - m0 ceq.append(mass_con / self.__mf) # Making the mismatches non dimensional for i in range(self.__n_legs): ceq[0 + i * 7] /= AU ceq[1 + i * 7] /= AU ceq[2 + i * 7] /= AU ceq[3 + i * 7] /= EARTH_VELOCITY ceq[4 + i * 7] /= EARTH_VELOCITY ceq[5 + i * 7] /= EARTH_VELOCITY ceq[6 + i * 7] /= self.__mf # We assemble the constraint vector retval = list() retval.extend(ceq) retval.extend(cineq) return retval