Ejemplo n.º 1
0
    def plot(self, x):
        import matplotlib as mpl
        from mpl_toolkits.mplot3d import Axes3D
        import matplotlib.pyplot as plt
        from pykep import epoch, AU, DAY2SEC
        from pykep.sims_flanagan import sc_state
        from pykep.orbit_plots import plot_planet, plot_sf_leg

        start = epoch(x[0])
        end = epoch(x[0] + x[1])

        r, v = self.__earth.eph(start)
        v = [a + b for a, b in zip(v, x[4:7])]
        x0 = sc_state(r, v, self.__sc.mass)

        r, v = self.__mars.eph(end)
        xe = sc_state(r, v, x[3])
        self.__leg.set(
            start, x0, x[-3 * self.__nseg:], end, xe, x[2] * DAY2SEC)

        fig = plt.figure()
        axis = fig.gca(projection='3d')
        # The Sun
        axis.scatter([0], [0], [0], color='y')
        # The leg
        plot_sf_leg(self.__leg, units=AU, N=10, ax=axis)
        # The planets
        plot_planet(
            self.__earth, start, units=AU, legend=True, color=(0.8, 0.8, 1), ax=axis)
        plot_planet(
            self.__mars, end, units=AU, legend=True, color=(0.8, 0.8, 1), ax=axis)
        plt.show()
Ejemplo n.º 2
0
def run_example5():
    import pygmo as pg
    from pykep import epoch
    from pykep.planet import jpl_lp
    from pykep.trajopt import mga_1dsm

    # We define an Earth-Venus-Earth problem (single-objective)
    seq = [jpl_lp('earth'), jpl_lp('venus'), jpl_lp('earth')]
    udp = mga_1dsm(
        seq=seq,
        t0=[epoch(5844), epoch(6209)],
        tof=[0.7 * 365.25, 3 * 365.25],
        vinf=[0.5, 2.5],
        add_vinf_dep=False,
        add_vinf_arr=True,
        multi_objective=False
    )

    pg.problem(udp)
    # We solve it!!
    uda = pg.sade(gen=100)
    archi = pg.archipelago(algo=uda, prob=udp, n=8, pop_size=20)
    print(
        "Running a Self-Adaptive Differential Evolution Algorithm .... on 8 parallel islands")
    archi.evolve(10)
    archi.wait()
    sols = archi.get_champions_f()
    idx = sols.index(min(sols))
    print("Done!! Solutions found are: ", archi.get_champions_f())
    udp.pretty(archi.get_champions_x()[idx])
    udp.plot(archi.get_champions_x()[idx])
Ejemplo n.º 3
0
    def _plot_traj(self, z, axes, units):
        """Plots spacecraft trajectory.

        Args:
            - z (``tuple``, ``list``, ``numpy.ndarray``): Decision chromosome.
            - axes (``matplotlib.axes._subplots.Axes3DSubplot``): 3D axes to use for the plot
            - units (``float``, ``int``): Length unit by which to normalise data.

        Examples:
            >>> prob.extract(pykep.trajopt.indirect_or2or).plot_traj(pop.champion_x)
        """

        # times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # Mean Anomalies
        M0 = z[1] - self.elem0[1] * np.sin(z[1])
        Mf = z[2] - self.elemf[1] * np.sin(z[2])

        elem0 = np.hstack([self.elem0[:5], [M0]])
        elemf = np.hstack([self.elemf[:5], [Mf]])

        # Keplerian points
        kep0 = pk.planet.keplerian(t0, elem0)
        kepf = pk.planet.keplerian(tf, elemf)

        # planets
        pk.orbit_plots.plot_planet(
            kep0, t0=t0, units=units, ax=axes, color=(0.8, 0.8, 0.8))
        pk.orbit_plots.plot_planet(
            kepf, t0=tf, units=units, ax=axes, color=(0.8, 0.8, 0.8))
Ejemplo n.º 4
0
    def _plot_traj(self, z, axes, units=pk.AU):
        """Plots spacecraft trajectory.

        Args:
            - z (``tuple``, ``list``, ``numpy.ndarray``): Decision chromosome.
            - axes (``matplotlib.axes._subplots.Axes3DSubplot``): 3D axes to use for the plot
            - units (``float``, ``int``): Length unit by which to normalise data.

        Examples:
            >>> prob.extract(pykep.trajopt.indirect_pt2or).plot_traj(pop.champion_x)
        """

        # times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[1])

        # Keplerian elements of the osculating orbit at start
        elem0 = list(pk.ic2par(self.x0[0:3], self.x0[3:6], self.leg.mu))
        # Eccentric to Mean Anomaly
        elem0[5] = elem0[5] - elem0[1] * np.sin(elem0[5])

        # Mean Anomaly at the target orbit
        Mf = z[1] - self.elemf[1] * np.sin(z[1])

        elemf = np.hstack([self.elemf[:5], [Mf]])

        # Keplerian elements
        kep0 = pk.planet.keplerian(t0, elem0)
        kepf = pk.planet.keplerian(tf, self.elemf)

        # plot departure and arrival
        pk.orbit_plots.plot_planet(
            kep0, t0, units=units, color=(0.8, 0.8, 0.8), ax=axes)
        pk.orbit_plots.plot_planet(
            kepf, tf, units=units, color=(0.8, 0.8, 0.8), ax=axes)
Ejemplo n.º 5
0
    def _plot_traj(self, z, axes, units):

        # states
        x0 = self.leg.x0
        xf = self.leg.xf

        # times
        t0 = pk.epoch(self.leg.t0)
        tf = pk.epoch(self.leg.tf)

        # Computes the osculating Keplerian elements at start and arrival
        elem0 = list(pk.ic2par(x0[0:3], x0[3:6], self.leg.mu))
        elemf = list(pk.ic2par(xf[0:3], xf[3:6], self.leg.mu))

        # Converts the eccentric anomaly into eccentric anomaly
        elem0[5] = elem0[5] - elem0[1] * np.sin(elem0[5])
        elemf[5] = elemf[5] - elemf[1] * np.sin(elemf[5])

        # Creates two virtual keplerian planets with the said elements
        kep0 = pk.planet.keplerian(t0, elem0)
        kepf = pk.planet.keplerian(tf, elemf)

        # Plots the departure and arrival osculating orbits
        pk.orbit_plots.plot_planet(
            kep0, t0, units=units, color=(0.8, 0.8, 0.8), ax=axes)
        pk.orbit_plots.plot_planet(
            kepf, tf, units=units, color=(0.8, 0.8, 0.8), ax=axes)
Ejemplo n.º 6
0
    def pretty(self, x):
        """
        prob.pretty(x)

        Args:
            - x (``list``, ``tuple``, ``numpy.ndarray``): Decision chromosome, e.g. (``pygmo.population.champion_x``).

        Prints human readable information on the trajectory represented by the decision vector x
        """

        if not len(x) == len(self.get_bounds()[0]):
            raise ValueError("Invalid length of the decision vector x")

        n_seg = self.__n_seg
        m_i = self.__sc.mass
        t0 = x[0]
        T = x[1]
        m_f = x[2]
        thrusts = [np.linalg.norm(x[3 + 3 * i: 6 + 3 * i])
                   for i in range(n_seg)]

        tf = t0 + T
        mP = m_i - m_f
        deltaV = self.__sc.isp * pk.G0 * np.log(m_i / m_f)

        dt = np.append(self.__fwd_dt, self.__bwd_dt) * T / pk.DAY2SEC
        time_thrusts_on = sum(dt[i] for i in range(
            len(thrusts)) if thrusts[i] > 0.1)

        print("Departure:", pk.epoch(t0), "(", t0, "mjd2000 )")
        print("Time of flight:", T, "days")
        print("Arrival:", pk.epoch(tf), "(", tf, "mjd2000 )")
        print("Delta-v:", deltaV, "m/s")
        print("Propellant consumption:", mP, "kg")
        print("Thrust-on time:", time_thrusts_on, "days")
Ejemplo n.º 7
0
def run_example11(n_seg=30):
    """
    This example demonstrates the use of the class lt_margo developed for the internal ESA CDF study on the 
    interplanetary mission named MARGO. The class was used to produce the preliminary traget selection
    for the mission resulting in 88 selected possible targets 
    (http://www.esa.int/spaceinimages/Images/2017/11/Deep-space_CubeSat)
    (http://www.esa.int/gsp/ACT/mad/projects/lt_to_NEA.html)
    """
    import pykep as pk
    import pygmo as pg
    import numpy as np
    from matplotlib import pyplot as plt
    from pykep.examples import add_gradient, algo_factory

    # 0 - Target asteroid from MPCORB
    mpcorbline = "K14Y00D 24.3   0.15 K1794 105.44160   34.12337  117.64264    1.73560  0.0865962  0.88781021   1.0721510  2 MPO369254   104   1  194 days 0.24 M-v 3Eh MPCALB     2803          2014 YD            20150618"

    # 1 - Algorithm
    algo = algo_factory("snopt7")

    # 2 - Problem
    udp = add_gradient(pk.trajopt.lt_margo(
        target=pk.planet.mpcorb(mpcorbline),
        n_seg=n_seg,
        grid_type="uniform",
        t0=[pk.epoch(8000), pk.epoch(9000)],
        tof=[200, 365.25 * 3],
        m0=20.0,
        Tmax=0.0017,
        Isp=3000.0,
        earth_gravity=False,
        sep=True,
        start="earth"),
        with_grad=False
    )
    prob = pg.problem(udp)
    prob.c_tol = [1e-5] * prob.get_nc()

    # 3 - Population
    pop = pg.population(prob, 1)

    # 4 - Solve the problem (evolve)
    pop = algo.evolve(pop)

    # 5 - Inspect the solution
    print("Feasible?:", prob.feasibility_x(pop.champion_x))

    # 6 - plot trajectory
    axis = udp.udp_inner.plot_traj(pop.champion_x, plot_segments=True)
    plt.title("The trajectory in the heliocentric frame")

    # 7 - plot control
    udp.udp_inner.plot_dists_thrust(pop.champion_x)

    # 8 - pretty
    udp.udp_inner.pretty(pop.champion_x)

    plt.ion()
    plt.show()
Ejemplo n.º 8
0
    def fitness(self, x_full):
        retval = []
        # 1 - obj fun
        if self.__objective == 'mass':
            retval.append(x_full[-1 - self.__dim_leg + 3])
        elif self.__objective == 'time':
            retval.append(x_full[-1 - self.__dim_leg] - x_full[0])

        sc_mass = self.__start_mass
        eqs = []
        ineqs = []

        # 2 - constraints
        for i in range(self.__num_legs):
            x = x_full[i * self.__dim_leg:(i + 1) * self.__dim_leg]

            start = pk.epoch(x[0])
            end = pk.epoch(x[0] + x[1])

            # Computing starting spaceraft state
            r, v = self.__seq[i].eph(start)
            x0 = pk.sims_flanagan.sc_state(r, v, sc_mass)

            # Computing ending spaceraft state
            r, v = self.__seq[i + 1].eph(end)
            xe = pk.sims_flanagan.sc_state(r, v, x[3])

            # Building the SF leg
            self.__legs[i].set_spacecraft(
                pk.sims_flanagan.spacecraft(sc_mass, .3, 3000.))
            self.__legs[i].set(start, x0, x[-3 * self.__nseg:], end, xe)

            # Setting all constraints
            eqs.extend(self.__legs[i].mismatch_constraints())
            ineqs.extend(self.__legs[i].throttles_constraints())

            eqs[-7] /= pk.AU
            eqs[-6] /= pk.AU
            eqs[-5] /= pk.AU
            eqs[-4] /= pk.EARTH_VELOCITY
            eqs[-3] /= pk.EARTH_VELOCITY
            eqs[-2] /= pk.EARTH_VELOCITY
            eqs[-1] /= self.__start_mass

            sc_mass = x[3]  # update mass to final mass of leg

            if i < self.__num_legs - 1:
                x_next = x_full[
                    (i + 1) * self.__dim_leg:(i + 2) * self.__dim_leg]
                time_ineq = x[0] + x[1] + x[2] - x_next[0]
                ineqs.append(time_ineq / 365.25)
            else:
                final_time_ineq = x[0] + x[1] + x[2] - \
                    x_full[0] - x_full[-1]  # <- total time
                ineqs.append(final_time_ineq / 365.25)

        retval = retval + eqs + ineqs
        return retval
Ejemplo n.º 9
0
    def fitness(self, z):

        # departure and arrival times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # departure and arrival eccentric anomolies
        M0 = z[1]
        Mf = z[2]

        # departure costates
        l0 = np.asarray(z[3:])

        # set Keplerian elements
        elem0 = np.hstack([self.elem0[:5], [M0]])
        elemf = np.hstack([self.elemf[:5], [Mf]])

        # compute Cartesian states
        r0, v0 = pk.par2ic(elem0, self.leg.mu)
        rf, vf = pk.par2ic(elemf, self.leg.mu)

        # departure and arrival states (xf[6] is unused)
        x0 = pk.sims_flanagan.sc_state(r0, v0, self.sc.mass)
        xf = pk.sims_flanagan.sc_state(rf, vf, self.sc.mass / 10)

        # set leg
        self.leg.set(t0, x0, l0, tf, xf)

        # equality constraints
        ceq = self.leg.mismatch_constraints(atol=self.atol, rtol=self.rtol)

        # final mass
        obj = self.leg.trajectory[-1, -1]

        # Transversality conditions
        # At start
        lambdas0 = np.array(self.leg.trajectory[0, 7:13])
        r0norm = np.sqrt(r0[0] * r0[0] + r0[1] * r0[1] + r0[2] * r0[2])
        tmp = - pk.MU_SUN / r0norm**3
        tangent = np.array([v0[0], v0[1], v0[2], tmp *
                            r0[0], tmp * r0[1], tmp * r0[2]])
        tangent_norm = np.linalg.norm(tangent)
        tangent = tangent / tangent_norm
        T0 = np.dot(lambdas0, tangent)

        # At end
        lambdasf = np.array(self.leg.trajectory[-1, 7:13])
        rfnorm = np.sqrt(rf[0] * rf[0] + rf[1] * rf[1] + rf[2] * rf[2])
        tmp = - pk.MU_SUN / rfnorm**3
        tangent = np.array([vf[0], vf[1], vf[2], tmp *
                            rf[0], tmp * rf[1], tmp * rf[2]])
        tangent_norm = np.linalg.norm(tangent)
        tangent = tangent / tangent_norm
        Tf = np.dot(lambdasf, tangent)

        return np.hstack(([1], ceq, [T0, Tf]))
