-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathevaluateFixedDawn.py
More file actions
308 lines (268 loc) · 12.2 KB
/
evaluateFixedDawn.py
File metadata and controls
308 lines (268 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
import time
import os
import numpy as np
import matplotlib as mlt
import matplotlib.pyplot as plt
import pygmo as pg
import pykep as pk
from plottingUtilsLaunchWindow import plottingGridSearch
from plottingUtilsIndividualTrajectory import plotting
from hodographicShaping_SI import hodographicShaping
from utils import *
from patchedTrajectoryUtils import *
from pygmoProblemsShaping import myProblemShapingSingle
from conversions import stateCyl2cart, stateCart2cyl
from plottingUtilsPatchedTrajectory import patchedPlots
from orbitFollowing import orbitFollowing
def getShapingResults(population, algorithm, time, initialGuess):
'''
Retrieve results from the final population and print a status report
'''
finalPop = population.get_x()
log = algorithm.extract(pg.nlopt).get_log()
bestTrajectory = np.array(population.get_x()[population.best_idx()])
bestDeltaV = population.get_f()[population.best_idx()]
nFevals = population.problem.get_fevals()
print('\n#################################################################')
print('Low-thrust transfer results')
print('Initial guess:\t', initialGuess)
print("Champion:\t", np.round(bestTrajectory[0], 2),
np.round(bestTrajectory[1], 2),
np.round(bestTrajectory[2], 2),
np.round(bestTrajectory[3], 2),
np.round(bestTrajectory[4], 2),
np.round(bestTrajectory[5], 2))
print('Best DeltaV:\t', np.round(bestDeltaV[0], 2))
print(f'Number of fitness evaluations:\t{nFevals}')
print(f'Finished computation in\t\t{time:.2f} s')
print(f'Time per fitness evaluation:\t{time/nFevals*1e3:.2f} ms')
return bestDeltaV, bestTrajectory
def optimizationSetup(problem):
'''
Setup Pygmo for the given problem
'''
nl = pg.nlopt('neldermead')
pop = pg.population(problem, 1)
nl.xtol_rel = 1E-6
nl.maxeval = 10_000
algo = pg.algorithm(nl)
algo.set_verbosity(100)
pop = pg.population(problem, 1)
pop.set_x(0, [0, 0, 0, 0, 0, 0])
initialGuess = pop.get_x()[pop.best_idx()]
return pop, algo, initialGuess
def main(folder = 'graveyard'):
"""
Evaluate patched low thrust trajectories
For explicit conditions resembling the Dawn mission:
Launch from Earth -> impulsive shot -> low-thrust to Mars -> swingby
-> low-thrust to Vesta -> rendezvous
All state vectors at this level are in cylindrical coordinates:
[radius, phi, z, v_r, vTheta, v_z]]
the only exception is the flyby computation, see below
"""
############################################################################
# Initialization
# output folder: Contents are overwritten each run!
outputFolder = os.path.join('output', folder)
checkFolder(outputFolder)
# reduce precision of printed numpy values
np.set_printoptions(precision=3)
# load spice kernels
ephems = 'spice'
loadSpiceKernels()
############################################################################
# Free parameters
# set up the problem: fixed parameters
ephems = 'spice'
# bodies
depBody = '3' # earth
arrBody = '4' # mars
arrBody2 = '2000004' # Vesta
arrBody4 = '2000001' # Ceres
# number of revolutions
N = 0
N2 = 1
N4 = 0
# orbit insertion (tangential inpulsive shot)
injectionDeltaV = [0, 2.42e3, 0]
# flyby parameters
swingbyPlanet = pk.planet.jpl_lp('mars')
arrVelMars = [-2.21e3, 2.17e4, -6.37e1]
flybyPlane = 2.71
flybyAltitude = 471e3
# dates
depMjd = 2782.2
tof = 407.6 # Earth - Mars
tof2 = 1099.1 # Mars- Vesta
tof3 = 559.2 # stay at Vesta
tof4 = 912.7 # transfer Vesta - Ceres
############################################################################
# Derived parameters
# Earth - Mars
arrMjd = depMjd + tof
planetStateDep, __, __ = ephemeris(depBody, depMjd, mode=ephems)
planetStateArr, plArCart, __ = ephemeris(arrBody, arrMjd, mode=ephems)
print('Mars arrival date', arrMjd)
print('Mars state cyl', planetStateArr)
print('Mars state cart', plArCart)
injectionDeltaVabs = np.linalg.norm(injectionDeltaV)
scStateDep = applyDeltaV(planetStateDep, injectionDeltaV)
scStateArr = np.array((planetStateArr[0:3], arrVelMars)).reshape(6,)
# swingby
scStateArrCart = stateCyl2cart(scStateArr) # convert state to Cartesian
# Mars - Vesta
depMjd2 = arrMjd
arrMjd2 = depMjd2 + tof2
depBody2 = arrBody
scStateArr2, __, __ = ephemeris(arrBody2, arrMjd2, mode=ephems)
# stay at Vesta
depMjd3 = arrMjd2
arrMjd3 = depMjd3 + tof3
body = arrBody2
# Vesta - Ceres
depMjd4 = arrMjd3
arrMjd4 = depMjd4 + tof4
depBody4 = body
scStateDep4, __, __ = ephemeris(depBody4, depMjd4, mode=ephems)
scStateArr4, __, __ = ephemeris(arrBody4, arrMjd4, mode=ephems)
############################################################################
# Computations
# low-thrust transfer to Mars
prob = pg.problem(myProblemShapingSingle(scStateDep, scStateArr,
depDate=depMjd, tof=tof, N=N,
depBody=depBody, target=arrBody))
pop, algo, initialGuess = optimizationSetup(prob)
print('Run Nelder-Mead to find good shape coefficients.')
start = time.process_time()
pop = algo.evolve(pop)
optiTime = time.process_time() - start
DeltaV1, c1 = getShapingResults(pop, algo, optiTime, initialGuess)
# flyby
scStateNewCart, swingbyDeltaV = flyby(scStateArrCart, 'mars',
flybyAltitude, flybyPlane, mode='jpl', mjd=arrMjd,
folder=outputFolder, makePlot=True, save=True, show=True)
scStateDep2 = stateCart2cyl(scStateNewCart) # convert back to Cylindrical
# low-thrust to Vesta
prob = pg.problem(myProblemShapingSingle(scStateDep2, scStateArr2,
depDate=depMjd2, tof=tof2, N=N2,
depBody=depBody2, target=arrBody2))
pop, algo, initialGuess = optimizationSetup(prob)
start = time.process_time()
print('Run Nelder-Mead to find good shape coefficients.')
pop = algo.evolve(pop)
optiTime = time.process_time() - start
DeltaV2, c2 = getShapingResults(pop, algo, optiTime, initialGuess)
# stay at Vesta
transfer3 = orbitFollowing(startDate=depMjd3, tof=tof3, body=body,
ephemSource=ephems)
# low-thrust to Ceres
prob = pg.problem(myProblemShapingSingle(scStateDep4, scStateArr4,
depDate=depMjd4, tof=tof4, N=N4,
depBody=depBody4, target=arrBody4))
pop, algo, initialGuess = optimizationSetup(prob)
start = time.process_time()
print('Run Nelder-Mead to find good shape coefficients.')
pop = algo.evolve(pop)
optiTime = time.process_time() - start
DeltaV4, c4 = getShapingResults(pop, algo, optiTime, initialGuess)
# compute the total DeltaV
totalDeltaV = np.squeeze(DeltaV1 + DeltaV2 + DeltaV4)
############################################################################
# Result outputs
# compute the individual transfers again for detailed results and plotting
details = False
print('Detailed results for each leg')
transfer = hodographicShaping(scStateDep, scStateArr,
departureDate=depMjd, tof=tof, N=N,
departureBody = depBody,
arrivalBody = arrBody,
rShape = 'CPowPow2_scaled',
thetaShape = 'CPowPow2_scaled',
zShape = 'CosR5P3CosR5P3SinR5_scaled',
rShapeFree = 'PSin05PCos05_scaled',
thetaShapeFree = 'PSin05PCos05_scaled',
zShapeFree = 'P4CosR5P4SinR5_scaled',
rFreeC = [c1[0], c1[1]],
thetaFreeC = [c1[2], c1[3]],
zFreeC = [c1[4], c1[5]],
)
transfer.shapingRadial()
transfer.shapingVertical()
transfer.shapingTransverse()
transfer.assembleThrust()
transfer.checkBoundaryConditions()
transfer.evaluate(evalThrust='Grid', printTime=False, nEvalPoints = 1000)
if details:
transfer.status(printBC=False)
transfer2 = hodographicShaping(scStateDep2, scStateArr2,
departureDate=depMjd2, tof=tof2, N=N2,
departureBody = depBody2,
arrivalBody = arrBody2,
rShape = 'CPowPow2_scaled',
thetaShape = 'CPowPow2_scaled',
zShape = 'CosR5P3CosR5P3SinR5_scaled',
rShapeFree = 'PSin05PCos05_scaled',
thetaShapeFree = 'PSin05PCos05_scaled',
zShapeFree = 'P4CosR5P4SinR5_scaled',
rFreeC = [c2[0], c2[1]],
thetaFreeC = [c2[2], c2[3]],
zFreeC = [c2[4], c2[5]],
)
transfer2.shapingRadial()
transfer2.shapingVertical()
transfer2.shapingTransverse()
transfer2.assembleThrust()
transfer2.checkBoundaryConditions()
transfer2.evaluate(evalThrust='Grid', printTime=False, nEvalPoints = 1000)
if details:
transfer2.status(printBC=True)
transfer4 = hodographicShaping(scStateDep4, scStateArr4,
departureDate=depMjd4, tof=tof4, N=N4,
departureBody = depBody4,
arrivalBody = arrBody4,
rShape = 'CPowPow2_scaled',
thetaShape = 'CPowPow2_scaled',
zShape = 'CosR5P3CosR5P3SinR5_scaled',
rShapeFree = 'PSin05PCos05_scaled',
thetaShapeFree = 'PSin05PCos05_scaled',
zShapeFree = 'P4CosR5P4SinR5_scaled',
rFreeC = [c4[0], c4[1]],
thetaFreeC = [c4[2], c4[3]],
zFreeC = [c4[4], c4[5]],
)
transfer4.shapingRadial()
transfer4.shapingVertical()
transfer4.shapingTransverse()
transfer4.assembleThrust()
transfer4.checkBoundaryConditions()
transfer4.evaluate(evalThrust='Grid', printTime=False, nEvalPoints = 1000)
if details:
transfer4.status(printBC=True)
# print overal results
print('###################################################################')
print(f'Results of patched trajectory computation')
print(f'Orbit injection impulse:\t{(injectionDeltaVabs)/1e3:>9.2f} km/s')
print(f'DeltaV Earth -> Mars:\t\t{np.squeeze(DeltaV1)/1e3:>9.2f} km/s')
print(f'Swingby DeltaV:\t\t\t{swingbyDeltaV/1e3:>9.2f} km/s')
print(f'DeltaV Mars -> Vesta:\t\t{np.squeeze(DeltaV2)/1e3:>9.2f} km/s')
print(f'DeltaV Vesta -> Ceres:\t\t{np.squeeze(DeltaV4)/1e3:>9.2f} km/s')
print(f'Total low-thrust DeltaV:\t{totalDeltaV/1e3:>9.2f} km/s')
print('###################################################################')
# generate combined plots
awesomePlotWonderland = patchedPlots(
[transfer, transfer2, transfer3, transfer4],
samples=1000,
folder=outputFolder,
save=True,
show=True,
addBody=[])
# awesomePlotWonderland.planetSystem(plotSOI=True, scaling=False)
awesomePlotWonderland.trajectory2D()
awesomePlotWonderland.trajectory3D(scaling=False)
# awesomePlotWonderland.hodograph()
# awesomePlotWonderland.trajectory3Danimation(scaling=False, staticOrbits=True, save=False)
# awesomePlotWonderland.trajectory2Danimation(staticOrbits=True, save=True)
# awesomePlotWonderland.thrust()
if __name__ == '__main__':
main(folder='dawn_fixed')