Haven't updated in awhile
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
module Thesis
|
||||
|
||||
homedir = "/home/connor/projects/thesis"
|
||||
|
||||
using LinearAlgebra
|
||||
using ForwardDiff
|
||||
using PlotlyJS
|
||||
@@ -11,8 +13,8 @@ module Thesis
|
||||
furnsh("../../spice_files/naif0012.tls")
|
||||
furnsh("../../spice_files/de430.bsp")
|
||||
catch
|
||||
furnsh("spice_files/naif0012.tls")
|
||||
furnsh("spice_files/de430.bsp")
|
||||
furnsh("/home/connor/projects/thesis/spice_files/naif0012.tls")
|
||||
furnsh("/home/connor/projects/thesis/spice_files/de430.bsp")
|
||||
end
|
||||
|
||||
include("./types/errors.jl")
|
||||
@@ -25,8 +27,8 @@ module Thesis
|
||||
include("./utilities/conversions.jl")
|
||||
include("./utilities/plotting.jl")
|
||||
include("./nlp_solver.jl")
|
||||
include("./utilities/lamberts.jl")
|
||||
include("./mbh.jl")
|
||||
include("./genetic_algorithm.jl")
|
||||
include("./utilities/lamberts.jl")
|
||||
|
||||
end
|
||||
|
||||
128
julia/src/mbh.jl
128
julia/src/mbh.jl
@@ -47,17 +47,17 @@ end
|
||||
"""
|
||||
Generates a new randomized guess for the mission decision variables
|
||||
"""
|
||||
function mission_guess( flybys::Vector{Body},
|
||||
sc::Sc,
|
||||
start_mass::Float64,
|
||||
launch_window::Tuple{DateTime, DateTime},
|
||||
max_C3::Float64,
|
||||
max_v∞_in_mag::Float64,
|
||||
latest_arrival::DateTime)
|
||||
function rand_mission_guess( flybys::Vector{Body},
|
||||
sc::Sc,
|
||||
start_mass::Float64,
|
||||
launch_window::Tuple{DateTime, DateTime},
|
||||
max_C3::Float64,
|
||||
max_v∞_in_mag::Float64,
|
||||
latest_arrival::DateTime)
|
||||
mission_guess = Bad_Mission("Keep trying to generate a guess")
|
||||
lambert_guess = Bad_Mission("Keep trying to generate a guess")
|
||||
while mission_guess == Bad_Mission("Keep trying to generate a guess")
|
||||
# TODO: Eventually I can calculate n more intelligently
|
||||
n = 40
|
||||
n = 20
|
||||
|
||||
# Determine the launch conditions
|
||||
launch_date = rand(launch_window...)
|
||||
@@ -76,8 +76,16 @@ function mission_guess( flybys::Vector{Body},
|
||||
total_tof = sum(tofs)
|
||||
end
|
||||
|
||||
times = [ launch_date ]
|
||||
current_time = launch_date
|
||||
for tof in tofs
|
||||
current_time += Second(tof)
|
||||
push!(times, current_time)
|
||||
end
|
||||
|
||||
# For each phase, determine the v∞_in and δ
|
||||
phases = Vector{Phase}()
|
||||
lambert_phases = Vector{Phase}()
|
||||
for i in 1:num_phases
|
||||
flyby = flybys[i+1]
|
||||
v∞_in_normalized = rand(-1:0.0001:1, 3)
|
||||
@@ -93,7 +101,12 @@ function mission_guess( flybys::Vector{Body},
|
||||
periapsis = (flyby.μ/(v∞_in ⋅ v∞_in)) * ( 1/sin(δ/2) - 1 )
|
||||
end
|
||||
thrusts = rand(-1:0.0001:1,(n,3))
|
||||
# Add the phases
|
||||
push!(phases, Phase(flyby, v∞_in, v∞_out, tofs[i], thrusts))
|
||||
|
||||
# Also add the lambert phases
|
||||
v∞_out_lambert = lamberts(flybys[i], flyby, times[i], times[i+1])[1]
|
||||
push!(lambert_phases, Phase(flyby, v∞_in, v∞_out_lambert, tofs[i], zeros(n,3)))
|
||||
end
|
||||
|
||||
# Finally, determine the arrival v∞
|
||||
@@ -103,6 +116,7 @@ function mission_guess( flybys::Vector{Body},
|
||||
# And we can construct a mission guess object with these values
|
||||
try
|
||||
mission_guess = Mission_Guess( sc, start_mass, launch_date, launch_v∞, phases )
|
||||
lambert_guess = Mission_Guess( sc, start_mass, launch_date, launch_v∞, lambert_phases )
|
||||
catch e
|
||||
if isa(e, Mass_Error) ||isa(e,V∞_Error) || isa(e,HitPlanet_Error)
|
||||
continue
|
||||
@@ -110,17 +124,18 @@ function mission_guess( flybys::Vector{Body},
|
||||
rethrow()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return mission_guess
|
||||
return mission_guess, lambert_guess
|
||||
end
|
||||
|
||||
function record(m::Mission, planets::Vector{Body})
|
||||
t = Dates.now()
|
||||
abbrev = join([ planet.name[1] for planet in planets ])
|
||||
mkdir("archive/$(abbrev)_$(t)")
|
||||
store(m, "archive/$(abbrev)_$(t)/mission")
|
||||
mkdir("$(homedir)/archive/$(abbrev)_$(t)")
|
||||
store(m, "$(homedir)/archive/$(abbrev)_$(t)/mission")
|
||||
p = plot(m, title="$(abbrev) Trajectory")
|
||||
savefig(p,"archive/$(abbrev)_$(t)/plot.html")
|
||||
savefig(p,"$(homedir)/archive/$(abbrev)_$(t)/plot.html")
|
||||
end
|
||||
|
||||
|
||||
@@ -143,7 +158,7 @@ function mbh( flybys::Vector{Body},
|
||||
test::Bool=false )
|
||||
|
||||
# Convenience Functions
|
||||
random_guess() = mission_guess(flybys,sc,start_mass,launch_window,max_C3,max_v∞,latest_arrival)
|
||||
random_guess() = rand_mission_guess(flybys,sc,start_mass,launch_window,max_C3,max_v∞,latest_arrival)
|
||||
cost(m::Union{Mission,Mission_Guess}) = cost_fn(m, max_C3, max_v∞)
|
||||
cost(_::Nothing) = Inf
|
||||
solve(g::Mission_Guess) = solve_mission(g, launch_window, latest_arrival, max_C3, max_v∞)
|
||||
@@ -169,43 +184,68 @@ function mbh( flybys::Vector{Body},
|
||||
search_count += 1
|
||||
drill_count = 0
|
||||
verbose && log()
|
||||
x_star = solve(random_guess())
|
||||
x_star.converged || continue
|
||||
x_basin = x_star
|
||||
x_star, x_lambert = solve.(random_guess())
|
||||
|
||||
# If it does, though, we check to see if it's better than the current
|
||||
if cost(x_star) < cost(x_current) x_current = x_star end
|
||||
|
||||
# Either way, we need to drill into this particular basin, since it's valid
|
||||
while drill_count < drill_patience
|
||||
|
||||
verbose && log()
|
||||
|
||||
#Perturb to generate a slightly different x_star
|
||||
x_star = solve(perturb(x_basin))
|
||||
|
||||
# If better than the best, then keep it as current
|
||||
if x_star.converged && cost(x_star) < cost(x_current)
|
||||
x_current = x_star
|
||||
x_basin = x_star
|
||||
drill_count = 0
|
||||
# If better than the best in this particular basin, keep it as basin
|
||||
elseif x_star.converged && cost(x_star) < cost(x_basin)
|
||||
x_basin = x_star
|
||||
drill_count = 0
|
||||
# Otherwise, keep drilling
|
||||
else
|
||||
drill_count += 1
|
||||
# To improve solution time, we'll try drilling down the lambert's solution first
|
||||
if x_lambert.converged
|
||||
x_lambert_best = x_lambert
|
||||
# If it does converge we check to see if it's better than the current
|
||||
if cost(x_lambert) < cost(x_current) x_current = x_lambert end
|
||||
while drill_count < drill_patience
|
||||
verbose && log()
|
||||
# If better than the best, then keep it as current
|
||||
if x_lambert.converged && cost(x_lambert) < cost(x_current)
|
||||
x_current = x_lambert
|
||||
x_lambert_best = x_lambert
|
||||
drill_count = 0
|
||||
# If better than the best of lambert trajectories so far, keep it as lambert_best
|
||||
elseif x_lambert.converged && cost(x_lambert) < cost(x_lambert_best)
|
||||
x_lambert_best = x_lambert
|
||||
drill_count = 0
|
||||
# Otherwise, keep drilling
|
||||
else
|
||||
drill_count += 1
|
||||
end
|
||||
end
|
||||
drill_count = 0
|
||||
if x_current ∉ archive
|
||||
push!(archive, x_current)
|
||||
record(x_current, flybys)
|
||||
end
|
||||
end
|
||||
|
||||
if x_current ∉ archive
|
||||
push!(archive, x_current)
|
||||
record(x_current, flybys)
|
||||
# Afterwards, we'll try a completely random guess
|
||||
if x_star.converged
|
||||
x_basin = x_star
|
||||
# If it does converge we check to see if it's better than the current
|
||||
if cost(x_star) < cost(x_current) x_current = x_star end
|
||||
# Either way, we need to drill into this particular basin, since it's valid
|
||||
while drill_count < drill_patience
|
||||
verbose && log()
|
||||
#Perturb to generate a slightly different x_star
|
||||
x_star = solve(perturb(x_basin))
|
||||
# If better than the best, then keep it as current
|
||||
if x_star.converged && cost(x_star) < cost(x_current)
|
||||
x_current = x_star
|
||||
x_basin = x_star
|
||||
drill_count = 0
|
||||
# If better than the best in this particular basin, keep it as basin
|
||||
elseif x_star.converged && cost(x_star) < cost(x_basin)
|
||||
x_basin = x_star
|
||||
drill_count = 0
|
||||
# Otherwise, keep drilling
|
||||
else
|
||||
drill_count += 1
|
||||
end
|
||||
end
|
||||
if x_current ∉ archive
|
||||
push!(archive, x_current)
|
||||
record(x_current, flybys)
|
||||
end
|
||||
end
|
||||
|
||||
# If in test mode, we don't need to actually optimize. Just grab the first valid basin-best
|
||||
if test
|
||||
if test && x_current !== nothing
|
||||
println()
|
||||
return x_current, [ x_current ]
|
||||
end
|
||||
|
||||
@@ -123,7 +123,7 @@ function solve_mission( guess::Mission_Guess,
|
||||
"acceptable_constr_viol_tol" => 100tol,
|
||||
"bound_relax_factor" => 0.,
|
||||
"max_iter" => 100_000,
|
||||
"max_cpu_time" => 3. * length(guess.phases),
|
||||
"max_cpu_time" => 5. * length(guess.phases),
|
||||
"print_level" => print_level)
|
||||
options = Options(solver=IPOPT(ipopt_options), derivatives=ForwardFD())
|
||||
|
||||
|
||||
Reference in New Issue
Block a user