Ejemplo n.º 10
0
    def _plot_traj(self, z, axis, units):

        # times
        t0 = pk.epoch(z[0])
        tf = pk.epoch(z[0] + z[1])

        # plot Keplerian
        pk.orbit_plots.plot_planet(
            self.p0, t0, units=units, color=(0.8, 0.8, 0.8), ax=axis)
        pk.orbit_plots.plot_planet(
            self.pf, tf, units=units, color=(0.8, 0.8, 0.8), ax=axis)
Ejemplo n.º 11
0
 def _pretty(self, z):
     print("\nLow-thrust NEP transfer from " +
           self.p0.name + " to " + self.pf.name)
     print("\nLaunch epoch: {!r} MJD2000, a.k.a. {!r}".format(
         z[0], pk.epoch(z[0])))
     print("Arrival epoch: {!r} MJD2000, a.k.a. {!r}".format(
         z[0] + z[1], pk.epoch(z[0] + z[1])))
     print("Time of flight (days): {!r} ".format(z[1]))
     print("\nLaunch DV (km/s) {!r} - [{!r},{!r},{!r}]".format(np.sqrt(
         z[3]**2 + z[4]**2 + z[5]**2) / 1000, z[3] / 1000, z[4] / 1000, z[5] / 1000))
     print("Arrival DV (km/s) {!r} - [{!r},{!r},{!r}]".format(np.sqrt(
         z[6]**2 + z[7]**2 + z[8]**2) / 1000, z[6] / 1000, z[7] / 1000, z[8] / 1000))
Ejemplo n.º 12
0
    def _plot_traj(self, z, axis, units):

        # times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # Keplerian
        kep0 = pk.planet.keplerian(t0, self.elem0)
        kepf = pk.planet.keplerian(tf, self.elemf)

        # plot Keplerian
        pk.orbit_plots.plot_planet(
            kep0, t0, units=units, color=(0.8, 0.8, 0.8), ax=axis)
        pk.orbit_plots.plot_planet(
            kepf, tf, units=units, color=(0.8, 0.8, 0.8), ax=axis)
Ejemplo n.º 13
0
    def plot(self, x, ax=None):
        """
        ax = prob.plot(x, ax=None)

        - x: encoded trajectory
        - ax: matplotlib axis where to plot. If None figure and axis will be created
        - [out] ax: matplotlib axis where to plot

        Plots the trajectory represented by a decision vector x on the 3d axis ax

        Example::

          ax = prob.plot(x)
        """
        import matplotlib as mpl
        from mpl_toolkits.mplot3d import Axes3D
        import matplotlib.pyplot as plt
        from pykep import epoch, AU
        from pykep.sims_flanagan import sc_state
        from pykep.orbit_plots import plot_planet, plot_sf_leg

        # Creating the axis if necessary
        if ax is None:
            mpl.rcParams['legend.fontsize'] = 10
            fig = plt.figure()
            axis = fig.gca(projection='3d')
        else:
            axis = ax

        # Plotting the Sun ........
        axis.scatter([0], [0], [0], color='y')

        # Plotting the pykep.planet both at departure and arrival dates
        for i in range(self.__num_legs):
            idx = i * self.__dim_leg
            plot_planet(self.__seq[i], epoch(x[idx]), units=AU, legend=True, color=(
                0.7, 0.7, 0.7), s=30, ax=axis)
            plot_planet(self.__seq[i + 1], epoch(x[idx] + x[idx + 1]),
                        units=AU, legend=False, color=(0.7, 0.7, 0.7), s=30, ax=axis)

        # Computing the legs
        self.fitness(x)

        # Plotting the legs
        for leg in self.__legs:
            plot_sf_leg(leg, units=AU, N=10, ax=axis, legend=False)

        return axis
Ejemplo n.º 14
0
    def fitness(self, z):

        # times
        t0 = self.t0
        tf = pk.epoch(t0.mjd2000 + z[0])

        # intial costates
        l0 = np.asarray(z[1:])

        # arrival conditions
        rf, vf = self.pf.eph(tf)

        # departure state
        x0 = pk.sims_flanagan.sc_state(self.x0[0:3], self.x0[3:6], self.x0[6])

        # arrival state (mass will be ignored)
        xf = pk.sims_flanagan.sc_state(rf, vf, self.sc.mass / 10)

        # set leg
        self.leg.set(t0, x0, l0, tf, xf)

        # equality constraints
        ceq = self.leg.mismatch_constraints(atol=self.atol, rtol=self.rtol)

        obj = self.leg.trajectory[-1, -1] * self.leg._dynamics.c2 * 1000

        return np.hstack(([obj], ceq))
Ejemplo n.º 15
0
    def _plot_traj(self, z, axes, units=pk.AU):
        """Plots spacecraft trajectory.

        Args:
            - z (``tuple``, ``list``, ``numpy.ndarray``): Decision chromosome.
            - axes (``matplotlib.axes._subplots.Axes3DSubplot``): 3D axes to use for the plot
            - units (``float``, ``int``): Length unit by which to normalise data.

        Examples:
            >>> prob.extract(pykep.trajopt.indirect_pt2or).plot_traj(pop.champion_x)
        """

        # states
        x0 = self.x0

        # times
        t0 = self.t0
        tf = pk.epoch(t0.mjd2000 + z[0])

        # Computes the osculating Keplerian elements at start
        elem0 = list(pk.ic2par(x0[0:3], x0[3:6], self.leg.mu))

        # Converts the eccentric anomaly into eccentric anomaly
        elem0[5] = elem0[5] - elem0[1] * np.sin(elem0[5])

        # Creates a virtual keplerian planet with the said elements
        kep0 = pk.planet.keplerian(t0, elem0)

        # Plots the departure and arrival osculating orbits
        pk.orbit_plots.plot_planet(
            kep0, t0, units=units, color=(0.8, 0.8, 0.8), ax=axes)
        pk.orbit_plots.plot_planet(
            self.pf, tf, units=units, color=(0.8, 0.8, 0.8), ax=axes)
Ejemplo n.º 16
0
    def plot(self, x, axes=None, units=pk.AU, N=60):
        """plot(self, x, axes=None, units=pk.AU, N=60)

        Plots the spacecraft trajectory.

        Args:
            - x (``tuple``, ``list``, ``numpy.ndarray``): Decision chromosome.
            - axes (``matplotlib.axes._subplots.Axes3DSubplot``): 3D axes to use for the plot
            - units (``float``, ``int``): Length unit by which to normalise data.
            - N (``float``): Number of points to plot per leg
        """
        import matplotlib as mpl
        import matplotlib.pyplot as plt
        from mpl_toolkits.mplot3d import Axes3D

        # Creating the axes if necessary
        if axes is None:
            mpl.rcParams['legend.fontsize'] = 10
            fig = plt.figure()
            axes = fig.gca(projection='3d')

        T = self._decode_tofs(x)
        ep = np.insert(T, 0, x[0])  # [t0, T1, T2 ...]
        ep = np.cumsum(ep)  # [t0, t1, t2, ...]
        DVlaunch, DVfb, DVarrival, l, _ = self._compute_dvs(x)
        for pl, e in zip(self.seq, ep):
            pk.orbit_plots.plot_planet(pl, pk.epoch(
                e), units=units, legend=True, color=(0.7, 0.7, 1), ax=axes)
        for lamb in l:
            pk.orbit_plots.plot_lambert(
                lamb, N=N, sol=0, units=units, color='k', legend=False, ax=axes, alpha=0.8)
        return axes
Ejemplo n.º 17
0
    def fitness(self, z):

        # times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # costates
        l0 = np.asarray(z[1:])

        # set leg
        self.leg.set(t0, self.x0, l0, tf, self.xf)

        # equality constraints
        ceq = self.leg.mismatch_constraints(atol=self.atol, rtol=self.rtol)

        return np.hstack(([1, ceq]))
Ejemplo n.º 18
0
    def fitness(self, z):

        # epochs (mjd2000)
        t0 = pk.epoch(z[0])
        tf = pk.epoch(z[0] + z[1])

        # final mass
        mf = z[2]

        # controls
        u = z[9:]

        # compute Cartesian states of planets
        r0, v0 = self.p0.eph(t0)
        rf, vf = self.pf.eph(tf)

        # add the vinfs from the chromosome
        v0 = [a + b for a, b in zip(v0, z[3:6])]
        vf = [a + b for a, b in zip(vf, z[6:9])]

        # spacecraft states
        x0 = pk.sims_flanagan.sc_state(r0, v0, self.sc.mass)
        xf = pk.sims_flanagan.sc_state(rf, vf, mf)

        # set leg
        self.leg.set(t0, x0, u, tf, xf)

        # compute equality constraints
        ceq = np.asarray(self.leg.mismatch_constraints(), np.float64)

        # nondimensionalise equality constraints
        ceq[0:3] /= pk.AU
        ceq[3:6] /= pk.EARTH_VELOCITY
        ceq[6] /= self.sc.mass

        # compute inequality constraints
        cineq = np.asarray(self.leg.throttles_constraints(), np.float64)

        # compute inequality constraints on departure and arrival velocities
        v_dep_con = (z[3] ** 2 + z[4] ** 2 + z[5] ** 2 - self.vinf_dep ** 2)
        v_arr_con = (z[6] ** 2 + z[7] ** 2 + z[8] ** 2 - self.vinf_arr ** 2)

        # nondimensionalize inequality constraints
        v_dep_con /= pk.EARTH_VELOCITY ** 2
        v_arr_con /= pk.EARTH_VELOCITY ** 2

        return np.hstack(([-mf], ceq, cineq, [v_dep_con, v_arr_con]))
Ejemplo n.º 19
0
    def plot(self, x):
        import matplotlib as mpl
        from mpl_toolkits.mplot3d import Axes3D
        import matplotlib.pyplot as plt
        from pykep import epoch, AU
        from pykep.sims_flanagan import sc_state
        from pykep.orbit_plots import plot_planet, plot_sf_leg

        t_E = epoch(x[0])
        t_V = epoch(x[0] + x[1])
        t_M = epoch(x[0] + x[1] + x[9])
        rE, vE = self.__earth.eph(t_E)
        rV, vV = self.__venus.eph(t_V)
        rM, vM = self.__mercury.eph(t_M)

        # First Leg
        v = [a + b for a, b in zip(vE, x[3:6])]
        x0 = sc_state(rE, v, self.__sc.mass)
        v = [a + b for a, b in zip(vV, x[6:9])]
        xe = sc_state(rV, v, x[2])
        self.__leg1.set(
            t_E, x0, x[-3 * (self.__nseg1 + self.__nseg2):-self.__nseg2 * 3], t_V, xe)

        # Second leg
        v = [a + b for a, b in zip(vV, x[11:14])]
        x0 = sc_state(rV, v, x[2])
        v = [a + b for a, b in zip(vM, x[14:17])]
        xe = sc_state(rM, v, x[10])
        self.__leg2.set(t_E, x0, x[(-3 * self.__nseg2):], t_V, xe)

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

        # The Sun
        axis.scatter([0], [0], [0], color='y')
        # The legs
        plot_sf_leg(self.__leg1, units=AU, N=10, ax=axis)
        plot_sf_leg(self.__leg2, units=AU, N=10, ax=axis)
        # The planets
        plot_planet(
            self.__earth, t_E, units=AU, legend=True, color=(0.7, 0.7, 1), ax=axis)
        plot_planet(
            self.__venus, t_V, units=AU, legend=True, color=(0.7, 0.7, 1), ax=axis)
        plot_planet(
            self.__mercury, t_M, units=AU, legend=True, color=(0.7, 0.7, 1), ax=axis)
        plt.show()
Ejemplo n.º 20
0
    def fitness(self, z):

        # epochs (mjd2000)
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # final mass
        mf = z[1]

        # eccentric anomolies
        E0 = z[2]
        Ef = z[3]

        # controls
        u = z[4:]

        # set Keplerian elements
        self.elem0[5] = E0
        self.elemf[5] = Ef

        # compute Cartesian states
        r0, v0 = pk.par2ic(self.elem0, self.mu)
        rf, vf = pk.par2ic(self.elemf, self.mu)

        # spacecraft states
        x0 = pk.sims_flanagan.sc_state(r0, v0, self.sc.mass)
        xf = pk.sims_flanagan.sc_state(rf, vf, mf)

        # set leg
        self.leg.set(t0, x0, u, tf, xf)

        # compute equality constraints
        ceq = np.asarray(self.leg.mismatch_constraints(), np.float64)

        # nondimensionalise equality constraints
        ceq[0:3] /= pk.AU
        ceq[3:6] /= pk.EARTH_VELOCITY
        ceq[6] /= self.sc.mass

        # compute inequality constraints
        cineq = np.asarray(self.leg.throttles_constraints(), np.float64)

        return np.hstack(([-mf], ceq, cineq))
