This post presents another optimised trajectory for getting from Earth to Jupiter. The trajectory starts at Earth, drops to Venus, then back to Earth, then out to Mars, then back to Earth and finally a transfer out to Jupiter. The total cost of the transfer is 3,630 m/s from LEO to Jupiter capture. And given that it takes, 3,200 m/s just to escape Earth's gravity - another 250 m/s or so to be captured by Jupiter - the balance (just 200 m/s or so) enables the transfer all the way out to Jupiter (via four ballistic flybys). Transfers from Earth to Jupiter don't really get any cheaper than this.
A 'top down' view of the trajectory is shown below. Distances are in AU, and the orbits of Venus, Earth, Mars and Jupiter are shown.
The optimised trajectory plan is as follows:
This trajectory plan is fly-able in Orbiter (although MCCs are likely to run to a few hundred m/s). It is based on a schedule of Earth to Jupiter transfers posted on this forum by 'dgatsoulis'. Here, PyKEP has been used to 'fill in the blanks' by providing some additional information about the optimised trajectory. It is assumed that LEO is a 300 x 300 km circular orbit
The Python code used to generate this plan is as follows:
A 'top down' view of the trajectory is shown below. Distances are in AU, and the orbits of Venus, Earth, Mars and Jupiter are shown.
The optimised trajectory plan is as follows:
Code:
Date of Earth departue: 2023-May-27 23:40:30.246197
Date of Venus encounter: 2023-Oct-21 21:53:11.311513
Date of Earth encounter: 2024-Sep-01 10:02:09.685537
Date of Mars encounter: 2025-Feb-10 21:50:49.497903
Date of Earth encounter: 2026-Nov-25 20:03:44.812798
Date of Jupiter arrival: 2029-Nov-06 23:55:40.784441
Transfer time from Earth to Venus: 146.93 days
Transfer time from Venus to Earth: 315.51 days
Transfer time from Earth to Mars: 162.49 days
Transfer time from Mars to Earth: 652.93 days
Transfer time from Earth to Jupiter: 1077.16 days
Total mission duration: 2355.01 days
TransX escape plan - Earth escape
--------------------------------------
MJD: 60091.9865
Prograde: -2498.827 m/s
Outward: -817.887 m/s
Plane: -1886.965 m/s
Hyp. excess velocity: 3236.311 m/s
Earth escape burn: 3669.374 m/s
Venus encounter
--------------------------------------
MJD: 60238.9119
Approach velocity: 5581.567 m/s
Departure velocity: 5581.567 m/s
Outward angle: -20.168 deg
Inclination: 24.867 deg
Turning angle: 47.861 deg
Periapsis altitude: 9227.455 km
dV needed: 0.000 m/s
Earth encounter
--------------------------------------
MJD: 60554.4182
Approach velocity: 8724.001 m/s
Departure velocity: 8724.001 m/s
Outward angle: -52.409 deg
Inclination: -13.843 deg
Turning angle: 45.313 deg
Periapsis altitude: 1980.691 km
dV needed for flyby: 0.000 m/s
Mars encounter
--------------------------------------
MJD: 60716.9103
Approach velocity: 10035.980 m/s
Departure velocity: 10035.980 m/s
Outward angle: 98.839 deg
Inclination: -0.985 deg
Turning angle: 9.827 deg
Periapsis altitude: 35867.103 km
dV needed for flyby: 0.000 m/s
Earth encounter
--------------------------------------
MJD: 61369.8359
Approach velocity: 11457.896 m/s
Departure velocity: 11457.896 m/s
Outward angle: 45.576 deg
Inclination: -9.078 deg
Turning angle: 26.971 deg
Periapsis altitude: 3605.498 km
dV needed for flyby: 0.000 m/s
Jupiter arrival
--------------------------------------
MJD: 62446.9970
Hyp. excess velocity: 5572.611 m/s
Orbit insertion burn 260.791 m/s - (C3 = 0)
Total fuel cost: 3930.166 m/s
This trajectory plan is fly-able in Orbiter (although MCCs are likely to run to a few hundred m/s). It is based on a schedule of Earth to Jupiter transfers posted on this forum by 'dgatsoulis'. Here, PyKEP has been used to 'fill in the blanks' by providing some additional information about the optimised trajectory. It is assumed that LEO is a 300 x 300 km circular orbit
The Python code used to generate this plan is as follows:
Code:
from PyGMO.problem import base
from PyGMO import algorithm, island, archipelago, topology
from PyKEP import planet, epoch, ic2par, fb_vel, lambert_problem, DAY2SEC, AU, MU_SUN
from PyKEP.planet import jpl_lp
from math import *
from numpy import *
earth = jpl_lp('earth' )
venus = jpl_lp('venus' )
mars = jpl_lp('mars' )
jupiter = jpl_lp('jupiter')
muE = earth.mu_self
muV = venus.mu_self
muM = mars.mu_self
muJ = jupiter.mu_self
radE = earth.radius + 300000
radV = venus.radius
radM = mars.radius
radJ = jupiter.radius + 300000
t1 = 60094.0
t2 = 60240.0
t3 = 60555.0
t4 = 60717.0
t5 = 61370.0
t6 = 62432.0
r1, v1 = earth.eph(epoch(t1, "mjd") )
r2, v2 = venus.eph(epoch(t2, "mjd") )
r3, v3 = earth.eph(epoch(t3, "mjd") )
r4, v4 = mars.eph(epoch(t4, "mjd") )
r5, v5 = earth.eph(epoch(t5, "mjd") )
r6, v6 = jupiter.eph(epoch(t6, "mjd") )
l1 = lambert_problem(r1, r2, (t2 - t1)*DAY2SEC, MU_SUN)
l2 = lambert_problem(r2, r3, (t3 - t2)*DAY2SEC, MU_SUN)
l3 = lambert_problem(r3, r4, (t4 - t3)*DAY2SEC, MU_SUN)
l4 = lambert_problem(r4, r5, (t5 - t4)*DAY2SEC, MU_SUN)
l5 = lambert_problem(r5, r6, (t6 - t5)*DAY2SEC, MU_SUN)
vo1 = array(l1.get_v1()[0]) - v1
vi2 = array(l1.get_v2()[0]) - v2
vo2 = array(l2.get_v1()[0]) - v2
vi3 = array(l2.get_v2()[0]) - v3
vo3 = array(l3.get_v1()[0]) - v3
vi4 = array(l3.get_v2()[0]) - v4
vo4 = array(l4.get_v1()[0]) - v4
vi5 = array(l4.get_v2()[0]) - v5
vo5 = array(l5.get_v1()[0]) - v5
vi6 = array(l5.get_v2()[0]) - v6
from PyGMO.problem import base
class my_problem_min(base):
"""
Put some descriptive text here
"""
def __init__(self):
super(my_problem_min, self).__init__(6) # a problem in three variables
self.set_bounds(0.0001, 0.9999) # place bounds on those variables
# Defines the objective function
def _objfun_impl(self, x):
# calculate the times
t1 = 60094.0 + (2*x[0]-1.0)*15 # epoch of Earth departure
t2 = 60240.0 + (2*x[1]-1.0)*15 # epoch of Venus encounter
t3 = 60555.0 + (2*x[2]-1.0)*15 # epoch of Earth encounter
t4 = 60717.0 + (2*x[3]-1.0)*15 # epoch of Mars encounter
t5 = 61370.0 + (2*x[4]-1.0)*15 # epoch of Earth encounter
t6 = 62432.0 + (2*x[5]-1.0)*15 # epoch of Jupiter encounter
# calculate the state vectors of Earth, Venus & Mercury using JPL's Low Precision
# ephemeris
r1, v1 = earth.eph(epoch(t1, "mjd") )
r2, v2 = venus.eph(epoch(t2, "mjd") )
r3, v3 = earth.eph(epoch(t3, "mjd") )
r4, v4 = mars.eph(epoch(t4, "mjd") )
r5, v5 = earth.eph(epoch(t5, "mjd") )
r6, v6 = jupiter.eph(epoch(t6, "mjd") )
# calculate the solutions of the two Lambert transfers
l1 = lambert_problem(r1, r2, (t2 - t1)*DAY2SEC, MU_SUN)
l2 = lambert_problem(r2, r3, (t3 - t2)*DAY2SEC, MU_SUN)
l3 = lambert_problem(r3, r4, (t4 - t3)*DAY2SEC, MU_SUN)
l4 = lambert_problem(r4, r5, (t5 - t4)*DAY2SEC, MU_SUN)
l5 = lambert_problem(r5, r6, (t6 - t5)*DAY2SEC, MU_SUN)
# perform the dV calculations
vo1 = array(l1.get_v1()[0]) - v1
vi2 = array(l1.get_v2()[0]) - v2
vo2 = array(l2.get_v1()[0]) - v2
vi3 = array(l2.get_v2()[0]) - v3
vo3 = array(l3.get_v1()[0]) - v3
vi4 = array(l3.get_v2()[0]) - v4
vo4 = array(l4.get_v1()[0]) - v4
vi5 = array(l4.get_v2()[0]) - v5
vo5 = array(l5.get_v1()[0]) - v5
vi6 = array(l5.get_v2()[0]) - v6
# sum the total fuel costs
f = sqrt(dot(vo1, vo1) + 2 * muE / radE) - sqrt(1 * muE / radE )
f = fb_vel(vi2, vo2, venus) + f
f = fb_vel(vi3, vo3, earth) + f
f = fb_vel(vi4, vo4, mars ) + f
f = fb_vel(vi5, vo5, earth) + f
f = sqrt(dot(vi6, vi6) + 2 * muJ / radJ) - sqrt(2 * muJ / radJ ) + f
# returb the total fuel cost
return (f, )
# Reimplement the virtual method that compares fitnesses - a minimisation problem
def _compare_fitness_impl(self, f1, f2):
return f1[0] < f2[0]
# Add some output to __repr__
def human_readable_extra(self):
return "\n\tMinimisation problem - Earth-Venus-Earth-Jupiter transfer"
prob = my_problem_min()
algo = algorithm.de(gen = 1000)
l = list()
for i in range(1):
archi = archipelago(algo,prob, 32, 10, topology = topology.ring())
for j in range(3):
archi.evolve(100)
print min([isl.population.champion.f[0] for isl in archi])
tmp = [isl for isl in archi]; tmp.sort(key = lambda x: x.population.champion.f[0]);
l.append(tmp[0].population.champion)
print
print "Results: \n"
print [ch.f[0] for ch in l]
l.sort(key = lambda x: x.f[0])
y = array(l[0].x)
# calculate the times
t1 = 60094.0 + (2*y[0]-1.0)*15 # epoch of Earth departure
t2 = 60240.0 + (2*y[1]-1.0)*15 # epoch of Venus encounter
t3 = 60555.0 + (2*y[2]-1.0)*15 # epoch of Earth encounter
t4 = 60717.0 + (2*y[3]-1.0)*15 # epoch of Mars encounter
t5 = 61370.0 + (2*y[4]-1.0)*15 # epoch of Earth encounter
t6 = 62432.0 + (2*y[5]-1.0)*15 # epoch of Jupiter encounter
# calculate the state vectors of Earth, Venus & Mercury using JPL's Low Precision
# ephemeris
r1, v1 = earth.eph(epoch(t1, "mjd") )
r2, v2 = venus.eph(epoch(t2, "mjd") )
r3, v3 = earth.eph(epoch(t3, "mjd") )
r4, v4 = mars.eph(epoch(t4, "mjd") )
r5, v5 = earth.eph(epoch(t5, "mjd") )
r6, v6 = jupiter.eph(epoch(t6, "mjd") )
# calculate the solutions of the two Lambert transfers
l1 = lambert_problem(r1, r2, (t2 - t1)*DAY2SEC, MU_SUN)
l2 = lambert_problem(r2, r3, (t3 - t2)*DAY2SEC, MU_SUN)
l3 = lambert_problem(r3, r4, (t4 - t3)*DAY2SEC, MU_SUN)
l4 = lambert_problem(r4, r5, (t5 - t4)*DAY2SEC, MU_SUN)
l5 = lambert_problem(r5, r6, (t6 - t5)*DAY2SEC, MU_SUN)
# perform the dV calculations
vo1 = array(l1.get_v1()[0]) - v1
vi2 = array(l1.get_v2()[0]) - v2
vo2 = array(l2.get_v1()[0]) - v2
vi3 = array(l2.get_v2()[0]) - v3
vo3 = array(l3.get_v1()[0]) - v3
vi4 = array(l3.get_v2()[0]) - v4
vo4 = array(l4.get_v1()[0]) - v4
vi5 = array(l4.get_v2()[0]) - v5
vo5 = array(l5.get_v1()[0]) - v5
vi6 = array(l5.get_v2()[0]) - v6
# sum the total fuel costs
f1 = sqrt(dot(vo1, vo1) + 2 * muE / radE) - sqrt(1 * muE / radE )
f2 = fb_vel(vi2, vo2, venus)
f3 = fb_vel(vi3, vo3, earth)
f4 = fb_vel(vi4, vo4, mars )
f5 = fb_vel(vi5, vo5, earth)
f6 = sqrt(dot(vi6, vi6) + 2 * muJ / radJ) - sqrt(2 * muJ / radJ )
# calculate the TransX cordinates - Earth departure
fward1 = v1 / linalg.norm(v1)
plane1 = cross(v1, r1)
plane1 = plane1 / linalg.norm(plane1)
oward1 = cross(plane1, fward1)
# calculate the TransX slingshot cordinates - Venus encounter
fward2 = v2 / linalg.norm(v2)
plane2 = cross(v2, r2)
plane2 = plane2 / linalg.norm(plane2)
oward2 = cross(plane2, fward2)
vx2 = dot(fward2, vo2)
vy2 = dot(oward2, vo2)
vz2 = dot(plane2, vo2)
# calculate the TransX slingshot cordinates - Earth encounter
fward3 = v3 / linalg.norm(v3)
plane3 = cross(v3, r3)
plane3 = plane3 / linalg.norm(plane3)
oward3 = cross(plane3, fward3)
vx3 = dot(fward3, vo3)
vy3 = dot(oward3, vo3)
vz3 = dot(plane3, vo3)
# calculate the TransX slingshot cordinates - Mars encounter
fward4 = v4 / linalg.norm(v4)
plane4 = cross(v4, r4)
plane4 = plane4 / linalg.norm(plane4)
oward4 = cross(plane4, fward4)
vx4 = dot(fward4, vo4)
vy4 = dot(oward4, vo4)
vz4 = dot(plane4, vo4)
# calculate the TransX slingshot cordinates - Jupiter arrival
fward5 = v5 / linalg.norm(v5)
plane5 = cross(v5, r5)
plane5 = plane5 / linalg.norm(plane5)
oward5 = cross(plane5, fward5)
vx5 = dot(fward5, vo5)
vy5 = dot(oward5, vo5)
vz5 = dot(plane5, vo5)
# print out the results
print "Date of Earth departue: ", epoch(t1, "mjd")
print "Date of Venus encounter: ", epoch(t2, "mjd")
print "Date of Earth encounter: ", epoch(t3, "mjd")
print "Date of Mars encounter: ", epoch(t4, "mjd")
print "Date of Earth encounter: ", epoch(t5, "mjd")
print "Date of Jupiter arrival: ", epoch(t6, "mjd")
print
print "Transfer time from Earth to Venus: ", round(t2 - t1, 2), " days"
print "Transfer time from Venus to Earth: ", round(t3 - t2, 2), " days"
print "Transfer time from Earth to Mars: ", round(t4 - t3, 2), " days"
print "Transfer time from Mars to Earth: ", round(t5 - t4, 2), " days"
print "Transfer time from Earth to Jupiter: ", round(t6 - t5, 2), " days"
print "Total mission duration: ", round(t6 - t1, 2), " days"
print
print
print "TransX escape plan - Earth escape"
print "--------------------------------------"
print("MJD: %10.4f " % round(epoch(t1, "mjd").mjd, 4))
print("Prograde: %10.3f m/s" % round(dot(fward1, vo1), 3))
print("Outward: %10.3f m/s" % round(dot(oward1, vo1), 3))
print("Plane: %10.3f m/s" % round(dot(plane1, vo1), 3))
print("Hyp. excess velocity:%10.3f m/s" % round(sqrt(dot(vo1, vo1)), 3))
print("Earth escape burn: %10.3f m/s" % round(f1, 3))
print
print
print "Venus encounter"
print "--------------------------------------"
print("MJD: %10.4f " % round(epoch(t2, "mjd").mjd, 4))
print("Approach velocity: %10.3f m/s" % round(sqrt(dot(vi2,vi2)), 3))
print("Departure velocity: %10.3f m/s" % round(sqrt(dot(vo2,vo2)), 3))
print("Outward angle: %10.3f deg" % round(180*atan2(vy2, vx2) / pi, 3))
print("Inclination: %10.3f deg" % round(180*atan2(vz2, sqrt(vx2*vx2+vy2*vy2)) / pi, 3))
ta = acos(dot(vi2, vo2)/sqrt(dot(vi2,vi2))/sqrt(dot(vo2,vo2)))
print("Turning angle: %10.3f deg" % round(ta*180/pi, 3))
alt = (muV/dot(vi2,vi2)*(1/sin(ta/2)-1) - venus.radius)/1000
print("Periapsis altitude: %10.3f km " % round(alt, 3))
print("dV needed: %10.3f m/s" % round(f2, 3))
print
print
print "Earth encounter"
print "--------------------------------------"
print("MJD: %10.4f " % round(epoch(t3, "mjd").mjd, 4))
print("Approach velocity: %10.3f m/s" % round(sqrt(dot(vi3,vi3)), 3))
print("Departure velocity: %10.3f m/s" % round(sqrt(dot(vo3,vo3)), 3))
print("Outward angle: %10.3f deg" % round(180*atan2(vy3, vx3) / pi, 3))
print("Inclination: %10.3f deg" % round(180*atan2(vz3, sqrt(vx3*vx3+vy3*vy3)) / pi, 3))
ta = acos(dot(vi3, vo3)/sqrt(dot(vi3,vi3))/sqrt(dot(vo3,vo3)))
print("Turning angle: %10.3f deg" % round(ta*180/pi, 3))
alt = (muE/dot(vi3,vi3)*(1/sin(ta/2)-1) - earth.radius)/1000
print("Periapsis altitude: %10.3f km " % round(alt, 3))
print("dV needed for flyby: %10.3f m/s" % round(f3, 3))
print
print
print "Mars encounter"
print "--------------------------------------"
print("MJD: %10.4f " % round(epoch(t4, "mjd").mjd, 4))
print("Approach velocity: %10.3f m/s" % round(sqrt(dot(vi4,vi4)), 3))
print("Departure velocity: %10.3f m/s" % round(sqrt(dot(vo4,vo4)), 3))
print("Outward angle: %10.3f deg" % round(180*atan2(vy4, vx4) / pi, 3))
print("Inclination: %10.3f deg" % round(180*atan2(vz4, sqrt(vx4*vx4+vy4*vy4)) / pi, 3))
ta = acos(dot(vi4, vo4)/sqrt(dot(vi4,vi4))/sqrt(dot(vo4,vo4)))
print("Turning angle: %10.3f deg" % round(ta*180/pi, 3))
alt = (muE/dot(vi4,vi4)*(1/sin(ta/2)-1) - earth.radius)/1000
print("Periapsis altitude: %10.3f km " % round(alt, 3))
print("dV needed for flyby: %10.3f m/s" % round(f4, 3))
print
print
print "Earth encounter"
print "--------------------------------------"
print("MJD: %10.4f " % round(epoch(t5, "mjd").mjd, 4))
print("Approach velocity: %10.3f m/s" % round(sqrt(dot(vi5,vi5)), 3))
print("Departure velocity: %10.3f m/s" % round(sqrt(dot(vo5,vo5)), 3))
print("Outward angle: %10.3f deg" % round(180*atan2(vy5, vx5) / pi, 3))
print("Inclination: %10.3f deg" % round(180*atan2(vz5, sqrt(vx5*vx5+vy5*vy5)) / pi, 3))
ta = acos(dot(vi5, vo5)/sqrt(dot(vi5,vi5))/sqrt(dot(vo5,vo5)))
print("Turning angle: %10.3f deg" % round(ta*180/pi, 3))
alt = (muE/dot(vi5,vi5)*(1/sin(ta/2)-1) - earth.radius)/1000
print("Periapsis altitude: %10.3f km " % round(alt, 3))
print("dV needed for flyby: %10.3f m/s" % round(f5, 3))
print
print
print "Jupiter arrival"
print "--------------------------------------"
print("MJD: %10.4f " % round(epoch(t6, "mjd").mjd, 4))
print("Hyp. excess velocity:%10.3f m/s" % round(sqrt(dot(vi6, vi6)), 3))
print("Orbit insertion burn %10.3f m/s - C3 = 0" % round(f6, 3))
print
print
Last edited: