Skip to content

[General] Can't add more than 3 arcs in the direct optimisation #581

Closed
@alesiagr

Description

@alesiagr

Voici le code.

Le debut est pour intégrer les toolbox nécessaire + définir les paramètres. Ensuite je formule 3 pbs: 1 arc fonctionne, 3 arcs aussi, 4 non...

Tout à la fin il y a une fonction de plot que je définis, pas nécessaire.

using SPICE
using OptimalControl
using NLPModelsIpopt
# using Interpolations
using JLD2
# using OrdinaryDiffEq
using DataInterpolations
using CSV
using JLD2
using Plots


using Downloads: download


# SPICE files that you have to download but only once
const LSK = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/lsk/naif0012.tls"
const SPK = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/spk/planets/de440.bsp"
const PCK = "https://naif.jpl.nasa.gov/pub/naif/generic_kernels/pck/pck00010.tpc"

# Download kernels
download(LSK, "naif0012.tls")
download(SPK, "de440.bsp")
download(PCK, "pck00010.tpc")

furnsh("naif0012.tls") # Leap seconds kernel
furnsh("de430.bsp") # Ephemeris kernel
furnsh("pck00010.tpc")  # PCK kernel for planetary constants


# Astrodynamical parameters
G = 6.6743e-11 / 1000^3 # km^3 kg^-1 s^-2
M_moon = 7.346e22 # kg
M_earth = 5.972168e24 # kg
M_sun = 1.989e30 # kg
AU = 1.495978707e11 / 1e3 # km
LU = 384399 # km
TU = sqrt(LU^3 / G / (M_moon + M_earth))
MUnit =  M_moon + M_earth
mu_Earth = 3.9860044188e14 / 1000^3 / LU^3 * TU^2
mu_Moon = 4.90486959e12 / 1000^3 / LU^3 * TU^2
mu_Sun = 1.327124400189e20  / 1000^3 / LU^3 * TU^2
mass_moon = M_moon / MUnit
mass_earth = M_earth / MUnit
mass_sun = M_sun / MUnit

# Spacecraft parameters
g0 = 9.80665 / 1000 / LU * TU^2
Isp = 1660 / TU 
wet_mass = 344 / MUnit 
fuel_mass = 90 / MUnit 
dry_mass = (wet_mass - fuel_mass) 
wet_by_dry = (dry_mass + fuel_mass) / dry_mass
Tmax =  0.090 / 1000 / MUnit / LU * TU^2 #thrust force in N
Q = Tmax / Isp / g0

mass_scaling_factor = wet_mass

# Mission data that I just copy paste here for simplicity
t0_J200 = 1.107747244e9
tf_J200 = 1.112803048e9
N = 15000 
t_values = LinRange(t0_J200, tf_J200, N-3)
t_values = vcat(-5e9, 0.0, collect(t_values), tf_J200 * 5)
states_moon = zeros(6, N)
states_earth = zeros(6, N)
states_sun = zeros(6, N)
t0 = t0_J200 / TU
tf = tf_J200 / TU

# Interpolations of the bodies positions/velocities
for i = 1:N
    states_moon[:,i], _ = spkezr("MOON", t_values[i], "ECLIPJ2000", "NONE", "EARTH MOON BARYCENTER")
    states_earth[:,i], _ = spkezr("EARTH", t_values[i], "ECLIPJ2000", "NONE", "EARTH MOON BARYCENTER")
    states_sun[:,i], _ = spkezr("SUN", t_values[i], "ECLIPJ2000", "NONE", "EARTH MOON BARYCENTER")
end

# Interpolation of the position and velocity of the celestial bodies (Sun, Moon, Earth)
x_moon = DataInterpolations.LinearInterpolation(states_moon[1,:] / LU, t_values / TU) 
y_moon = DataInterpolations.LinearInterpolation(states_moon[2,:] / LU, t_values / TU) 
z_moon = DataInterpolations.LinearInterpolation(states_moon[3,:] / LU, t_values / TU) 

x_earth = DataInterpolations.LinearInterpolation(states_earth[1,:] / LU, t_values / TU) 
y_earth = DataInterpolations.LinearInterpolation(states_earth[2,:] / LU, t_values / TU) 
z_earth = DataInterpolations.LinearInterpolation(states_earth[3,:] / LU, t_values / TU) 

x_sun = DataInterpolations.LinearInterpolation(states_sun[1,:] / LU, t_values / TU) 
y_sun = DataInterpolations.LinearInterpolation(states_sun[2,:] / LU, t_values / TU) 
z_sun = DataInterpolations.LinearInterpolation(states_sun[3,:] / LU, t_values / TU) 

# Times
t0 = 2952.5065962806448
t1 = 2953.955962786101
t2 = 2954.4423792964794
t3 = 2955.398985817685
t4 = 2957.4519685112937
t5 = 2959.0986010622196
t6 = 2960.6895789585565

# States at the previous times
ap0      =  [-0.992463207586249; 0.7937735622182638; 0.07902677416947182; 0.4497665242298916;  0.5768992856452368; -0.08990077540870026]
occult1  =  [0.024011456548615025; 1.0839463211562548; -0.06721110889958525; 0.8370532723530986; -0.2849379073937811; -0.09055054145691602]
lunar2   =  [0.42191676845234877; 0.8365166413216278; -0.10058044976319964; 1.0641134073373073;  -0.7420861511380829; 0.2221102307286784]
ap3      =  [0.8866648294530993; 0.07703956973358668; 0.28758014926093095; 0.010909379448810359; -1.0104415437867642; 0.3065975859809964]
lunar4   =  [-0.5240519542473246; -0.8727170323241018; 0.06983526263136841; -1.0656424593386877; 0.4013541226489389; -0.24177176981236737]
ap5      =  [-1.2845625006191574; 0.07452729181167739; -0.02061966816776342; 0.03379116945381267; 0.7236740339189934; -0.05964259399261467]
occult6  =  [-0.5063291057829847; 0.9375405520827109; -0.0856392904912281; 0.906825723975573; 0.17758145410610057; -0.009952663265456345]


# Changement de variable pour le temps
function phi(s, t0, t1)
    return t0 + (t1 - t0) * s
end

# Dynamique
function Fu(t, x, u)
    # Earth & Moon & Sun gravity
    
    r = x[1:3]
    v = x[4:6]
    m = x[7] * mass_scaling_factor

    x_e = [x_earth(t), y_earth(t), z_earth(t)]
    x_m = [x_moon(t), y_moon(t), z_moon(t)]
    x_s = [x_sun(t), y_sun(t), z_sun(t)]

    normrE = sqrt(sum((x_e - r).^2))
    normrM = sqrt(sum((x_m - r).^2))
    normrS = sqrt(sum((x_s - r).^2))

    normrSE = sqrt(sum((x_e - x_s).^2))
    normrMS = sqrt(sum((x_m - x_s).^2))

    dv = mu_Earth / normrE^3 * (x_e - r) + mu_Moon / normrM^3 * (x_m - r) + mu_Sun / normrS^3 * (x_s - r) - (1 / (mass_earth + mass_moon)) * ( x_s * (mu_Sun * mass_earth / normrSE^3 + mu_Moon * mass_sun / normrMS^3) - x_m * (mu_Moon * mass_sun / normrMS^3) - x_e * (mu_Sun * mass_earth / normrSE^3)) 
    dvu = Tmax * u / m
    dm = - Q * sqrt(sum(u.^2)) / mass_scaling_factor

    dx = [v; dv + dvu; dm]
    return dx
end


# Pb avec 1 arc
@def ocp1arc begin
    s  [ 0, 1 ], time
    y  R^7, state
    w  R^3, control

    x1  = y[1:7]

    u1  = w[1:3]

    mf  = y[end]

    -5  x1[1](s)  5
    -5  x1[2](s)  5
    -5  x1[3](s)  5
    -5  x1[4](s)  5
    -5  x1[5](s)  5
    -5  x1[6](s)  5
    0.5  x1[7](s)  1 # careful here ! dry mass > 0

    0  sum(u1(s).^2)  1

    x1[1:6](0)    == occult1
    x1[7](0)      == 1 
    x1[1:6](1)    == lunar2


    (s) == (t2 - t1) * Fu(phi(s, t1, t2), x1(s), u1(s))
    mf(1)  max

end


sol = solve(ocp1arc)
plot(sol)
# sol = solve(ocp1arc, grid_size = 100, max_iter = 3000, tol = 1e-6, acceptable_tol = 1e-5)