Ejemplo n.º 21
0
    def fitness(self, z):

        # times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # final eccentric anomaly
        Mf = z[1]

        # intial costates
        l0 = np.asarray(z[2:])

        # set arrival Keplerian elements
        self.elemf[5] = Mf

        # departure state
        x0 = pk.sims_flanagan.sc_state(self.x0[0:3], self.x0[3:6], self.x0[6])

        # compute Cartesian arrival state
        rf, vf = pk.par2ic(self.elemf, self.leg.mu)
        xf = pk.sims_flanagan.sc_state(rf, vf, self.sc.mass / 10)

        # set leg
        self.leg.set(t0, x0, l0, tf, xf)

        # equality constraints
        ceq = self.leg.mismatch_constraints(atol=self.atol, rtol=self.rtol)

        # final mass
        # mf = self.leg.trajectory[-1, 6]

        # Transversality condition at the end
        lambdasf = np.array(self.leg.trajectory[-1, 7:13])
        rfnorm = np.sqrt(rf[0] * rf[0] + rf[1] * rf[1] + rf[2] * rf[2])
        tmp = - pk.MU_SUN / rfnorm**3
        tangent = np.array([vf[0], vf[1], vf[2], tmp *
                            rf[0], tmp * rf[1], tmp * rf[2]])
        tangent_norm = np.linalg.norm(tangent)
        tangent = tangent / tangent_norm
        Tf = np.dot(lambdasf, tangent)

        return np.hstack(([1], ceq, [Tf]))
def plotContours(start_planet, end_planet, eph1, eph2, flt1, flt2,
                 sampling_size):

    start_epochs = np.arange(eph1, eph2, sampling_size)
    duration = np.arange(flt1, flt2, sampling_size)
    data = list()
    for start in start_epochs:
        row = list()
        for T in duration:
            r1, v1 = start_planet.eph(pk.epoch(start))
            r2, v2 = end_planet.eph(pk.epoch(start + T))
            l = pk.lambert_problem(r1, r2, T * 60 * 60 * 24,
                                   start_planet.mu_central_body)
            DV1 = np.linalg.norm(array(v1) - array(l.get_v1()[0]))
            DV2 = np.linalg.norm(array(v2) - array(l.get_v2()[0]))
            DV1 = max([0, DV1 - eph1])
            DV = DV1 + DV2
            row.append(DV)
        data.append(row)

    minrows = [min(l) for l in data]
    i_idx = np.argmin(minrows)
    j_idx = np.argmin(data[i_idx])
    best = data[i_idx][j_idx]
    print('\nBest DV: ', best)
    print('Launch epoch (MJD2000): ', start_epochs[i_idx])
    print('Duration (days): ', duration[j_idx])
    duration_pl2, start_epochs_pl2 = np.meshgrid(duration, start_epochs)

    CP2 = plt.contourf(start_epochs_pl2,
                       duration_pl2,
                       array(data),
                       levels=list(np.linspace(best, 5000, 10)))
    plt.colorbar(CP2).set_label('△V km/s')
    plt.title(f'{start_planet.name} - {end_planet.name} Total △V Requirements'.
              title())
    plt.xlabel('Launch Date (MJD2000)')
    plt.ylabel('Mission Duration (days)')
    plt.show()
Ejemplo n.º 23
0
    def double_segments(self, x):
        """
        new_prob, new_x = prob.double_segments(self,x)

        Args:
            - x (``list``, ``tuple``, ``numpy.ndarray``): Decision chromosome, e.g. (``pygmo.population.champion_x``).

        Returns:
            - the new udp having twice the segments
            - list: the new chromosome to be used as initial guess

        Returns the decision vector encoding a low trust trajectory having double the number of segments with respect to x
        and a 'similar' throttle history. In case high fidelity is True, and x is a feasible trajectory, the returned decision vector
        also encodes a feasible trajectory that can be further optimized
        Returns the problem and the decision vector encoding a low-thrust trajectory having double the number of
        segments with respect to x and the same throttle history. If x is a feasible trajectory, the new chromosome is "slightly
        unfeasible", due to the new refined Earth's gravity and/or SEP thrust that are now computed in the 2 halves of each segment.
        """

        if not len(x) == len(self.get_bounds()[0]):
            raise ValueError("Invalid length of the decision vector x")

        new_x = np.append(x[:3], np.repeat(x[3:].reshape((-1, 3)), 2, axis=0))

        new_prob = lt_margo(
            target=self.target,
            n_seg=2 * self.__n_seg,
            grid_type=self.__grid_type,
            t0=[pk.epoch(self.__lb[0]), pk.epoch(self.__ub[0])],
            tof=[self.__lb[1], self.__ub[1]],
            m0=self.__sc.mass,
            Tmax=self.__sc.thrust,
            Isp=self.__sc.isp,
            earth_gravity=self.__earth_gravity,
            sep=self.__sep,
            start=self.__start
        )

        return new_prob, new_x
Ejemplo n.º 24
0
    def __init__(
        self,
        t0_limits=[7000, 8000],
        tof_limits=[[50, 420], [50, 400], [50, 400]],
        max_revs: int = 2,
        resonances=[[[1, 1], [5, 4], [4, 3]], [[1, 1], [5, 4], [4, 3]],
                    [[1, 1], [5, 4], [4, 3]], [[4, 3], [3, 2], [5, 3]],
                    [[4, 3], [3, 2], [5, 3]], [[4, 3], [3, 2], [5, 3]]],
        safe_distance=350000,
        max_mission_time=11.0 * 365.25,
        max_dv0=5600,
    ):
        """
        Args:
            - t0_limits (``list`` of ``float``): start time bounds. 
            - tof_limits (``list`` of ``list`` of ``float``): time of flight bounds. 
            - max_revs (``int``): maximal number of revolutions for Lambert transfer.
            - resonances (``list`` of ``list`` of ``int``): resonance options. 
            - safe_distance: (``float``): safe distance from planet at GA maneuver in m.
            - max_mission_time: (``float``): max mission time in days.
            - max_dv0: (``float``): max delta velocity at start.
        """

        self._safe_distance = safe_distance
        self._max_mission_time = max_mission_time
        self._max_dv0 = max_dv0
        self._min_beta = -math.pi
        self._max_beta = math.pi

        self._earth = jpl_lp("earth")
        self._venus = jpl_lp("venus")
        self._seq = [
            self._earth, self._venus, self._venus, self._earth, self._venus,
            self._venus, self._venus, self._venus, self._venus, self._venus
        ]

        assert len(self._seq) - 4 == len(
            resonances)  # one resonance option selection for each VV sequence

        self._resonances = resonances
        self._t0 = t0_limits
        self._tof = tof_limits
        self._max_revs = max_revs

        self._n_legs = len(self._seq) - 1

        # initialize data to compute heliolatitude
        t_plane_crossing = epoch(7645)
        rotation_axis = self._seq[0].eph(t_plane_crossing)[0]
        self._rotation_axis = rotation_axis / np.linalg.norm(rotation_axis)
        self._theta = -7.25 * DEG2RAD  # fixed direction of the rotation
Ejemplo n.º 25
0
    def _plot_traj(self, z, axes, units):
        """Plots spacecraft trajectory.

        Args:
            - z (``tuple``, ``list``, ``numpy.ndarray``): Decision chromosome.
            - axes (``matplotlib.axes._subplots.Axes3DSubplot``): 3D axes to use for the plot
            - units (``float``, ``int``): Length unit by which to normalise data.

        Examples:
            >>> prob.extract(pykep.trajopt.indirect_or2or).plot_traj(pop.champion_x)
        """

        # times
        t0 = pk.epoch(0)
        tf = pk.epoch(z[0])

        # Mean Anomalies
        M0 = z[1] - self.elem0[1] * np.sin(z[1])
        Mf = z[2] - self.elemf[1] * np.sin(z[2])

        elem0 = np.hstack([self.elem0[:5], [M0]])
        elemf = np.hstack([self.elemf[:5], [Mf]])

        # Keplerian points
        kep0 = pk.planet.keplerian(t0, elem0)
        kepf = pk.planet.keplerian(tf, elemf)

        # planets
        pk.orbit_plots.plot_planet(kep0,
                                   t0=t0,
                                   units=units,
                                   axes=axes,
                                   color=(0.8, 0.8, 0.8))
        pk.orbit_plots.plot_planet(kepf,
                                   t0=tf,
                                   units=units,
                                   axes=axes,
                                   color=(0.8, 0.8, 0.8))
Ejemplo n.º 26
0
    def fitness(self, x):
        from pykep import epoch, AU, EARTH_VELOCITY, DAY2SEC
        from pykep.sims_flanagan import sc_state
        # This is the objective function
        objfun = [-x[3]]

        # And these are the constraints
        start = epoch(x[0])
        end = epoch(x[0] + x[1])

        r, v = self.__earth.eph(start)
        v = [a + b for a, b in zip(v, x[4:7])]
        x0 = sc_state(r, v, self.__sc.mass)

        r, v = self.__mars.eph(end)
        xe = sc_state(r, v, x[3])
        self.__leg.set(start, x0, x[-3 * self.__nseg:],
                       end, xe, x[2] * DAY2SEC)
        v_inf_con = (x[4] * x[4] + x[5] * x[5] + x[6] * x[6] -
                     self.__Vinf * self.__Vinf) / (EARTH_VELOCITY * EARTH_VELOCITY)
        try:
            constraints = list(self.__leg.mismatch_constraints(
            ) + self.__leg.throttles_constraints()) + [v_inf_con]
        except:
            print(
                "warning: CANNOT EVALUATE constraints .... possible problem in the Taylor integration in the Sundmann variable")
            constraints = (1e14,) * (8 + 1 + self.__nseg + 2)
        # We then scale all constraints to non-dimensional values
        constraints[0] /= AU
        constraints[1] /= AU
        constraints[2] /= AU
        constraints[3] /= EARTH_VELOCITY
        constraints[4] /= EARTH_VELOCITY
        constraints[5] /= EARTH_VELOCITY
        constraints[6] /= self.__sc.mass
        constraints[7] /= 365.25 * DAY2SEC
        return objfun + constraints
Ejemplo n.º 27
0
def run_example1(impulses=4):
    import pykep as pk
    import pygmo as pg
    import numpy as np
    from matplotlib import pyplot as plt
    from pykep.examples import add_gradient, algo_factory

    # problem
    udp = add_gradient(pk.trajopt.pl2pl_N_impulses(
        start=pk.planet.jpl_lp('earth'),
        target=pk.planet.jpl_lp('venus'),
        N_max=impulses,
        tof=[100., 1000.],
        vinf=[0., 4],
        phase_free=False,
        multi_objective=False,
        t0=[pk.epoch(0), pk.epoch(1000)]),
                       with_grad=False)
    prob = pg.problem(udp)

    # algorithm
    uda = pg.cmaes(gen=1000, force_bounds=True)
    algo = pg.algorithm(uda)
    algo.set_verbosity(10)

    # population
    pop = pg.population(prob, 20)

    # solve the problem
    pop = algo.evolve(pop)

    # inspect the solution
    udp.udp_inner.plot(pop.champion_x)
    plt.ion()
    plt.show()

    udp.udp_inner.pretty(pop.champion_x)
Ejemplo n.º 28
0
    def fitness(self, x):
        from pykep import epoch, AU, EARTH_VELOCITY, DAY2SEC
        from pykep.sims_flanagan import sc_state
        # This is the objective function
        objfun = [-x[3]]

        # And these are the constraints
        start = epoch(x[0])
        end = epoch(x[0] + x[1])

        r, v = self.__earth.eph(start)
        v = [a + b for a, b in zip(v, x[4:7])]
        x0 = sc_state(r, v, self.__sc.mass)

        r, v = self.__mars.eph(end)
        xe = sc_state(r, v, x[3])
        self.__leg.set(start, x0, x[-3 * self.__nseg:],
                       end, xe, x[2] * DAY2SEC)
        v_inf_con = (x[4] * x[4] + x[5] * x[5] + x[6] * x[6] -
                     self.__Vinf * self.__Vinf) / (EARTH_VELOCITY * EARTH_VELOCITY)
        try:
            constraints = list(self.__leg.mismatch_constraints(
            ) + self.__leg.throttles_constraints()) + [v_inf_con]
        except:
            print(
                "warning: CANNOT EVALUATE constraints .... possible problem in the Taylor integration in the Sundmann variable")
            constraints = (1e14,) * (8 + 1 + self.__nseg + 2)
        # We then scale all constraints to non-dimensional values
        constraints[0] /= AU
        constraints[1] /= AU
        constraints[2] /= AU
        constraints[3] /= EARTH_VELOCITY
        constraints[4] /= EARTH_VELOCITY
        constraints[5] /= EARTH_VELOCITY
        constraints[6] /= self.__sc.mass
        constraints[7] /= 365.25 * DAY2SEC
        return objfun + constraints
Ejemplo n.º 29
0
    def __init__(self,
                 x0=[
                     -24482087316.947845, -150000284705.77328,
                     -196089391.29376224, 31677.87649549203,
                     -5859.747563624047, -351.75278222719828, 1000
                 ],
                 pf="mars",
                 mass=1000,
                 thrust=0.3,
                 isp=3000,
                 tof=[230, 280],
                 t0=1251.0286746844447,
                 mu=pk.MU_SUN,
                 alpha=0,
                 bound=False,
                 atol=1e-12,
                 rtol=1e-12):
        """Initialises ``pykep.trajopt.indirect_pt2or`` problem.

        Args:
            - x0 (``list``, ``tuple``, ``numpy.ndarray``): Departure state [m, m, m, m/s, m/s, m/s, kg].
            - pf (``str``): Arrival planet name. (will be used to construct a planet.jpl_lp object)            - mass (``float``, ``int``): Spacecraft wet mass [kg].
            - thrust (``float``, ``int``): Spacecraft maximum thrust [N].
            - isp (``float``, ``int``): Spacecraft specific impulse [s].
            - atol (``float``, ``int``): Absolute integration solution tolerance.
            - rtol (``float``, ``int``): Relative integration solution tolerance.
            - tof (``list``): Transfer time bounds [days].
            - t0 (``float``): launch epoch [MJD2000].
            - freetime (``bool``): Activates final time transversality condition. Allows final time to vary.
            - alpha (``float``, ``int``): Homotopy parameter, governing the degree to which the theoretical control law is intended to reduce propellant expenditure or energy.
            - bound (``bool``): Activates bounded control, in which the control throttle is bounded between 0 and 1, otherwise the control throttle is allowed to unbounded.
            - mu (``float``): Gravitational parameter of primary body [m^3/s^2].

        """

        # initialise base
        _indirect_base.__init__(self, mass, thrust, isp, mu, True, False,
                                alpha, bound, atol, rtol)

        # departure epoch
        self.t0 = pk.epoch(t0)
        # departure state
        self.x0 = np.asarray(x0, np.float64)
        # arrival planet
        self.pf = pk.planet.jpl_lp(pf)
        # bounds on the time of flight
        self.tof = tof
        # store the alfa value (immutable)
        self._alpha = alpha
