Esempio n. 1
0
 def ipvPlot3DMoon(self):
     import ipyvolume as ipv
     lunarPositions = np.zeros((self.history.datetime.shape[0], 3))
     for idx in range(0, self.history.datetime.shape[0]):
         lunarPositions[idx, :] = models.lunarPositionAlmanac2013(
             self.history.datetime[idx]) / 1e3
     ipv.pylab.plot(lunarPositions[:, 0], lunarPositions[:, 2],
                    lunarPositions[:, 1])
     ipv.pylab.scatter(np.array([lunarPositions[-1, 0]]),
                       np.array([lunarPositions[-1, 2]]),
                       np.array([lunarPositions[-1, 1]]),
                       color="gray",
                       marker="sphere")
Esempio n. 2
0
    def plot(self, item, itemHistory=None, **kwargs):
        useDate = False
        for key in kwargs:
            if key == "useDate":
                useDate = kwargs[key]

        if item == "coe":
            # PLOTTING CLASSICAL ORBITAL ELEMENTS
            titles = ["a", "e", "i", "$\omega$", "$\Omega$", "$\\nu$"]
            ylabels = ["[km]", "", "[°]", "[°]", "[°]", "[°]"]
            timeAxis = self.history.datetime if useDate else self.history.t / 60 / 60 / 24
            fig, axes = plt.subplots(3, 2, figsize=(10, 8), sharex=True)
            for i in range(0, 6):
                for j in range(0, len(self.history.maneuverIdxs) - 1):
                    maneuverSlice = slice(self.history.maneuverIdxs[j],
                                          self.history.maneuverIdxs[j + 1])
                    if i in [2, 3, 4, 5]:
                        axes[int((i - i % 2) / 2), i % 2].plot(
                            timeAxis[maneuverSlice],
                            self.history.coe[maneuverSlice, i] * 180 / np.pi)
                    else:
                        if i == 0:
                            axes[int((i - i % 2) / 2), i % 2].plot(
                                timeAxis[maneuverSlice],
                                self.history.coe[maneuverSlice, i] / 1000)
                        else:
                            axes[int((i - i % 2) / 2), i % 2].plot(
                                timeAxis[maneuverSlice],
                                self.history.coe[maneuverSlice, i])
                    axes[int((i - i % 2) / 2),
                         i % 2].set_title(titles[i] + " " + ylabels[i])

                if useDate:
                    fig.autofmt_xdate()
                    axes[int((i - i % 2) / 2),
                         i % 2].xaxis.set_major_formatter(
                             mdates.DateFormatter('%Y-%m-%d'))
                else:
                    if i in [4, 5]:
                        axes[int((i - i % 2) / 2),
                             i % 2].set_xlabel("Tiempo [días]")
                axes[int((i - i % 2) / 2),
                     i % 2].yaxis.get_major_formatter().set_scientific(False)
                axes[int((i - i % 2) / 2),
                     i % 2].yaxis.get_major_formatter().set_useOffset(False)
                axes[int((i - i % 2) / 2), i % 2].grid(b=True)
                if i in [0, 1]:
                    axes[int((i - i % 2) / 2), i %
                         2].yaxis.get_major_formatter().set_scientific(True)
                    axes[int((i - i % 2) / 2),
                         i % 2].yaxis.get_major_formatter().set_useOffset(True)
        if item == "secularCoe":
            # PLOTTING CLASSICAL ORBITAL ELEMENTS
            titles = ["a", "e", "i", "$\omega$", "$\Omega$", "$\\nu$"]
            ylabels = ["[km]", "", "[°]", "[°]", "[°]", "[°]"]
            timeAxis = self.history.datetime if useDate else self.history.tSecular / 60 / 60 / 24
            fig, axes = plt.subplots(3, 2, figsize=(10, 8), sharex=True)
            for i in range(0, 5):
                if i in [2, 3, 4]:
                    axes[int((i - i % 2) / 2), i % 2].plot(
                        timeAxis, self.history.secularCoe[:, i] * 180 / np.pi)
                else:
                    if i == 0:
                        axes[int((i - i % 2) / 2),
                             i % 2].plot(timeAxis,
                                         self.history.secularCoe[:, i] / 1e3)
                    else:
                        axes[int((i - i % 2) / 2),
                             i % 2].plot(timeAxis, self.history.secularCoe[:,
                                                                           i])
                axes[int((i - i % 2) / 2),
                     i % 2].set_title(titles[i] + " " + ylabels[i])

                if (useDate):
                    fig.autofmt_xdate()
                    axes[int((i - i % 2) / 2),
                         i % 2].xaxis.set_major_formatter(
                             mdates.DateFormatter('%Y-%m-%d'))
                axes[int((i - i % 2) / 2),
                     i % 2].yaxis.get_major_formatter().set_scientific(False)
                axes[int((i - i % 2) / 2),
                     i % 2].yaxis.get_major_formatter().set_useOffset(False)
                axes[int((i - i % 2) / 2), i % 2].grid(b=True)

        if item == "3d-trajectory":
            for key in kwargs:
                if key == "ax":
                    axExtern = kwargs["ax"]
            #Plot 3D Trajectory
            if 'axExtern' not in locals():
                fig = plt.figure(figsize=(10, 10))
                ax = fig.add_subplot(111, projection='3d')
            else:
                ax = axExtern

            markers = np.zeros([len(self.history.maneuverIdxs) - 1, 3])

            for i in range(0, len(self.history.maneuverIdxs) - 1):
                maneuverSlice = slice(self.history.maneuverIdxs[i],
                                      self.history.maneuverIdxs[i + 1])
                ax.plot3D(self.history.r[maneuverSlice, 0] / 1000,
                          self.history.r[maneuverSlice, 1] / 1000,
                          self.history.r[maneuverSlice, 2] / 1000,
                          linewidth=1)
                markers[i, :] = self.history.r[
                    self.history.maneuverIdxs[i], :] / 1000
            ax.plot3D(markers[:, 0], markers[:, 1], markers[:, 2], "k.")

            if 'axExtern' not in locals():
                auxiliary.set_axes_equal(ax)
                ax.set_aspect("equal")
                scale_x = 1.2
                scale_y = 1.2
                scale_z = 1.2
                ax.get_proj = lambda: np.dot(
                    Axes3D.get_proj(ax), np.diag(
                        [scale_x, scale_y, scale_z, 1]))

                figXLim = ax.get_xlim()
                figYLim = ax.get_ylim()
                figZLim = ax.get_zlim()
                xx, yy = np.meshgrid(figXLim, figYLim)
                z = np.array([[0, 0], [0, 0]])
                ax.plot_surface(xx, yy, z, alpha=0.3, color="lightgray")

                ax.set_title("Satellite Trajectory [km]")
                ax.set_xlabel("X [km]")
                ax.set_ylabel("Y [km]")
                ax.set_zlabel("Z [km]")
            return ax

        if item == "orbitalEnergy":
            fig, ax = plt.subplots(figsize=(10, 4))
            moonDistances = np.array([])
            for num, date in enumerate(self.history.datetime):
                moonVector = models.lunarPositionAlmanac2013(date)
                moonDistances = np.append(
                    moonDistances,
                    np.linalg.norm(moonVector - self.history.r[num]))

            earthEnergy = np.linalg.norm(
                self.history.v, axis=1
            )**2 / 2 - constants.mu_E / np.linalg.norm(self.history.r, axis=1)
            moonEnergy = np.linalg.norm(
                self.history.v, axis=1)**2 / 2 - constants.mu_M / moonDistances
            ax.plot(self.history.datetime, earthEnergy, label="Earth Energy")
            ax.plot(self.history.datetime, moonEnergy, label="Moon Energy")
            fig.legend()
            fig.autofmt_xdate()
            ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
            plt.grid()
            #fig, ax = plt.subplots(figsize=(10,4))
            #ax.plot(self.history.datetime,moonDistances);

        if item == "energyUsage":
            timeAxis = self.history.datetime if useDate else self.history.t / 60 / 60 / 24
            fig, ax = plt.subplots(figsize=(10, 4))
            PSolarPanels = np.diff(
                self.history.energy["solar panels"]) / np.diff(self.history.t)
            PThruster = np.diff(self.history.energy["thruster"]) / np.diff(
                self.history.t)
            POtherDevices = np.ones((len(self.history.t))) * (
                self.spacecraft.solarPanels.nominalPower) * 0.6
            EBattery = self.history.energy["battery"] / 60 / 60
            ax.plot(timeAxis[:-1],
                    PSolarPanels,
                    linewidth=1,
                    label="Potencia Paneles Solares")
            ax.plot(timeAxis[:-1],
                    PThruster,
                    linewidth=1,
                    label="Potencia Propulsor")
            ax.plot(timeAxis,
                    POtherDevices,
                    linewidth=1,
                    label="Potencia Otros Dispositivos")
            ax.set_ylabel("Potencia [W]")
            #ax.set_ylim([-1,2])

            if useDate:
                fig.autofmt_xdate()
                ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
            else:
                ax.set_xlabel("Tiempo [días]")
            ax.yaxis.set_major_formatter(mticker.ScalarFormatter())
            ax.yaxis.get_major_formatter().set_scientific(False)
            ax.yaxis.get_major_formatter().set_useOffset(False)

            ax2 = ax.twinx()
            ax2.plot(timeAxis,
                     EBattery,
                     linewidth=1,
                     label="Energía Baterías",
                     color="purple")
            ax2.set_ylabel("Energía [Wh]")
            h1, l1 = ax.get_legend_handles_labels()
            h2, l2 = ax2.get_legend_handles_labels()
            ax2.legend(h1 + h2, l1 + l2)
            ax2.set_ylim([-2, self.spacecraft.battery.energy + 2])
            ax2.grid()
            #ax2.set_ylim([-.5,.5])

        if item == "singleItem":
            timeAxis = self.history.datetime if useDate else self.history.t / 60 / 60 / 24
            if np.isscalar(itemHistory) and itemHistory == None:
                raise Exception("History Data not specified.")
            else:
                fig, ax = plt.subplots(figsize=(10, 4))
                for i in range(0, len(self.history.maneuverIdxs) - 1):
                    maneuverSlice = slice(self.history.maneuverIdxs[i],
                                          self.history.maneuverIdxs[i + 1])
                    ax.plot(timeAxis[maneuverSlice],
                            itemHistory[maneuverSlice],
                            linewidth=1)

                if useDate:
                    fig.autofmt_xdate()
                    ax.xaxis.set_major_formatter(
                        mdates.DateFormatter('%Y-%m-%d'))
                    ax.yaxis.set_major_formatter(mticker.ScalarFormatter())
                    ax.yaxis.get_major_formatter().set_scientific(False)
                    ax.yaxis.get_major_formatter().set_useOffset(False)
                else:
                    ax.set_xlabel("Time [days]")
                plt.grid()
                mplcursors.cursor(hover=True)