# 3 Arcs
@def ocp3arc begin
    s  [ 0, 1 ], time
    y  R^21, state
    w  R^9, control

    x1  = y[1:7]
    x2  = y[8:14]
    x3  = y[15:21]

    u1  = w[1:3]
    u2  = w[4:6]
    u3  = w[7:9]

    mf  = y[end]

    -5  x1[1](s)  5
    -5  x1[2](s)  5
    -5  x1[3](s)  5
    -5  x1[4](s)  5
    -5  x1[5](s)  5
    -5  x1[6](s)  5
    0.5  x1[7](s)  1 # careful here ! dry mass > 0

    -5  x2[1](s)  5
    -5  x2[2](s)  5
    -5  x2[3](s)  5
    -5  x2[4](s)  5
    -5  x2[5](s)  5
    -5  x2[6](s)  5
    0.5  x2[7](s)  1 # careful here ! dry mass > 0

    -5  x3[1](s)  5
    -5  x3[2](s)  5
    -5  x3[3](s)  5
    -5  x3[4](s)  5
    -5  x3[5](s)  5
    -5  x3[6](s)  5
    0.5  x3[7](s)  1 # careful here ! dry mass > 0


    0  sum(u1(s).^2)  1
    0  sum(u2(s).^2)  1
    0  sum(u3(s).^2)  1


    x1[1:6](0)    == ap0
    x1[7](0)      == 1 
    x1[1:6](1)    == occult1
    x2(0) - x1(1) == [0, 0, 0, 0, 0, 0, 0]
    x2[1:6](1)    == lunar2
    x3(0) - x2(1) == [0, 0, 0, 0, 0, 0, 0]
    x3[1:6](1)    == ap3


    (s) == [(t1 - t0) * Fu(phi(s, t0, t1), x1(s), u1(s)); (t2 - t1) * Fu(phi(s, t1, t2), x2(s), u2(s)); (t3 - t2) * Fu(phi(s, t2, t3), x3(s), u3(s))]
    mf(1)  max

end

sol = solve(ocp3arc, grid_size = 100, tol = 1e-6, disc_method=:gauss_legendre_2)
plot(sol)
# plot_trajNV_multiarc(sol, 3, [t0,t1,t2,t3])

# 4 arcs
@def ocp4arc begin
    s  [ 0, 1 ], time
    y  R^28, state
    w  R^12, control

    x1  = y[1:7]
    x2  = y[8:14]
    x3  = y[15:21]
    x4  = y[22:28]

    u1  = w[1:3]
    u2  = w[4:6]
    u3  = w[7:9]
    u4  = w[10:12]

    mf  = y[end]

    -5  x1[1](s)  5
    -5  x1[2](s)  5
    -5  x1[3](s)  5
    -5  x1[4](s)  5
    -5  x1[5](s)  5
    -5  x1[6](s)  5
    0.5  x1[7](s)  1 # careful here ! dry mass > 0

    -5  x2[1](s)  5
    -5  x2[2](s)  5
    -5  x2[3](s)  5
    -5  x2[4](s)  5
    -5  x2[5](s)  5
    -5  x2[6](s)  5
    0.5  x2[7](s)  1 # careful here ! dry mass > 0

    -5  x3[1](s)  5
    -5  x3[2](s)  5
    -5  x3[3](s)  5
    -5  x3[4](s)  5
    -5  x3[5](s)  5
    -5  x3[6](s)  5
    0.5  x3[7](s)  1 # careful here ! dry mass > 0

    -5  x4[1](s)  5
    -5  x4[2](s)  5
    -5  x4[3](s)  5
    -5  x4[4](s)  5
    -5  x4[5](s)  5
    -5  x4[6](s)  5
    0.5  x4[7](s)  1 # careful here ! dry mass > 0


    0  sum(u1(s).^2)  1
    0  sum(u2(s).^2)  1
    0  sum(u3(s).^2)  1
    0  sum(u4(s).^2)  1

    x1[1:6](0)    == ap0
    x1[7](0)      == 1 
    x1[1:6](1)    == occult1
    x2(0) - x1(1) == [0, 0, 0, 0, 0, 0, 0]
    x2[1:6](1)    == lunar2
    x3(0) - x2(1) == [0, 0, 0, 0, 0, 0, 0]
    x3[1:6](1)    == ap3
    x4(0) - x3(1) == [0, 0, 0, 0, 0, 0, 0]
    x4[1:6](1)    == lunar4

    (s) == [(t1 - t0) * Fu(phi(s, t0, t1), x1(s), u1(s)); (t2 - t1) * Fu(phi(s, t1, t2), x2(s), u2(s)); (t3 - t2) * Fu(phi(s, t2, t3), x3(s), u3(s)); (t4 - t3) * Fu(phi(s, t3, t4), x4(s), u4(s))]
    mf(1)  max

