Пример #1
0
def changeReferenceFrame():
    # From Howard Curtis: pg218
    # For a given earth orbit, the elements are h 1⁄4 80,000 km 2 /s, e 1⁄4 1.4, i 1⁄4 30  , U 1⁄4 40  , u 1⁄4 60  , and q 1⁄4 30  .
    # Using Algorithm 4.5, find the state vectors r and v in the geocentric equatorial frame.
    h = 80000 * 1e6 #m^2/s
    e = 1.4
    i = AL_BF.deg2rad(30)
    RAAN = AL_BF.deg2rad(40)
    omega = AL_BF.deg2rad(60)
    theta = AL_BF.deg2rad(30)

    # rv in perifocal
    r_norm = h**2/Cts.mu_E_m / (1+e*np.cos(theta))
    r = r_norm* np.array([np.cos(theta), np.sin(theta),0])
    v = Cts.mu_E_m / h * np.array([-np.sin(theta), e+ np.cos(theta),0])
    print(r, v) # Validated 

    # r, v in geocentric
    Frame1 = AL_Eph.FramesOfReference([omega, i, RAAN], 'perif')
    r2 = Frame1.transform(r, 'helioc')
    v2 = Frame1.transform(v, 'helioc')
    print(r2, v2) # Validated

    # Back to perifocal
    r3 = Frame1.transform(r2, 'perif')
    v3 = Frame1.transform(v2, 'perif')
    print(r3, v3) # Validated: same as initial
Пример #2
0
    def objFunction(self, Error, m_fuel=False, typeError='vec'):

        if typeError == 'vec':
            fc1 = np.linalg.norm(Error[0:3] / AL_BF.AU)  # Normalize with AU
            fc2 = np.linalg.norm(Error[3:] / AL_BF.AU * AL_BF.year2sec(1))
            fc1_SI = np.linalg.norm(Error[0:3])
            fc2_SI = np.linalg.norm(Error[3:])
        else:
            fc1 = Error[0] / AL_BF.AU
            fc2 = Error[1] / AL_BF.AU * AL_BF.year2sec(1)
            fc1_SI = fc1
            fc2_SI = fc2

        self.Epnorm_norm = fc1
        self.Evnorm_norm = fc2
        self.Epnorm = fc1_SI
        self.Evnorm = fc2_SI

        factor_pos = CONF['FEASIB']['factor_pos']
        factor_vel = CONF['FEASIB']['factor_vel']
        factor_mass = CONF['FEASIB']['factor_mass']

        # if CONF['FEASIB']['log'] == 1:
        #     fc1 = np.log10(fc1)
        #     fc2 = np.log10(fc2)
        #     factor_pos = np.log10(factor_pos)
        #     factor_vel = np.log10(factor_vel)

        # print('------------------------')
        # print(m_fuel, Error)
        # print(fc1, fc2)
        if type(m_fuel) == bool:
            value = fc1 * factor_pos + \
                    fc2 * factor_vel
        else:
            fc0 = m_fuel / self.Spacecraft.m_dry

            # else:
            res = [fc0, fc1, fc2]
            res2 = [fc0, fc1_SI, fc2_SI]
            # print(res)

            # print('###################')
            # print(fc1,factor_pos*fc1)
            # print(fc2, factor_vel*fc2)
            # print(fc0, factor_mass*fc0)

            # print(res)
            value = res[0]* factor_mass +\
                    res[1]* factor_pos + \
                    res[2]* factor_vel  # Has to be in AU for the coeff to work in balance

        return value
Пример #3
0
def test_convertAngleForm():
    vector0 = np.array([90,0,0])
    vector1 = AL_BF.convert3dvector(vector0, "cartesian")
    print(vector1) # validated
    vector0 = np.array([90,90,90])
    vector1 = AL_BF.convert3dvector(vector0, "cartesian")
    print(vector1) # validated
    vector0 = np.array([155, 0.78, 0.61])
    vector1 = AL_BF.convert3dvector(vector0, "polar")
    print(vector1) # validated

    print(np.arcsin(-0.7071067811865475))
    vector0 = np.array([-90,-90,-90])
    vector1 = AL_BF.convert3dvector(vector0, "cartesian")
    print(vector1*AL_BF.rad2deg(1)) 
Пример #4
0
    def to_helioc(r, vx, vy):
        v_body = np.array([vx, vy, 0])
        # Convert to heliocentric
        angle = np.arctan2(r[1], r[0])
        v_h = AL_BF.rot_matrix(v_body, angle, 'z')

        return v_h
Пример #5
0
    def plot_tvsT(self):

        t = np.linspace(self.t0,
                        self.t0 + AL_BF.sec2days(self.t_t),
                        num=self.Nimp + 2)
        deltaV_i = [
            np.linalg.norm(self.DeltaV_list[i, :]) * self.DeltaV_max
            for i in range(len(self.DeltaV_list[:, 0]))
        ]
        deltaV = np.zeros(self.Nimp + 2)
        deltaV[1:-1] = deltaV_i

        fig, ax = plt.subplots()
        plt.plot(t, deltaV, 'o-', color='k')

        plt.title("Epoch vs Delta V")
        plt.ylabel("Delta V (m/s)")
        plt.xlabel("JD0 (days)")
        plt.grid(alpha=0.5)
        # AL_Plot.set_axes_equal(ax)

        dpi = 200
        layoutSave = 'tight'
        plt.savefig('OptSol/tvsT.png', dpi=dpi, bbox_inches=layoutSave)

        plt.show()
Пример #6
0
def propagateLambert():
    ### Using ephemeris
    # Lambert trajectory obtain terminal velocity vectors
    date0 = np.array([27,1,2016,0])
    t_0 = AL_Eph.DateConv(date0,'calendar') #To JD
    transfertime = 250

    # Create bodies
    sun = AL_2BP.Body('sun', 'yellow', mu = Cts.mu_S_m)
    earth = AL_2BP.Body('earth', 'blue', mu = Cts.mu_E_m)
    mars = AL_2BP.Body('mars', 'red', mu = Cts.mu_M_m)

    # Calculate trajectory of the bodies based on ephem
    earthephem = pk.planet.jpl_lp('earth')
    marsephem = pk.planet.jpl_lp('mars')
    r_E, v_E = earthephem.eph(t_0.JD_0)
    r_M, v_M = marsephem.eph(t_0.JD_0 + transfertime)

    orbit_E = AL_2BP.BodyOrbit(np.append(r_E, v_E), 'Cartesian', sun)
    earth.addOrbit(orbit_E)
    orbit_M = AL_2BP.BodyOrbit(np.append(r_M, v_M), 'Cartesian', sun)
    mars.addOrbit(orbit_M)

    # Create transfer in the first moment
    lambert = AL_TR.Lambert(np.array(r_E), np.array(r_M), AL_BF.days2sec(transfertime), sun.mu)
    v_0, v_f = lambert.TerminalVelVect()
    print(v_0)

    # Propagate
    orbit_sp = AL_2BP.BodyOrbit(np.append(r_E, v_0), 'Cartesian', sun)
    x = orbit_sp.Propagation(AL_BF.days2sec(transfertime), 'Cartesian') # Coordinates after propagation

    r0 = np.array(r_E)
    rf = np.array(r_M)

    print('Mars', r_M, 'Propagation', x, 'Error', abs(rf - x[0:3])) # Almost zero

    fig = plt.figure()
    ax = fig.gca(projection = '3d')

    ax.scatter(0,0,0, color = 'yellow', s = 100)
    ax.scatter(r0[0],r0[1],r0[2], color = 'blue')
    ax.scatter(rf[0],rf[1],rf[2], color = 'red')
    ax.scatter(x[0], x[1], x[2], color = 'green')

    AL_Plot.set_axes_equal(ax)
    plt.show() # Validated
Пример #7
0
def findValidLambert():
    SF = CONFIG.SimsFlan_config()

    earthephem = pk.planet.jpl_lp('earth')
    marsephem = pk.planet.jpl_lp('mars')

    counter = 0

    valid = False
    while valid == False:
        decv = np.zeros(len(SF.bnds))
        for i in range(6,8): 
            decv[i] = np.random.uniform(low = SF.bnds[i][0], \
                high = SF.bnds[i][1], size = 1)

        r_E, v_E = earthephem.eph(decv[6])
        r_M, v_M = marsephem.eph(decv[6] + AL_BF.sec2days(decv[7]) )

        # Create transfer in the first moment
        nrevs = 2
        l = pk.lambert_problem(r1 = r_E, r2 = r_M, tof = decv[7], \
            cw = False, mu =  Cts.mu_S_m, max_revs=nrevs)
        v1 = np.array(l.get_v1())
        v2 = np.array(l.get_v2())

        v_i_prev = 1e12 # Excessive random value
        for rev in range(len(v1)):
            v_i = np.linalg.norm(v1[rev] - np.array(v_E)) # Relative velocities for the bounds 
            v_i2 = np.linalg.norm(v2[rev] - np.array(v_M))
            # Change to polar for the bounds
            if v_i >= SF.bnds[0][0] and  v_i <= SF.bnds[0][1] and \
            v_i2 >= SF.bnds[3][0] and  v_i2 <= SF.bnds[3][1]:
                print('decv')
                print(v1[rev]-v_E,v2[rev]-v_M)
                decv[0:3] = AL_BF.convert3dvector(v1[rev]-v_E, "cartesian")
                decv[3:6] = AL_BF.convert3dvector(v2[rev]-v_M, "cartesian")
                print(decv[0:6])
                valid = True

                print('rev', rev, v1[rev], v2[rev])

        counter += 1
        print(counter)
    return decv, l
Пример #8
0
def propagateSimsFlanagan():
    "Test the propagation of SimsFlanagan back and forth using the velocities from Lambert"
    ### Using ephemeris
    # Lambert trajectory obtain terminal velocity vectors
    SF = CONFIG.SimsFlan_config()

    # Create bodies
    sun = AL_2BP.Body('sun', 'yellow', mu = Cts.mu_S_m)
    earth = AL_2BP.Body('earth', 'blue', mu = Cts.mu_E_m)
    mars = AL_2BP.Body('mars', 'red', mu = Cts.mu_M_m)

    # Calculate trajectory of the bodies based on ephem
    earthephem = pk.planet.jpl_lp('earth')
    marsephem = pk.planet.jpl_lp('mars')
    
    decv, l = findValidLambert()

    print(decv)

    Fit = Fitness(Nimp = SF.Nimp)
    Fit.calculateFitness(decv)
    Fit.printResult()

    # We plot
    mpl.rcParams['legend.fontsize'] = 10

    # Create the figure and axis
    fig = plt.figure(figsize = (16,5))
    ax1 = fig.add_subplot(1, 3, 1, projection='3d')
    ax1.scatter([0], [0], [0], color=['y'])

    ax2 = fig.add_subplot(1, 3, 2, projection='3d')
    ax2.scatter([0], [0], [0], color=['y'])
    ax2.view_init(90, 0)

    ax3 = fig.add_subplot(1, 3, 3, projection='3d')
    ax3.scatter([0], [0], [0], color=['y'])
    ax3.view_init(0,0)

    t1 = SF.t0.JD
    t2 = t1 + AL_BF.sec2days(decv[7])

    for ax in [ax1, ax2, ax3]:
        # Plot the planet orbits
        # plot_planet(earth, t0=t1, color=(0.8, 0.8, 1), legend=True, units=AU, axes=ax)
        # plot_planet(mars, t0=t2, color=(0.8, 0.8, 1), legend=True, units=AU, axes=ax)

        # Plot the Lambert solutions
        axis = plot_lambert(l, color='b', legend=True, units=AU, axes=ax)
        # axis = plot_lambert(l, sol=1, color='g', legend=True, units=AU, axes=ax)
        # axis = plot_lambert(l, sol=2, color='g', legend=True, units=AU, axes=ax)

    plt.show()
Пример #9
0
def propagateSimsFlanaganForward():
    "Test the propagation of SimsFlanagan forward using the velocities from Lambert"
    ### Using ephemeris
    # Lambert trajectory obtain terminal velocity vectors
    SF = CONFIG.SimsFlan_config()

    # Create bodies
    sun = AL_2BP.Body('sun', 'yellow', mu = Cts.mu_S_m)
    earth = AL_2BP.Body('earth', 'blue', mu = Cts.mu_E_m)
    mars = AL_2BP.Body('mars', 'red', mu = Cts.mu_M_m)

    # Calculate trajectory of the bodies based on ephem
    earthephem = pk.planet.jpl_lp('earth')
    marsephem = pk.planet.jpl_lp('mars')
    
    decv, l = findValidLambert()
    print(decv)

    r_M, v_M = marsephem.eph(decv[6] + AL_BF.sec2days(decv[7]) )

    Fit = Propagate(Nimp = SF.Nimp)
    Fit.prop(decv, plot = True)
    print("Final", Fit.rv_final)
    print("Theoretical final", r_M,  AL_BF.convert3dvector(decv[3:6], "polar")+v_M)
Пример #10
0
    def __init__(self, *args, **kwargs):

        #Constants used
        Cts = AL_BF.ConstantsBook()  #Constants for planets

        # Define bodies involved
        self.Spacecraft = AL_2BP.Spacecraft()
        self.earthephem = pk.planet.jpl_lp('earth')
        self.marsephem = pk.planet.jpl_lp('mars')
        self.jupiterephem = pk.planet.jpl_lp('jupiter')
        self.venusephem = pk.planet.jpl_lp('venus')

        self.sun = AL_2BP.Body('Sun', 'yellow', mu=Cts.mu_S_m)
        self.earth = AL_2BP.Body('Earth', 'blue', mu=Cts.mu_E_m)
        self.mars = AL_2BP.Body('Mars', 'red', mu=Cts.mu_M_m)
        self.jupiter = AL_2BP.Body('Jupiter', 'green', mu=Cts.mu_J_m)
        self.venus = AL_2BP.Body('Venus', 'brown', mu=Cts.mu_V_m)

        departure = kwargs.get('departure', "Earth")
        arrival = kwargs.get('arrival', "Mars")

        if departure == 'Earth':
            self.departure = self.earth
            self.departureephem = self.earthephem
        elif departure == 'Mars':
            self.departure = self.mars
            self.departureephem = self.marsephem

        if arrival == 'Mars':
            self.arrival = self.mars
            self.arrivalephem = self.marsephem
        elif arrival == 'Jupiter':
            self.arrival = self.jupiter
            self.arrivalephem = self.jupiterephem
        elif arrival == 'Venus':
            self.arrival = self.venus
            self.arrivalephem = self.venusephem
        elif arrival == 'Earth':
            self.arrival = self.earth
            self.arrivalephem = self.earthephem

        # Settings
        self.color = ['blue', 'green', 'black', 'red', 'yellow', 'orange']

        # Choose odd number to compare easily in middle point
        self.Nimp = kwargs.get('Nimp', 11)
Пример #11
0
def EvolAlgorithm_cons(f, bounds, *args, **kwargs):
    """
    EvolAlgorithm: evolutionary algorithm
    INPUTS:
        f: function to be analyzed
        x: decision variables
        bounds: bounds of x to initialize the random function
        x_add: additional parameters for the function. As a vector
        ind: number of individuals. 
        cuts: number of cuts to the variable
        tol: tolerance for convergence
        max_iter: maximum number of iterations (generations)
        max_iter_success
        elitism: percentage of population elitism
        mut: mutation rate
        immig: migration rate (new individuals)
        cons: list of functions to constrain a function. Function should return a vector. return[0] = 0 if unfeasible, return[1] returns penalty
    """
    x_add = kwargs.get('x_add', False)
    ind = kwargs.get('ind', 100)
    cuts = kwargs.get('cuts', 1)
    tol = kwargs.get('tol', 1e-4)
    max_iter = kwargs.get('max_iter', 1e3)
    max_iter_success = kwargs.get('max_iter_success', 1e2)
    elitism = kwargs.get('elitism', 0.1)
    mut = kwargs.get('mutation', 0.01)
    immig = kwargs.get('immig', 0.01)
    cons = kwargs.get('cons', None)

    ###############################################
    ###### GENERATION OF INITIAL POPULATION #######
    ###############################################
    pop_0 = np.zeros([ind, len(bounds) + 1])
    for i in range(len(bounds)):
        pop_0[:, i + 1] = np.random.rand(ind) * (bounds[i][1] -
                                                 bounds[i][0]) + bounds[i][0]

    ###############################################
    ###### FITNESS EVALUATION               #######
    ###############################################
    if x_add == False:  # No additional arguments needed
        for i in range(ind):
            pop_0[i, 0] = f(pop_0[i, 1:])
    else:
        for i in range(ind):
            pop_0[i, 0] = f(pop_0[i, 1:], x_add)

    for j in range(ind):
        for i in range(len(cons)):
            feas = cons[i](pop_0[j, 1:])  # evaluate constraint function
            if feas[0] == 0:  # it is unfeasible
                pop_0[:, 0] += feas[1]  # Add penalty to unfeasible ones

    Sol = pop_0[pop_0[:, 0].argsort()]
    minVal = min(Sol[:, 0])
    x_minVal = Sol[0, :]

    ###############################################
    ###### NEXT GENERATION                  #######
    ###############################################
    noImprove = 0
    counter = 0
    lastMin = minVal

    Best = np.zeros([max_iter + 1, len(bounds) + 1])
    while noImprove <= max_iter_success and counter <= max_iter:

        ###############################################
        #Generate descendents

        #Elitism
        ind_elit = int(round(elitism * ind))

        children = np.zeros(np.shape(pop_0))
        children[:, 1:] = Sol[:, 1:]

        #Separate into the number of parents
        pop = np.zeros(np.shape(pop_0))
        pop[:ind_elit, :] = children[:ind_elit, :]  #Keep best ones
        np.random.shuffle(children[:, :])  #shuffle the others

        for j in range((len(children) - ind_elit) // 2):
            if len(bounds) == 2:
                cut = 1
            else:
                cut = np.random.randint(1, len(bounds) - 1)

            pop[ind_elit + 2 * j, 1:] = np.concatenate(
                (children[2 * j, 1:cut + 1], children[2 * j + 1, cut + 1:]),
                axis=0)
            pop[ind_elit + 2 * j + 1, 1:] = np.concatenate(
                (children[2 * j + 1, 1:cut + 1], children[2 * j, cut + 1:]),
                axis=0)
        if (len(children) - ind_elit) % 2 != 0:
            pop[-1, :] = children[-ind_elit, :]

        #Mutation
        for i in range(ind):
            for j in range(len(bounds)):
                if np.random.rand(1) < mut:  #probability of mut
                    pop[i, j +
                        1] = np.random.rand(1) * (bounds[j][1] -
                                                  bounds[j][0]) + bounds[j][0]

        #Immigration
        ind_immig = int(round(immig * ind))
        for i in range(len(bounds)):
            pop[-ind_immig:, i +
                1] = np.random.rand(ind_immig) * (bounds[i][1] -
                                                  bounds[i][0]) + bounds[i][0]

        ###############################################
        # Fitness
        if x_add == False:  # No additional arguments needed
            for i in range(ind):
                pop[i, 0] = f(pop[i, 1:])
        else:
            for i in range(ind):
                pop[i, 0] = f(pop[i, 1:], x_add)

        for j in range(ind):
            for i in range(len(cons)):
                feas = cons[i](pop[j, 1:])  # evaluate constraint function
                if feas[0] == 0:  # it is unfeasible
                    pop[:, 0] += feas[1]  # Add penalty to unfeasible ones

        Sol = pop[pop[:, 0].argsort()]
        minVal = min(Sol[:, 0])

        ###############################################
        #Check convergence
        if minVal >= lastMin:
            noImprove += 1

        else:
            lastMin = minVal
            x_minVal = Sol[0, 1:]
            noImprove = 0
            Best[counter, :] = Sol[0, :]

        print(counter, "Minimum: ", minVal)
        counter += 1  #Count generations
        if counter % 20 == 0:
            AL_BF.writeData(x_minVal, 'w', 'SolutionEA.txt')

        # print(counter)
    print("minimum:", lastMin)
    print("Iterations:", counter)
    print("Iterations with no improvement:", noImprove)

    return x_minVal, lastMin
Пример #12
0
def EvolAlgorithm_integerinput(f, bounds, *args, **kwargs):
    """
    EvolAlgorithm_integerinput: evolutionary algorithm, some inputs will be fixed to integers if decided
    INPUTS:
        f: function to be analyzed
        x: decision variables
        bounds: bounds of x to initialize the random function
        x_add: additional parameters for the function. As a vector
        ind: number of individuals. 
        cuts: number of cuts to the variable
        tol: tolerance for convergence
        max_iter: maximum number of iterations (generations)
        max_iter_success
        elitism: percentage of population elitism
        bulk_fitness: if True, the data has to be passed to the function all 
                    at once as a matrix with each row being an individual
        int_input: force some inputs to be integers. Vector with zero (not integer) or one if integer
    """
    x_add = kwargs.get('x_add', False)
    ind = kwargs.get('ind', 100)
    cuts = kwargs.get('cuts', 1)
    tol = kwargs.get('tol', 1e-4)
    max_iter = kwargs.get('max_iter', 1e3)
    max_iter_success = kwargs.get('max_iter_success', 1e2)
    elitism = kwargs.get('elitism', 0.1)
    mut = kwargs.get('mutation', 0.01)
    bulk = kwargs.get('bulk_fitness', False)
    int_input = kwargs.get('int_input', np.zeros(len(bounds)))

    def f_evaluate(pop_0):
        if bulk == True:
            if x_add == False:
                pop_0[:, 0] = f(pop_0[:, 1:])
            else:
                pop_0[:, 0] = f(pop_0[:, 1:], x_add)
        else:
            if x_add == False:  # No additional arguments needed
                for i in range(ind):
                    pop_0[i, 0] = f(pop_0[i, 1:])
            else:
                for i in range(ind):
                    pop_0[i, 0] = f(pop_0[i, 1:], x_add)

        return pop_0

    ###############################################
    ###### GENERATION OF INITIAL POPULATION #######
    ###############################################
    pop_0 = np.zeros([ind, len(bounds) + 1])
    for i in range(len(bounds)):
        pop_0[:, i + 1] = np.random.uniform(low=bounds[i][0],
                                            high=bounds[i][1],
                                            size=ind)
        if int_input[i] != 0:  # Force it to be an integer
            pop_0[:, i + 1] = [int(pop_0[indx, i + 1]) for indx in range(ind)]

    print(pop_0)
    ###############################################
    ###### FITNESS EVALUATION               #######
    ###############################################
    pop_0 = f_evaluate(pop_0)

    Sol = pop_0[pop_0[:, 0].argsort()]
    minVal = min(Sol[:, 0])
    x_minVal = Sol[0, :]

    ###############################################
    ###### NEXT GENERATION                  #######
    ###############################################
    noImprove = 0
    counter = 0
    lastMin = minVal

    Best = np.zeros([max_iter + 1, len(bounds) + 1])
    while noImprove <= max_iter_success and counter <= max_iter:

        ###############################################
        #Generate descendents

        #Elitism
        ind_elit = int(round(elitism * ind))

        children = np.zeros(np.shape(pop_0))
        children[:, 1:] = Sol[:, 1:]

        #Separate into the number of parents
        pop = np.zeros(np.shape(pop_0))
        pop[:ind_elit, :] = children[:ind_elit, :]  #Keep best ones
        np.random.shuffle(children[:, :])  #shuffle the others

        for j in range((len(children) - ind_elit) // 2):
            if len(bounds) == 2:
                cut = 1
            else:
                cut = np.random.randint(1, len(bounds) - 1)

            pop[ind_elit + 2 * j, 1:] = np.concatenate(
                (children[2 * j, 1:cut + 1], children[2 * j + 1, cut + 1:]),
                axis=0)
            pop[ind_elit + 2 * j + 1, 1:] = np.concatenate(
                (children[2 * j + 1, 1:cut + 1], children[2 * j, cut + 1:]),
                axis=0)

        if (len(children) - ind_elit) % 2 != 0:
            pop[-1, :] = children[-ind_elit, :]

        #Mutation
        for i in range(ind):
            for j in range(len(bounds)):
                if np.random.rand(1) < mut:  #probability of mut
                    pop[i, j +
                        1] = np.random.rand(1) * (bounds[j][1] -
                                                  bounds[j][0]) + bounds[j][0]
                    if int_input[i] != 0:  # Force to be an int
                        pop[i, j + 1] = int(pop[i, j + 1])
        ###############################################
        # Fitness
        pop = f_evaluate(pop)

        Sol = pop[pop[:, 0].argsort()]
        minVal = min(Sol[:, 0])

        ###############################################
        #Check convergence
        if minVal >= lastMin:
            noImprove += 1
#         elif abs(lastMin-minVal)/lastMin > tol:
#             noImprove += 1
        else:
            #             print('here')
            lastMin = minVal
            x_minVal = Sol[0, 1:]
            noImprove = 0
            Best[counter, :] = Sol[0, :]

        print(counter, "Minimum: ", minVal)
        counter += 1  #Count generations
        if counter % 20 == 0:
            AL_BF.writeData(x_minVal, 'w', 'SolutionEA.txt')

        # print(counter)
    print("minimum:", lastMin)
    print("Iterations:", counter)
    print("Iterations with no improvement:", noImprove)

    return x_minVal, lastMin
Пример #13
0
def test_convertRange():
    angle = -3.02
    print(AL_BF.convertRange(angle, 'deg', 0, 360))
Пример #14
0
def test_Exposin():

    # Verify with example
    print("VERIFICATION")
    r1 = 1
    r2 =  5
    psi = np.pi/2
    k2 = 1/4

    # eSin = AL_Sh.shapingMethod(sun.mu / Cts.AU_m**3)
    # gammaOptim_v = eSin.start(r1, r2, psi, 365*1.5, k2) # verified
    # Ni = 1
    # print(gammaOptim_v)
    # eSin.plot_sphere(r1, r2, psi, gammaOptim_v[Ni], Ni) # verified

    # Real life case
    sun = AL_2BP.Body('sun', 'yellow', mu = Cts.mu_S_m)
    earth = AL_2BP.Body('earth', 'blue', mu = Cts.mu_E_m)
    mars = AL_2BP.Body('mars', 'red', mu = Cts.mu_M_m)

    # Calculate trajectory of the bodies based on ephem
    earthephem = pk.planet.jpl_lp('earth')
    marsephem = pk.planet.jpl_lp('mars')
    
    date0 = np.array([27,1,2018,0])
    t0 = AL_Eph.DateConv(date0,'calendar') #To JD
    t_t = 350

    r_E, v_E = earthephem.eph( t0.JD_0 )
    r_M, v_M = marsephem.eph(t0.JD_0+ t_t )

    r_1 = r_E 
    r_2 = r_M 
    r_1_norm = np.linalg.norm( r_1 )
    r_2_norm = np.linalg.norm( r_2 )
    
    dot = np.dot(r_1[0:2], r_2[0:2])      # dot product between [x1, y1] and [x2, y2]
    det = r_1[0]*r_2[1] - r_2[0]*r_1[1]     # determinant
    psi = np.arctan2(det, dot) 
    psi = AL_BF.convertRange(psi, 'rad', 0 ,2*np.pi)
    
    k2 = 1/12

    eSin = AL_Sh.shapingMethod(sun.mu / AL_BF.AU**3)
    gammaOptim_v = eSin.calculategamma1(r_1_norm / AL_BF.AU, r_2_norm / AL_BF.AU, psi, \
        t_t, k2, plot = False)
    
    Ni = 1
    eSin.calculateExposin(Ni, gammaOptim_v[Ni],r_1_norm / AL_BF.AU, r_2_norm / AL_BF.AU, psi )
    eSin.plot_sphere(r_1_norm / AL_BF.AU, r_2_norm / AL_BF.AU, psi)
    v1, v2 = eSin.terminalVel(r_1_norm / AL_BF.AU, r_2_norm / AL_BF.AU, psi)
    t, a_T = eSin.calculateThrustProfile(r_1_norm / AL_BF.AU, r_2_norm / AL_BF.AU, psi)
    # print('a', a_T*AL_BF.AU)


    print("body coord", v1, v2)

    # print(v1[0]*Cts.AU_m, v1[1], v2[0]*Cts.AU_m, v2[1])

    # To heliocentric coordinates (2d approximation)
    def to_helioc(r, vx, vy):
        v_body = np.array([vx, vy, 0])
        # Convert to heliocentric
        angle = np.arctan2(r[1], r[0])
        v_h = AL_BF.rot_matrix(v_body, angle, 'z')

        return v_h

    v_1 = to_helioc(r_1, v1[0]*AL_BF.AU, v1[1]*AL_BF.AU)
    v_2 = to_helioc(r_2, v2[0]*AL_BF.AU, v2[1]*AL_BF.AU) 

    # def to_helioc(r, v, gamma):
    #     v_body = np.array([v*np.sin(gamma), \
    #                        v*np.cos(gamma),\
    #                        0])

    #     # Convert to heliocentric
    #     angle = np.arctan2(r[1], r[0])
    #     v_h = AL_BF.rot_matrix(v_body, angle, 'z')

    #     return v_h
    # v_1 = to_helioc(r_1, v1[0]*Cts.AU_m, v1[1])
    # v_2 = to_helioc(r_2, v2[0]*Cts.AU_m, v2[1])
    print("Helioc vel", v_1, v_2)
    print("with respect to body ", v_1-v_E, v_2-v_M)

    v_1_E = np.linalg.norm(v_1-v_E)
    v_2_M = np.linalg.norm(v_2-v_M)

    print("Final vel", v_1_E, v_2_M)
    
    ################################################3
    # Propagate with terminal velocity vectors
    SF = CONFIG.SimsFlan_config()    
    Fit = Fitness(Nimp = SF.Nimp)

    decv = np.zeros(len(SF.bnds))
    decv[6] = t0.JD_0
    decv[7] = AL_BF.days2sec(t_t)
    decv[0:3] = AL_BF.convert3dvector(v_1-v_E,'cartesian')
    decv[3:6] = AL_BF.convert3dvector(v_2- v_M,'cartesian')

    print('decv', decv[0:9])
    
    for i in range(SF.Nimp):
        # Acceleration on segment is average of extreme accelerations
        t_i = AL_BF.days2sec(t_t) / (SF.Nimp+1) *i
        t_i1 = AL_BF.days2sec(t_t) / (SF.Nimp+1) *(i+1)

        #find acceleration at a certain time
        a_i = eSin.accelerationAtTime(t_i)
        a_i1 = eSin.accelerationAtTime(t_i1)
        
        a = (a_i+a_i1)/2 # find the acceleration at a certain time
        print("a", a_i, a_i1, a)
        deltav_i = AL_BF.days2sec(t_t) / (SF.Nimp+1) * a*AL_BF.AU
        print(deltav_i)
        decv[8+3*i] = deltav_i /100
        decv[8+3*i+1] = 0
        decv[8+3*i+2] = 0

    Fit.calculateFeasibility(decv, plot = True, thrust = 'tangential')
    Fit.printResult()
Пример #15
0
    def adaptDecisionVector(self, DecV, optMode=True):
        """ 
        adaptDecisionVector: modify decision vector to input in the problem
        """
        self.DecV = DecV
        v0 = np.array(DecV[0:3])  # vector, [magnitude, angle, angle]
        vf = np.array(DecV[3:6])  # vector, [magnitude, angle, angle]
        self.t0, self.t_t = DecV[6:8]

        # Delta V
        if optMode == True:
            DeltaV_list = np.array(DecV[8:]).reshape(
                -1, 3)  # make a Nimp x 3 matrix
        else:
            DeltaV_list = DecV[8:][0]

        ########################################################################
        # INITIAL CALCULATION OF VARIABLES
        ########################################################################
        # Modify from magnitude angle angle to cartesian
        self.DeltaV_list = np.zeros(np.shape(DeltaV_list))
        DeltaV_sum = np.zeros(len(
            self.DeltaV_list))  # Magnitude of the impulses
        for i in range(len(self.DeltaV_list)):
            self.DeltaV_list[i, :] = AL_BF.convert3dvector(
                DeltaV_list[i, :], "polar")
            DeltaV_sum[i] = np.linalg.norm(self.DeltaV_list[i])

        # Write velocity as x,y,z vector
        v0_cart = AL_BF.convert3dvector(v0, "polar")
        vf_cart = AL_BF.convert3dvector(vf, "polar")

        # Sum of all the Delta V = DeltaV max * sum Delta V_list
        # Assumption: the DeltaV_max is calculated as if mass is constant and
        # equal to the dry mass as it is the largest contribution. This means
        # that the DelaV_max is actually smaller than it will be obtained in this
        # problem
        # = Thrust for segment
        self.DeltaV_max = self.Spacecraft.T / self.Spacecraft.m_dry * \
            self.t_t / (self.Nimp + 1)

        # Total DeltaV
        DeltaV_total = sum(DeltaV_sum) * self.DeltaV_max

        #Calculate total mass of fuel for the given impulses
        self.m0 = \
            self.Spacecraft.MassChangeInverse(self.Spacecraft.m_dry, DeltaV_total)
        self.m_fuel = self.m0 - self.Spacecraft.m_dry

        # Times and ephemeris
        # t_0 = AL_Eph.DateConv(self.date0,'calendar') #To JD
        self.t_1 = AL_Eph.DateConv(self.t0 + AL_BF.sec2days(self.t_t), 'JD_0')

        self.r_p0, self.v_p0 = self.departureephem.eph(self.t0)
        self.r_p1, self.v_p1 = self.arrivalephem.eph(self.t_1.JD_0)

        # Change from relative to heliocentric velocity
        self.v0 = v0_cart + self.v_p0
        self.vf = vf_cart + self.v_p1

        # Create state vector for initial and final point
        self.SV_0 = np.append(self.r_p0, self.v0)
        self.SV_f = np.append(self.r_p1, self.vf)  # - to propagate backwards
        self.SV_f_corrected = np.append(self.r_p1,
                                        -self.vf)  # - to propagate backwards
Пример #16
0
def validateSimsFlanagan():
    SF = CONFIG.SimsFlan_config()

    # Create bodies
    sun = AL_2BP.Body('sun', 'yellow', mu = Cts.mu_S_m)
    earth = AL_2BP.Body('earth', 'blue', mu = Cts.mu_E_m)
    mars = AL_2BP.Body('mars', 'red', mu = Cts.mu_M_m)
    Spacecraft = AL_2BP.Spacecraft( )

    # Calculate trajectory of the bodies based on ephem
    earthephem = pk.planet.jpl_lp('earth')
    marsephem = pk.planet.jpl_lp('mars')

    # Create a random decision vector
    DecV = np.zeros(len(SF.bnds))
    samples_rand = 1
    np.random.seed(1)
    for decv in range(len(SF.bnds)): 
        DecV[decv] = np.random.rand(samples_rand) * (SF.bnds[decv][1]-SF.bnds[decv][0]) + SF.bnds[decv][0]
    
    DecV[8:] = np.zeros(3*SF.Nimp)

    Fit = Fitness(Nimp = 21)
    Fit.adaptDecisionVector(DecV)
    r = Fit.r_p0
    r2 = Fit.r_p1
    v = Fit.v0
    v2 = Fit.vf
    imp = Fit.DeltaV_list.flatten()
    # imp = (0,0,0,0,0,0,0,0,0,0,0,0)
    m0 = Fit.m0

    # Pykep Sims-Flanagan
    start = pk.epoch(DecV[6])
    end = pk.epoch(DecV[6] + AL_BF.sec2days(DecV[7]) )
    sc = pk.sims_flanagan.spacecraft(m0, Spacecraft.T, Spacecraft.Isp)
    
    
    x0 = pk.sims_flanagan.sc_state(r,v,sc.mass)
    xe = pk.sims_flanagan.sc_state(r2,v2,sc.mass)
    l = pk.sims_flanagan.leg(start, x0, imp, end, xe, sc,pk.MU_SUN)

    ceq = l.mismatch_constraints()
    c = l.throttles_constraints()
    times,r,v,m = l.get_states()
    r_vec = np.zeros((len(r),3))
    for i in range(len(r)):
        r_vec[i, :] = r[i]
        plt.scatter(r[i][0], r[i][1], color = 'black')
        if i == 0:
            plt.scatter(r[i][0], r[i][1], color = 'blue')
        elif i == len(r)-1:
            plt.scatter(r[i][0], r[i][1], color = 'red')
        elif i == len(r)//2+1:
            plt.scatter(r[i][0], r[i][1], color = 'orange')
        elif i == len(r)//2:
            plt.scatter(r[i][0], r[i][1], color = 'green')
    # plt.show()
    # plt.plot(r_vec[:,0], r_vec[:,1])
    plt.grid()

    print("State middle point")
    print(r[len(r)//2], v[len(r)//2])
    print(r[len(r)//2+1], v[len(r)//2+1])

    print("Mismatch middle point")
    mis_r = -(np.array(r[len(r)//2]) - np.array(r[len(r)//2+1]))
    mis_v = -(np.array(v[len(r)//2] )- np.array(v[len(r)//2+1]))
    print(mis_r, mis_v)
    mis = np.append(mis_r, mis_v)


    Fit = Fitness(Nimp = SF.Nimp)
    Fit.calculateFitness(DecV, plot=True)
    cep2 = Fit.Error
    # print(Fit.SV_0, Fit.SV_f)

    for i in range(6):
        print(i, ceq[i], '%.4E'%cep2[i], '%.4E'%mis[i])
Пример #17
0
from FitnessFunction import Fitness
import AstroLibraries.AstroLib_Basic as AL_BF 
from AstroLibraries import AstroLib_2BP as AL_2BP
from AstroLibraries import AstroLib_Ephem as AL_Eph
from AstroLibraries import AstroLib_Plots as AL_Plot
from AstroLibraries import AstroLib_Trajectories as AL_TR
from AstroLibraries import AstroLib_ShapingMethod as AL_Sh


import LoadConfigFiles as CONFIG

# # In[]
# ##############################################
# ############# VALIDATION #####################
# ##############################################
Cts = AL_BF.ConstantsBook()

def pykepephem():
    # earth = pk.planet.jpl_lp('earth')
    # marsephem = pk.planet.jpl_lp('mars')

    earth = pk.planet.jpl_lp('earth')

    K_0 = earth.eph(0)
    # print(K_0)
    earth.mu_central_body
    print(earth.mu_self)
    elem = earth.osculating_elements(pk.epoch(2345.3, 'mjd2000'))
    print(elem)
    print(np.array(elem))
Пример #18
0
def MonotonicBasinHopping(f, x, take_step, *args, **kwargs):
    """
    Step for jump is small, as minimum cluster together.
    Jump from current min until n_no improve reaches the lim, then the jump is random again.
    """

    niter = kwargs.get('niter', 100)
    niter_success = kwargs.get('niter_success', 50)
    niter_local = kwargs.get('niter_local', 50)
    bnds = kwargs.get('bnds', None)
    cons = kwargs.get('cons', 0)
    jumpMagnitude_default = kwargs.get(
        'jumpMagnitude', 0.1)  # Small jumps to search around the minimum
    tolLocal = kwargs.get('tolLocal', 1e2)
    tolGlobal = kwargs.get('tolGobal', 1e-5)

    n_itercounter = 1
    n_noimprove = 0

    Best = x
    bestMin = f(x)
    previousMin = f(x)
    jumpMagnitude = jumpMagnitude_default

    while n_itercounter < niter:
        n_itercounter += 1

        # Change decision vector to find one within the bounds
        feasible = False
        while feasible == False and bnds != None:
            x_test = take_step.call(x, jumpMagnitude)
            feasible = check_feasibility(x_test, bnds)
            # if feasible == True:
            #     feasible = check_constraints(x, cons)

        # Local optimization
        # solutionLocal = spy.minimize(f, x, method = 'COBYLA', constraints = cons, options = {'maxiter': niter_local} )
        if type(cons) == int:
            solutionLocal = spy.minimize(f, x_test, method = 'SLSQP', \
                tol = tolLocal, bounds = bnds, options = {'maxiter': niter_local} )
        else:
            solutionLocal = spy.minimize(f, x_test, method = 'SLSQP', \
                tol = tolLocal, bounds = bnds, options = {'maxiter': niter_local},\
                constraints = cons )
        currentMin = f(solutionLocal.x)
        feasible = check_feasibility(solutionLocal.x, bnds)

        # if feasible == True: # jump from current point even if it is not optimum
        #     x = solutionLocal.x

        # Check te current point from which to jump: after doing a long jump or
        # when the solution is improved
        if jumpMagnitude == 1 or currentMin < previousMin:
            x = solutionLocal.x

        # Check improvement
        if currentMin < bestMin and feasible == True:  # Improvement
            Best = x
            bestMin = currentMin
            accepted = True

            # If the improvement is not large, assume it is not improvement
            if (previousMin - currentMin) < tolGlobal:
                n_noimprove += 1
            else:
                n_noimprove = 0
            jumpMagnitude = jumpMagnitude_default

        elif n_noimprove == niter_success:  # Not much improvement
            accepted = False
            jumpMagnitude = 1
            n_noimprove = 0  # Restart count so that it performs jumps around a point
        else:
            accepted = False
            jumpMagnitude = jumpMagnitude_default
            n_noimprove += 1

        previousMin = currentMin

        # Save results every 5 iter
        if n_itercounter % 20 == 0:
            AL_BF.writeData(Best, 'w', 'SolutionMBH_self.txt')

        print("iter", n_itercounter)
        print("Current min vs best one", currentMin, bestMin)
        print_fun(f, x, accepted)

    # Print solution
    # print_sol(Best, bestMin, n_itercounter, niter_success)
    return Best, bestMin
Пример #19
0
def MonotonicBasinHopping_batch(f, x, take_step, *args, **kwargs):
    """
    Step for jump is small, as minimum cluster together.
    Jump from current min until n_no improve reaches the lim, then the jump is random again.
    """
    f_batch = kwargs.get('f_batch', False)  # Function allows for batch eval
    f_opt = kwargs.get('f_opt', None)  # function to optimze locally
    nind = kwargs.get('nind', 100)
    niter = kwargs.get('niter', 100)
    niter_success = kwargs.get('niter_success', 50)
    bnds = kwargs.get('bnds', None)
    jumpMagnitude_default = kwargs.get(
        'jumpMagnitude', 0.1)  # Small jumps to search around the minimum
    tolGlobal = kwargs.get('tolGobal', 1e-5)

    niter_local = kwargs.get('niter_local', 50)
    tolLocal = kwargs.get('tolLocal', 1e2)

    n_itercounter = 1
    n_noimprove = np.zeros((nind))

    Best = x
    bestMin = seqEval(f, x)
    previousMin = seqEval(f, x)
    jumpMagnitude = np.ones((nind)) * jumpMagnitude_default
    accepted = np.zeros((nind))
    feasibility = np.zeros((nind))

    while n_itercounter < niter:
        n_itercounter += 1

        # Change decision vector to find one within the bounds
        x_test = np.zeros(np.shape(x))
        for ind in range(nind):
            feasible = False
            while feasible == False and bnds != None:
                x_test[ind] = take_step.call(x[ind], jumpMagnitude[ind])
                feasible = check_feasibility(x_test[ind], bnds)

        # Local optimization
        if f_opt != None:
            currentMin = f_opt(x_test)
            solutionLocal = x_test
        else:
            currentMin = np.zeros((nind))
            solutionLocal = np.zeros(np.shape(x))
            for ind in range(nind):
                solLocal = spy.minimize(f, x_test[ind], method = 'SLSQP', \
                tol = tolLocal, bounds = bnds, options = {'maxiter': niter_local} )
                solutionLocal[ind] = solLocal.x

                feasibility[ind] = check_feasibility(solLocal.x, bnds)
                if feasibility[ind] == False:
                    print("Warning: Point out of limits")

            currentMin = seqEval(f, solutionLocal)

        for ind in range(nind):

            # Check te current point from which to jump: after doing a long jump or
            # when the solution is improved
            if jumpMagnitude[ind] == 1 or currentMin[ind] < previousMin[ind]:
                x[ind] = solutionLocal[ind]

            # Check improvement
            if currentMin[ind] < bestMin[ind] and feasibility[
                    ind] == True:  # Improvement
                Best[ind] = x[ind]
                bestMin[ind] = currentMin[ind]
                accepted[ind] = True
                # If the improvement is not large, assume it is not improvement
                if (previousMin[ind] - currentMin[ind]) < tolGlobal:
                    n_noimprove[ind] += 1
                else:
                    n_noimprove[ind] = 0
                jumpMagnitude[ind] = jumpMagnitude_default

            elif n_noimprove[ind] == niter_success:  # Go to a bigger jump
                accepted[ind] = False
                jumpMagnitude[ind] = 1
                n_noimprove[
                    ind] = 0  # Restart count so that it performs jumps around a point
            else:
                accepted[ind] = False
                jumpMagnitude[ind] = jumpMagnitude_default
                n_noimprove[ind] += 1

            previousMin[ind] = currentMin[ind]

        # Save results every 5 iter
        if n_itercounter % 20 == 0:
            AL_BF.writeData(Best, 'w', './OptSol/allMBH_batch.txt')

        print("iter", n_itercounter)
        print("Current min vs best one", min(currentMin), min(bestMin))
        print_fun(min(currentMin), min(bestMin),
                  np.count_nonzero(accepted == True))

    # Print solution
    # print_sol(Best, bestMin, n_itercounter, niter_success)
    return Best, bestMin
Пример #20
0
    def DecV2inputV(self, typeinputs, newDecV=0):

        if type(newDecV) != int:
            self.adaptDecisionVector(newDecV)

        inputs = np.zeros(8)
        inputs[0] = self.t_t
        inputs[1] = self.m0

        if typeinputs == "deltakeplerian":

            # Elements of the spacecraft
            earth_elem = AL_2BP.BodyOrbit(self.SV_0, "Cartesian", self.sun)
            elem_0 = earth_elem.KeplerElem
            mars_elem = AL_2BP.BodyOrbit(self.SV_f, "Cartesian", self.sun)
            elem_f = mars_elem.KeplerElem

            K_0 = np.array(elem_0)
            K_f = np.array(elem_f)

            # Mean anomaly to true anomaly
            K_0[-1] = AL_2BP.Kepler(K_0[-1], K_0[1], 'Mean')[0]
            K_f[-1] = AL_2BP.Kepler(K_f[-1], K_f[1], 'Mean')[0]

            inputs[2:] = K_f - K_0
            inputs[2] = abs(inputs[2])  # absolute value
            inputs[3] = abs(inputs[3])  # absolute value
            inputs[4] = np.cos(inputs[4])  # cosine

            labels = [
                r'$t_t$', r'$m_0$', r'$\vert \Delta a \vert$',
                r'$\vert \Delta e \vert$', r'$cos( \Delta i) $',
                r'$ \Delta \Omega$', r'$ \Delta \omega$', r'$ \Delta \theta$'
            ]

        elif typeinputs == "deltakeplerian_planet":
            t_1 = self.t0 + AL_BF.sec2days(self.t_t)

            # Elements of the planets
            elem_0 = self.departureephem.osculating_elements(
                pk.epoch(self.t0, 'mjd2000'))
            elem_f = self.arrivalephem.osculating_elements(
                pk.epoch(t_1, 'mjd2000'))

            K_0 = np.array(elem_0)
            K_f = np.array(elem_f)

            # Mean anomaly to true anomaly
            K_0[-1] = AL_2BP.Kepler(K_0[-1], K_0[1], 'Mean')[0]
            K_f[-1] = AL_2BP.Kepler(K_f[-1], K_f[1], 'Mean')[0]

            inputs[2:] = K_f - K_0
            inputs[2] = abs(inputs[2])  # absolute value
            inputs[3] = abs(inputs[3])  # absolute value
            inputs[4] = np.cos(inputs[4])  # cosine

            labels = [
                r'$t_t$', r'$m_0$', r'$\vert \Delta a \vert$',
                r'$\vert \Delta e \vert$', r'$cos( \Delta i) $',
                r'$ \Delta \Omega$', r'$ \Delta \omega$', r'$ \Delta \theta$'
            ]

        elif typeinputs == "cartesian":
            delta_r = np.array(self.SV_f[0:3]) - np.array(self.SV_0[0:3])
            delta_v = np.array(self.SV_f[3:]) - np.array(self.SV_0[3:])
            inputs[2:5] = np.abs(delta_r)
            inputs[5:] = np.abs(delta_v)

            labels = [
                r'$t_t$', r'$m_0$', r'$\vert \Delta x \vert$',
                r'$\vert \Delta y \vert$', r'$\vert \Delta z \vert$',
                r'$\vert \Delta v_x \vert$', r'$\vert \Delta v_y \vert$',
                r'$\vert \Delta v_z \vert$'
            ]

        return inputs, labels