def mee_ocp_central_difference(x):
    """
    Central different computation of the Jacobian of the cost funtion.
    Parameters:
    ===========
    tspan   -- vector containting initial and final time
    p0      -- initial costates guess
    states0 -- initial state vector (modified equinoctial elements)
    rho     -- switch smoothing parameter
    eclipse -- boolean (true or false)
    Returns:
    ========
    Jac -- Jacobian
    External:
    =========
    numpy, spipy.integrate
    """

    # TEMP
    tspan = np.array([0, 642.54])
    rho = 1
    eclipse = False
    meef = np.array([6.610864583184714, 0.0, 0.0, 0.0, 0.0, 0.0])

    # Initialization
    IC1 = np.zeros(14)
    IC2 = np.zeros(14)
    grad = np.zeros(7)
    DEL = 1e-5 * (x[7:14] / np.linalg.norm(x[7:14]))

    for i in range(0, 7):

        IC1 = x
        IC2 = x
        IC1[i + 7] = IC1[i + 7] + DEL[i]
        IC2[i + 7] = IC2[i + 7] - DEL[i]

        # Integrate Dynamics
        sol1 = integrator(
            lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
            tspan,
            IC1,
            method='LSODA',
            rtol=1e-13)
        sol2 = integrator(
            lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
            tspan,
            IC2,
            method='LSODA',
            rtol=1e-13)

        res1 = np.linalg.norm(meef[0:5] - sol1.y[0:5, -1])
        res2 = np.linalg.norm(meef[0:5] - sol2.y[0:5, -1])

        grad[i] = (res1 - res2) / (2 * DEL[i])

    return grad
def residuals_mee_ocp(p0, tspan, mee0, meef, rho, eclipse):
    """
    Computes error between current final state and desired final state for the
    low thrust, min-fuel, optimal trajectory using modified equinoctial elements.
    Parameters:
    ===========
    p0    -- current initial costate
    tspan -- vector containing initial and final time
    mee0  -- initial states (modified equinoctial elements)
    meef  -- final states (modified equinoctial elements)
    rho   -- switch smoothing parameter
    Returns:
    ========
    res -- residual
    External:
    =========
    numpy, scipy.integrate
    """
    ## Computes the error between the current and desired final state.
    states_in = np.zeros(14)
    states_in[0:7] = mee0[0:7]
    states_in[7:14] = p0[0:7]
    # sol = integrator(eom_mee_twobody_minfuel,(tspan[0],tspan[-1]),states_in,method='LSODA',rtol=1e-12)
    sol = integrator(
        lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
        tspan,
        states_in,
        method='LSODA',
        rtol=1e-12)
    # Free final mass and free final true longitude (angle)
    res = np.linalg.norm(meef[0:5] - sol.y[0:5, -1])
    print(res)
    return res
Beispiel #3
0
def residuals(p0):
    # Residual function
    # TEMP: For now I have copied these parameters into the function to make it more inline with the Rosenbrock
    # function above, but eventually we'll need to pass them as input arguments
    tspan = np.array([0, 642.54])
    rho = 1
    eclipse = False
    mee0 = np.array(
        [1.8225634499541166, 0.725, 0.0, 0.06116262015048431, 0.0, 0, 100])
    meef = np.array([6.610864583184714, 0.0, 0.0, 0.0, 0.0, 0.0])

    ## Computes the error between the current and desired final state.
    states_in = np.zeros(14)
    states_in[0:7] = mee0[0:7]
    states_in[7:14] = p0[0:7]
    # sol = integrator(eom_mee_twobody_minfuel,(tspan[0],tspan[-1]),states_in,method='LSODA',rtol=1e-12)
    sol = integrator(
        lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
        tspan,
        states_in,
        method='LSODA',
        rtol=1e-12)
    # Free final mass and free final true longitude (angle)
    res = np.linalg.norm(meef[0:5] - sol.y[0:5, -1])
    print(res)
    return res
Beispiel #4
0
def mee_ocp_central_difference(states0,tspan,p0,rho,eclipse):
    """
    Central different computation of the Jacobian of the cost funtion.
    Parameters:
    ===========
    tspan   -- vector containting initial and final time
    p0      -- initial costates guess
    states0 -- initial state vector (modified equinoctial elements)
    rho     -- switch smoothing parameter
    eclipse -- boolean (true or false)
    Returns:
    ========
    Jac -- Jacobian
    External:
    =========
    numpy, spipy.integrate
    """

    # Sizes
    sz1 = np.size(states0)
    sz2 = sz1 - 2 # Number of fixed final states

    # Initialization
    IC        = np.zeros(2*sz1)
    Jac       = np.zeros((sz2,sz1))
    Del_plus  = np.zeros((sz2,sz1))
    Del_minus = np.zeros((sz2,sz1))
    DEL       = 1e-5*(p0/np.linalg.norm(p0))

    for tcnt in range(0,2*sz1):
        if (tcnt < sz1):
            IC[0:sz1]    = states0[0:sz1]
            IC[0:sz1]    = p0[0:sz1]
            IC[tcnt+sz1] = IC[tcnt+sz1]+DEL[tcnt]
        elif (tcnt >= sz1):
            IC[0:sz1]     = states0[0:sz1]
            IC[sz1:2*sz1] = p0[0:sz1]
            IC[tcnt]      = IC[tcnt]-DEL[tcnt-sz1]

        # Integrate Dynamics
        sol = integrator(lambda t,y: eom_mee_twobodyJ2_minfuel(t,y,rho,eclipse),tspan,IC,method='LSODA',rtol=1e-13)
        soln = sol.y[0:sz1,-1]
        if (tcnt < sz1):
            Del_plus[0:sz2,tcnt-1] = soln[0:sz2]  # Free final mass & free final true longitude (angle)
        elif (tcnt >= sz1):
            Del_minus[0:sz2,tcnt-sz1] = soln[0:sz2]  # Free final mass & free final true longitude (angle)

    # Compute Jacobian (central differences)
    for i in range(sz2):
        for j in range(sz1):
            Jac[i,j] = (Del_plus[i,j] - Del_minus[i,j])/(2*DEL[j])

    return Jac
    [soln, p0, mps_err] = mps_mee_ocp(tspan, p0, mee0, meef, rho, eclipse,
                                      mps_tol)
    print("rho:", rho, "mps err:", mps_err)
    rho = rho * rho_rate

    # Update
    iter = iter + 1

# Final Solution
rho = rho / rho_rate  # rho for converged solution
mee0_new = np.zeros(14)
mee0_new[0:7] = mee0[0:7]
mee0_new[7:14] = p0[0:7]

# Propagation Solution
sol = integrator(lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
                 tspan,
                 mee0_new,
                 method='LSODA',
                 rtol=1e-13)
data = np.array(soln.y, dtype=float).T
time = np.array(soln.t, dtype=float).T

# Plot Solution
plot_mee_minfuel(time, data, rho, eclipse)

# Save Solution
df = pd.DataFrame(np.array([time, data]).T, columns=['time', 'trajectory'])
df.to_csv("output_soln.csv", index=False)
# Save Solution Parameters
df = pd.DataFrame(np.array([rho, eclipse, sc.Isp, sc.A, sc.eff]).T,
Beispiel #6
0
def mps_mee_ocp(tspan, p0, states0, statesf, rho, eclipse, mps_tol):
    """
    Shooting method to solve min-fuel optimal control prolem
    Parameters:
    ===========
    tspan   -- vector containing initial and final time
    p0      -- initial costates guess
    states0 -- initial state vector (modified equinoctial elements)
    statesf -- final state vector (modified equinoctial elements)
    rho     -- switch smoothing parameter
    eclipse -- boolean (true or false)
    mps_tol -- user specified convergence tolerance
    Returns:
    ========
    traj    -- optimal trajectory
    p0      -- initial costate for optimal trajectory
    mps_err -- shooting method convergence error
    External:
    =========
    numpy, const.py, spipy.integrate
    """
    mps_err = 1
    cnt = 0
    IC = np.zeros(14)
    Del = np.zeros((5, 7))
    Del_plus = np.zeros((5, 7))
    Del_minus = np.zeros((5, 7))
    DEL = np.array([1e-5, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5])
    # p0      = states0[7:14]
    MatInv = np.zeros((7, 5))
    res = np.zeros(7)
    del_p0 = np.zeros(7)
    while mps_err > mps_tol and cnt < 30:
        for tcnt in range(0, 15):
            if tcnt == 0:
                IC[0:7] = states0[0:7]
                IC[7:14] = p0[0:7]
            elif tcnt > 0 and tcnt < 8:
                IC[0:7] = states0[0:7]
                IC[7:14] = p0[0:7]
                IC[tcnt + 6] = IC[tcnt + 6] + DEL[tcnt - 1]
            elif tcnt > 7 and tcnt < 15:
                IC[0:7] = states0[0:7]
                IC[7:14] = p0[0:7]
                IC[tcnt + 6 - 7] = IC[tcnt + 6 - 7] - DEL[tcnt - 1 - 7]

            # Integrate Dynamics
            sol = integrator(
                lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
                tspan,
                IC,
                method='LSODA',
                rtol=1e-13)
            # sol = integrator(eom_mee_twobody_minfuel,(tspan[0],tspan[-1]),IC,method='LSODA',rtol=1e-12)
            soln = sol.y[0:7, -1]
            if tcnt == 0:
                ref = soln
                traj = sol
            elif tcnt > 0 and tcnt < 8:
                # Del_plus[0:5,tcnt-1] = (soln[0:5]-ref[0:5])/DEL  # Free final mass & free final true longitude (angle)
                Del_plus[0:5, tcnt - 1] = soln[
                    0:5]  # Free final mass & free final true longitude (angle)
            elif tcnt > 7 and tcnt < 15:
                Del_minus[0:5, tcnt - 1 - 7] = soln[
                    0:5]  # Free final mass & free final true longitude (angle)

        # Compute Updated Variables
        for i in range(5):
            for j in range(7):
                Del[i, j] = (Del_plus[i, j] - Del_minus[i, j]) / (2 * DEL[j])
        MatInv = np.linalg.pinv(Del)
        res = statesf[0:5] - ref[
            0:5]  # Free final mass & free final true longitude (angle)
        del_p0 = np.matmul(MatInv, res)
        p0 = p0 + del_p0
        DEL = 1e-5 * (p0 / np.linalg.norm(p0))

        # Compute Error
        mps_err = np.linalg.norm(res)
        print(mps_err)

        # Counter
        cnt = cnt + 1

    return traj, p0, mps_err
Beispiel #7
0
def mee_ocp_central_difference(p0):
    """
    Central different computation of the Jacobian of the cost funtion.
    Parameters:
    ===========
    tspan   -- vector containting initial and final time
    p0      -- initial costates guess
    states0 -- initial state vector (modified equinoctial elements)
    rho     -- switch smoothing parameter
    eclipse -- boolean (true or false)
    Returns:
    ========
    Jac -- Jacobian
    External:
    =========
    numpy, spipy.integrate
    """

    # TEMP
    tspan = np.array([0, 642.54])
    rho = 1
    eclipse = False
    states0 = np.array(
        [1.8225634499541166, 0.725, 0.0, 0.06116262015048431, 0.0, 0, 100])
    statesf = np.array([6.610864583184714, 0.0, 0.0, 0.0, 0.0, 0.0])

    # Initialization
    IC = np.zeros(14)
    Jac = np.zeros((14, 14))
    Del_plus = np.zeros((7, 7))
    Del_minus = np.zeros((7, 7))
    DEL = 1e-5 * (p0 / np.linalg.norm(p0))
    # DEL       = np.array([1e-5,1e-5,1e-5,1e-5,1e-5,1e-5,1e-5])

    for tcnt in range(0, 14):
        print(tcnt)
        if (tcnt < 7):
            IC[0:7] = states0[0:7]
            IC[7:14] = p0[0:7]
            IC[tcnt + 7] = IC[tcnt + 7] + DEL[tcnt]
        elif (tcnt >= 7):
            IC[0:7] = states0[0:7]
            IC[7:14] = p0[0:7]
            IC[tcnt] = IC[tcnt] - DEL[tcnt - 7]

        # Integrate Dynamics
        sol = integrator(
            lambda t, y: eom_mee_twobodyJ2_minfuel(t, y, rho, eclipse),
            tspan,
            IC,
            method='LSODA',
            rtol=1e-12)
        soln = sol.y[0:7, -1]
        if (tcnt < 7):
            Del_plus[0:7, tcnt] = soln[
                0:7]  # Free final mass & free final true longitude (angle)
        elif (tcnt >= 7):
            Del_minus[0:7, tcnt - 7] = soln[
                0:7]  # Free final mass & free final true longitude (angle)

    # Compute Jacobian (central differences)
    for i in range(7):
        for j in range(7):
            Jac[i + 7, j] = (Del_plus[i, j] - Del_minus[i, j]) / (2 * DEL[j])

    # print(Jac)
    # sys.exit()
    # MatInv = np.linalg.pinv(Del)
    # res    = statesf[0:5] - ref[0:5]     # Free final mass & free final true longitude (angle)
    # del_p0 = np.matmul(MatInv,res)

    return Jac