end

sol = solve(ocp4arc)



function plot_trajNV_multiarc(sol, nb_arcs, tvec)

    sol_time = sol.time_grid.value 


    Nsol = length(sol_time)
    sol_state = zeros(7 * nb_arcs, Nsol)
    sol_control = zeros(4 * nb_arcs, Nsol)
    for i in range(1, length(sol.time_grid.value))
        sol_state[:, i] = sol.state.value(sol.time_grid.value[I])
    end


    x_vals_opti = zeros(nb_arcs, Nsol)
    y_vals_opti = zeros(nb_arcs, Nsol)
    z_vals_opti = zeros(nb_arcs, Nsol)
    vx_vals_opti = zeros(nb_arcs, Nsol)
    vy_vals_opti = zeros(nb_arcs, Nsol)
    vz_vals_opti = zeros(nb_arcs, Nsol)
    m_vals_opti = zeros(nb_arcs, Nsol)

    for i in range(1, nb_arcs)
        x_vals_opti[i, :] = sol_state[1 + 7 * (i - 1), :]
        y_vals_opti[i, :] = sol_state[2 + 7 * (i - 1), :]
        z_vals_opti[i, :] = sol_state[3 + 7 * (i - 1), :]
        vx_vals_opti[i, :] = sol_state[4 + 7 * (i - 1), :]
        vy_vals_opti[i, :] = sol_state[5 + 7 * (i - 1), :]
        vz_vals_opti[i, :] = sol_state[6 + 7 * (i - 1), :]
        m_vals_opti[i, :] = sol_state[7 + 7 * (i - 1), :]
    end
 
    sol_time_plot = LinRange(tvec[1], tvec[end], N)
    x_moon_pos = [x_moon(t) for t in sol_time_plot]
    y_moon_pos = [y_moon(t) for t in sol_time_plot]
    z_moon_pos = [z_moon(t) for t in sol_time_plot]
    x_earth_pos = [x_earth(t) for t in sol_time_plot]
    y_earth_pos = [y_earth(t) for t in sol_time_plot]
    z_earth_pos = [z_earth(t) for t in sol_time_plot]

    p = plot(x_moon_pos, y_moon_pos, z_moon_pos, label = "moon orbit")
    plot!(x_earth_pos, y_earth_pos, z_earth_pos, label = "earth orbit")

    scatter!([x_vals_opti[1, 1]], [y_vals_opti[1, 1]], [z_vals_opti[1, 1]], label = "previous occultation")

    for i in range(1, nb_arcs)
        rand_color = RGB(rand(), rand(), rand()) 
        plot!(x_vals_opti[i, :], y_vals_opti[i, :], z_vals_opti[i, :], size=(600, 600), camera = (30,30), xlabel="x", ylabel="y", zlabel="z", label="solar sail trajectory", linewidth = 2, color = "black", legend =:topleft)
        scatter!([x_vals_opti[i, end]], [y_vals_opti[i, end]], [z_vals_opti[i, end]], label = "next occultation")
    end


    xlims!(-2, 2)
    ylims!(-2, 2)
    zlims!(-1.5, 1.5)
    
    display(p)
    # arrow_factor = 1e-1
    # quiver!(x_vals_opti[u_norm .> 0.1][1:2:end], y_vals_opti[u_norm .> 0.1][1:2:end], z_vals_opti[u_norm .> 0.1][1:2:end], quiver=(ux[u_norm .> 0.1][1:2:end] * arrow_factor, uy[u_norm .> 0.1][1:2:end] * arrow_factor, uz[u_norm .> 0.1][1:2:end] * arrow_factor), label="thrust directions", arrow=true, color = "red")

end

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions