NLP seems to be doing pretty well
This commit is contained in:
@@ -5,19 +5,36 @@ export solve_mission
|
||||
struct Result
|
||||
converged::Bool
|
||||
info::Symbol
|
||||
sol::Matrix{Float64}
|
||||
sol::Mission_Guess
|
||||
end
|
||||
|
||||
function constraint_bounds(guess::Mission_Guess)
|
||||
low_constraint = Vector{Float64}()
|
||||
high_constraint = Vector{Float64}()
|
||||
|
||||
for phase in guess.phases
|
||||
if phase != guess.phases[end]
|
||||
push!(low_constraint, -100., -100., -100., -0.005, -0.005, -0.005, -30., 100.)
|
||||
push!(high_constraint, 100., 100., 100., 0.005, 0.005, 0.005, 30., 100_000.)
|
||||
else
|
||||
push!(low_constraint, -100., -100., -100., 0.)
|
||||
push!(high_constraint, 100., 100., 100., guess.start_mass - guess.sc.dry_mass)
|
||||
end
|
||||
end
|
||||
return low_constraint, high_constraint
|
||||
|
||||
end
|
||||
"""
|
||||
This function will take an initial guess to a mission profile and leverage Ipopt to solve the mission
|
||||
|
||||
NOTE: This function will output a proper mission if it succeeded and just re-return the original
|
||||
guess otherwise
|
||||
"""
|
||||
function solve_mission( guess::Mission_Guess;
|
||||
tol=1e-8,
|
||||
function solve_mission( guess::Mission_Guess,
|
||||
launch_window::Vector{DateTime},
|
||||
latest_arrival::DateTime;
|
||||
tol=1e-10,
|
||||
verbose::Bool=false )
|
||||
# First we need to define a function that propagates the mission all the way through
|
||||
# The function takes in a constraints vector (g) and an input vector (x) and spits out
|
||||
# the objective function. In my case, the objective will be constant.
|
||||
#
|
||||
|
||||
# First we define our starting point
|
||||
x0 = Vector(guess)
|
||||
@@ -52,59 +69,39 @@ function solve_mission( guess::Mission_Guess;
|
||||
goal = state(current_planet, time, v∞_in)
|
||||
final = prop(reshape(thrusts, (n,3)), start, guess.sc, tof)[2]
|
||||
if flyby != flybys[end]
|
||||
g[1+8i:6+8i] .= final[1:6] .- goal[1:6]
|
||||
g[7+8i] = norm(v∞_out) - norm(v∞_in)
|
||||
g[1+8i:6+8i] .= (final[1:6] .- goal[1:6]) .* [1., 1., 1., 10_000., 10_000., 10_000.]
|
||||
g[7+8i] = (norm(v∞_out) - norm(v∞_in)) * 10_000.
|
||||
δ = acos( ( v∞_in ⋅ v∞_out ) / ( norm(v∞_in) * norm(v∞_out) ) )
|
||||
g[8+8i] = (current_planet.μ/(v∞_in ⋅ v∞_in)) * ( 1/sin(δ/2) - 1 )
|
||||
g[8+8i] = (current_planet.μ/(v∞_in ⋅ v∞_in)) * ( 1/sin(δ/2) - 1 ) - current_planet.r
|
||||
else
|
||||
g[8length(flybys)+1:8length(flybys)+3] .= final[1:3] .- goal[1:3]
|
||||
g[8length(flybys)+4] = final[7]
|
||||
g[8*(length(flybys)-1)+1:8*(length(flybys)-1)+3] .= final[1:3] .- goal[1:3]
|
||||
g[8*(length(flybys)-1)+4] = final[7] - guess.sc.dry_mass
|
||||
end
|
||||
start = state(current_planet, time, v∞_out, final[7])
|
||||
i += 1
|
||||
return 1.0
|
||||
end
|
||||
return 1.0
|
||||
end
|
||||
g = zeros(8length(flybys)+4)
|
||||
optimizer!(g,x0)
|
||||
return g
|
||||
|
||||
max_time = Dates.datetime2unix(latest_arrival) - Dates.datetime2unix(launch_window[1])
|
||||
lower_x = lowest_mission_vector(launch_window, length(guess.phases), n)
|
||||
upper_x = highest_mission_vector(launch_window, max_time, length(guess.phases), n)
|
||||
num_constraints = 8*(length(guess.phases)-1) + 4
|
||||
g_low, g_high = constraint_bounds(guess)
|
||||
ipopt_options = Dict("constr_viol_tol" => tol,
|
||||
"acceptable_constr_viol_tol" => 100tol,
|
||||
"max_iter" => 10_000,
|
||||
"max_cpu_time" => 300.,
|
||||
"print_level" => 5)
|
||||
options = Options(solver=IPOPT(ipopt_options), derivatives=ForwardFD())
|
||||
|
||||
x, _, info = minimize(optimizer!, x0, num_constraints, lower_x, upper_x, g_low, g_high, options)
|
||||
if verbose println(info) end
|
||||
|
||||
# n = size(x0)[1]
|
||||
|
||||
# function f!(g,x)
|
||||
# try
|
||||
# g[1:6] .= prop(reshape(x,(n,3)), start, craft, tof, primary)[2][1:6]
|
||||
# return 1.
|
||||
# catch e
|
||||
# if isa(e,LaGuerreConway_Error) || isa(e, Mass_Error) || isa(e, PropOne_Error)
|
||||
# return 10_000.
|
||||
# else
|
||||
# rethrow
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
# lower_x = -1 * ones(3n)
|
||||
# upper_x = ones(3n)
|
||||
# num_constraints = 6
|
||||
# filename = "ipopt_"*string(rand(UInt))
|
||||
# ipopt_options = Dict("constr_viol_tol" => tol,
|
||||
# "acceptable_constr_viol_tol" => 1e-4,
|
||||
# "max_iter" => 10_000,
|
||||
# "max_cpu_time" => 30.,
|
||||
# "print_level" => 0,
|
||||
# "output_file" => filename)
|
||||
# options = Options(solver=IPOPT(ipopt_options),
|
||||
# derivatives=ForwardAD())
|
||||
# x, _, info = minimize(f!, vec(x0), num_constraints, lower_x, upper_x, final[1:6], final[1:6], options)
|
||||
# rm(filename)
|
||||
# if info in [:Solve_Succeeded, :Solved_To_Acceptable_Level]
|
||||
# return Result(true, info, reshape(x,(n,3)))
|
||||
# else
|
||||
# if verbose println(info) end
|
||||
# return Result(false, info, x0)
|
||||
# end
|
||||
if info in [:Solve_Succeeded, :Solved_To_Acceptable_Level]
|
||||
return Mission(x, guess.sc, guess.start_mass, flybys)
|
||||
else
|
||||
return guess
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -56,7 +56,20 @@ function prop(ΔVs::Matrix{T},
|
||||
for k in 1:7 push!(states[k], interpolated_state[k]) end
|
||||
end
|
||||
end
|
||||
state = prop_one(ΔVs[i,:], state, craft, time/n, primary)
|
||||
try
|
||||
state = prop_one(ΔVs[i,:], state, craft, time/n, primary)
|
||||
catch e
|
||||
if isa(e,PropOne_Error)
|
||||
for val in e.ΔV_unit
|
||||
# If this isn't true, then we just let it slide
|
||||
if abs(val) > 1.0001
|
||||
rethrow()
|
||||
end
|
||||
end
|
||||
else
|
||||
rethrow()
|
||||
end
|
||||
end
|
||||
for j in 1:7 push!(states[j], state[j]) end
|
||||
state[7] >= craft.dry_mass || throw(Mass_Error(state[7]))
|
||||
end
|
||||
@@ -68,4 +81,4 @@ end
|
||||
"""
|
||||
Convenience function for propagating a state with no thrust
|
||||
"""
|
||||
prop(x::Vector{Float64}, t::Float64, p::Body=Sun) = prop(zeros(1000,3), [x;1e10], no_thrust, t, p)[1]
|
||||
prop(x::Vector{Float64}, t::Float64, p::Body=Sun) = prop(zeros(1000,3), [x;1.], no_thrust, t, p)[1]
|
||||
|
||||
Reference in New Issue
Block a user