Ejemplo n.º 30
0
    def __init__(self,
                 x0=[-24482087316.947845, -150000284705.77328, -196089391.29376224,
                     31677.87649549203, -5859.747563624047, -351.75278222719828, 1000],
                 pf="mars",
                 mass=1000,
                 thrust=0.3,
                 isp=3000,
                 tof=[230, 280],
                 t0=1251.0286746844447,
                 mu=pk.MU_SUN,
                 alpha=0,
                 bound=False,
                 atol=1e-12,
                 rtol=1e-12
                 ):
        """Initialises ``pykep.trajopt.indirect_pt2or`` problem.

        Args:
            - x0 (``list``, ``tuple``, ``numpy.ndarray``): Departure state [m, m, m, m/s, m/s, m/s, kg].
            - pf (``str``): Arrival planet name. (will be used to construct a planet.jpl_lp object)            - mass (``float``, ``int``): Spacecraft wet mass [kg].
            - thrust (``float``, ``int``): Spacecraft maximum thrust [N].
            - isp (``float``, ``int``): Spacecraft specific impulse [s].
            - atol (``float``, ``int``): Absolute integration solution tolerance.
            - rtol (``float``, ``int``): Relative integration solution tolerance.
            - tof (``list``): Transfer time bounds [days].
            - t0 (``float``): launch epoch [MJD2000].
            - freetime (``bool``): Activates final time transversality condition. Allows final time to vary.
            - alpha (``float``, ``int``): Homotopy parametre, governing the degree to which the theoretical control law is intended to reduce propellant expenditure or energy.
            - bound (``bool``): Activates bounded control, in which the control throttle is bounded between 0 and 1, otherwise the control throttle is allowed to unbounded.
            - mu (``float``): Gravitational parametre of primary body [m^3/s^2].

        """

        # initialise base
        _indirect_base.__init__(
            self, mass, thrust, isp, mu, True, False, alpha, bound,
            atol, rtol
        )

        # departure epoch
        self.t0 = pk.epoch(t0)
        # departure state
        self.x0 = np.asarray(x0, np.float64)
        # arrival planet
        self.pf = pk.planet.jpl_lp(pf)
        # bounds on the time of flight
        self.tof = tof
        # store the alfa value (immutable)
        self._alpha = alpha
Ejemplo n.º 31
0
    def planet(self):
        """PyKep object (pykep.planet.keplerian) representation of Planet."""
        if self.pykep_planet is None:
            if self.planet_radius is None:
                planet_radius_constant = Constant("Rpln")
                self.planet_radius = planet_radius_constant.value

            self.pykep_planet = keplerian(
                epoch(0),
                (self.semimajor_axis * AU, self.eccentricity, self.inclination,
                 self.longitude_of_ascending_node, self.argument_of_periapsis,
                 self.true_anomaly_at_epoch), self._star.gm, self.gm,
                self.radius * self.planet_radius,
                self.radius * self.planet_radius, self.name)
        return self.pykep_planet
Ejemplo n.º 32
0
def rate__orbital(dep_ast, dep_t, leg_dT, **kwargs):
    """
    Orbital Phasing Indicator.
    See: http://arxiv.org/pdf/1511.00821.pdf#page=12

    Estimates the cost of a `leg_dT` days transfer from departure asteroid
    `dep_ast` at epoch `dep_t`, towards each of the available asteroids.
    """
    dep_t = pk.epoch(dep_t, "mjd")
    leg_dT *= DAY2SEC
    orbi = [
        orbital_indicator(ast, dep_t, leg_dT, **kwargs) for ast in asteroids
    ]
    ast_orbi = np.array(orbi[dep_ast])
    return np.linalg.norm(ast_orbi - orbi, axis=1)
Ejemplo n.º 33
0
    def pretty(self, x):
        """
        prob.pretty(x)

        Args:
            - x (``list``, ``tuple``, ``numpy.ndarray``): Decision chromosome, e.g. (``pygmo.population.champion_x``).

        Prints human readable information on the trajectory represented by the decision vector x
        """

        if not len(x) == len(self.get_bounds()[0]):
            raise ValueError("Invalid length of the decision vector x")

        n_seg = self.__n_seg
        m_i = self.__sc.mass
        t0 = x[0]
        T = x[1]
        m_f = x[2]
        thrusts = [
            np.linalg.norm(x[3 + 3 * i:6 + 3 * i]) for i in range(n_seg)
        ]

        tf = t0 + T
        mP = m_i - m_f
        deltaV = self.__sc.isp * pk.G0 * np.log(m_i / m_f)

        dt = np.append(self.__fwd_dt, self.__bwd_dt) * T / pk.DAY2SEC
        time_thrusts_on = sum(dt[i] for i in range(len(thrusts))
                              if thrusts[i] > 0.1)

        print("Departure:", pk.epoch(t0), "(", t0, "mjd2000 )")
        print("Time of flight:", T, "days")
        print("Arrival:", pk.epoch(tf), "(", tf, "mjd2000 )")
        print("Delta-v:", deltaV, "m/s")
        print("Propellant consumption:", mP, "kg")
        print("Thrust-on time:", time_thrusts_on, "days")
Ejemplo n.º 34
0
def plot_planet_2d(planet, t0):
    T = planet.compute_period(t0) * SEC2DAY
    when = np.linspace(0, T, 60)

    x = np.array([0.0] * 60)
    y = np.array([0.0] * 60)
    z = np.array([0.0] * 60)

    for i, day in enumerate(when):
        r, _ = planet.eph(epoch(t0.mjd2000 + day))
        x[i] = r[0] / AU
        y[i] = r[1] / AU
        z[i] = r[2] / AU

    return x, y, z
Ejemplo n.º 35
0
    def plot(self, x, axes=None, units=AU, N=60):
        import matplotlib as mpl
        import matplotlib.pyplot as plt
        from pykep.orbit_plots import plot_planet

        rvt_outs, rvt_ins, rvt_pls, _, _ = self._compute_dvs(x)
        rvt_outs = [
            rvt.rotate(self._rotation_axis, self._theta) for rvt in rvt_outs
        ]
        rvt_ins[1:] = [
            rvt.rotate(self._rotation_axis, self._theta) for rvt in rvt_ins[1:]
        ]
        rvt_pls = [
            rvt.rotate(self._rotation_axis, self._theta) for rvt in rvt_pls
        ]

        ep = [epoch(rvt_pl._t * SEC2DAY) for rvt_pl in rvt_pls]

        # Creating the axes if necessary
        if axes is None:
            mpl.rcParams["legend.fontsize"] = 10
            fig = plt.figure()
            axes = fig.gca(projection="3d")

        plt.xlim([-1, 1])
        # planets
        for pl, e in zip(self._seq, ep):
            plot_planet(pl,
                        e,
                        units=units,
                        legend=True,
                        color=(0.7, 0.7, 1),
                        axes=axes)

        # lamberts and resonances
        for i in range(0, len(self._seq) - 1):
            pl = self._seq[i]
            # stay at planet: it is a resonance colored black
            is_reso = pl == self._seq[i + 1]
            rvt_out = rvt_outs[i]
            tof = rvt_ins[i + 1]._t - rvt_out._t
            rvt_out.plot(tof,
                         units=units,
                         N=4 * N,
                         color="k" if is_reso else "r",
                         axes=axes)
        return axes
Ejemplo n.º 36
0
def eph_reference(ref_ast, t):
    """
    Calculate reference r and v magnitudes for use in the normalization
    of asteroid ephemeris.

    Returns:
            (|r|, |v|)
    where (r,v) is the ephemeris of the given asteroid `ref_ast` (id, or object)
    at epoch `t` (int/float, or epoch object).
    """
    if type(ref_ast) is int:
        ref_ast = asteroids[ref_ast]
    if type(t) in [float, int]:
        t = pk.epoch(t, "mjd")

    r, v = ref_ast.eph(t)
    return np.linalg.norm(r), np.linalg.norm(v)
Ejemplo n.º 37
0
def epoch_offset():
    planet = Planet(1817514095, 1905216634, -455609026)

    winter = np.arctan2(-1, 0)

    a = -75.0
    b = 75.0

    for _ in range(1000):
        c = (a + b) / 2
        r_c, _ = planet.planet.eph(epoch(c))

        angle = np.arctan2(r_c[1], r_c[0])

        if angle - winter < 0:
            a = c
        else:
            b = c

    return jsonify(c) if has_app_context() else c
Ejemplo n.º 38
0
    def _plot_traj(self, z, axes, units=pk.AU):
        """Plots spacecraft trajectory.

        Args:
            - z (``tuple``, ``list``, ``numpy.ndarray``): Decision chromosome.
            - atol (``float``, ``int``): Absolute integration solution tolerance.
            - rtol (``float``, ``int``): Relative integration solution tolerance.
            - units (``float``, ``int``): Length unit by which to normalise data.

        Examples:
            >>> prob.extract(pykep.trajopt.indirect_pt2or).plot_traj(pop.champion_x)
        """

        # states
        x0 = self.x0

        # times
        t0 = self.t0
        tf = pk.epoch(t0.mjd2000 + z[0])

        # Computes the osculating Keplerian elements at start
        elem0 = list(pk.ic2par(x0[0:3], x0[3:6], self.leg.mu))

        # Converts the eccentric anomaly into eccentric anomaly
        elem0[5] = elem0[5] - elem0[1] * np.sin(elem0[5])

        # Creates a virtual keplerian planet with the said elements
        kep0 = pk.planet.keplerian(t0, elem0)

        # Plots the departure and arrival osculating orbits
        pk.orbit_plots.plot_planet(kep0,
                                   t0,
                                   units=units,
                                   color=(0.8, 0.8, 0.8),
                                   ax=axes)
        pk.orbit_plots.plot_planet(self.pf,
                                   tf,
                                   units=units,
                                   color=(0.8, 0.8, 0.8),
                                   ax=axes)
Ejemplo n.º 39
0
def ephemeris(planet, modifiedJulianDay, mode='jpl', ref='sun'):
    '''
    Query the ephemeris for the specified planet and epoch
    Based on the Pykep package by ESA/ACT, developed with version 2.3
    Returns the state vector (pos, vel) in Cartesian and Cylindrical coordinates
    mode='jpl' uses low precision ephemerides of the planets ('earth', etc)
    mode='spice' uses high precision spice kernel. These need to be loaded
        into memory using loadSpiceKernels(). The  kernel (430.bsp)
        includes ephemerides for Earth, Moon and the planet system barycenters
        ('399', 301', '4', etc)
    mode='gtoc2' uses the asteroids from the GTOC2 competition (Keplerian)
    '''

    epoch = pk.epoch(modifiedJulianDay, 'mjd2000')

    if mode == 'jpl':
        planet = pk.planet.jpl_lp(planet)
    elif mode == 'spice':
        planet = pk.planet.spice(planet, ref, 'eclipj2000')
    elif mode == 'gtoc2':
        planet = pk.planet.gtoc2(planet)
    else:
        print('ERROR: This is not a valid source of ephemerides.')

    # retrieve Cartesian state vectors in SI units
    rCart, vCart = planet.eph(epoch)

    # conversion to cylindrical values to get boundary conditions
    rCyl = Pcart2cyl(rCart)
    vCyl = Vcart2cyl(vCart, rCart)

    # combine into (6,) vectors (3xposition, 3xvelocity)
    stateVectorCartesian = np.array((rCart, vCart)).reshape(6, )
    stateVectorCylindrical = np.array((rCyl, vCyl)).reshape(6, )

    return stateVectorCylindrical, stateVectorCartesian, planet
Ejemplo n.º 40
0
    def plot_dists_thrust(self, x, axes=None):
        """
        axes = prob.plot_dists_thrust(self, x, axes=None)

        Args:
            - x (``list``, ``tuple``, ``numpy.ndarray``): Decision chromosome, e.g. (``pygmo.population.champion_x``).

        Returns:
            matplotlib.axes: axes where to plot

        Plots the distance of the spacecraft from the Earth/Sun and the thrust profile
        """

        if not len(x) == len(self.get_bounds()[0]):
            raise ValueError("Invalid length of the decision vector x")

        import matplotlib as mpl
        import matplotlib.pyplot as plt

        # Creating the axes if necessary
        if axes is None:
            mpl.rcParams['legend.fontsize'] = 10
            fig = plt.figure()
            axes = fig.add_subplot(111)

        n_seg = self.__n_seg
        fwd_seg = self.__fwd_seg
        bwd_seg = self.__bwd_seg
        t0 = x[0]
        T = x[1]
        fwd_grid = t0 + T * self.__fwd_grid  # days
        bwd_grid = t0 + T * self.__bwd_grid  # days

        throttles = [np.linalg.norm(x[3 + 3 * i: 6 + 3 * i])
                     for i in range(n_seg)]

        dist_earth = [0.0] * (n_seg + 2)  # distances spacecraft - Earth
        dist_sun = [0.0] * (n_seg + 2)  # distances spacecraft - Sun
        times = np.concatenate((fwd_grid, bwd_grid))

        rfwd, rbwd, vfwd, vbwd, mfwd, mbwd, ufwd, ubwd, fwd_dt, bwd_dt, _, _ = self._propagate(
            x)

        # Forward propagation
        xfwd = [0.0] * (fwd_seg + 1)
        yfwd = [0.0] * (fwd_seg + 1)
        zfwd = [0.0] * (fwd_seg + 1)
        xfwd[0] = rfwd[0][0] / pk.AU
        yfwd[0] = rfwd[0][1] / pk.AU
        zfwd[0] = rfwd[0][2] / pk.AU
        r_E = [ri / pk.AU for ri in self.__earth.eph(pk.epoch(fwd_grid[0]))[0]]
        dist_earth[0] = np.linalg.norm(
            [r_E[0] - xfwd[0], r_E[1] - yfwd[0], r_E[2] - zfwd[0]])
        dist_sun[0] = np.linalg.norm([xfwd[0], yfwd[0], zfwd[0]])

        for i in range(fwd_seg):
            xfwd[i + 1] = rfwd[i + 1][0] / pk.AU
            yfwd[i + 1] = rfwd[i + 1][1] / pk.AU
            zfwd[i + 1] = rfwd[i + 1][2] / pk.AU
            r_E = [
                ri / pk.AU for ri in self.__earth.eph(pk.epoch(fwd_grid[i + 1]))[0]]
            dist_earth[
                i + 1] = np.linalg.norm([r_E[0] - xfwd[i + 1], r_E[1] - yfwd[i + 1], r_E[2] - zfwd[i + 1]])
            dist_sun[
                i + 1] = np.linalg.norm([xfwd[i + 1], yfwd[i + 1], zfwd[i + 1]])

        # Backward propagation
        xbwd = [0.0] * (bwd_seg + 1)
        ybwd = [0.0] * (bwd_seg + 1)
        zbwd = [0.0] * (bwd_seg + 1)
        xbwd[-1] = rbwd[-1][0] / pk.AU
        ybwd[-1] = rbwd[-1][1] / pk.AU
        zbwd[-1] = rbwd[-1][2] / pk.AU
        r_E = [
            ri / pk.AU for ri in self.__earth.eph(pk.epoch(bwd_grid[-1]))[0]]
        dist_earth[-1] = np.linalg.norm([r_E[0] - xbwd[-1],
                                         r_E[1] - ybwd[-1], r_E[2] - zbwd[-1]])
        dist_sun[-1] = np.linalg.norm([xbwd[-1], ybwd[-1], zbwd[-1]])

        for i in range(bwd_seg):
            xbwd[-i - 2] = rbwd[-i - 2][0] / pk.AU
            ybwd[-i - 2] = rbwd[-i - 2][1] / pk.AU
            zbwd[-i - 2] = rbwd[-i - 2][2] / pk.AU
            r_E = [
                ri / pk.AU for ri in self.__earth.eph(pk.epoch(bwd_grid[-i - 2]))[0]]
            dist_earth[-i - 2] = np.linalg.norm(
                [r_E[0] - xbwd[-i - 2], r_E[1] - ybwd[-i - 2], r_E[2] - zbwd[-i - 2]])
            dist_sun[-i -
                     2] = np.linalg.norm([xbwd[-i - 2], ybwd[-i - 2], zbwd[-i - 2]])

        axes.set_xlabel("t [mjd2000]")
        # Plot Earth distance
        axes.plot(times, dist_earth, c='b', label="sc-Earth")
        # Plot Sun distance
        axes.plot(times, dist_sun, c='y', label="sc-Sun")
        axes.set_ylabel("distance [AU]", color='k')
        axes.set_ylim(bottom=0.)
        axes.tick_params('y', colors='k')
        axes.legend(loc=2)
        # draw threshold where Earth gravity equals 0.1*Tmax
        if self.__earth_gravity:
            axes.axhline(y=np.sqrt(pk.MU_EARTH * self.__sc.mass / (self.__sc.thrust * 0.1)
                                   ) / pk.AU, c='g', ls=":", lw=1, label="earth_g = 0.1*Tmax")
        # Plot thrust profile
        axes = axes.twinx()
        if self.__sep:
            max_thrust = self.__sc.thrust
            thrusts = np.linalg.norm(
                np.array(ufwd + ubwd), axis=1) / max_thrust
            # plot maximum thrust achievable at that distance from the Sun
            distsSun = dist_sun[:fwd_seg] + \
                dist_sun[-bwd_seg:] + [dist_sun[-1]]
            Tmaxs = [self._sep_model(d)[0] / max_thrust for d in distsSun]
            axes.step(np.concatenate(
                (fwd_grid, bwd_grid[1:])), Tmaxs, where="post", c='lightgray', linestyle=':')
        else:
            thrusts = throttles.copy()
        # duplicate the last for plotting
        thrusts = np.append(thrusts, thrusts[-1])
        axes.step(np.concatenate(
            (fwd_grid, bwd_grid[1:])), thrusts, where="post", c='r', linestyle='--')
        axes.set_ylabel("T/Tmax$_{1AU}$", color='r')
        axes.tick_params('y', colors='r')
        axes.set_xlim([times[0], times[-1]])
        axes.set_ylim([0, max(thrusts) + 0.2])

        return axes
Ejemplo n.º 41
0
def rate__edelbaum(dep_ast, dep_t, **kwargs):
    dep_ast = asteroids[dep_ast]
    dep_t = pk.epoch(dep_t, "mjd")
    return [edelbaum_dv(dep_ast, arr_ast, dep_t) for arr_ast in asteroids]
Ejemplo n.º 42
0
intervals = 1.0
start_epochs = np.arange(start_date, end_date, intervals)
max_tof = 400.0
duration = np.arange(120.0, max_tof, 1.0)
origin = 'earth'
destination = 'mars'
earth = pk.planet.jpl_lp(origin)
mars = pk.planet.jpl_lp(destination)
data = list()

for start in start_epochs:
    row = list()

    for tof in duration:

        pos_1, v1 = earth.eph(pk.epoch(start, 'mjd2000'))
        pos_2, v2 = mars.eph(pk.epoch(start + tof, 'mjd2000'))

        seconds_elapsed = tof * 60 * 60 * 24 if tof > 0 else 1 * 60 * 60 * 24

        l = pk.lambert_problem(pos_1, pos_2, seconds_elapsed, pk.MU_SUN)

        DV1 = np.linalg.norm(np.array(v1) - np.array(l.get_v1()[0]))
        DV2 = np.linalg.norm(np.array(v2) - np.array(l.get_v2()[0]))

        DV1 = max([0, DV1 - 4000])
        DV = DV1 + DV2

        row.append(DV)

    data.append(row)
Ejemplo n.º 43
0
from pykep.trajopt import mga_1dsm
from pykep.planet import jpl_lp, keplerian
from pykep import AU, DEG2RAD, MU_SUN, epoch

# ROSETTA (we need to modify the safe radius of the planets to match the wanted problem)
_churyumov = keplerian(epoch(52504.23754000012, "mjd"), [
    3.50294972836275 * AU, 0.6319356, 7.12723 * DEG2RAD, 50.92302 * DEG2RAD,
    11.36788 * DEG2RAD, 0. * DEG2RAD
], MU_SUN, 0., 0., 0., "Churyumov-Gerasimenko")

_mars_rosetta = jpl_lp('mars')
_mars_rosetta.safe_radius = 1.05
_seq_rosetta = [
    jpl_lp('earth'),
    jpl_lp('earth'), _mars_rosetta,
    jpl_lp('earth'),
    jpl_lp('earth'), _churyumov
]