Esempio n. 3
0
    def calculatePerturbations(self, t, r, v, propMass):
        p = [0, 0, 0]

        if self._PERTURBATION_ATMDRAG_:
            z = np.linalg.norm(r) - constants.Re
            #Atmospheric Drag
            vrel = v - np.cross(constants.wE, r)
            rho = models.USSA76(z)
            #rhoMin, rhoMax = models.HarrisPriester(z)
            #rho = rhoMax
            #rho = models.MSISE90(z,"mean")
            #rhoMin = models.MSISE90(z,"low")
            #rhoMax = models.MSISE90(z,"high")
            #rho = models.mixAtmosphericModels(self.history.datetime[0]+timedelta(seconds=t),rhoMin,rhoMax)
            Fd = -0.5 * rho * np.linalg.norm(vrel) * vrel * (
                1 / self.spacecraft.BC(self.spacecraft.dryMass + propMass))
            p = p + Fd

        if self._PERTURBATION_J2_:
            J2 = 0.00108263

            zz = r[2]

            rNorm = np.linalg.norm(r)
            bigTerm = np.array([
                1 / rNorm * (5 * zz**2 / rNorm**2 - 1),
                1 / rNorm * (5 * zz**2 / rNorm**2 - 1),
                1 / rNorm * (5 * zz**2 / rNorm**2 - 3)
            ])

            #J2 Gravity Gradient
            FJ2 = (
                3 / 2
            ) * J2 * constants.mu_E * constants.Re**2 / rNorm**4 * bigTerm * r
            p = p + FJ2

        if self._PERTURBATION_SOLARPRESS_:
            #u-hat vector pointing from Sun to Earth and Sun position vector
            uhat, rS = models.solarPosition(self.history.datetime[0] +
                                            timedelta(seconds=t))

            #Solar Radiation Pressure
            PSR = 4.56e-6
            #Absorbing Area
            As = self.spacecraft.area

            #Shadow function
            rSNorm = np.linalg.norm(rS)
            rNorm = np.linalg.norm(r)
            theta = np.arccos(np.dot(rS, r) / (rSNorm * rNorm))
            theta1 = np.arccos(constants.Re / rNorm)
            theta2 = np.arccos(constants.Re / rSNorm)
            if (theta1 + theta2 > theta):
                nu = 1
            else:
                nu = 0

            #Radiation Pressure Coefficient (lies between 1 and 2)
            Cr = self.spacecraft.Cr
            #Spacecraft mass
            mass = self.spacecraft.dryMass + propMass
            #Radiation Pressure acceleration
            FR = -nu * PSR * Cr * As / mass * uhat

            p = p + FR

        if self._PERTURBATION_MOON_:
            r_m = models.lunarPositionAlmanac2013(self.history.datetime[0] +
                                                  timedelta(seconds=t))
            r_ms = r_m - r
            #pMoon = constants.mu_M*(r_ms/np.linalg.norm(r_ms)**3-r_m/np.linalg.norm(r_m)**3)

            #F(q) formula from F.3 Appendix Curtis 2013
            # 	c = b - a; a << b
            # 	F = 1 - c**3/b**2
            qq = np.dot(r, (2 * r_m - r)) / np.linalg.norm(r_m)**2
            Fq = (qq**2 - 3 * qq + 3) * qq / (1 + (1 - qq)**(3 / 2))
            pMoon = constants.mu_M / np.linalg.norm(r_ms)**3 * (Fq * r_m - r)

            p = p + pMoon

        if self._PERTURBATION_SUN_:
            uhat, r_s = models.solarPosition(self.history.datetime[0] +
                                             timedelta(seconds=t))
            r_sunSat = r_s - r
            #F(q) formula from F.3 Appendix Curtis 2013
            # 	c = b - a; a << b
            # 	F = 1 - c**3/b**2
            qq = np.dot(r, (2 * r_s - r)) / np.linalg.norm(r_s)**2
            Fq = (qq**2 - 3 * qq + 3) * qq / (1 + (1 - qq)**(3 / 2))
            pSun = constants.mu_S / np.linalg.norm(r_sunSat)**3 * (Fq * r_s -
                                                                   r)

            p = p + pSun

        return p