Esempio n. 1
0
    def set_boundary_cond(self, BC):
        """Setter for attribute BC.

                Args:
                    BC (utils.BoundaryConditions): constraints for two-point boundary value problem.

        """

        self.BC = utils.BoundaryConditions(BC.nu0, BC.nuf, BC.x0, BC.xf)
        self.plotter.set_boundary_cond(BC)
Esempio n. 2
0
    def run(self, BC):
        """Wrapper for all solving strategies (analytical, numerical and both).

                Args:
                    BC (utils.BoundaryConditions): constraints for two-point boundary value problem.

                Returns:
                     (utils.ControlLaw): optimal control law.

        """

        if BC.half_dim == 1 and self.prop_ana:  # out-of-plane analytical solving
            if self.dyn.mu != 0 and self.dyn.ecc == 0. and (
                    self.dyn.Li == 1 or self.dyn.Li == 2 or self.dyn.Li == 3):
                # special case of circular out-of-plane L1, 2 or 3 where analytical solution can be obtained from
                # 2-body solution by rescaling anomaly
                return self._circular_oop_L123(BC)
            else:  # out-of-plane for elliptical 2-body problem or elliptical 3-body around L4 and 5 or circular around L1, 2 and 3
                z = self.dyn.compute_rhs(BC, analytical=self.prop_ana)
                (nus, DVs, lamb) = solver_ana(z, self.dyn.ecc,
                                              self.dyn.mean_motion, BC.nu0,
                                              BC.nuf)
                return utils.ControlLaw(BC.half_dim, nus, DVs, lamb)

        elif (BC.half_dim == 3) and (
                self.p == 1
        ):  # merge analytical and numerical solutions in the case of complete
            #  dynamics with the 1-norm
            x0_ip, x0_oop = unstack_state(BC.x0)
            xf_ip, xf_oop = unstack_state(BC.xf)
            BC_oop = utils.BoundaryConditions(BC.nu0, BC.nuf, x0_oop, xf_oop)
            CL_oop = self.run(BC_oop)
            BC_ip = utils.BoundaryConditions(BC.nu0, BC.nuf, x0_ip, xf_ip)
            CL_ip = self.run(BC_ip)
            return utils.merge_control(CL_ip, CL_oop)

        else:  # numerical solving
            return self.indirect_num(BC)
Esempio n. 3
0
    def __init__(self, indirect, p, plr):
        """Constructor for class master.

                Args:
                    indirect (bool): set to True for indirect approach and False for direct one.
                    p (int): type of norm to be minimized.
                    plr (plotter.Plotter): plotter object for plotting.

        """

        self.BC = utils.BoundaryConditions(plr.BC.nu0, plr.BC.nuf, plr.BC.x0,
                                           plr.BC.xf)
        self.plotter = plotter.Plotter(plr.dyn, plr.BC, plr.p, plr.anomaly,
                                       plr.linearized, plr.analytical)
        self.CL = utils.NoControl(self.BC.half_dim)
        if indirect:
            self._solver = indirect_solver.IndirectSolver(
                self.plotter.dyn, p, plr.analytical)
        else:  # direct approach chosen
            self._solver = direct_solver.DirectSolver(self.plotter.dyn, p,
                                                      plr.analytical)
Esempio n. 4
0
    def __init__(self, dyn, BC, p, anomaly, linearized, analytical, CL=None):
        """Constructor for class plotter.

                Args:
                    dyn (dynamical_system.DynamicalSystem): dynamics to be used for two-boundary value problem.
                    BC (utils.BoundaryConditions): constraints for two-point boundary value problem.
                    p (int): type of norm for control law to be plotted.
                    anomaly (bool): set to True if independent variable is the true anomaly and to False if it is time.
                    linearized (bool): set to True to plot linearized dynamics, False otherwise
                    analytical (bool): set to True to propagate the state vector analytically if possible, False otherwise
                    CL (utils.ControlLaw): control law to be simulated.

        """

        self.p = p
        self._q = indirect_num.dual_to_primal_norm_type(p)
        self.dyn = dynamical_system.DynamicalSystem(dyn.mu, dyn.ecc,
                                                    dyn.period, dyn.sma,
                                                    dyn.Li)
        self.BC = utils.BoundaryConditions(BC.nu0, BC.nuf, BC.x0, BC.xf)
        if CL is None:
            self.CL = utils.NoControl(BC.half_dim)
        self.linearized = linearized
        self.anomaly = anomaly
        if analytical and dyn.mu != 0. and dyn.ecc != 0. and (
                dyn.Li == 1 or dyn.Li == 2 or dyn.Li == 3 or BC.half_dim > 1):
            print(
                'WARNING: propagation type within plotter changed to numerical'
            )
            self.analytical = False
        else:  # propagation has to be numerical for elliptical out-of-plane L1, 2 or 3 or elliptical in-plane of any LP
            self.analytical = analytical

        self._nb = plot_params["mesh_plot"]
        self._nus = None
        self._times = None
        self._pts = None
        self._compute_points()

        self._states = None
Esempio n. 5
0
    def _circular_oop_L123(self, BC):
        """Function computing the optimal control law analytically in the special case of out-of-plane dynamics
        in the circular L1, 2 or 3.

                Args:
                    BC (utils.BoundaryConditions): constraints for two-point boundary value problem.

                Returns:
                     (utils.ControlLaw): analytical optimal control law.

        """

        # getting scaling factor for time
        puls = orbital_mechanics.puls_oop_LP(self.dyn.x_eq_normalized,
                                             self.dyn.mu)

        # scaling inputs
        BC_rescaled = utils.BoundaryConditions(BC.nu0 * puls, BC.nuf * puls,
                                               BC.x0, BC.xf)
        dyn_rescaled = dynamical_system.DynamicalSystem(
            0., 0., self.dyn.period / puls, self.dyn.sma)
        z_rescaled = dyn_rescaled.compute_rhs(BC_rescaled, analytical=True)

        # 'classic' call to numerical solver
        (nus, DVs, lamb) = solver_ana(z_rescaled, 0., dyn_rescaled.mean_motion,
                                      BC_rescaled.nu0, BC_rescaled.nuf)

        factor = linalg.norm(self.dyn.compute_rhs(
            BC, analytical=True)) / linalg.norm(z_rescaled)

        # un-scaling
        for k in range(0, len(nus)):
            nus[k] /= puls
        for k in range(0, len(lamb)):
            lamb[k] /= factor

        return utils.ControlLaw(BC.half_dim, nus, DVs, lamb)
Esempio n. 6
0
)  # 3-body restricted dynamics is linearized around Earth-Moon Lagrange Point 4

hd = 3  # half-dimension of state vector (1 for out-of-plane dynamics only, 2 for in-plane only and 3 for complete)
x0 = numpy.zeros(hd * 2)
xf = numpy.zeros(hd * 2)
for i in range(0, len(x0)):
    if i < hd:
        x0[i] = (-1.0 + 2.0 * random.random()) * 1.0e3
        xf[i] = (-1.0 + 2.0 * random.random()) * 1.0e3
    else:
        x0[i] = (-1.0 + 2.0 * random.random()) * 1.0e3 * math.pi / dyn.period
        xf[i] = (-1.0 + 2.0 * random.random()) * 1.0e3 * math.pi / dyn.period

p = 2  # norm for minimization (1 or 2)

BC = utils.BoundaryConditions(nu0, nuf, x0, xf)
plr = plotter.Plotter(dyn,
                      BC,
                      p,
                      anomaly=True,
                      linearized=True,
                      analytical=True)
master = master.Master(indirect=True, p=p, plr=plr)

t1 = time.time()
master.solve()
print("Time elapsed with indirect approach: " + str(time.time() - t1) + " s")
master.plot()
master.write_boundary_cond("boundary_conditions_compa_approach.txt")
master.write_control_law("control_law_indirect.txt")
Esempio n. 7
0
    def compute_rhs(self, BC, analytical):
        """Function that computes right-hand side of moment equation.

                Args:
                    BC (utils.BoundaryConditions): constraints for two-point boundary value problem.
                    analytical (bool): set to true for analytical propagation of motion, false for integration.

                Returns:
                    u (numpy.array): right-hand side of moment equation.

        """

        factor = 1.0 - self.ecc * self.ecc
        multiplier = self.mean_motion / math.sqrt(factor * factor * factor)
        x1 = self.transformation(BC.x0, BC.nu0)
        x2 = self.transformation(BC.xf, BC.nuf)

        if analytical:
            u = numpy.zeros(2 * BC.half_dim)

            if BC.half_dim == 1:
                if (self.mu != 0.) and (self.Li == 1 or self.Li == 2
                                        or self.Li == 3):
                    if self.ecc == 0.:
                        u += phi_harmo(
                            -BC.nuf, puls_oop_LP(self.x_eq_normalized,
                                                 self.mu)).dot(x2)
                        u -= phi_harmo(
                            -BC.nu0, puls_oop_LP(self.x_eq_normalized,
                                                 self.mu)).dot(x1)
                    else:
                        print(
                            'compute_rhs: analytical 3-body elliptical out-of-plane near L1, 2 and 3 not coded yet'
                        )
                else:  # out-of-plane elliptical 2-body problem or 3-body near L4 and 5
                    u += phi_harmo(-BC.nuf, 1.0).dot(x2)
                    u -= phi_harmo(-BC.nu0, 1.0).dot(x1)
                u[0] *= multiplier
                u[1] *= multiplier

            elif BC.half_dim == 2:
                if self.mu == 0.:
                    if self.ecc == 0.:
                        u += exp_HCW(-BC.nuf).dot(x2)
                        u -= exp_HCW(-BC.nu0).dot(x1)
                    else:  # elliptical case
                        M = phi_YA(self.ecc, self.mean_motion, 0., BC.nuf)
                        u += linalg.inv(M).dot(x2)
                        M = phi_YA(self.ecc, self.mean_motion, 0., BC.nu0)
                        u -= linalg.inv(M).dot(x1)
                    for i in range(0, len(u)):
                        u[i] *= multiplier
                else:  # in-plane restricted 3-body problem
                    if self.ecc == 0.:
                        if (self.Li == 1) or (self.Li == 2) or (self.Li == 3):
                            u += self.exp_LP123(-BC.nuf).dot(x2)
                            u -= self.exp_LP123(-BC.nu0).dot(x1)
                        elif self.Li == 4:
                            u += self.exp_LP45(-BC.nuf,
                                               1. - 2. * self.mu).dot(x2)
                            u -= self.exp_LP45(-BC.nu0,
                                               1. - 2. * self.mu).dot(x1)
                        else:  # Li = 5
                            u += self.exp_LP45(-BC.nuf,
                                               -1. + 2. * self.mu).dot(x2)
                            u -= self.exp_LP45(-BC.nu0,
                                               -1. + 2. * self.mu).dot(x1)
                    else:  # elliptical case
                        print(
                            'compute_rhs: analytical elliptical 3-body problem in-plane dynamics case not coded yet'
                        )

                    for i in range(0, len(u)):
                        u[i] *= multiplier

            else:  # complete dynamics
                x0_ip, x0_oop = utils.unstack_state(BC.x0)
                xf_ip, xf_oop = utils.unstack_state(BC.xf)
                BC_ip = utils.BoundaryConditions(BC.nu0, BC.nuf, x0_ip, xf_ip)
                BC_oop = utils.BoundaryConditions(BC.nu0, BC.nuf, x0_oop,
                                                  xf_oop)
                z_oop = self.compute_rhs(BC_oop, analytical=True)
                z_ip = self.compute_rhs(BC_ip, analytical=True)
                u = utils.stack_state(z_ip, z_oop)

        else:  # numerical integration

            matrices = self.integrate_phi_inv([BC.nu0, BC.nuf], BC.half_dim)

            IC_matrix = matrices[0]
            FC_matrix = matrices[-1]

            u = (FC_matrix.dot(x2) - IC_matrix.dot(x1)) * multiplier

        return u