class _rosetta_udp(mga_1dsm):
    """
    This class represents a rendezvous mission to the comet 67P/Churyumov-Gerasimenko modelled as an MGA-1DSM transfer.
    The fly-by sequence selected (i.e. E-EMEE-C) is similar to the one planned for the spacecraft Rosetta. 
    The objective function considered is the total mission delta V. No launcher model is employed and a final randezvous
    with the comet is included in the delta V computations.

    .. note::

       A significantly similar version of this problem was part of the no longer maintained GTOP database, 
       https://www.esa.int/gsp/ACT/projects/gtop/gtop.html. The exact definition is, though, different and results
Ejemplo n.º 44
0
def plot_planet(plnt,
                t0=0,
                tf=None,
                N=60,
                units=1.0,
                color='k',
                alpha=1.0,
                s=40,
                legend=(False, False),
                axes=None):
    """
    ax = plot_planet(plnt, t0=0, tf=None, N=60, units=1.0, color='k', alpha=1.0, s=40, legend=(False, False), axes=None):

    - axes:      3D axis object created using fig.gca(projection='3d')
    - plnt:      pykep.planet object we want to plot
    - t0:        a pykep.epoch or float (mjd2000) indicating the first date we want to plot the planet position
    - tf:        a pykep.epoch or float (mjd2000) indicating the final date we want to plot the planet position.
                 if None this is computed automatically from the orbital period (prone to error for non periodic orbits)
    - units:     the length unit to be used in the plot
    - color:     color to use to plot the orbit (passed to matplotlib)
    - s:         planet size (passed to matplotlib)
    - legend     2-D tuple of bool or string: The first element activates the planet scatter plot, 
                 the second to the actual orbit. If a bool value is used, then an automated legend label is generated (if True), if a string is used, the string is the legend. Its also possible but deprecated to use a single bool value. In which case that value is used for both the tuple components.

    Plots the planet position and its orbit.

    Example::

	import pykep as pk
	import matplotlib.pyplot as plt

	fig = plt.figure()
	ax = fig.gca(projection = '3d')
	pl = pk.planet.jpl_lp('earth')
	t_plot = pk.epoch(219)
	ax = pk.orbit_plots.plot_planet(pl, ax = ax, color='b')
    """
    from pykep import MU_SUN, SEC2DAY, epoch, AU, RAD2DEG
    from pykep.planet import keplerian
    from math import pi, sqrt
    import numpy as np
    import matplotlib.pylab as plt
    from mpl_toolkits.mplot3d import Axes3D

    if axes is None:
        fig = plt.figure()
        ax = fig.gca(projection='3d')
    else:
        ax = axes

    if type(t0) is not epoch:
        t0 = epoch(t0)

    # This is to make the tuple API compatible with the old API
    if type(legend) is bool:
        legend = (legend, legend)

    if tf is None:
        # orbit period at epoch
        T = plnt.compute_period(t0) * SEC2DAY
    else:
        if type(tf) is not epoch:
            tf = epoch(tf)
        T = (tf.mjd2000 - t0.mjd2000)
        if T < 0:
            raise ValueError("tf should be after t0 when plotting an orbit")

    # points where the orbit will be plotted
    when = np.linspace(0, T, N)

    # Ephemerides Calculation for the given planet
    x = np.array([0.0] * N)
    y = np.array([0.0] * N)
    z = np.array([0.0] * N)

    for i, day in enumerate(when):
        r, v = plnt.eph(epoch(t0.mjd2000 + day))
        x[i] = r[0] / units
        y[i] = r[1] / units
        z[i] = r[2] / units

    # Actual plot commands
    if (legend[0] is True):
        label1 = plnt.name + " " + t0.__repr__()[0:11]
    elif (legend[0] is False):
        label1 = None
    elif (legend[0] is None):
        label1 = None
    else:
        label1 = legend[0]

    if (legend[1] is True):
        label2 = plnt.name + " orbit"
    elif (legend[1] is False):
        label2 = None
    elif (legend[1] is None):
        label2 = None
    else:
        label2 = legend[1]

    ax.plot(x, y, z, label=label2, c=color, alpha=alpha)
    ax.scatter([x[0]], [y[0]], [z[0]],
               s=s,
               marker='o',
               alpha=0.8,
               c=[color],
               label=label1)

    if legend[0] or legend[1]:
        ax.legend()
    return ax
Ejemplo n.º 45
0
    def fineCorrectionBurn(self):
        #Propagate orbit to correction burn 1, then apply it to orbit, then propagage further and check.
        #If okay, then add in the manual inclination correction, and then do a final Lambert.
        self.AddOrbitPoint("1:319:0:0:0", 14646793325, 9353.0)
        rMan1, vMan1 = propagate_lagrangian(self.OrbitPoints[-2].r,
                                            self.OrbitPoints[-2].v,
                                            self.OrbitPoints[-1].t, self.mu_c)
        print(str(vMan1))
        vMan1 = np.asarray(vMan1)
        vMan1 += [-34.8, 35.9,
                  0]  #?????? WTF norm ok but direction is wrong (apprently)
        #vMan1 += [-25.87664536,+42.44449723,0]
        print(str(vMan1))
        self.OrbitPoints[-1].r = rMan1
        self.OrbitPoints[-1].r_n = norm(rMan1)
        self.OrbitPoints[-1].v = vMan1
        self.OrbitPoints[-1].v_n = norm(vMan1)

        #Propagate to a new point
        self.AddOrbitPoint("1:399:3:33:30", 17739170771, 7823.5)
        rCheck, vCheck = propagate_lagrangian(
            self.OrbitPoints[-2].r, self.OrbitPoints[-2].v,
            self.OrbitPoints[-1].t - self.OrbitPoints[-2].t, self.mu_c)
        self.printVect(rCheck, "r2 pred")
        self.printVect(vCheck, "v2 pred")
        self.deltasAtPoint(norm(rCheck), norm(vCheck),
                           (self.OrbitPoints[-1].r_n),
                           (self.OrbitPoints[-1].v_n), "r check fromZero",
                           "v check fromZero")
        self.AddOrbitPoint("1:417:2:58:04", 18284938767, 7574.6)
        rCheck, vCheck = propagate_lagrangian(
            self.OrbitPoints[-3].r, self.OrbitPoints[-3].v,
            self.OrbitPoints[-1].t - self.OrbitPoints[-3].t, self.mu_c)
        self.printVect(rCheck, "r3 pred")
        self.printVect(vCheck, "v3 pred")
        self.deltasAtPoint(norm(rCheck), norm(vCheck),
                           (self.OrbitPoints[-1].r_n),
                           (self.OrbitPoints[-1].v_n), "r check2 fromZero",
                           "v check2 fromZero")

        #self.OrbitPoints[-3].r, self.OrbitPoints[-3].v = propagate_lagrangian(self.OrbitPoints[-3].r,self.OrbitPoints[-3].v,0,self.mu_c)

        plt.rcParams['savefig.dpi'] = 100
        ManT = 76  # manoevre time
        ManT_W = 5  # manoevre window
        Edy2s = 24 * 3600
        dy2s = 6 * 3600
        start_epochs = np.arange(ManT, (ManT + ManT_W), 0.25)
        ETA = 20
        ETA_W = 200
        duration = np.arange(ETA, (ETA + ETA_W), 0.25)

        data = list()
        v_data = list()
        r_data = list()
        v1_data = list()
        for start in start_epochs:
            row = list()
            v_row = list()
            r_row = list()
            v1_row = list()
            for T in duration:
                #Need to replace the kerbin start point by the ship at time t using
                r1, v1 = propagate_lagrangian(
                    self.OrbitPoints[-3].r, self.OrbitPoints[-3].v,
                    (start) * Edy2s - self.OrbitPoints[-3].t, self.mu_c)
                #r1,v1 = Kerbin.eph(epoch(start))
                r2, v2 = Duna.eph(epoch(start + T))
                l = lambert_problem(r1, r2, T * Edy2s,
                                    Kerbin.mu_central_body)  #K day = 6h
                DV1 = np.linalg.norm(array(v1) - array(l.get_v1()[0]))
                v_DV1 = array(v1) - array(l.get_v1()[0])

                #DV2 = np.linalg.norm( array(v2)-array(l.get_v2()[0]) )
                #DV1 = max([0,DV1-4000])
                #DV = DV1+DV2
                DV = DV1
                #DV = sqrt(dot(DV1, DV1) + 2 * Kerbin.mu_self / Kerbin.safe_radius) - sqrt(Kerbin.mu_self / Kerbin.safe_radius )
                r_row.append(r1)
                v1_row.append(v1)
                v_row.append(v_DV1)
                row.append(DV)
            data.append(row)
            v_data.append(v_row)
            r_data.append(r_row)
            v1_data.append(v1_row)

        minrows = [min(l) for l in data]
        i_idx = np.argmin(minrows)
        j_idx = np.argmin(data[i_idx])
        best = data[i_idx][j_idx]
        v_best = v_data[i_idx][j_idx]
        r1 = r_data[i_idx][j_idx]
        v1 = v1_data[i_idx][j_idx]

        progrd_uv = -array(v1) / linalg.norm(v1)

        plane_uv = cross(v1, r1)
        plane_uv = plane_uv / linalg.norm(plane_uv)
        radial_uv = cross(plane_uv, progrd_uv)
        EJBK = sqrt(
            dot(v_best, v_best) + 2 * Kerbin.mu_central_body /
            norm(r1)) - sqrt(Kerbin.mu_central_body / norm(r1))

        progrd_v = dot(progrd_uv, v_best)
        radial_v = dot(radial_uv, v_best)

        #print(rad2deg(atan(radial_v/progrd_v)))

        print("TransX escape plan - Kerbin escape")
        print("--------------------------------------")
        print("Best DV: " + str(best))
        print("Best DV heliocentric components:" + str(v_best))
        print("Launch epoch (K-days): " + str((start_epochs[i_idx]) * 4))
        print("Duration (K-days): " + str(duration[j_idx] * 4))
        print("Prograde:            %10.3f m/s" %
              np.round(dot(progrd_uv, v_best), 3))
        print("Radial:              %10.3f m/s" %
              np.round(dot(radial_uv, v_best), 3))
        print("Planar:              %10.3f m/s" %
              np.round(dot(plane_uv, v_best), 3))
        print("Hyp. excess velocity:%10.3f m/s" %
              np.round(sqrt(dot(v_best, v_best)), 3))
        #print("Earth escape burn:   %10.3f m/s" % np.round(EJBK, 3))

        duration_pl, start_epochs_pl = np.meshgrid(duration, start_epochs)
        plt.contour(start_epochs_pl * 4,
                    duration_pl * 4,
                    array(data),
                    levels=list(np.linspace(best, 3000, 12)))
        #plt.imshow(array(data).T, cmap=plt.cm.rainbow, origin = "lower", vmin = best, vmax = 5000, extent=[0.0, 850, 10, 470.0], interpolation='bilinear')

        #plt.colorbar(im);
        plt.colorbar()
        plt.show()
Ejemplo n.º 46
0
    def fitness(self, x):
        from pykep import epoch, AU, EARTH_VELOCITY, fb_con
        from pykep.sims_flanagan import leg, sc_state
        from numpy.linalg import norm
        from math import sqrt, asin, acos

        retval = [-x[10]]

        # Ephemerides
        t_E = epoch(x[0])
        t_V = epoch(x[0] + x[1])
        t_M = epoch(x[0] + x[1] + x[9])
        rE, vE = self.__earth.eph(t_E)
        rV, vV = self.__venus.eph(t_V)
        rM, vM = self.__mercury.eph(t_M)

        # First Leg
        v = [a + b for a, b in zip(vE, x[3:6])]
        x0 = sc_state(rE, v, self.__sc.mass)
        v = [a + b for a, b in zip(vV, x[6:9])]
        xe = sc_state(rV, v, x[2])
        self.__leg1.set(
            t_E, x0, x[-3 * (self.__nseg1 + self.__nseg2):-self.__nseg2 * 3], t_V, xe)

        # Second leg
        v = [a + b for a, b in zip(vV, x[11:14])]
        x0 = sc_state(rV, v, x[2])
        v = [a + b for a, b in zip(vM, x[14:17])]
        xe = sc_state(rM, v, x[10])
        self.__leg2.set(t_E, x0, x[(-3 * self.__nseg2):], t_V, xe)

        # Defining the constraints
        # departure
        v_dep_con = (x[3] * x[3] + x[4] * x[4] + x[5] * x[5] -
                     self.__Vinf_dep * self.__Vinf_dep) / (EARTH_VELOCITY * EARTH_VELOCITY)
        # arrival
        v_arr_con = (x[14] * x[14] + x[15] * x[15] + x[16] * x[16] -
                     self.__Vinf_arr * self.__Vinf_arr) / (EARTH_VELOCITY * EARTH_VELOCITY)
        # fly-by at Venus
        DV_eq, alpha_ineq = fb_con(x[6:9], x[11:14], self.__venus)

        # Assembling the constraints
        constraints = list(self.__leg1.mismatch_constraints() + self.__leg2.mismatch_constraints()) + [DV_eq] + list(
            self.__leg1.throttles_constraints() + self.__leg2.throttles_constraints()) + [v_dep_con] + [v_arr_con] + [alpha_ineq]

        # We then scale all constraints to non-dimensional values
        # leg 1
        constraints[0] /= AU
        constraints[1] /= AU
        constraints[2] /= AU
        constraints[3] /= EARTH_VELOCITY
        constraints[4] /= EARTH_VELOCITY
        constraints[5] /= EARTH_VELOCITY
        constraints[6] /= self.__sc.mass
        # leg 2
        constraints[7] /= AU
        constraints[8] /= AU
        constraints[9] /= AU
        constraints[10] /= EARTH_VELOCITY
        constraints[11] /= EARTH_VELOCITY
        constraints[12] /= EARTH_VELOCITY
        constraints[13] /= self.__sc.mass
        # fly-by at Venus
        constraints[14] /= (EARTH_VELOCITY * EARTH_VELOCITY)

        return retval + constraints
Ejemplo n.º 47
0
    def fitness(self, x):
        from pykep import epoch, AU, EARTH_VELOCITY, fb_con
        from pykep.sims_flanagan import leg, sc_state
        from numpy.linalg import norm
        from math import sqrt, asin, acos

        retval = [-x[10]]

        # Ephemerides
        t_E = epoch(x[0])
        t_V = epoch(x[0] + x[1])
        t_M = epoch(x[0] + x[1] + x[9])
        rE, vE = self.__earth.eph(t_E)
        rV, vV = self.__venus.eph(t_V)
        rM, vM = self.__mercury.eph(t_M)

        # First Leg
        v = [a + b for a, b in zip(vE, x[3:6])]
        x0 = sc_state(rE, v, self.__sc.mass)
        v = [a + b for a, b in zip(vV, x[6:9])]
        xe = sc_state(rV, v, x[2])
        self.__leg1.set(
            t_E, x0, x[-3 * (self.__nseg1 + self.__nseg2):-self.__nseg2 * 3], t_V, xe)

        # Second leg
        v = [a + b for a, b in zip(vV, x[11:14])]
        x0 = sc_state(rV, v, x[2])
        v = [a + b for a, b in zip(vM, x[14:17])]
        xe = sc_state(rM, v, x[10])
        self.__leg2.set(t_E, x0, x[(-3 * self.__nseg2):], t_V, xe)

        # Defining the constraints
        # departure
        v_dep_con = (x[3] * x[3] + x[4] * x[4] + x[5] * x[5] -
                     self.__Vinf_dep * self.__Vinf_dep) / (EARTH_VELOCITY * EARTH_VELOCITY)
        # arrival
        v_arr_con = (x[14] * x[14] + x[15] * x[15] + x[16] * x[16] -
                     self.__Vinf_arr * self.__Vinf_arr) / (EARTH_VELOCITY * EARTH_VELOCITY)
        # fly-by at Venus
        DV_eq, alpha_ineq = fb_con(x[6:9], x[11:14], self.__venus)

        # Assembling the constraints
        constraints = list(self.__leg1.mismatch_constraints() + self.__leg2.mismatch_constraints()) + [DV_eq] + list(
            self.__leg1.throttles_constraints() + self.__leg2.throttles_constraints()) + [v_dep_con] + [v_arr_con] + [alpha_ineq]

        # We then scale all constraints to non-dimensional values
        # leg 1
        constraints[0] /= AU
        constraints[1] /= AU
        constraints[2] /= AU
        constraints[3] /= EARTH_VELOCITY
        constraints[4] /= EARTH_VELOCITY
        constraints[5] /= EARTH_VELOCITY
        constraints[6] /= self.__sc.mass
        # leg 2
        constraints[7] /= AU
        constraints[8] /= AU
        constraints[9] /= AU
        constraints[10] /= EARTH_VELOCITY
        constraints[11] /= EARTH_VELOCITY
        constraints[12] /= EARTH_VELOCITY
        constraints[13] /= self.__sc.mass
        # fly-by at Venus
        constraints[14] /= (EARTH_VELOCITY * EARTH_VELOCITY)

        return retval + constraints
Ejemplo n.º 48
0
    def correctionBurn(self):
        plt.rcParams['savefig.dpi'] = 100
        ManT = 76  # manoevre time
        ManT_W = 200  # manoevre window
        Edy2s = 24 * 3600
        dy2s = 6 * 3600
        start_epochs = np.arange(ManT, (ManT + ManT_W), 0.25)
        ETA = 250
        ETA_W = 250
        duration = np.arange(ETA, (ETA + ETA_W), 0.25)
        '''        
        #these are Earth days, to *4 to Kdays (for eph function).

        
        #Sanity checks.
        r2,v2 = Duna.eph(epoch(312.8*0.25)) #check jool position
        print(norm(r2)-self.r_c)
        print(norm(v2))
        
        r1,v1 = propagate_lagrangian(self.OrbitPoints[-1].r,self.OrbitPoints[-1].v,312.8*dy2s,self.mu_c)        
        print(norm(r1)-self.r_c)
        print(norm(v1))       
        '''
        '''
        Solving the lambert problem. the function need times in Edays, so convert later to Kdays.
        Carefull with the Jool ephemeris, since kerbol year starts at y1 d1, substract 1Kday = 0.25Eday
        '''

        data = list()
        v_data = list()
        r_data = list()
        v1_data = list()
        for start in start_epochs:
            row = list()
            v_row = list()
            r_row = list()
            v1_row = list()
            for T in duration:
                #Need to replace the kerbin start point by the ship at time t using
                r1, v1 = propagate_lagrangian(self.OrbitPoints[-1].r,
                                              self.OrbitPoints[-1].v,
                                              (start) * Edy2s, self.mu_c)
                #r1,v1 = Kerbin.eph(epoch(start))
                r2, v2 = Jool.eph(epoch(start + T))
                l = lambert_problem(r1, r2, T * Edy2s,
                                    Kerbin.mu_central_body)  #K day = 6h
                DV1 = np.linalg.norm(array(v1) - array(l.get_v1()[0]))
                v_DV1 = array(v1) - array(l.get_v1()[0])

                #DV2 = np.linalg.norm( array(v2)-array(l.get_v2()[0]) )
                #DV1 = max([0,DV1-4000])
                #DV = DV1+DV2
                DV = DV1
                #DV = sqrt(dot(DV1, DV1) + 2 * Kerbin.mu_self / Kerbin.safe_radius) - sqrt(Kerbin.mu_self / Kerbin.safe_radius )
                r_row.append(r1)
                v1_row.append(v1)
                v_row.append(v_DV1)
                row.append(DV)
            data.append(row)
            v_data.append(v_row)
            r_data.append(r_row)
            v1_data.append(v1_row)

        minrows = [min(l) for l in data]
        i_idx = np.argmin(minrows)
        j_idx = np.argmin(data[i_idx])
        best = data[i_idx][j_idx]
        v_best = v_data[i_idx][j_idx]
        r1 = r_data[i_idx][j_idx]
        v1 = v1_data[i_idx][j_idx]

        progrd_uv = -array(v1) / linalg.norm(v1)

        plane_uv = cross(v1, r1)
        plane_uv = plane_uv / linalg.norm(plane_uv)
        radial_uv = cross(plane_uv, progrd_uv)
        EJBK = sqrt(
            dot(v_best, v_best) + 2 * Kerbin.mu_central_body /
            norm(r1)) - sqrt(Kerbin.mu_central_body / norm(r1))

        progrd_v = dot(progrd_uv, v_best)
        radial_v = dot(radial_uv, v_best)

        #print(rad2deg(atan(radial_v/progrd_v)))

        print("TransX escape plan - Kerbin escape")
        print("--------------------------------------")
        print("Best DV: " + str(best))
        print("Best DV heliocentric components:" + str(v_best))
        print("Launch epoch (K-days): " + str((start_epochs[i_idx]) * 4))
        print("Duration (K-days): " + str(duration[j_idx] * 4))
        print("Prograde:            %10.3f m/s" %
              np.round(dot(progrd_uv, v_best), 3))
        print("Radial:              %10.3f m/s" %
              np.round(dot(radial_uv, v_best), 3))
        print("Planar:              %10.3f m/s" %
              np.round(dot(plane_uv, v_best), 3))
        print("Hyp. excess velocity:%10.3f m/s" %
              np.round(sqrt(dot(v_best, v_best)), 3))
        #print("Earth escape burn:   %10.3f m/s" % np.round(EJBK, 3))

        duration_pl, start_epochs_pl = np.meshgrid(duration, start_epochs)
        plt.contour(start_epochs_pl * 4,
                    duration_pl * 4,
                    array(data),
                    levels=list(np.linspace(best, 3000, 12)))
        #plt.imshow(array(data).T, cmap=plt.cm.rainbow, origin = "lower", vmin = best, vmax = 5000, extent=[0.0, 850, 10, 470.0], interpolation='bilinear')

        #plt.colorbar(im);
        plt.colorbar()
        plt.show()
Ejemplo n.º 49
0
            tof=tof,
            vinf=[0.5, 2.5],
            add_vinf_dep=False,
            add_vinf_arr=True,
            tof_encoding=tof_encoding,
            multi_objective=False)

    def get_name(self):
        return "Earth-Venus-Earth mga-1dsm (Trajectory Optimisation Gym P7-9)"

    def get_extra_info(self):
        retval = "\ttof_encoding: " + self._tof_encoding
        return retval

    def __repr__(self):
        return self.get_name()


# Problem P7: Earth-Venus-Earth MGA1DSM, single objective , direct encoding
eve_mga1dsm = _eve_mga1dsm_udp(tof_encoding='direct',
                               t0=[epoch(0), epoch(3000)],
                               tof=[[10, 500], [10, 500]])
# Problem P8: Earth-Venus-Earth MGA1DSM, single objective , alpha encoding
eve_mga1dsm_a = _eve_mga1dsm_udp(tof_encoding='alpha',
                                 t0=[epoch(0), epoch(3000)],
                                 tof=[300, 700])
# Problem P9: Earth-Venus-Earth MGA1DSM, single objective , eta encoding
eve_mga1dsm_n = _eve_mga1dsm_udp(tof_encoding='eta',
                                 t0=[epoch(0), epoch(3000)],
                                 tof=700)
Ejemplo n.º 50
0
    def __init__(self,
                 seq=[pk.planet.jpl_lp('earth'), pk.planet.jpl_lp(
                     'venus'), pk.planet.jpl_lp('earth')],
                 t0=[0, 1000],
                 tof=[100, 500],
                 vinf=2.5,
                 multi_objective=False,
                 tof_encoding='direct',
                 orbit_insertion=False,
                 e_target=None,
                 rp_target=None
                 ):
        """mga(seq=[pk.planet.jpl_lp('earth'), pk.planet.jpl_lp('venus'), pk.planet.jpl_lp('earth')], t0=[0, 1000], tof=[100, 500], vinf=2.5, multi_objective=False, alpha_encoding=False, orbit_insertion=False, e_target=None, rp_target=None)

        Args:
            - seq (``list of pk.planet``): sequence of body encounters including the starting object
            - t0 (``list of pk.epoch``): the launch window
            - tof (``list`` or ``float``): bounds on the time of flight. If *tof_encoding* is 'direct', this contains a list
              of 2D lists defining the upper and lower bounds on each leg. If *tof_encoding* is 'alpha',
              this contains a 2D list with the lower and upper bounds on the time-of-flight. If *tof_encoding*
              is 'eta' tof is a float defining the upper bound on the time-of-flight
            - vinf (``float``): the vinf provided at launch for free
            - multi_objective (``bool``): when True constructs a multiobjective problem (dv, T). In this case, 'alpha' or `eta` encodings are reccomended
            - tof_encoding (``str``): one of 'direct', 'alpha' or 'eta'. Selects the encoding for the time of flights
            - orbit_insertion (``bool``): when True the arrival dv is computed as that required to acquire a target orbit defined by e_target and rp_target
            - e_target (``float``): if orbit_insertion is True this defines the target orbit eccentricity around the final planet
            - rp_target (``float``): if orbit_insertion is True this defines the target orbit pericenter around the final planet

        Raises:
            - ValueError: if *planets* do not share the same central body (checked on the mu_central_body attribute)
            - ValueError: if *t0* does not contain objects able to construct a pk.epoch (e.g. pk. epoch or floats)
            - ValueError: if *tof* is badly defined
            - ValueError: it the target orbit is not defined and *orbit_insertion* is True
        """

        # Sanity checks
        # 1 - All planets need to have the same mu_central_body
        if ([r.mu_central_body for r in seq].count(seq[0].mu_central_body) != len(seq)):
            raise ValueError(
                'All planets in the sequence need to have exactly the same mu_central_body')
        # 2 - We try to build epochs out of the t0 list (mjd2000 by default)
        for i in range(len(t0)):
            if (type(t0[i]) != type(pk.epoch(0))):
                t0[i] = pk.epoch(t0[i])
        # 3 - Check the tof bounds
        if tof_encoding is 'alpha':
            if len(tof) != 2:
                raise ValueError(
                    'When tof_encoding is alpha, the tof must have a length of 2 (lower and upper bounds on the tof)')
        elif tof_encoding is 'direct':
            if len(tof) != (len(seq) - 1):
                raise ValueError(
                    'When tof_encoding is direct, the tof must be a float (upper bound on the time of flight)' + str(len(seq) - 1))
        elif tof_encoding is 'eta':
            if type(tof) != type(0.1):
                raise ValueError(
                    'The tof needs to be have len equal to  ' + str(len(seq) - 1))
        if not tof_encoding in ['alpha', 'eta', 'direct']:
            raise ValueError(
                "tof_encoding must be one of 'alpha', 'eta', 'direct'")

        # 4 - Check that if orbit insertion is selected e_target and r_p are
        # defined
        if orbit_insertion:
            if rp_target is None:
                raise ValueError(
                    'The rp_target needs to be specified when orbit insertion is selected')
            if e_target is None:
                raise ValueError(
                    'The e_target needs to be specified when orbit insertion is selected')

        # Public data members
        self.seq = seq
        self.t0 = t0
        self.tof = tof
        self.vinf = vinf * 1000
        self.multi_objective = multi_objective
        self.tof_encoding = tof_encoding
        self.orbit_insertion = orbit_insertion
        self.e_target = e_target
        self.rp_target = rp_target

        # Private data members
        self._n_legs = len(seq) - 1
        self._common_mu = seq[0].mu_central_body
Ejemplo n.º 51
0
    def __init__(self,
                 target=pk.planet.mpcorb(mpcorbline),
                 n_seg=30,
                 grid_type="uniform",
                 t0=[pk.epoch(8000), pk.epoch(9000)],
                 tof=[200, 365.25 * 3],
                 m0=20.0,
                 Tmax=0.0017,
                 Isp=3000.0,
                 earth_gravity=False,
                 sep=False,
                 start="earth"):
        """
        prob = lt_margo(target = pk.planet.mpcorb(mpcorbline), n_seg = 30, grid_type = "uniform", t0 = [epoch(8000), epoch(9000)], tof = [200, 365.25*3], m0 = 20.0, Tmax = 0.0017, Isp = 3000.0, earth_gravity = False, sep = False, start = "earth")

        Args:
            - target (``pykep.planet``): target planet
            - n_seg (``int``): number of segments to use in the problem transcription (time grid)
            - grid_type (``string``): "uniform" for uniform segments, "nonuniform" toi use a denser grid in the first part of the trajectory
            - t0 (``list``): list of two pykep.epoch defining the bounds on the launch epoch
            - tof (``list``): list of two floats defining the bounds on the time of flight (days)
            - m0 (``float``): initial mass of the spacecraft (kg)
            - Tmax (``float``): maximum thrust at 1 AU (N)
            - Isp (``float``): engine specific impulse (s)
            - earth_gravity (``bool``): activates the Earth gravity effect in the dynamics
            - sep (``bool``): Activates a Solar Electric Propulsion model for the thrust - distance dependency.
            - start(``string``): Starting point ("earth", "l1", or "l2").

        .. note::

           L1 and L2 are approximated as the points on the line connecting the Sun and the Earth at a distance of, respectively, 0.99 and 1.01 AU from the Sun.

        .. note::

           If the Earth's gravity is enabled, the starting point cannot be the Earth
        """

        # 1) Various checks
        if start not in ["earth", "l1", "l2"]:
            raise ValueError("start must be either 'earth', 'l1' or 'l2'")
        if grid_type not in ["uniform", "nonuniform"]:
            raise ValueError(
                "grid_type must be either 'uniform' or 'nonuniform'")
        if earth_gravity and start == "earth":
            raise ValueError(
                "If Earth gravity is enabled the starting point cannot be the Earth")

        # 2) Class data members
        # public:
        self.target = target
        # private:
        self.__n_seg = n_seg
        self.__grid_type = grid_type
        self.__sc = pk.sims_flanagan._sims_flanagan.spacecraft(m0, Tmax, Isp)
        self.__earth = pk.planet.jpl_lp('earth')
        self.__earth_gravity = earth_gravity
        self.__sep = sep
        self.__start = start
        # grid construction
        if grid_type == "uniform":
            grid = np.array([i / n_seg for i in range(n_seg + 1)])
        elif grid_type == "nonuniform":
            grid_f = lambda x: x**2 if x < 0.5 else 0.25 + 1.5 * \
                (x - 0.5)  # quadratic in [0,0.5], linear in [0.5,1]
            grid = np.array([grid_f(i / n_seg) for i in range(n_seg + 1)])
        # index corresponding to the middle of the transfer
        fwd_seg = int(np.searchsorted(grid, 0.5, side='right'))
        bwd_seg = n_seg - fwd_seg
        fwd_grid = grid[:fwd_seg + 1]
        bwd_grid = grid[fwd_seg:]
        self.__fwd_seg = fwd_seg
        self.__fwd_grid = fwd_grid
        self.__fwd_dt = np.array([(fwd_grid[i + 1] - fwd_grid[i])
                                  for i in range(fwd_seg)]) * pk.DAY2SEC
        self.__bwd_seg = bwd_seg
        self.__bwd_grid = bwd_grid
        self.__bwd_dt = np.array([(bwd_grid[i + 1] - bwd_grid[i])
                                  for i in range(bwd_seg)]) * pk.DAY2SEC

        # 3) Bounds
        lb = [t0[0].mjd2000] + [tof[0]] + [0] + [-1, -1, -1] * n_seg
        ub = [t0[1].mjd2000] + [tof[1]] + [m0] + [1, 1, 1] * n_seg
        self.__lb = lb
        self.__ub = ub
Ejemplo n.º 52
0
    def plot_traj(self, x, units=pk.AU, plot_segments=True, plot_thrusts=False, axes=None):
        """
        ax = prob.plot_traj(self, x, units=AU, plot_segments=True, plot_thrusts=False, axes=None)

        Args:
            - x (``list``, ``tuple``, ``numpy.ndarray``): Decision chromosome, e.g. (``pygmo.population.champion_x``).
            - units (``float``): the length unit to be used in the plot
            - plot_segments (``bool``): when True plots also the segments boundaries
            - plot_thrusts (``bool``): when True plots also the thrust vectors

        Returns:
            matplotlib.axes: axes where to plot

        Visualizes the the trajectory in a 3D plot
        """

        if not len(x) == len(self.get_bounds()[0]):
            raise ValueError("Invalid length of the decision vector x")

        import matplotlib as mpl
        import matplotlib.pyplot as plt
        from mpl_toolkits.mplot3d import Axes3D

        # Creating the axes if necessary
        if axes is None:
            mpl.rcParams['legend.fontsize'] = 10
            fig = plt.figure()
            axes = fig.gca(projection='3d')

        n_seg = self.__n_seg
        fwd_seg = self.__fwd_seg
        bwd_seg = self.__bwd_seg
        t0 = x[0]
        T = x[1]
        isp = self.__sc.isp
        veff = isp * pk.G0
        fwd_grid = t0 + T * self.__fwd_grid  # days
        bwd_grid = t0 + T * self.__bwd_grid  # days

        throttles = [x[3 + 3 * i: 6 + 3 * i] for i in range(n_seg)]
        alphas = [min(1., np.linalg.norm(t)) for t in throttles]

        times = np.concatenate((fwd_grid, bwd_grid))

        rfwd, rbwd, vfwd, vbwd, mfwd, mbwd, ufwd, ubwd, fwd_dt, bwd_dt, dfwd, dbwd = self._propagate(
            x)

        # Plotting the Sun, the Earth and the target
        axes.scatter([0], [0], [0], color='y')
        pk.orbit_plots.plot_planet(self.__earth, pk.epoch(
            t0), units=units, legend=True, color=(0.7, 0.7, 1), ax=axes)
        pk.orbit_plots.plot_planet(self.target, pk.epoch(
            t0 + T), units=units, legend=True, color=(0.7, 0.7, 1), ax=axes)

        # Forward propagation
        xfwd = [0.0] * (fwd_seg + 1)
        yfwd = [0.0] * (fwd_seg + 1)
        zfwd = [0.0] * (fwd_seg + 1)
        xfwd[0] = rfwd[0][0] / units
        yfwd[0] = rfwd[0][1] / units
        zfwd[0] = rfwd[0][2] / units

        for i in range(fwd_seg):
            if self.__sep:
                r = math.sqrt(rfwd[i][0]**2 + rfwd[i][1]
                              ** 2 + rfwd[i][2]**2) / pk.AU
                _, isp = self._sep_model(r)
                veff = isp * pk.G0
            if self.__earth_gravity:
                r3 = sum([r**2 for r in dfwd[i]])**(3 / 2)
                disturbance = [mfwd[i] * pk.MU_EARTH /
                               r3 * ri for ri in dfwd[i]]
                pk.orbit_plots.plot_taylor_disturbance(rfwd[i], vfwd[i], mfwd[i], ufwd[i], disturbance, fwd_dt[
                                                       i], pk.MU_SUN, veff, N=10, units=units, color=(alphas[i], 0, 1 - alphas[i]), ax=axes)
            else:
                pk.orbit_plots.plot_taylor(rfwd[i], vfwd[i], mfwd[i], ufwd[i], fwd_dt[
                                           i], pk.MU_SUN, veff, N=10, units=units, color=(alphas[i], 0, 1 - alphas[i]), ax=axes)
            xfwd[i + 1] = rfwd[i + 1][0] / units
            yfwd[i + 1] = rfwd[i + 1][1] / units
            zfwd[i + 1] = rfwd[i + 1][2] / units
        if plot_segments:
            axes.scatter(xfwd[:-1], yfwd[:-1], zfwd[:-1],
                         label='nodes', marker='o', s=5, c='k')

        # Backward propagation
        xbwd = [0.0] * (bwd_seg + 1)
        ybwd = [0.0] * (bwd_seg + 1)
        zbwd = [0.0] * (bwd_seg + 1)
        xbwd[-1] = rbwd[-1][0] / units
        ybwd[-1] = rbwd[-1][1] / units
        zbwd[-1] = rbwd[-1][2] / units

        for i in range(bwd_seg):
            if self.__sep:
                r = math.sqrt(rbwd[-i - 1][0]**2 + rbwd[-i - 1]
                              [1]**2 + rbwd[-i - 1][2]**2) / pk.AU
                _, isp = self._sep_model(r)
                veff = isp * pk.G0
            if self.__earth_gravity:
                r3 = sum([r**2 for r in dbwd[-i - 1]])**(3 / 2)
                disturbance = [mfwd[i] * pk.MU_EARTH /
                               r3 * ri for ri in dbwd[-i - 1]]
                pk.orbit_plots.plot_taylor_disturbance(rbwd[-i - 1], vbwd[-i - 1], mbwd[-i - 1], ubwd[-i - 1], disturbance, -bwd_dt[
                                                       -i - 1], pk.MU_SUN, veff, N=10, units=units, color=(alphas[-i - 1], 0, 1 - alphas[-i - 1]), ax=axes)
            else:
                pk.orbit_plots.plot_taylor(rbwd[-i - 1], vbwd[-i - 1], mbwd[-i - 1], ubwd[-i - 1], -bwd_dt[-i - 1],
                                           pk.MU_SUN, veff, N=10, units=units, color=(alphas[-i - 1], 0, 1 - alphas[-i - 1]), ax=axes)
            xbwd[-i - 2] = rbwd[-i - 2][0] / units
            ybwd[-i - 2] = rbwd[-i - 2][1] / units
            zbwd[-i - 2] = rbwd[-i - 2][2] / units
        if plot_segments:
            axes.scatter(xbwd[1:], ybwd[1:], zbwd[1:], marker='o', s=5, c='k')

        # Plotting the thrust vectors
        if plot_thrusts:
            throttles = np.array(throttles)
            xlim = axes.get_xlim()
            xrange = xlim[1] - xlim[0]
            ylim = axes.get_ylim()
            yrange = ylim[1] - ylim[0]
            zlim = axes.get_zlim()
            zrange = zlim[1] - zlim[0]

            scale = 0.1

            throttles[:, 0] *= xrange
            throttles[:, 1] *= yrange
            throttles[:, 2] *= zrange

            throttles *= scale

            for (x, y, z, t) in zip(xfwd[:-1] + xbwd[:-1], yfwd[:-1] + ybwd[:-1], zfwd[:-1] + zbwd[:-1], throttles):
                axes.plot([x, x + t[0]], [y, y + t[1]], [z, z + t[2]], c='g')

        return axes
    # http://en.wikipedia.org/wiki/Orbital_period#Calculation


# Instantiating PyKEP planet objects for each of the bodies (and making them indexable by body name)
# http://keptoolbox.sourceforge.net/documentation.html#PyKEP.planet

_planet = pk.planet.keplerian
### Problem is with the planet consutrctor or smth.

body_obj = OrderedDict([
    (
        _b.body,
        _planet(
            # when
            # 	a PyKEP.epoch indicating the orbital elements epoch
            pk.epoch(_b.Epoch),  #, pk.epoch.epoch_type.MJD ),

            # orbital_elements
            # 	a sequence of six containing a,e,i,W,w,M (SI units, i.e. meters and radiants)
            (
                _b.a * 1000.,
                _b.e,
                radians(_b.i),
                radians(_b.Node),
                radians(_b.w),
                _b.M,
            ),

            # mu_central_body
            # 	gravity parameter of the central body (SI units, i.e. m^2/s^3)
            _b.mu_c * 1000.**3,
Ejemplo n.º 54
0
# asteroid. The second asteroid encounter (fly-by) corresponds to the delivery
# of a 1 kg penetrator."
MASS_EQUIPMENT = 40.0
MASS_PENETRATOR = 1.0

# constraint for the flyby to deliver the penetrator:
# "flyby asteroid with a velocity not less than dV_min = 0.4 km/s."
dV_fb_min = 400.0  # m/s


# "The flight time, measured from start to the end must not exceed 15 years"
TIME_MAX = 15 * YEAR2DAY  # 5478.75 days

# "The year of launch must lie in the range 2015 to 2025, inclusive:
# 57023 MJD <= t_s <= 61041 MJD."
TRAJ_START_MIN = pk.epoch(57023, "mjd")
TRAJ_START_MAX = pk.epoch(61041, "mjd")
# >>> TRAJ_START_MIN, TRAJ_START_MAX
# (2015-Jan-01 00:00:00, 2026-Jan-01 00:00:00)

TRAJ_END_MIN = pk.epoch(TRAJ_START_MIN.mjd + TIME_MAX, "mjd")
TRAJ_END_MAX = pk.epoch(TRAJ_START_MAX.mjd + TIME_MAX, "mjd")
# >>> TRAJ_END_MIN, TRAJ_END_MAX
# (2029-Dec-31 18:00:00, 2040-Dec-31 18:00:00)


# ==================================== # GTOC5 asteroids (body objects)

# Earth's Keplerian orbital parameters
# Source: http://dx.doi.org/10.2420/AF08.2014.9 (Table 1)
_earth_op = (
Ejemplo n.º 55
0
def lpop_single(target_mjd):
    return pykep_satellite.eph(pykep.epoch(target_mjd, 'mjd'))
Ejemplo n.º 56
0
for qq in range(1, numOfExperiments + 1):
    satcat = loadData_satcat()
    debris = loadData_tle()

    # list of all EU states and ESA and its bodies
    EU_list = [
        "EU", "ASRA", "BEL", "CZCH", "DEN", "ESA", "ESRO", "EST", "EUME",
        "EUTE", "FGER", "FR", "FRIT", "GER", "GREC", "HUN", "IT", "LTU",
        "LUXE", "NETH", "NOR", "POL", "POR", "SPN", "SWED", "SWTZ", "UK"
    ]
    agentList = ['CIS', 'US', 'PRC', 'EU']
    agentListWithEU = ['CIS', 'US', 'PRC', EU_list]

    #  filtering only objects in LEO
    debris_LEO = []
    ep = kep.epoch(16. * 365.25)
    for p in debris:
        try:
            oe = p.osculating_elements(ep)
            if oe[0] * (1 - oe[1]) < 6378000.0 + 2000000:
                debris_LEO.append(p)
        except:
            pass
    debris = debris_LEO
    logger.info(len(debris))

    # osculating elements distributions
    oe_histograms = []
    oe_histograms = findHistograms(agentListWithEU)
    yearLaunchesDistributions = oe_histograms[10]
Ejemplo n.º 57
0
    def _propagate(self, x):
        # 1 - We decode the chromosome
        t0 = x[0]
        T = x[1]
        m_f = x[2]
        # We extract the number of segments for forward and backward
        # propagation
        n_seg = self.__n_seg
        fwd_seg = self.__fwd_seg
        bwd_seg = self.__bwd_seg
        # We extract information on the spacecraft
        m_i = self.__sc.mass
        max_thrust = self.__sc.thrust
        isp = self.__sc.isp
        veff = isp * pk.G0
        # And on the leg
        throttles = [x[3 + 3 * i: 6 + 3 * i] for i in range(n_seg)]
        # Return lists
        n_points_fwd = fwd_seg + 1
        n_points_bwd = bwd_seg + 1
        rfwd = [[0.0] * 3] * (n_points_fwd)
        vfwd = [[0.0] * 3] * (n_points_fwd)
        mfwd = [0.0] * (n_points_fwd)
        ufwd = [[0.0] * 3] * (fwd_seg)
        dfwd = [[0.0] * 3] * (fwd_seg)  # distances E/S
        rbwd = [[0.0] * 3] * (n_points_bwd)
        vbwd = [[0.0] * 3] * (n_points_bwd)
        mbwd = [0.0] * (n_points_bwd)
        ubwd = [[0.0] * 3] * (bwd_seg)
        dbwd = [[0.0] * 3] * (bwd_seg)

        # 2 - We compute the initial and final epochs and ephemerides
        t_i = pk.epoch(t0)
        r_i, v_i = self.__earth.eph(t_i)
        if self.__start == 'l1':
            r_i = [r * 0.99 for r in r_i]
            v_i = [v * 0.99 for v in v_i]
        elif self.__start == 'l2':
            r_i = [r * 1.01 for r in r_i]
            v_i = [v * 1.01 for v in v_i]
        t_f = pk.epoch(t0 + T)
        r_f, v_f = self.target.eph(t_f)

        # 3 - Forward propagation
        fwd_grid = t0 + T * self.__fwd_grid  # days
        fwd_dt = T * self.__fwd_dt  # seconds
        # Initial conditions
        rfwd[0] = r_i
        vfwd[0] = v_i
        mfwd[0] = m_i
        # Propagate
        for i, t in enumerate(throttles[:fwd_seg]):
            if self.__sep:
                r = math.sqrt(rfwd[i][0]**2 + rfwd[i][1]
                              ** 2 + rfwd[i][2]**2) / pk.AU
                max_thrust, isp = self._sep_model(r)
                veff = isp * pk.G0
            ufwd[i] = [max_thrust * thr for thr in t]
            if self.__earth_gravity:
                r_E, v_E = self.__earth.eph(pk.epoch(fwd_grid[i]))
                dfwd[i] = [a - b for a, b in zip(r_E, rfwd[i])]
                r3 = sum([r**2 for r in dfwd[i]])**(3 / 2)
                disturbance = [mfwd[i] * pk.MU_EARTH /
                               r3 * ri for ri in dfwd[i]]
                rfwd[i + 1], vfwd[i + 1], mfwd[i + 1] = pk.propagate_taylor_disturbance(
                    rfwd[i], vfwd[i], mfwd[i], ufwd[i], disturbance, fwd_dt[i], pk.MU_SUN, veff, -10, -10)
            else:
                rfwd[i + 1], vfwd[i + 1], mfwd[i + 1] = pk.propagate_taylor(
                    rfwd[i], vfwd[i], mfwd[i], ufwd[i], fwd_dt[i], pk.MU_SUN, veff, -10, -10)

        # 4 - Backward propagation
        bwd_grid = t0 + T * self.__bwd_grid  # days
        bwd_dt = T * self.__bwd_dt  # seconds
        # Final conditions
        rbwd[-1] = r_f
        vbwd[-1] = v_f
        mbwd[-1] = m_f
        # Propagate
        for i, t in enumerate(throttles[-1:-bwd_seg - 1:-1]):
            if self.__sep:
                r = math.sqrt(rbwd[-i - 1][0]**2 + rbwd[-i - 1]
                              [1]**2 + rbwd[-i - 1][2]**2) / pk.AU
                max_thrust, isp = self._sep_model(r)
                veff = isp * pk.G0
            ubwd[-i - 1] = [max_thrust * thr for thr in t]
            if self.__earth_gravity:
                r_E, v_E = self.__earth.eph(pk.epoch(bwd_grid[-i - 1]))
                dbwd[-i - 1] = [a - b for a, b in zip(r_E, rbwd[-i - 1])]
                r3 = sum([r**2 for r in dbwd[-i - 1]])**(3 / 2)
                disturbance = [mfwd[i] * pk.MU_EARTH /
                               r3 * ri for ri in dbwd[-i - 1]]
                rbwd[-i - 2], vbwd[-i - 2], mbwd[-i - 2] = pk.propagate_taylor_disturbance(
                    rbwd[-i - 1], vbwd[-i - 1], mbwd[-i - 1], ubwd[-i - 1], disturbance, -bwd_dt[-i - 1], pk.MU_SUN, veff, -10, -10)
            else:
                rbwd[-i - 2], vbwd[-i - 2], mbwd[-i - 2] = pk.propagate_taylor(
                    rbwd[-i - 1], vbwd[-i - 1], mbwd[-i - 1], ubwd[-i - 1], -bwd_dt[-i - 1], pk.MU_SUN, veff, -10, -10)

        return rfwd, rbwd, vfwd, vbwd, mfwd, mbwd, ufwd, ubwd, fwd_dt, bwd_dt, dfwd, dbwd
Ejemplo n.º 58
0
def from_mjd_to_datetime(mjd_date):
    e = pykep.epoch(mjd_date, 'mjd')
    return datetime.datetime.strptime(str(e), '%Y-%b-%d %H:%M:%S.%f')
Ejemplo n.º 59
0
        self.SMA = (self.Pe + self.Ap) / 2
        self.e = 1 - 2 * self.Pe / (self.Pe + self.Ap)
        self.t0 = 0
        self.t1 = 0
        self.r0 = 0
        self.r1 = 0
        self.v0 = 0
        self.v1 = 0
        self.N = sqrt(Kerbin.mu_c / (self.SMA ^ 3))

    def setT0(self, year, day, hour, minute, second):
        h2s = 3600
        d2s = 6 * h2s
        y2s = 2556.5 * h2s
        self.t0 = year * y2s + day * d2s + hour * h2s + minute * 60 + second

    def setT1(self, year, day, hour, minute, second):
        h2s = 3600
        d2s = 6 * h2s
        y2s = 2556.5 * h2s
        self.t0 = year * y2s + day * d2s + hour * h2s + minute * 60 + second

    def EccAnom(self):
        K = PI / 180
        max_i = 50
        i = 0
        delta = 0.0001


plot_innerKerbol(epoch(100))