Haven't updated in awhile

This commit is contained in:
Connor
2021-12-13 22:23:31 -07:00
parent 48535e732f
commit a39dea7377
152 changed files with 4735 additions and 182 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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())