Example #1
0
def main():
    for size in 10, 1000, 100000:
        jd = np.linspace(2414992.5, 2471184.50, size)
        kernel = SPK.open('de421.bsp')
        ephem = Ephemeris(de421)
        mars = kernel[0,4]

        print(size)
        print('-- old code (2 successive runs):')

        t0 = time()
        ephem.position('mars', jd)
        print(time() - t0)

        t0 = time()
        ephem.position('mars', jd)
        print(time() - t0)

        print('-- new SPK-powered code (2 successive runs):')

        t0 = time()
        mars.compute(jd)
        print(time() - t0)

        t0 = time()
        mars.compute(jd)
        print(time() - t0)

        print()
Example #2
0
    def test_scalar_input(self):
        import de421

        e = Ephemeris(de421)

        self.check0(*e.compute("earthmoon", 2414994.0))
        self.check1(*e.compute("earthmoon", 2415112.5))
Example #3
0
def get_earth_to_sun(JD):
    eph = Ephemeris(de421)
    AU = 149597870.7 # km/AU
    barycenter = eph.position('earthmoon', JD)
    moonvector = eph.position('moon', JD)
    earth = barycenter - moonvector * eph.earth_share
    return -1.0 * vector(earth)/AU
Example #4
0
 def setUp(self):
     try:
         import de421
     except ImportError:
         raise SkipTest('the "de421" ephemeris package is not installed')
     self.eph = Ephemeris(de421)
     self.jalpha = self.eph.jalpha
     self.jomega = self.eph.jomega
Example #5
0
    def test_ephemeris_end_date(self):
        import de421

        e = Ephemeris(de421)
        x, y, z = e.position("earthmoon", e.jomega)
        self.assertAlmostEqual(x, -2.81196460e07, delta=1.0)
        self.assertAlmostEqual(y, 1.32000379e08, delta=1.0)
        self.assertAlmostEqual(z, 5.72139011e07, delta=1.0)
Example #6
0
 def setUp(self):
     try:
         import de421
     except ImportError:
         raise SkipTest('the "de421" ephemeris package has not been'
                        ' installed with "pip install de421"')
     self.eph = Ephemeris(de421)
     self.jalpha = self.eph.jalpha
     self.jomega = self.eph.jomega
Example #7
0
    def test_array_input(self):
        import de421

        e = Ephemeris(de421)

        v = e.compute("earthmoon", np.array([2414994.0, 2415112.5]))

        v = np.array(v)
        self.check0(*v[:, 0])
        self.check1(*v[:, 1])
Example #8
0
def find_residuals(r, rdot, inputJulian, dec_to_check, ra_to_check, timePass):

    #Verlet Integrator
    k = 0.01720209895 # Gaussian gravitational consgtant
    dtau = 0.001  # This is Gaussian Days
    dt = dtau / k     # This is in mean solar days
    tao = 0.0
    deltao = 0.001

    r = r2guess
    rdot = r2Dot

    r0Verlet = r
    r1Verlet = r0Verlet + (rdot * deltao) + (0.5*acceleration(r0Verlet, Rho2hat*Rho2)*(deltao**2))

    while tao <= timePass*k:
        r2Update = (2*r1Verlet) - r0Verlet + acceleration(r1Verlet, Rho2hat*Rho2)*(deltao**2)
        r0Verlet = r1Verlet
        r1Verlet = r2Update

        tao += deltao

    #print r1Verlet


    #Ephemeris Generation

    AU = 149597870.7 # km/AU

    eph = Ephemeris(de421)
    barycenter = eph.position('earthmoon', inputJulian)
    moonvector = eph.position('moon', inputJulian)
    earth = barycenter - moonvector * eph.earth_share
    R0 = vector(earth)/AU # This is the Sun to Earth center vector in Equatorial system
    #print R0
    R_geocentric = -1.0*R0

    #gg = ?

    rInput = r1Verlet

    rho = (rInput + R_geocentric)
    rhohat = norm(rho)
    declination = arcsin(rhohat.z)
    RA = arccos(rhohat.x/(cos(declination)))
    if rhohat.y < 0:
        RA = 2*math.pi - RA

    RA_residuals = abs(RA - ra_to_check)/ra_to_check
    Dec_residuals = abs(declination - dec_to_check)/dec_to_check

    return RA_residuals, Dec_residuals
Example #9
0
def EphemR (JulianDate):
    #Import Ephem 421 to get vector from Earth to Sun (R)
    AU = 149597870.7 # km/AU

    eph = Ephemeris(de421)
    barycenter = eph.position('earthmoon', JulianDate)
    moonvector = eph.position('moon', JulianDate)
    earth = barycenter - moonvector * eph.earth_share
    R0 = vector(earth)/(AU)  #This is the Sun to Earth center vector in Equatorial system
    R_geocentric = -1.*R0  #Multiply by -1 to get Earth to Sun
    #gg =                #Our geocentric vector

    #R_topocentric =  R_geocentric - gg  #Subtract our topocentric vector
    return R_geocentric
def ephemeris_sun_lunar_ECRF(Julian_date):

    # import Julian_date
    # month = 6
    # day = 1
    # year = 1980
    # hour = 12
    # minute = 0
    # second = 0
    # jd = Julian_date.Julian_date(month, day, year, hour, minute, second)
    # k = ephemeris('moon', jd)#2444391.5
    # print('position=',k[0,:])
    # print('velocity=', k[1, :])

    barycenter_position = ephemeris_position_ICRF('earthmoon', Julian_date)

    import de405
    from jplephem import Ephemeris
    eph = Ephemeris(de405)
    Position_sun = ephemeris_position_ICRF('sun', Julian_date)
    Position_moon_ECRF = ephemeris_position_ICRF('moon',
                                                 Julian_date)  # 本身就是相对地球的
    Position_earth = barycenter_position - Position_moon_ECRF * eph.earth_share
    Position_sun_ECRF = Position_sun - Position_earth

    return Position_sun_ECRF, Position_moon_ECRF
Example #11
0
    def planets_pos(self):
        from jplephem import Ephemeris
        import de421
        from PyKEP import epoch
        self.eph = Ephemeris(de421)

        earthpos = []
        marspos = []
        venuspos = []

        for ep in self.sc_state[3]:
            posSun, __ = self.eph.position_and_velocity('sun', epoch(ep, epoch.epoch_type.MJD2000).jd)

            positione, __ = self.eph.position_and_velocity('earthmoon', epoch(ep, epoch.epoch_type.MJD2000).jd)
            positione = self.eq2eclipt(positione - posSun)
            earthpos.append(positione)

            positionm, __ = self.eph.position_and_velocity('mars', epoch(ep, epoch.epoch_type.MJD2000).jd)
            positionm = self.eq2eclipt(positionm - posSun)
            marspos.append(positionm)

            positionv, __ = self.eph.position_and_velocity('venus', epoch(ep, epoch.epoch_type.MJD2000).jd)
            positionv = self.eq2eclipt(positionv - posSun)
            venuspos.append(positionv)

        self.earthpos_km = [earthpos[i].reshape((1,3)).tolist()[0] for i in range(len(earthpos))]
        self.marspos_km = [marspos[i].reshape((1,3)).tolist()[0] for i in range(len(earthpos))]
        self.venuspos_km = [venuspos[i].reshape((1,3)).tolist()[0] for i in range(len(earthpos))]
Example #12
0
def test_ephemeris():

    # import Julian_date
    # month = 6
    # day = 1
    # year = 1980
    # hour = 12
    # minute = 0
    # second = 0
    # jd = Julian_date.Julian_date(month, day, year, hour, minute, second)
    # k = ephemeris('moon', jd)#2444391.5
    # print('position=',k[0,:])
    # print('velocity=', k[1, :])

    Sun_state = ephemeris('sun', 2444391.5)  # 太阳星历
    barycenter_statement = ephemeris('earthmoon', 2444391.5)

    import de405
    from jplephem import Ephemeris
    eph = Ephemeris(de405)
    Position_sun = Sun_state[0, :]
    Velocity_sun = Sun_state[1, :]
    Moon_state = ephemeris('moon', 2444391.5)  # 本身就是相对地球的
    Position_moon = Moon_state[0, :]
    Velocity_moon = Moon_state[1, :]
    Earth_state = barycenter_statement - Moon_state * eph.earth_share
    Position_earth = Earth_state[0, :]
    Velocity_earth = Earth_state[1, :]

    R_sun_earth = Position_sun - Position_earth  # 地心ICRF参考系下太阳的位置矢量
    V_sun_earth = Velocity_sun - Velocity_earth  # 地心ICRF参考系下太阳的速度矢量

    print(R_sun_earth, V_sun_earth)
Example #13
0
class LegacyTests(_CommonTests, TestCase):
    def setUp(self):
        try:
            import de421
        except ImportError:
            raise SkipTest('the "de421" ephemeris package has not been'
                           ' installed with "pip install de421"')
        self.eph = Ephemeris(de421)
        self.jalpha = self.eph.jalpha
        self.jomega = self.eph.jomega

    def position(self, name, tdb, tdb2=0.0):
        return self.eph.position(name, tdb, tdb2)

    def position_and_velocity(self, name, tdb, tdb2=0.0):
        return self.eph.position_and_velocity(name, tdb, tdb2)

    def test_names(self):
        self.assertEqual(self.eph.names, (
            'earthmoon',
            'jupiter',
            'librations',
            'mars',
            'mercury',
            'moon',
            'neptune',
            'nutations',
            'pluto',
            'saturn',
            'sun',
            'uranus',
            'venus',
        ))

    def test_legacy_compute_method(self):
        pv = self.eph.compute('earthmoon', 2414994.0)
        self.check0(pv[:3], pv[3:])
        pv = self.eph.compute('earthmoon', np.array([2414994.0, 2415112.5]))
        self.check0(pv[:3, 0], pv[3:, 0])
        self.check1(pv[:3, 1], pv[3:, 1])

    def test_ephemeris_end_date(self):
        x, y, z = self.position('earthmoon', self.jomega)
        self.assertAlmostEqual(x, -94189805.73967789, delta=epsilon_m)
        self.assertAlmostEqual(y, 1.05103857e+08, delta=1.0)
        self.assertAlmostEqual(z, 45550861.44383482, delta=epsilon_m)
Example #14
0
 def setUp(self):
     try:
         import de421
     except ImportError:
         raise SkipTest('the "de421" ephemeris package is not installed')
     self.eph = Ephemeris(de421)
     self.jalpha = self.eph.jalpha
     self.jomega = self.eph.jomega
def planet_elements_and_sv(planet_id, year, month, day, hour, minute, second):
    global mu
    mu = 1.327124e11

    #calculating julian time
    j0 = sum(jdcal.gcal2jd(year, month, day))
    ut = (hour+minute/60+second/3600)/24
    jd = j0+ut

    #determining state vectors
    eph = Ephemeris(de421)
    planet = month_planet_names.planet_name(planet_id)
    if planet=="earth":
        barycenter = eph.position_and_velocity('earthmoon', jd)
        moonvector = eph.position_and_velocity('moon', jd)
        r = barycenter[0] - eph.earth_share*moonvector[0]
        v = barycenter[1] - eph.earth_share*moonvector[1]

    elif planet=="moon":
        barycenter = eph.position_and_velocity('earthmoon', jd)
        moonvector = eph.position_and_velocity('moon', jd)
        r = barycenter[0] - eph.moon_share*moonvector[0]
        v = barycenter[1] - eph.moon_share*moonvector[1]
        mu = 3.986e14

    else:
        r, v = eph.position_and_velocity(planet, jd)

    r = r.flatten()
    v = v.flatten()/(24*3600)

    coe = coe_from_sv.coe_from_sv(r, v, mu)

    return [coe, r, v, jd]
Example #16
0
 def setUp(self):
     try:
         import de421
     except ImportError:
         raise SkipTest('the "de421" ephemeris package has not been'
                        ' installed with "pip install de421"')
     self.eph = Ephemeris(de421)
     self.jalpha = self.eph.jalpha
     self.jomega = self.eph.jomega
def JPL_Eph_DE405(JD):
    '''

    :param JD:
    :return: unit: m type: ndarray  r_Mercury(ECRF), r_Venus(ECRF), r_Earth(ICRF), r_Mars(ECRF),
    r_Jupiter(ECRF), r_Saturn(ECRF), r_Uranus(ECRF), \
    r_Neptune(ECRF), r_Pluto(ECRF), r_Moon(ECRF), r_Sun(ECRF),r_SunSSB(ICRF)
    '''

    Sun_state = ephemeris('sun', JD)  # 太阳星历
    barycenter_statement = ephemeris('earthmoon', JD)

    import de405
    from jplephem import Ephemeris
    eph = Ephemeris(de405)

    Moon_To_Earth_state = ephemeris('moon', JD)  # 本身就是相对地球的

    Earth_state = barycenter_statement - Moon_To_Earth_state * eph.earth_share
    r_Earth = Earth_state[0, :]

    r_Sun = Sun_state[0, :] - r_Earth

    Moon_state = Moon_To_Earth_state

    r_Moon = Moon_state[0, :]

    Mercury_state = ephemeris('mercury', JD)
    r_Mercury = Mercury_state[0, :] - r_Earth

    Venus_state = ephemeris('venus', JD)
    r_Venus = Venus_state[0, :] - r_Earth

    Mars_state = ephemeris('mars', JD)
    r_Mars = Mars_state[0, :] - r_Earth

    Jupiter_state = ephemeris('jupiter', JD)
    r_Jupiter = Jupiter_state[0, :] - r_Earth

    Saturn_state = ephemeris('saturn', JD)
    r_Saturn = Saturn_state[0, :] - r_Earth

    Uranus_state = ephemeris('uranus', JD)
    r_Uranus = Uranus_state[0, :] - r_Earth

    Neptune_state = ephemeris('neptune', JD)
    r_Neptune = Neptune_state[0, :] - r_Earth

    Pluto_state = ephemeris('pluto', JD)
    r_Pluto = Pluto_state[0, :] - r_Earth

    r_SunSSB = Sun_state[0, :]

    #获取的数据是以km为单位,返回值要求为m为单位,需要乘以1e3转化
    return r_Mercury*1e3,r_Venus*1e3,r_Earth*1e3,r_Mars*1e3,r_Jupiter*1e3,r_Saturn*1e3,r_Uranus*1e3, \
           r_Neptune*1e3,r_Pluto*1e3,r_Moon*1e3,r_Sun*1e3,r_SunSSB*1e3
def ephemeris_position_ICRF(celestial_body, Julian_date):
    '''

    :param celestial_body:  earthmoon   mercury    pluto   venus
                            jupiter     moon       saturn
                            librations  neptune    sun
                            mars        nutations  uranus
    :param Julian_date:儒略日
    :return:天体的位置(km),在ICRF下的,以太阳系质心为原点
    '''
    import de405
    from jplephem import Ephemeris

    eph = Ephemeris(de405)
    position = eph.position(celestial_body, Julian_date)  # 1980.06.01
    position = np.transpose(position)
    position = np.array(position).flatten()

    return np.array(position)
Example #19
0
def main():
    for size in 10, 1000, 100000:
        jd = np.linspace(2414992.5, 2471184.50, size)
        kernel = SPK.open('de432.bsp')
        ephem = Ephemeris(de421)
        mars = kernel[0,4]

        print(size)
        print('-- old code (2 successive runs):')

        t0 = time()
        ephem.position('mars', jd)
        print(time() - t0)

        t0 = time()
        ephem.position('mars', jd)
        print(time() - t0)

        print('-- new SPK-powered code (2 successive runs):')

        t0 = time()
        mars.compute(jd)
        print(time() - t0)

        t0 = time()
        mars.compute(jd)
        print(time() - t0)

        print()
Example #20
0
class LegacyTests(_CommonTests, TestCase):

    def setUp(self):
        try:
            import de421
        except ImportError:
            raise SkipTest('the "de421" ephemeris package has not been'
                           ' installed with "pip install de421"')
        self.eph = Ephemeris(de421)
        self.jalpha = self.eph.jalpha
        self.jomega = self.eph.jomega

    def position(self, name, tdb, tdb2=0.0):
        return self.eph.position(name, tdb, tdb2)

    def position_and_velocity(self, name, tdb, tdb2=0.0):
        return self.eph.position_and_velocity(name, tdb, tdb2)

    def test_names(self):
        self.assertEqual(self.eph.names,  (
            'earthmoon', 'jupiter', 'librations', 'mars', 'mercury',
            'moon', 'neptune', 'nutations', 'pluto', 'saturn', 'sun',
            'uranus', 'venus',
            ))

    def test_legacy_compute_method(self):
        pv = self.eph.compute('earthmoon', 2414994.0)
        self.check0(pv[:3], pv[3:])
        pv = self.eph.compute('earthmoon', np.array([2414994.0, 2415112.5]))
        self.check0(pv[:3,0], pv[3:,0])
        self.check1(pv[:3,1], pv[3:,1])

    def test_ephemeris_end_date(self):
        x, y, z = self.position('earthmoon', self.jomega)
        self.assertAlmostEqual(x, -94189805.73967789, delta=epsilon_m)
        self.assertAlmostEqual(y, 1.05103857e+08, delta=1.0)
        self.assertAlmostEqual(z, 45550861.44383482, delta=epsilon_m)
Example #21
0
def ephemeris(celestial_body, Julian_date):
    '''

    :param celestial_body:  earthmoon   mercury    pluto   venus
                            jupiter     moon       saturn
                            librations  neptune    sun
                            mars        nutations  uranus
    :param Julian_date:儒略日
    :return:天体的位置(km),速度(km/s)
    '''
    import de405
    from jplephem import Ephemeris

    eph = Ephemeris(de405)
    position, velocity = eph.position_and_velocity(celestial_body,
                                                   Julian_date)  # 1980.06.01
    position = np.transpose(position)
    position = np.array(position).flatten()
    velocity = np.transpose(velocity)
    velocity = np.array(velocity).flatten()
    velocity = velocity / 86400
    state = np.array([position, velocity])

    return np.array(state)
def find_residuals(check_index, decs, ras, JDs, r, r_dot):
    dec_res_total = 0
    ra_res_total = 0
    total_ra = 0
    total_dec = 0

    for i in range(len(decs)):
        #print str(i + 1) + "/" + str(len(decs))
        k = 0.01720209895
        time_difference = JDs[i] - JDs[check_index]
        tau = 0.0
        d_tau = 0.0001 * is_negative(time_difference)
        end_tau = time_difference * k
        mu = 1.0
        r_last = r
        r_now = r_last + r_dot * d_tau + 0.5 * accel(r_last, mu) * (d_tau**2)
        tau += d_tau

        while abs(tau) <= abs(end_tau):
            tau += d_tau
            temp = verlet_position(r_now, r_last, d_tau, mu)
            r_last = temp[1]
            r_now = temp[0]

        AU = 149597870.7  # km/AU
        jd = JDs[i]
        eph = Ephemeris(de421)

        R_geocentric = get_earth_to_sun(JD)
        sun_to_asteroid = r_now
        earth_to_asteroid = norm(
            R_geocentric +
            sun_to_asteroid)  # Gets unit vector from Earth to Asteroid
        RA, Dec = location_to_angles(earth_to_asteroid)
        RA_Residual = abs(ras[i] - RA)
        Dec_Residual = abs(decs[i] - Dec)
        ra_res_total += RA_Residual**2
        dec_res_total += Dec_Residual**2

        tau = 0
        d_tau = 0.000001
        k = 0.01720209895
        mu = 1.0

    sigma = sqrt(ra_res_total + dec_res_total)
    return sigma
Example #23
0
def find_residuals(check_index, decs, ras, JDs, r, r_dot):
    dec = []
    ra = []

    for i in range(len(decs)):
        k = 0.01720209895
        time_difference = JDs[i] - JDs[check_index]
        tau = 0.0
        d_tau = 0.0001 * neg(time_difference)
        end_tau = time_difference * k
        mu = 1.0
        r_last = r
        r_now = r_last + r_dot * d_tau + 0.5 * accel(r_last, mu) * (d_tau ** 2)
        tau += d_tau

        while abs(tau) <= abs(end_tau):
            tau += d_tau
            temp = verlet_position(r_now, r_last, d_tau, mu)
            r_last = temp[1]
            r_now = temp[0]


        AU = 149597870.7# km/AU
        jd = JDs[i]
        eph = Ephemeris(de421)

        R_geocentric = get_earth_to_sun(jd)
        sun_to_asteroid = r_now
        earth_to_asteroid = norm(R_geocentric + sun_to_asteroid) # Gets unit vector from Earth to Asteroid
        RA, Dec = location_to_angles(earth_to_asteroid)
        ra.append(RA)
        dec.append(Dec)
        tau = 0
        d_tau = 0.000001
        k = 0.01720209895
        mu = 1.0

    return ra, dec
Example #24
0
def find_endpoints(check_index, decs, ras, JDs, r, r_dot):
    dec_res_total = 0
    ra_res_total = 0
    total_ra = 0
    total_dec = 0
    times = []
    times.append(JDs[0])
    times.append(JDs[len(JDs) - 1])
    new_RAs = []
    new_decs = []
    for i in range(len(JDs)):
        k = 0.01720209895
        time_difference = JDs[i] - JDs[check_index]
        tau = time_difference * k

        f, g = best_f_and_g(tau, r, r_dot)
        r_now = f * r + g * r_dot

        AU = 149597870.7  #km/AU
        jd = JDs[i]
        eph = Ephemeris(de421)

        R_geocentric = get_earth_to_sun(JD)
        sun_to_asteroid = r_now
        earth_to_asteroid = norm(
            R_geocentric +
            sun_to_asteroid)  #Gets unit vector from Earth to Asteroid
        RA, Dec = location_to_angles(earth_to_asteroid)
        new_RAs.append(RA)
        new_decs.append(Dec)
        """
        tau = 0
        d_tau = 0.000001
        k = 0.01720209895
        mu = 1.0
        """

    return new_RAs, new_decs
Example #25
0
def find_residuals(check_index, decs, ras, JDs, r, r_dot):
    dec_res_total = 0
    ra_res_total = 0
    total_ra = 0
    total_dec = 0

    for i in range(len(decs)):
        k = 0.01720209895
        time_difference = JDs[i] - JDs[check_index]
        tau = time_difference * k
        mu = 1.0
        f, g = better_f_and_g(tau, r, r_dot)
        r_now = f * r + g * r_dot

        AU = 149597870.7  # km/AU
        jd = JDs[i]
        eph = Ephemeris(de421)

        R_geocentric = get_earth_to_sun(JD)
        sun_to_asteroid = r_now
        earth_to_asteroid = norm(
            R_geocentric +
            sun_to_asteroid)  # Gets unit vector from Earth to Asteroid
        RA, Dec = location_to_angles(earth_to_asteroid)
        RA_Residual = abs(ras[i] - RA)
        Dec_Residual = abs(decs[i] - Dec)
        ra_res_total += RA_Residual**2
        dec_res_total += Dec_Residual**2

        tau = 0
        d_tau = 0.000001
        k = 0.01720209895
        mu = 1.0

    sigma = sqrt(ra_res_total + dec_res_total)
    return sigma
Example #26
0
class pos(object):
    def __init__(self):
        self.trajectory_positions = []

        axtl = 23.43929*DEG2RAD # Earth axial tlit
        # Macierz przejscia z  ECI do helio
        self.mactran = matrix([ [1, 0, 0],
                                [0, cos(axtl), sin(axtl)],
                                [0, -sin(axtl), cos(axtl)] ])
        self.day = 86400.0

    def positions_lambert(self, l, sol=0, units = 1.0, index = 0):
        """
        Plots a particular solution to a Lambert's problem

        USAGE: plot_lambert(ax,l, N=60, sol=0, units = 'PyKEP.AU', legend = 'False')
          * l:      PyKEP.lambert_problem object
          * sol:    solution to the Lambert's problem we want to plot (must be in 0..Nmax*2)
                where Nmax is the maximum number of revolutions for which there exist a solution.
          * units:  the length unit to be used in the plot
        """
        from PyKEP import propagate_lagrangian, AU

        if sol > l.get_Nmax()*2:
            raise ValueError("sol must be in 0 .. NMax*2 \n * Nmax is the maximum number of revolutions for which there exist a solution to the Lambert's problem \n * You can compute Nmax calling the get_Nmax() method of the lambert_problem object")

        #We extract the relevant information from the Lambert's problem
        r = l.get_r1()
        v = l.get_v1()[sol]
        T = l.get_tof()
        mu = l.get_mu()

        #We define the integration time ...
        if T/86400. < 1:
            N = int(T) #...compute number of points...
            dt = T / (N-1.)
        else:
            N = int(2*T/86400.) #...compute number of points...
            dt = T / (N-1.)
        timetuple = [i*dt for i in range(N)]

        #... and alocate the cartesian components for r
        x = [0.0]*N
        y = [0.0]*N
        z = [0.0]*N

        #We calculate the spacecraft position at each dt
        for i in range(N):
            x[i] = r[0]/units
            y[i] = r[1]/units
            z[i] = r[2]/units
            r,v = propagate_lagrangian(r,v,dt,mu)

        self.trajectory_positions.append([index, x, y, z, timetuple])

    def positions_kepler(self, r,v,t,mu, units = 1, index = 0):
        """
        Plots the result of a keplerian propagation

        USAGE: plot_kepler(ax,r,v,t,mu, N=60, units = 1, color = 'b', legend = False):
          * r:      initial position (cartesian coordinates)
          * v:      initial velocity (cartesian coordinates)
          * t:      propagation time
          * mu:     gravitational parameter
          * units:  the length unit to be used in the plot
        """

        from PyKEP import propagate_lagrangian

        #We define the integration time ...
        if t/86400. < 1:
            N = int(t) #...compute number of points...
            dt = t / (N-1.)
        else:
            N = int(2*t/86400.) #...compute number of points...
            dt = t / (N-1.)
        timetuple = [i*dt for i in range(N)]

        #... and calcuate the cartesian components for r
        x = [0.0]*N
        y = [0.0]*N
        z = [0.0]*N

        #We calculate the spacecraft position at each dt
        for i in range(N):
            x[i] = r[0]/units
            y[i] = r[1]/units
            z[i] = r[2]/units
            r,v = propagate_lagrangian(r,v,dt,mu)

        self.trajectory_positions.append([index, x, y, z, timetuple])

    def return_sc_positions(self):
        return self.trajectory_positions

    def set_launch_epoch(self, mjd2000_epoch):
        self.Lepoch = mjd2000_epoch

    def rework_time(self):
        T = self.trajectory_positions
        n = len(T)

        ep = self.Lepoch
        timespans = [T[i][4][-1]/86400. for i in range(n)]
        beginings = [ep + sum(timespans[:i]) for i in range(n)]

        # initialize lists...
        t = []
        x = []
        y = []
        z = []

        # ...and join values, correcting for time
        for g in range(n):
            t = t + [beginings[g]+i/86400. for i in T[g][4]]
            x = x + T[g][1]
            y = y + T[g][2]
            z = z + T[g][3]

        # save spacecraft state
        self.sc_state = [x, y, z, t]

    def eq2eclipt(self, xyz):
        macxyz = matrix(xyz)
        return self.mactran.dot(macxyz)

    def planets_pos(self):
        from jplephem import Ephemeris
        import de421
        from PyKEP import epoch
        self.eph = Ephemeris(de421)

        earthpos = []
        marspos = []
        venuspos = []

        for ep in self.sc_state[3]:
            posSun, __ = self.eph.position_and_velocity('sun', epoch(ep, epoch.epoch_type.MJD2000).jd)

            positione, __ = self.eph.position_and_velocity('earthmoon', epoch(ep, epoch.epoch_type.MJD2000).jd)
            positione = self.eq2eclipt(positione - posSun)
            earthpos.append(positione)

            positionm, __ = self.eph.position_and_velocity('mars', epoch(ep, epoch.epoch_type.MJD2000).jd)
            positionm = self.eq2eclipt(positionm - posSun)
            marspos.append(positionm)

            positionv, __ = self.eph.position_and_velocity('venus', epoch(ep, epoch.epoch_type.MJD2000).jd)
            positionv = self.eq2eclipt(positionv - posSun)
            venuspos.append(positionv)

        self.earthpos_km = [earthpos[i].reshape((1,3)).tolist()[0] for i in range(len(earthpos))]
        self.marspos_km = [marspos[i].reshape((1,3)).tolist()[0] for i in range(len(earthpos))]
        self.venuspos_km = [venuspos[i].reshape((1,3)).tolist()[0] for i in range(len(earthpos))]

    def distance_to_planets(self):
        dre = []
        drm = []
        drv = []

        for i in range(len(self.sc_state[3])):
            ep = self.earthpos_km[i]
            dist = [ep[0] - self.sc_state[0][i] / 1000.,
                    ep[1] - self.sc_state[1][i] / 1000.,
                    ep[2] - self.sc_state[2][i] / 1000.]
            dre.append((sum([g**2 for g in dist]))**.5)

            mp = self.marspos_km[i]
            dist = [mp[0] - self.sc_state[0][i] / 1000.,
                    mp[1] - self.sc_state[1][i] / 1000.,
                    mp[2] - self.sc_state[2][i] / 1000.]
            drm.append((sum([g**2 for g in dist]))**.5)

            vp = self.venuspos_km[i]
            dist = [vp[0] - self.sc_state[0][i] / 1000.,
                    vp[1] - self.sc_state[1][i] / 1000.,
                    vp[2] - self.sc_state[2][i] / 1000.]
            drv.append((sum([g**2 for g in dist]))**.5)

        return dre,drm, drv, self.sc_state[3]
Example #27
0
    def GenerateJourneyDataPlot(self, DataAxesLeft, DataAxesRight, PlotOptions, firstpass):

        #generate a vector of dates
        date_string_vector = []
        for event in self.missionevents:
            if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                date_string_vector.append(event.GregorianDate)

        date_vector = [datetime.datetime.strptime(d,'%m/%d/%Y').date() for d in date_string_vector]

        #dummy line across the bottom so that neither axes object crashes
        DataAxesLeft.plot(date_vector, np.zeros_like(date_vector), c='w', lw = 0.1)
        DataAxesRight.plot(date_vector, np.zeros_like(date_vector), c='w', lw = 0.1)

        #plot distance from central body
        if PlotOptions.PlotR:
            Rvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Rvector.append(math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2) / self.LU)
            if firstpass:
                unitstring = 'LU'
                if self.central_body.lower() == 'sun' and math.fabs(self.LU - 149597870.69100001) < 1.0:
                    unitstring = 'AU'
                labelstring = 'Distance from ' + self.central_body + ' (' + unitstring + ')'
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2, label=labelstring)
            else:
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2)

        #plot velocity
        if PlotOptions.PlotV:
            Vvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Vvector.append(math.sqrt(event.SpacecraftState[3]**2 + event.SpacecraftState[4]**2 + event.SpacecraftState[5]**2) / self.LU * self.TU)
            if firstpass:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.', label='Velocity magnitude (LU/TU)')
            else:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.')

        #plot Thrust
        if PlotOptions.PlotThrust:
            Thrustvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Thrustvector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) * 10.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Thrustvector, c='r', lw=2, ls='-', label='Applied thrust (0.1 N)')
            else:
                DataAxesLeft.plot(date_vector, Thrustvector, c='r', lw=2, ls='-')

        #plot Isp
        if PlotOptions.PlotIsp:
            Ispvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Ispvector.append(event.Isp / 1000.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Ispvector, c='c', lw=2, ls='-', label='Isp (1000 s)')
            else:
                DataAxesLeft.plot(date_vector, Ispvector, c='c', lw=2, ls='-')

        #plot mass flow rate
        if PlotOptions.PlotMdot:
            Mdotvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Mdotvector.append(event.MassFlowRate * 1.0e6)
            if firstpass:
                DataAxesLeft.plot(date_vector, Mdotvector, c='brown', lw=2, ls='-', label='Mass flow rate (mg/s)')
            else:
                DataAxesLeft.plot(date_vector, Mdotvector, c='brown', lw=2, ls='-')

        #plot Efficiency
        if PlotOptions.PlotEfficiency:
            Efficiencyvector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    Efficiencyvector.append(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower))
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Efficiencyvector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Efficiencyvector, c='DarkGreen', lw=2, ls='-', label='Propulsion system efficiency')
            else:
                DataAxesLeft.plot(date_vector, Efficiencyvector, c='DarkGreen', lw=2, ls='-')

        #plot Throttle
        if PlotOptions.PlotThrottle:
            Throttlevector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    Throttlevector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust * self.thruster_duty_cycle))
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Throttlevector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Throttlevector, c='r', lw=2, ls='--', label='Throttle')
            else:
                DataAxesLeft.plot(date_vector, Throttlevector, c='r', lw=2, ls='--')

        #plot power
        if PlotOptions.PlotPower:
            Powervector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    if event.AvailablePower > 0.0:
                        Powervector.append(event.AvailablePower)
                    else:
                        Powervector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Powervector, c='Navy', lw=2, ls='-', label='Power produced by spacecraft (kW)')
            else:
                DataAxesLeft.plot(date_vector, Powervector, c='Navy', lw=2, ls='-')

        #plot gamma
        if PlotOptions.PlotGamma:
            gammavector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    gammavector.append(math.atan2(event.Thrust[1], event.Thrust[0]) * 180.0 / math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    gammavector.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector, gammavector, c='DarkGreen', lw=2, ls='--', label=r'$\gamma$ (radians)')
            else:
                DataAxesRight.plot(date_vector, gammavector, c='DarkGreen', lw=2, ls='--')

        #plot delta
        if PlotOptions.PlotDelta:
            deltavector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    deltavector.append(math.asin(event.Thrust[2] / AppliedThrust) * 180.0 / math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    deltavector.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector, deltavector, c='LightGreen', lw=2, ls='--', label=r'$\delta$ (radians)')
            else:
                DataAxesRight.plot(date_vector, deltavector, c='LightGreen', lw=2, ls='--')


        #plot central body to thrust vector angle
        if PlotOptions.PlotCB_thrust_angle:
            CBthrustvector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    CBthrustvector.append( math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    CBthrustvector.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector, CBthrustvector, c='Salmon', lw=2, ls='--', label='CB-thrust angle (radians)')
            else:
                DataAxesRight.plot(date_vector, CBthrustvector, c='Salmon', lw=2, ls='--')

        #plot mass
        if PlotOptions.PlotMass:
            mass = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    mass.append(event.Mass * 1.0e-3)
            if firstpass:
                DataAxesLeft.plot(date_vector, mass, c='DarkGrey', lw=2, ls='-', label='Mass (1000 kg)')
            else:
                DataAxesLeft.plot(date_vector, mass, c='DarkGrey', lw=2, ls='-')

        #plot number of active thrusters
        if PlotOptions.PlotNumberOfEngines:
            numberofengines = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    numberofengines.append(event.Number_of_Active_Engines)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    numberofengines.append(0)
            if firstpass:
                DataAxesLeft.plot(date_vector, numberofengines, c='Orange', lw=2, ls='-', label='Number of active thrusters')
            else:
                DataAxesLeft.plot(date_vector, numberofengines, c='Orange', lw=2, ls='-')

        #plot power actively used by the thrusters
        if PlotOptions.PlotActivePower:
            activepowervector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    activepowervector.append(event.ActivePower)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    activepowervector.append(0.0)

            if firstpass:
                DataAxesLeft.plot(date_vector, activepowervector, c='Navy', lw=2, ls='--', label='Power used by the propulsion system (kW)')
            else:
                DataAxesLeft.plot(date_vector, activepowervector, c='Navy', lw=2, ls='--')

        #plot waste heat from the propulsion system
        if PlotOptions.PlotWasteHeat:
            WasteHeatvector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    WasteHeatvector.append( (1 - event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower)) * event.ActivePower )
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    WasteHeatvector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, WasteHeatvector, c='Crimson', lw=2, ls='--', label='Waste heat from propulsion system (kW)')
            else:
                DataAxesLeft.plot(date_vector, WasteHeatvector, c='Crimson', lw=2, ls='--')

        #plot Earth distance in LU and SPE angle
        if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunEarthSpacecraftAngle:
            if self.central_body.lower() != 'sun':
                print 'getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun'
            else:
                import de423
                from jplephem import Ephemeris
                eph = Ephemeris(de423)

                EarthDistanceVector = []
                SunEarthSpacecraftAngle = []
                for event in self.missionevents:
                    if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    
                        
                        #get the position of the central body relative to the solar system barycenter
                        cb_relative_to_solar_system_barycenter_in_ICRC = eph.position(self.central_body.lower(), event.JulianDate)

                        #get the position of the Earth relative to the central body
                        embarycenter_in_ICRC = eph.position('earthmoon', event.JulianDate)
                        moonvector_in_ICRC = eph.position('moon', event.JulianDate)
                        Earth_relative_to_solar_system_barycenter_in_ICRC = embarycenter_in_ICRC - moonvector_in_ICRC * eph.earth_share
                        Earth_relative_to_cb_in_ICRC = Earth_relative_to_solar_system_barycenter_in_ICRC + cb_relative_to_solar_system_barycenter_in_ICRC

                        #rotate the spacecraft state relative to the central body into the ICRF frame
                        spacecraft_state_relative_to_central_body_in_ICRF = AstroFunctions.rotate_from_ecliptic_to_equatorial3(np.array(event.SpacecraftState[0:3]))

                        #get the vector from the Earth to the Spacecraft
                        Earth_Spacecraft_Vector = spacecraft_state_relative_to_central_body_in_ICRF - np.transpose(Earth_relative_to_cb_in_ICRC)[0]

                        #return the magnitude of the Earth-centered position vector
                        EarthDistanceVector.append(np.linalg.norm(Earth_Spacecraft_Vector) / self.LU)

                        #if applicable, compute sun-spacecraft-Earth angle
                        if PlotOptions.PlotSunEarthSpacecraftAngle:
                            cosAngle = np.dot(-Earth_Spacecraft_Vector, -spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(Earth_Spacecraft_Vector)
                            SunEarthSpacecraftAngle.append(np.arccos(cosAngle) * 180.0/math.pi)

                
                if PlotOptions.PlotEarthDistance:
                    if firstpass:
                        unitstring = 'LU'
                        if self.central_body.lower() == 'sun' and math.fabs(self.LU - 149597870.69100001) < 1.0:
                            unitstring = 'AU'
                        labelstring = 'Distance from Earth (' + unitstring + ')'
                        DataAxesLeft.plot(date_vector, EarthDistanceVector, c='g', lw=2, label=labelstring)
                    else:
                        DataAxesLeft.plot(date_vector, EarthDistanceVector, c='g', lw=2)
                if PlotOptions.PlotSunEarthSpacecraftAngle:
                    if firstpass:
                        DataAxesRight.plot(date_vector, SunEarthSpacecraftAngle, c='orangered', lw=2, ls = '-.', label='Sun-Spacecraft-Earth Angle')
                    else:
                        DataAxesRight.plot(date_vector, SunEarthSpacecraftAngle, c='orangered', lw=2, ls = '-.')
Example #28
0
    def WriteDateReport(self, PlotOptions, reportfile):
        #write header
        reportfile.write('JD, MM-DD-YYYY, Event duration (days), Event type, Event location')
        if PlotOptions.IncludeStateVectorInReport:
            reportfile.write(',x (km), y (km), z (km), xdot (km/s), ydot (km/s), zdot (km/s)')
        if PlotOptions.PlotR:
            unitstring = 'LU'
            if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                unitstring = 'AU'
            reportfile.write(', Distance from ' + self.central_body + ' (' + unitstring + ')')
        if PlotOptions.PlotV:
            reportfile.write(', Velocity magnitude (LU/TU)')
        if PlotOptions.PlotThrust:
            reportfile.write(', Applied thrust (N)')
        if PlotOptions.PlotIsp:
            reportfile.write(', Isp (s)')
        if PlotOptions.PlotMdot:
            reportfile.write(', Mass flow rate (kg/s)')
        if PlotOptions.PlotEfficiency:
            reportfile.write(', Propulsion system efficiency')
        if PlotOptions.PlotThrottle:
            reportfile.write(', Control magnitude')
        if PlotOptions.PlotPower:
            reportfile.write(', Power produced by spacecraft (kW)')
        if PlotOptions.PlotGamma:
            reportfile.write(', in-plane control angle (degrees)')
        if PlotOptions.PlotDelta:
            reportfile.write(', out-of-plane control angle (degrees)')
        if PlotOptions.PlotArray_Thrust_Angle:
            reportfile.write(', Array to thrust angle (degrees)')
        if PlotOptions.PlotMass:
            reportfile.write(', Mass (kg)')
        if PlotOptions.PlotNumberOfEngines:
            reportfile.write(', Number of active thrusters')
        if PlotOptions.PlotActivePower:
            reportfile.write(', Power used by the propulsion system (kW)')
        if PlotOptions.PlotWasteHeat:
            reportfile.write(', Waste heat from propulsion system (kW)')  
        if PlotOptions.PlotEarthDistance:
            unitstring = 'LU'
            if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                unitstring = 'AU'
            reportfile.write(', Distance from Earth (' + unitstring + ')')
        if PlotOptions.PlotSunSpacecraftEarthAngle:
            reportfile.write(', Sun-Spacecraft-Earth Angle')
        if PlotOptions.PlotSpacecraftViewingAngle:
            reportfile.write(', Latitude of Earth-Spacecraft Vector')
        if PlotOptions.PlotThrottleLevel:
            reportfile.write(', Throttle level')
        if PlotOptions.PlotSunBoresightAngle:
            reportfile.write(', Sun-Boresight Angle')
        reportfile.write('\n')

        #load stuff if necessary
        if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunSpacecraftEarthAngle or PlotOptions.PlotSpacecraftViewingAngle:
            if not 'sun' in self.central_body.lower():
                print('getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun')
            else:
                import de423
                from jplephem import Ephemeris
                self.eph = Ephemeris(de423)
        if PlotOptions.PlotThrottleLevel:
            #instantiate a throttle table object
            thruster_throttle_table = ThrottleTable.ThrottleTable(PlotOptions.throttletablefile)
            self.high_Mdot_set, self.low_Mdot_set = thruster_throttle_table.create_non_dominated_sets()

        #now print the report
        for event in self.missionevents:
            reportfile.write(str(event.JulianDate))
            reportfile.write(', ' + event.GregorianDate)
            reportfile.write(', ' + str(event.TimestepLength))
            reportfile.write(', ' + event.EventType)
            reportfile.write(', ' + event.Location)
            if PlotOptions.IncludeStateVectorInReport:
                for state in event.SpacecraftState:
                    reportfile.write(', ' + str(state))
            if PlotOptions.PlotR:
                reportfile.write(', ' + str(math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2) / self.LU))
            if PlotOptions.PlotV:
                reportfile.write(', ' + str(math.sqrt(event.SpacecraftState[3]**2 + event.SpacecraftState[4]**2 + event.SpacecraftState[5]**2) / self.LU * self.TU))
            if PlotOptions.PlotThrust:
                if event.EventType not in ['match_point','upwr_flyby','pwr_flyby','LT_rndzvs','LT_spiral']:
                    reportfile.write(', ' + str(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)))
                elif event.EventType == 'LT_spiral':
                    reportfile.write(', ' + str(event.AvailableThrust * self.thruster_duty_cycle))
                else:
                    reportfile.write(', 0.0')
            if PlotOptions.PlotIsp:
                reportfile.write(', ' + str(event.Isp))
            if PlotOptions.PlotMdot:
                reportfile.write(', ' + str(event.MassFlowRate))
            if PlotOptions.PlotEfficiency:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower)))
                else:
                    reportfile.write(', 0.0')
            if PlotOptions.PlotThrottle:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust']:
                    reportfile.write(', ' + str(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust * self.thruster_duty_cycle)))
                elif event.EventType == 'LT_spiral':
                    reportfile.write(', ' + str(1.0))
                elif event.EventType not in ['match_point','upwr_flyby','pwr_flyby','LT_rndzvs']:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotPower:
                if event.EventType not in ['match_point','upwr_flyby','pwr_flyby','LT_rndzvs']:
                    if (event.AvailablePower > 0.0):
                        reportfile.write(', ' + str(event.AvailablePower))
                    else:
                        reportfile.write(', ' + str(0.0))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotGamma:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(math.atan2(event.Thrust[1], event.Thrust[0]) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotDelta:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    reportfile.write(', ' + str(math.asin(event.Thrust[2] / AppliedThrust) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotArray_Thrust_Angle:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    reportfile.write(', ' + str(math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotMass:
                reportfile.write(', ' + str(event.Mass))
            if PlotOptions.PlotNumberOfEngines:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(event.Number_of_Active_Engines))
                else:
                    reportfile.write(', ' + str(0))
            if PlotOptions.PlotActivePower:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(event.ActivePower))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotWasteHeat:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str((1.0 - event.AvailableThrust * event.Isp * 9.80665 / (2000.0 * event.ActivePower)) * event.ActivePower))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunSpacecraftEarthAngle or PlotOptions.PlotSpacecraftViewingAngle:
                if not 'sun' in self.central_body.lower():
                    print('getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun')
                else:
                    #get the position of the central body relative to the solar system barycenter
                    cb_relative_to_solar_system_barycenter_in_ICRF = self.eph.position('sun', event.JulianDate)

                    #get the position of the Earth relative to the central body
                    embarycenter_in_ICRF = self.eph.position('earthmoon', event.JulianDate)
                    moonvector_in_ICRF = self.eph.position('moon', event.JulianDate)
                    Earth_relative_to_solar_system_barycenter_in_ICRF = embarycenter_in_ICRF - moonvector_in_ICRF * self.eph.earth_share
                    Earth_relative_to_cb_in_ICRF = Earth_relative_to_solar_system_barycenter_in_ICRF + cb_relative_to_solar_system_barycenter_in_ICRF

                    #rotate the spacecraft state relative to the central body into the ICRF frame
                    spacecraft_state_relative_to_central_body_in_ICRF = AstroFunctions.rotate_from_ecliptic_to_equatorial3(np.array(event.SpacecraftState[0:3]))

                    #get the vector from the Earth to the Spacecraft
                    Earth_Spacecraft_Vector = spacecraft_state_relative_to_central_body_in_ICRF - np.transpose(Earth_relative_to_cb_in_ICRF)[0]

                    #return the magnitude of the Earth-centered position vector
                    EarthDistance = np.linalg.norm(Earth_Spacecraft_Vector) / self.LU

                    if PlotOptions.PlotEarthDistance:
                        reportfile.write(', ' + str(EarthDistance))
                    if PlotOptions.PlotSunSpacecraftEarthAngle:
                        cosAngle = np.dot(-Earth_Spacecraft_Vector, -spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(Earth_Spacecraft_Vector)
                        reportfile.write(', ' + str(np.arccos(cosAngle) * 180.0/math.pi))
                    if PlotOptions.PlotSpacecraftViewingAngle:
                        tanAngle = Earth_Spacecraft_Vector[2]/math.sqrt(Earth_Spacecraft_Vector[0]*Earth_Spacecraft_Vector[0]+Earth_Spacecraft_Vector[1]*Earth_Spacecraft_Vector[1])
                        reportfile.write(', ' + str(np.arctan(tanAngle) * 180.0/math.pi))   
                        
            if PlotOptions.PlotThrottleLevel:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust','PSFBthrust', 'end_spiral']:
                    if PlotOptions.throttlesetmode == 0:
                        reportfile.write(', ' + str(int(self.high_Mdot_set.find_nearest_throttle_setting_1D(event.ActivePower / event.Number_of_Active_Engines).TL.strip('TL'))))
                    elif PlotOptions.throttlesetmode == 1:
                        reportfile.write(', ' + str(int(self.low_Mdot_set.find_nearest_throttle_setting_1D(event.ActivePower / event.Number_of_Active_Engines).TL.strip('TL'))))
                    elif PlotOptions.throttlesetmode == 2:
                        print('2D throttle matching not currently implemented')
                else:
                    reportfile.write(', ' + str(0.0))
            #plot sun-boresight angle
            if PlotOptions.PlotSunBoresightAngle:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', "PSBIthrust",'PSFBthrust']:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    reportfile.write(', ' + str(math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            reportfile.write('\n')
Example #29
0
    mu = 1.0
    r_dot /= k
    r_now = r_last + r_dot * d_tau + 0.5 * accel(r_last, mu) * (d_tau ** 2)
    tau += d_tau

    while abs(tau) <= abs(end_tau):
        tau += d_tau
        temp = verlet_position(r_now, r_last, d_tau, mu)
        r_last = temp[1]
        r_now = temp[0]

    return r_now

AU = 149597870.7 # km/AU
epsilon = 23.43687   # obliquity of the Ecliptic
eph = Ephemeris(de421)

def location_to_angles(location):
    dec = asin(location.z)
    #print dec
    ra = acos(location.x/cos(dec))
    if location.y < 0:
        ra = 2 * pi - ra
    return degrees(ra), degrees(dec)

def get_ra_dec(r, julian_date):
    barycenter = eph.position('earthmoon', julian_date)
    moonvector = eph.position('moon', julian_date)
    earth = barycenter - moonvector * eph.earth_share
    R0 = vector(earth)/AU # This is the Sun to Earth center vector in Equatorial system
Example #30
0
class Journey(object):
    def __init__(self, parent):
        self.parent = parent

        self.missionevents = []
        self.journey_name = "AJourney"
        self.journey_number = 0
        self.central_body = "Sun"
        self.central_body_radius = 4.379e+6
        self.mu = 132712440017.99
        self.LU = 1.49597870691e+8
        self.TU = 5022642.890912973
        self.boundary_states = []
        self.flyby_periapse_states = [[0.0]*6]
        self.thruster_duty_cycle = 1.0
        self.journey_post_arrival_deltav = 0.0
        self.journey_post_arrival_propellant_used = 0.0
        self.journey_initial_mass_increment = 0.0
        self.journey_final_mass_increment = 0.0

        #default values for entry things
        self.journey_entryinterface_velocity_with_respect_to_rotating_atmosphere = 0.0
        self.journey_entry_landing_interface_point = [0.0]*6
        self.entry_latitude = 0.0
        self.entry_longitude = 0.0
        self.entry_sun_angle = 0.0
        self.journey_arrival_spacecraft_sun_Earth_angle = 180.0
        self.state_frame = ''
        self.alpha0 = 0.0
        self.delta0 = 0.0

    def PlotJourney(self, JourneyAxes, PlotOptions, CustomLabels = None):
        #plot each mission event
        BeforeMatchPoint = True
        if PlotOptions.ShowMissionEvents:
            for event in self.missionevents:
                #do we have a custom label?
                if CustomLabels != None:
                    for label in CustomLabels: #this is a list of lists, [eventNumber, labelstring]
                        if label[0] == event.EventNumber:
                            BeforeMatchPoint = event.PlotEvent(JourneyAxes, self.LU, self.TU, self.mu, PlotOptions, BeforeMatchPoint, label[1])
                        else:
                            BeforeMatchPoint = event.PlotEvent(JourneyAxes, self.LU, self.TU, self.mu, PlotOptions, BeforeMatchPoint)
                else:
                    BeforeMatchPoint = event.PlotEvent(JourneyAxes, self.LU, self.TU, self.mu, PlotOptions, BeforeMatchPoint)

        

    def PlotJourneyBoundaryOrbits(self, JourneyAxes, PlotOptions):
        from scipy.integrate import ode

        for boundaryStateIndex in range(0, len(self.boundary_states)):
            if not ((boundaryStateIndex == 0 and self.missionevents[0].Location == 'free point') \
                or (boundaryStateIndex == (len(self.boundary_states) - 1) and self.missionevents[-1].Location == 'free point')) \
                or PlotOptions.ShowFreePointBoundaryOrbits:
                boundarystate = self.boundary_states[boundaryStateIndex]
                BoundaryStateScaled = np.array(boundarystate) / self.LU
                BoundaryStateScaled[3:6] *= self.TU
                r = np.linalg.norm(BoundaryStateScaled[0:3])
                v = np.linalg.norm(BoundaryStateScaled[3:6])

                if r == 0.0:
                    continue
                
                a = r / (2.0 - r*v*v)
                if a > 0.0:
                    T = 2*math.pi*math.sqrt(a**3)
                else:
                    T = 2*math.pi*self.LU / self.TU

                StateIntegrateObject = ode(EOM.EOM_inertial_2body, jac=EOM.EOM_jacobian_intertial_2body).set_integrator('dop853', atol=1.0e-8, rtol=1.0e-8)
                StateIntegrateObject.set_initial_value(BoundaryStateScaled).set_f_params(1.0).set_jac_params(1.0)

                dt = T / 10000
                StateHistory = []

                epoch = (self.missionevents[0].JulianDate - 2451544.5) * 86400.0
                while StateIntegrateObject.successful() and StateIntegrateObject.t < T * 1.01:
                    epoch += dt * self.TU
                    stateArray = StateIntegrateObject.integrate(StateIntegrateObject.t + dt)
                    state = [stateArray[0] * self.LU, stateArray[1] * self.LU, stateArray[2] * self.LU, epoch]
                    StateHistory.append(state)

                X = []
                Y = []
                Z = []
                for StateLine in StateHistory:
                    if PlotOptions.PlotCentralBody != 'Journey central body':
                        import spiceypy
                        journey_central_body = self.central_body
                            
                        if journey_central_body in ['Mars','Jupiter','Uranus','Neptune','Pluto']:
                            journey_central_body = journey_central_body + ' Barycenter'

                        if journey_central_body != PlotOptions.PlotCentralBody:
                            body_state, LT = spiceypy.spkezr(journey_central_body, StateLine[-1], 'J2000', "None", PlotOptions.PlotCentralBody)
                            
                            X.append(StateLine[0] + body_state[0])
                            Y.append(StateLine[1] + body_state[1])
                            Z.append(StateLine[2] + body_state[2])
                        else:
                            X.append(StateLine[0])
                            Y.append(StateLine[1])
                            Z.append(StateLine[2])
                    else:
                        X.append(StateLine[0])
                        Y.append(StateLine[1])
                        Z.append(StateLine[2])

                JourneyAxes.plot(X, Y, Z, lw=1, c='0.75')

    def PlotJourneyCentralBodyOrbits(self, JourneyAxes, PlotOptions):
        if PlotOptions.PlotCentralBody != 'Journey central body':
            import spiceypy
            journey_central_body = self.central_body
                            
            if journey_central_body in ['Mars','Jupiter','Uranus','Neptune','Pluto']:
                journey_central_body = journey_central_body + ' Barycenter'

            if journey_central_body != PlotOptions.PlotCentralBody:
                body_state, LT = spiceypy.spkezr(journey_central_body, (self.missionevents[0].JulianDate - 2451545.0) * 86400.0, 'J2000', "None", PlotOptions.PlotCentralBody)
                
                
                r = np.linalg.norm(body_state[0:3])
                v = np.linalg.norm(body_state[3:6])

                mu = {'Mercury':                   22031.780000,
                      'Venus':                    324858.592000,
                      'Earth':                    398600.435436,
                      'Mars':                      42828.375214,
                      'Jupiter Barycenter':    126712764.800000,
                      'Saturn Barycenter':      37940585.200000,
                      'Uranus Barycenter':       5794548.600000,
                      'Neptune Barycenter':      6836527.100580,
                      'Pluto Barycenter':            977.000000,
                      'Sun':                132712440041.939400,
                      'Moon':                       4902.800066,
                      'Earth-Moon Barycenter':    403503.235502}

                elements = spiceypy.oscltx(body_state, (self.missionevents[0].JulianDate - 2451545.0) * 86400.0, mu[PlotOptions.PlotCentralBody])
                a = elements[-2]
                #a = r / (2.0 - r*v*v)
                if a > 0.0:
                    T = 2*math.pi  *math.sqrt(a**3 / mu[PlotOptions.PlotCentralBody]) 
                else:
                    T = 2*math.pi * self.TU

                t0 = (self.missionevents[0].JulianDate - 2451545.0) * 86400.0
                tf = t0 + T
                X = []
                Y = []
                Z = []
                for epoch in np.linspace(t0, tf, num=100):
                    body_state, LT = spiceypy.spkezr(journey_central_body, epoch, 'J2000', "None", PlotOptions.PlotCentralBody)
                            
                    X.append(body_state[0])
                    Y.append(body_state[1])
                    Z.append(body_state[2])

                JourneyAxes.plot(X, Y, Z, lw=1, c='0.75')

    def UpdateLabelPosition(self, Figure, Axes):
        for event in self.missionevents:
            event.UpdateLabelPosition(Figure, Axes)

    def PlotPhaseBoundariesOnDataPlot(self, DataAxes, PlotOptions, firstpass, Ybounds):

        #create vertical lines at important events
        date_string_vector = []
        boundarylegendflag = True
        burnlegendflag = True
        for event in self.missionevents:
            if event.EventType in ['upwr_flyby', 'pwr_flyby', 'LT_rndzvs', 'rendezvous', 'intercept', 'insertion', 'match-vinf', 'launch', 'departure', "begin_spiral", "end_spiral"]:
                event_epoch = datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date()
                if firstpass and boundarylegendflag:
                    DataAxes.plot([event_epoch]*2, Ybounds, c='k', marker='+', ls = '-.', lw=3)#, label='Phase boundary')
                    boundarylegendflag = False
                else:
                    DataAxes.plot([event_epoch]*2, Ybounds, c='k', marker='+', ls = '-.', lw=3)

            if event.EventType == 'chem_burn':
                event_epoch = datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date()
                if firstpass and burnlegendflag:
                    DataAxes.plot([event_epoch]*2, Ybounds, c='r', marker='+', ls = '-.', lw=3, label='Deep-Space Maneuver')
                    burnlegendflag = False
                else:
                    DataAxes.plot([event_epoch]*2, Ybounds, c='r', marker='+', ls = '-.', lw=3)


    def GenerateJourneyDataPlot(self, DataAxesLeft, DataAxesRight, PlotOptions, firstpass):
        import math
        import astropy
        #generate a vector of dates
        date_string_vector = []
        for event in self.missionevents:
            if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                date_string_vector.append(event.GregorianDate)

        date_vector = [datetime.datetime.strptime(d,'%m/%d/%Y').date() for d in date_string_vector]

        #dummy line across the bottom so that neither axes object crashes
        DataAxesLeft.plot(date_vector, np.zeros_like(date_vector), c='w', lw = 0.1)
        DataAxesRight.plot(date_vector, np.zeros_like(date_vector), c='w', lw = 0.1)

        #plot distance from central body
        if PlotOptions.PlotR:
            Rvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    Rvector.append(math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2) / self.LU)
            if firstpass:
                unitstring = 'LU'
                if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                    unitstring = 'AU'
                labelstring = 'Distance from ' + self.central_body + ' (' + unitstring + ')'
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2, label=labelstring)
            else:
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2)

        #plot velocity
        if PlotOptions.PlotV:
            Vvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    Vvector.append(math.sqrt(event.SpacecraftState[3]**2 + event.SpacecraftState[4]**2 + event.SpacecraftState[5]**2) / self.LU * self.TU)
            if firstpass:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.', label='Velocity magnitude (LU/TU)')
            else:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.')

        #plot Thrust
        if PlotOptions.PlotThrust:
            Thrustvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust']:
                    Thrustvector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) * 10.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Thrustvector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) * 10.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType == 'LT_spiral':
                    Thrustvector.append(event.AvailableThrust * self.thruster_duty_cycle*10.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Thrustvector.append(event.AvailableThrust * self.thruster_duty_cycle*10.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Thrustvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Thrustvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)


            if firstpass:
                DataAxesLeft.plot(shortDateVector, Thrustvector, c='r', lw=2, ls='--', label='Applied thrust (0.1 N)')
            else:
                DataAxesLeft.plot(shortDateVector, Thrustvector, c='r', lw=2, ls='--')

        #plot Isp
        if PlotOptions.PlotIsp:
            Ispvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    Ispvector.append(event.Isp / 1000.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Ispvector.append(event.Isp / 1000.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Ispvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Ispvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)

            if firstpass:
                DataAxesLeft.plot(shortDateVector, Ispvector, 'dodgerblue', lw=4, ls='-.', label='Isp (1000 s)')
            else:
                DataAxesLeft.plot(shortDateVector, Ispvector, 'dodgerblue', lw=4, ls='-.')

        #plot mass flow rate
        if PlotOptions.PlotMdot:
            Mdotvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    Mdotvector.append(event.MassFlowRate * 1.0e6)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Mdotvector.append(event.MassFlowRate * 1.0e6)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Mdotvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Mdotvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)

            if firstpass:
                DataAxesLeft.plot(shortDateVector, Mdotvector, c='brown', lw=2, ls='-', label='Mass flow rate (mg/s)')
            else:
                DataAxesLeft.plot(shortDateVector, Mdotvector, c='brown', lw=2, ls='-')

        #plot Efficiency
        if PlotOptions.PlotEfficiency:
            Efficiencyvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    Efficiencyvector.append(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower))
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Efficiencyvector.append(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower))
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Efficiencyvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Efficiencyvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)


            if firstpass:
                DataAxesLeft.plot(shortDateVector, Efficiencyvector, c='DarkGreen', lw=2, ls='-', label='Propulsion system efficiency')
            else:
                DataAxesLeft.plot(shortDateVector, Efficiencyvector, c='DarkGreen', lw=2, ls='-')

        #plot control magnitude
        if PlotOptions.PlotThrottle:
            Throttlevector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'PSBIthrust']:
                    Throttlevector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust))
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust))
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType in ['FBLTthrust','FBLTSthrust','PSFBthrust']:
                    Throttlevector.append(event.DVmagorThrottle)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(event.DVmagorThrottle)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType == 'LT_spiral':
                    Throttlevector.append(1.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(1.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Throttlevector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)

            if firstpass:
                DataAxesLeft.plot(shortDateVector, Throttlevector, c='r', lw=2, ls='--', label='Control magnitude')
            else:
                DataAxesLeft.plot(shortDateVector, Throttlevector, c='r', lw=2, ls='--')

        #plot power
        if PlotOptions.PlotPower:
            Powervector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    if event.AvailablePower > 0.0:
                        Powervector.append(event.AvailablePower)
                    else:
                        Powervector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Powervector, c='Navy', lw=2, ls='-.', label='Power available for propulsion (kW)')
            else:
                DataAxesLeft.plot(date_vector, Powervector, c='Navy', lw=2, ls='-.')

        #plot gamma
        if PlotOptions.PlotGamma:
            gammavector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    gammavector.append(math.atan2(event.Thrust[1], event.Thrust[0]) * 180.0 / math.pi)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesRight.plot(shortDateVector, gammavector, c='DarkGreen', lw=2, ls='--', label=r'$\gamma$ (degrees)')
            else:
                DataAxesRight.plot(shortDateVector, gammavector, c='DarkGreen', lw=2, ls='--')

        #plot delta
        if PlotOptions.PlotDelta:
            deltavector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    deltavector.append(math.asin(event.Thrust[2] / AppliedThrust) * 180.0 / math.pi)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesRight.plot(shortDateVector, deltavector, c='LightGreen', lw=2, ls='--', label=r'$\delta$ (degrees)')
            else:
                DataAxesRight.plot(shortDateVector, deltavector, c='LightGreen', lw=2, ls='--')


        #plot central body to thrust vector angle
        if PlotOptions.PlotArray_Thrust_Angle:
            CBthrustvector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    CBthrustvector.append( 90.0 - math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesRight.plot(shortDateVector, CBthrustvector, c='Salmon', marker='o', ls='None', label='Array to thrust angle (degrees)')
            else:
                DataAxesRight.plot(shortDateVector, CBthrustvector, c='Salmon', marker='o', ls='None')

        #plot mass
        if PlotOptions.PlotMass:
            mass = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    mass.append(event.Mass * 1.0e-3)
            if firstpass:
                DataAxesLeft.plot(date_vector, mass, c='DarkGrey', lw=2, ls='-', label='Mass (1000 kg)')
            else:
                DataAxesLeft.plot(date_vector, mass, c='DarkGrey', lw=2, ls='-')

        #plot number of active thrusters
        if PlotOptions.PlotNumberOfEngines:
            numberofengines = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    numberofengines.append(event.ActivePower)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesLeft.plot(shortDateVector, numberofengines, 'k*', mew=2, markersize=7, label='Number of active thrusters')
            else:
                DataAxesLeft.plot(shortDateVector, numberofengines, 'k*', mew=2, markersize=7)

        #plot power actively used by the thrusters
        if PlotOptions.PlotActivePower:
            activepowervector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    activepowervector.append(event.ActivePower)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesLeft.plot(shortDateVector, activepowervector, c='Navy', lw=2, ls='-', label='Power used by the propulsion system (kW)')
            else:
                DataAxesLeft.plot(shortDateVector, activepowervector, c='Navy', lw=2, ls='-')

        #plot waste heat from the propulsion system
        if PlotOptions.PlotWasteHeat:
            WasteHeatvector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    WasteHeatvector.append( (1 - event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower)) * event.ActivePower )
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesLeft.plot(shortDateVector, WasteHeatvector, c='Crimson', lw=2, ls='--', label='Waste heat from propulsion system (kW)')
            else:
                DataAxesLeft.plot(shortDateVector, WasteHeatvector, c='Crimson', lw=2, ls='--')

        #plot Earth distance in LU and SPE angle
        if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunSpacecraftEarthAngle or PlotOptions.PlotSpacecraftViewingAngle:
            if not 'sun' in self.central_body.lower():
                print('getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun')
            else:
                import de423
                from jplephem import Ephemeris
                eph = Ephemeris(de423)

                EarthDistanceVector = []
                SunSpacecraftEarthAngle = []
                SpacecraftViewingAngle = []
                for event in self.missionevents:
                    if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    
                        #get the position of the central body relative to the solar system barycenter
                        cb_relative_to_solar_system_barycenter_in_ICRF = eph.position('sun', event.JulianDate)

                        #get the position of the Earth relative to the central body
                        embarycenter_in_ICRF = eph.position('earthmoon', event.JulianDate)
                        moonvector_in_ICRF = eph.position('moon', event.JulianDate)
                        Earth_relative_to_solar_system_barycenter_in_ICRF = embarycenter_in_ICRF - moonvector_in_ICRF * eph.earth_share
                        Earth_relative_to_cb_in_ICRF = Earth_relative_to_solar_system_barycenter_in_ICRF + cb_relative_to_solar_system_barycenter_in_ICRF

                        #rotate the spacecraft state relative to the central body into the ICRF frame
                        spacecraft_state_relative_to_central_body_in_ICRF = AstroFunctions.rotate_from_ecliptic_to_equatorial3(np.array(event.SpacecraftState[0:3]))

                        #get the vector from the Earth to the Spacecraft
                        Earth_Spacecraft_Vector = spacecraft_state_relative_to_central_body_in_ICRF - np.transpose(Earth_relative_to_cb_in_ICRF)[0]

                        #return the magnitude of the Earth-centered position vector
                        EarthDistanceVector.append(np.linalg.norm(Earth_Spacecraft_Vector) / self.LU)

                        #if applicable, compute sun-spacecraft-Earth angle
                        if PlotOptions.PlotSunSpacecraftEarthAngle:
                            cosAngle = np.dot(-Earth_Spacecraft_Vector, -spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(Earth_Spacecraft_Vector)
                            SunSpacecraftEarthAngle.append(np.arccos(cosAngle) * 180.0/math.pi)
                            
                        if PlotOptions.PlotSpacecraftViewingAngle:
                            tanAngle = Earth_Spacecraft_Vector[2]/math.sqrt(Earth_Spacecraft_Vector[0]*Earth_Spacecraft_Vector[0]+Earth_Spacecraft_Vector[1]*Earth_Spacecraft_Vector[1])
                            SpacecraftViewingAngle.append(np.arctan(tanAngle) * 180.0/math.pi)  
                
                if PlotOptions.PlotEarthDistance:
                    if firstpass:
                        unitstring = 'LU'
                        if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                            unitstring = 'AU'
                        labelstring = 'Distance from Earth (' + unitstring + ')'
                        DataAxesLeft.plot(date_vector, EarthDistanceVector, c='g', lw=2, label=labelstring)
                    else:
                        DataAxesLeft.plot(date_vector, EarthDistanceVector, c='g', lw=2)
                if PlotOptions.PlotSunSpacecraftEarthAngle:
                    if firstpass:
                        DataAxesRight.plot(date_vector, SunSpacecraftEarthAngle, c='orangered', lw=2, ls = '-.', label='Sun-Spacecraft-Earth Angle')
                    else:
                        DataAxesRight.plot(date_vector, SunSpacecraftEarthAngle, c='orangered', lw=2, ls = '-.')
                if PlotOptions.PlotSpacecraftViewingAngle:
                    if firstpass:
                        DataAxesRight.plot(date_vector, SpacecraftViewingAngle, c='orangered', lw=2, ls = '-.', label='Latitude of Earth-Spacecraft Vector')
                    else:
                        DataAxesRight.plot(date_vector, SpacecraftViewingAngle, c='orangered', lw=2, ls = '-.')

        #plot throttle level
        if PlotOptions.PlotThrottleLevel:            
            ThrottleLevelVector = []
            shortDateVector = []
        
            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    ThrottleLevelVector.append(event.ThrottleLevel)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())
                    
            if firstpass:
                DataAxesLeft.scatter(shortDateVector, ThrottleLevelVector, c='midnightblue', marker='h' , label='Throttle level')
            else:                                                                                   
                DataAxesLeft.scatter(shortDateVector, ThrottleLevelVector, c='midnightblue', marker='h' )
                
        #plot sun-boresight angle
        if PlotOptions.PlotSunBoresightAngle:
            SunBoresightAngle = []
            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSFBthrust', "PSBIthrust"]:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = -event.SpacecraftState[0]*event.Thrust[0] - event.SpacecraftState[1]*event.Thrust[1] - event.SpacecraftState[2]*event.Thrust[2]
                    SunBoresightAngle.append(math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    SunBoresightAngle.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector, SunBoresightAngle, c='purple', marker='o', ls='None', label='Sun-to-Boresight angle (degrees)')
            else:
                DataAxesRight.plot(date_vector, SunBoresightAngle, c='purple', marker='o', ls='None')
        
        #DataAxesLeft.set_ylim(bottom=-0.7)
        #DataAxesRight.set_ylim(bottom=-0.7)
        #DataAxesLeft.set_ylim([-0.2,2.5])
        #DataAxesLeft.set_ylim([-0.2,2.5])

    def WriteDateReport(self, PlotOptions, reportfile):
        #write header
        reportfile.write('JD, MM-DD-YYYY, Event duration (days), Event type, Event location')
        if PlotOptions.IncludeStateVectorInReport:
            reportfile.write(',x (km), y (km), z (km), xdot (km/s), ydot (km/s), zdot (km/s)')
        if PlotOptions.PlotR:
            unitstring = 'LU'
            if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                unitstring = 'AU'
            reportfile.write(', Distance from ' + self.central_body + ' (' + unitstring + ')')
        if PlotOptions.PlotV:
            reportfile.write(', Velocity magnitude (LU/TU)')
        if PlotOptions.PlotThrust:
            reportfile.write(', Applied thrust (N)')
        if PlotOptions.PlotIsp:
            reportfile.write(', Isp (s)')
        if PlotOptions.PlotMdot:
            reportfile.write(', Mass flow rate (kg/s)')
        if PlotOptions.PlotEfficiency:
            reportfile.write(', Propulsion system efficiency')
        if PlotOptions.PlotThrottle:
            reportfile.write(', Control magnitude')
        if PlotOptions.PlotPower:
            reportfile.write(', Power produced by spacecraft (kW)')
        if PlotOptions.PlotGamma:
            reportfile.write(', in-plane control angle (degrees)')
        if PlotOptions.PlotDelta:
            reportfile.write(', out-of-plane control angle (degrees)')
        if PlotOptions.PlotArray_Thrust_Angle:
            reportfile.write(', Array to thrust angle (degrees)')
        if PlotOptions.PlotMass:
            reportfile.write(', Mass (kg)')
        if PlotOptions.PlotNumberOfEngines:
            reportfile.write(', Number of active thrusters')
        if PlotOptions.PlotActivePower:
            reportfile.write(', Power used by the propulsion system (kW)')
        if PlotOptions.PlotWasteHeat:
            reportfile.write(', Waste heat from propulsion system (kW)')  
        if PlotOptions.PlotEarthDistance:
            unitstring = 'LU'
            if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                unitstring = 'AU'
            reportfile.write(', Distance from Earth (' + unitstring + ')')
        if PlotOptions.PlotSunSpacecraftEarthAngle:
            reportfile.write(', Sun-Spacecraft-Earth Angle')
        if PlotOptions.PlotSpacecraftViewingAngle:
            reportfile.write(', Latitude of Earth-Spacecraft Vector')
        if PlotOptions.PlotThrottleLevel:
            reportfile.write(', Throttle level')
        if PlotOptions.PlotSunBoresightAngle:
            reportfile.write(', Sun-Boresight Angle')
        reportfile.write('\n')

        #load stuff if necessary
        if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunSpacecraftEarthAngle or PlotOptions.PlotSpacecraftViewingAngle:
            if not 'sun' in self.central_body.lower():
                print('getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun')
            else:
                import de423
                from jplephem import Ephemeris
                self.eph = Ephemeris(de423)
        if PlotOptions.PlotThrottleLevel:
            #instantiate a throttle table object
            thruster_throttle_table = ThrottleTable.ThrottleTable(PlotOptions.throttletablefile)
            self.high_Mdot_set, self.low_Mdot_set = thruster_throttle_table.create_non_dominated_sets()

        #now print the report
        for event in self.missionevents:
            reportfile.write(str(event.JulianDate))
            reportfile.write(', ' + event.GregorianDate)
            reportfile.write(', ' + str(event.TimestepLength))
            reportfile.write(', ' + event.EventType)
            reportfile.write(', ' + event.Location)
            if PlotOptions.IncludeStateVectorInReport:
                for state in event.SpacecraftState:
                    reportfile.write(', ' + str(state))
            if PlotOptions.PlotR:
                reportfile.write(', ' + str(math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2) / self.LU))
            if PlotOptions.PlotV:
                reportfile.write(', ' + str(math.sqrt(event.SpacecraftState[3]**2 + event.SpacecraftState[4]**2 + event.SpacecraftState[5]**2) / self.LU * self.TU))
            if PlotOptions.PlotThrust:
                if event.EventType not in ['match_point','upwr_flyby','pwr_flyby','LT_rndzvs','LT_spiral']:
                    reportfile.write(', ' + str(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)))
                elif event.EventType == 'LT_spiral':
                    reportfile.write(', ' + str(event.AvailableThrust * self.thruster_duty_cycle))
                else:
                    reportfile.write(', 0.0')
            if PlotOptions.PlotIsp:
                reportfile.write(', ' + str(event.Isp))
            if PlotOptions.PlotMdot:
                reportfile.write(', ' + str(event.MassFlowRate))
            if PlotOptions.PlotEfficiency:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower)))
                else:
                    reportfile.write(', 0.0')
            if PlotOptions.PlotThrottle:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust']:
                    reportfile.write(', ' + str(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust * self.thruster_duty_cycle)))
                elif event.EventType == 'LT_spiral':
                    reportfile.write(', ' + str(1.0))
                elif event.EventType not in ['match_point','upwr_flyby','pwr_flyby','LT_rndzvs']:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotPower:
                if event.EventType not in ['match_point','upwr_flyby','pwr_flyby','LT_rndzvs']:
                    if (event.AvailablePower > 0.0):
                        reportfile.write(', ' + str(event.AvailablePower))
                    else:
                        reportfile.write(', ' + str(0.0))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotGamma:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(math.atan2(event.Thrust[1], event.Thrust[0]) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotDelta:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    reportfile.write(', ' + str(math.asin(event.Thrust[2] / AppliedThrust) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotArray_Thrust_Angle:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    reportfile.write(', ' + str(math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotMass:
                reportfile.write(', ' + str(event.Mass))
            if PlotOptions.PlotNumberOfEngines:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(event.Number_of_Active_Engines))
                else:
                    reportfile.write(', ' + str(0))
            if PlotOptions.PlotActivePower:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str(event.ActivePower))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotWasteHeat:
                if event.EventType in ['SFthrust', 'SSFthrust','FBLTSthrust','FBLTthrust','PSBIthrust','PSFBthrust','LT_spiral']:
                    reportfile.write(', ' + str((1.0 - event.AvailableThrust * event.Isp * 9.80665 / (2000.0 * event.ActivePower)) * event.ActivePower))
                else:
                    reportfile.write(', ' + str(0.0))
            if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunSpacecraftEarthAngle or PlotOptions.PlotSpacecraftViewingAngle:
                if not 'sun' in self.central_body.lower():
                    print('getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun')
                else:
                    #get the position of the central body relative to the solar system barycenter
                    cb_relative_to_solar_system_barycenter_in_ICRF = self.eph.position('sun', event.JulianDate)

                    #get the position of the Earth relative to the central body
                    embarycenter_in_ICRF = self.eph.position('earthmoon', event.JulianDate)
                    moonvector_in_ICRF = self.eph.position('moon', event.JulianDate)
                    Earth_relative_to_solar_system_barycenter_in_ICRF = embarycenter_in_ICRF - moonvector_in_ICRF * self.eph.earth_share
                    Earth_relative_to_cb_in_ICRF = Earth_relative_to_solar_system_barycenter_in_ICRF + cb_relative_to_solar_system_barycenter_in_ICRF

                    #rotate the spacecraft state relative to the central body into the ICRF frame
                    spacecraft_state_relative_to_central_body_in_ICRF = AstroFunctions.rotate_from_ecliptic_to_equatorial3(np.array(event.SpacecraftState[0:3]))

                    #get the vector from the Earth to the Spacecraft
                    Earth_Spacecraft_Vector = spacecraft_state_relative_to_central_body_in_ICRF - np.transpose(Earth_relative_to_cb_in_ICRF)[0]

                    #return the magnitude of the Earth-centered position vector
                    EarthDistance = np.linalg.norm(Earth_Spacecraft_Vector) / self.LU

                    if PlotOptions.PlotEarthDistance:
                        reportfile.write(', ' + str(EarthDistance))
                    if PlotOptions.PlotSunSpacecraftEarthAngle:
                        cosAngle = np.dot(-Earth_Spacecraft_Vector, -spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(Earth_Spacecraft_Vector)
                        reportfile.write(', ' + str(np.arccos(cosAngle) * 180.0/math.pi))
                    if PlotOptions.PlotSpacecraftViewingAngle:
                        tanAngle = Earth_Spacecraft_Vector[2]/math.sqrt(Earth_Spacecraft_Vector[0]*Earth_Spacecraft_Vector[0]+Earth_Spacecraft_Vector[1]*Earth_Spacecraft_Vector[1])
                        reportfile.write(', ' + str(np.arctan(tanAngle) * 180.0/math.pi))   
                        
            if PlotOptions.PlotThrottleLevel:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust','PSFBthrust', 'end_spiral']:
                    if PlotOptions.throttlesetmode == 0:
                        reportfile.write(', ' + str(int(self.high_Mdot_set.find_nearest_throttle_setting_1D(event.ActivePower / event.Number_of_Active_Engines).TL.strip('TL'))))
                    elif PlotOptions.throttlesetmode == 1:
                        reportfile.write(', ' + str(int(self.low_Mdot_set.find_nearest_throttle_setting_1D(event.ActivePower / event.Number_of_Active_Engines).TL.strip('TL'))))
                    elif PlotOptions.throttlesetmode == 2:
                        print('2D throttle matching not currently implemented')
                else:
                    reportfile.write(', ' + str(0.0))
            #plot sun-boresight angle
            if PlotOptions.PlotSunBoresightAngle:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', "PSBIthrust",'PSFBthrust']:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    reportfile.write(', ' + str(math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi))
                else:
                    reportfile.write(', ' + str(0.0))
            reportfile.write('\n')

    def AutoTableJourney(self, TableFile, PlotOptions, skipNext):
        for event in self.missionevents:
            skipNext = event.AutoTableLine(TableFile, PlotOptions, skipNext)
        return skipNext

    def getManeuver(self, phaseIndex = 0, maneuverIndex = 0):
        #function to get the nth DSM/TCM in a phase
        #if that maneuver does not exist, return None
        
        #Step 1: search through the journey to find the right phase. We do this by counting the number of boundary events until we get to the end of the journey or the phase that we want
        #since phase boundaries are always upwr_flyby or pwr_flyby, this isn't too hard!
        phaseCount = 0
        maneuverCount = 0
        for event in self.missionevents:
            if event.EventType in ['pwr_flyby','upwr_flyby']:
                phaseCount += 1
                maneuverCount = 0

            if event.EventType == 'chem_burn':
                if maneuverCount == maneuverIndex:
                    #this is the maneuver that we want, so return it
                    return event
                
                #if we didn't just return, increment the maneuver count
                maneuverCount += 1

        #if we got this far then the event that the user asked for does not exist, so return "none"
        return None

    def getPeriapseDistance(self, scale = None):
        r_min = 1.0e+10

        if scale == None:
            scale = self.LU

        for event in self.missionevents:
            r = (event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2 ) ** 0.5

            if r < r_min:
                r_min = r

        return r_min / scale
Example #31
0
    def GenerateJourneyDataPlot(self, DataAxesLeft, DataAxesRight, PlotOptions, firstpass):
        import math
        import astropy
        #generate a vector of dates
        date_string_vector = []
        for event in self.missionevents:
            if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                date_string_vector.append(event.GregorianDate)

        date_vector = [datetime.datetime.strptime(d,'%m/%d/%Y').date() for d in date_string_vector]

        #dummy line across the bottom so that neither axes object crashes
        DataAxesLeft.plot(date_vector, np.zeros_like(date_vector), c='w', lw = 0.1)
        DataAxesRight.plot(date_vector, np.zeros_like(date_vector), c='w', lw = 0.1)

        #plot distance from central body
        if PlotOptions.PlotR:
            Rvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    Rvector.append(math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2) / self.LU)
            if firstpass:
                unitstring = 'LU'
                if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                    unitstring = 'AU'
                labelstring = 'Distance from ' + self.central_body + ' (' + unitstring + ')'
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2, label=labelstring)
            else:
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2)

        #plot velocity
        if PlotOptions.PlotV:
            Vvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    Vvector.append(math.sqrt(event.SpacecraftState[3]**2 + event.SpacecraftState[4]**2 + event.SpacecraftState[5]**2) / self.LU * self.TU)
            if firstpass:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.', label='Velocity magnitude (LU/TU)')
            else:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.')

        #plot Thrust
        if PlotOptions.PlotThrust:
            Thrustvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust']:
                    Thrustvector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) * 10.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Thrustvector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) * 10.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType == 'LT_spiral':
                    Thrustvector.append(event.AvailableThrust * self.thruster_duty_cycle*10.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Thrustvector.append(event.AvailableThrust * self.thruster_duty_cycle*10.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Thrustvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Thrustvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)


            if firstpass:
                DataAxesLeft.plot(shortDateVector, Thrustvector, c='r', lw=2, ls='--', label='Applied thrust (0.1 N)')
            else:
                DataAxesLeft.plot(shortDateVector, Thrustvector, c='r', lw=2, ls='--')

        #plot Isp
        if PlotOptions.PlotIsp:
            Ispvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    Ispvector.append(event.Isp / 1000.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Ispvector.append(event.Isp / 1000.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Ispvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Ispvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)

            if firstpass:
                DataAxesLeft.plot(shortDateVector, Ispvector, 'dodgerblue', lw=4, ls='-.', label='Isp (1000 s)')
            else:
                DataAxesLeft.plot(shortDateVector, Ispvector, 'dodgerblue', lw=4, ls='-.')

        #plot mass flow rate
        if PlotOptions.PlotMdot:
            Mdotvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    Mdotvector.append(event.MassFlowRate * 1.0e6)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Mdotvector.append(event.MassFlowRate * 1.0e6)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Mdotvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Mdotvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)

            if firstpass:
                DataAxesLeft.plot(shortDateVector, Mdotvector, c='brown', lw=2, ls='-', label='Mass flow rate (mg/s)')
            else:
                DataAxesLeft.plot(shortDateVector, Mdotvector, c='brown', lw=2, ls='-')

        #plot Efficiency
        if PlotOptions.PlotEfficiency:
            Efficiencyvector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    Efficiencyvector.append(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower))
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Efficiencyvector.append(event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower))
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Efficiencyvector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Efficiencyvector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)


            if firstpass:
                DataAxesLeft.plot(shortDateVector, Efficiencyvector, c='DarkGreen', lw=2, ls='-', label='Propulsion system efficiency')
            else:
                DataAxesLeft.plot(shortDateVector, Efficiencyvector, c='DarkGreen', lw=2, ls='-')

        #plot control magnitude
        if PlotOptions.PlotThrottle:
            Throttlevector = []
            shortDateVector = []

            for event in self.missionevents:
                epoch = astropy.time.Time(event.JulianDate, format='jd', scale='tdb')
                if event.EventType in ['SFthrust', 'SSFthrust', 'PSBIthrust']:
                    Throttlevector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust))
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2) / (event.AvailableThrust))
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType in ['FBLTthrust','FBLTSthrust','PSFBthrust']:
                    Throttlevector.append(event.DVmagorThrottle)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(event.DVmagorThrottle)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType == 'LT_spiral':
                    Throttlevector.append(1.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(1.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)
                elif event.EventType != 'match_point':
                    Throttlevector.append(0.0)
                    shortDateVector.append((epoch - event.TimestepLength / 2).datetime)
                    Throttlevector.append(0.0)
                    shortDateVector.append((epoch + event.TimestepLength / 2).datetime)

            if firstpass:
                DataAxesLeft.plot(shortDateVector, Throttlevector, c='r', lw=2, ls='--', label='Control magnitude')
            else:
                DataAxesLeft.plot(shortDateVector, Throttlevector, c='r', lw=2, ls='--')

        #plot power
        if PlotOptions.PlotPower:
            Powervector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    if event.AvailablePower > 0.0:
                        Powervector.append(event.AvailablePower)
                    else:
                        Powervector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector, Powervector, c='Navy', lw=2, ls='-.', label='Power available for propulsion (kW)')
            else:
                DataAxesLeft.plot(date_vector, Powervector, c='Navy', lw=2, ls='-.')

        #plot gamma
        if PlotOptions.PlotGamma:
            gammavector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    gammavector.append(math.atan2(event.Thrust[1], event.Thrust[0]) * 180.0 / math.pi)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesRight.plot(shortDateVector, gammavector, c='DarkGreen', lw=2, ls='--', label=r'$\gamma$ (degrees)')
            else:
                DataAxesRight.plot(shortDateVector, gammavector, c='DarkGreen', lw=2, ls='--')

        #plot delta
        if PlotOptions.PlotDelta:
            deltavector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    deltavector.append(math.asin(event.Thrust[2] / AppliedThrust) * 180.0 / math.pi)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesRight.plot(shortDateVector, deltavector, c='LightGreen', lw=2, ls='--', label=r'$\delta$ (degrees)')
            else:
                DataAxesRight.plot(shortDateVector, deltavector, c='LightGreen', lw=2, ls='--')


        #plot central body to thrust vector angle
        if PlotOptions.PlotArray_Thrust_Angle:
            CBthrustvector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0]*event.Thrust[0] + event.SpacecraftState[1]*event.Thrust[1] + event.SpacecraftState[2]*event.Thrust[2]
                    CBthrustvector.append( 90.0 - math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesRight.plot(shortDateVector, CBthrustvector, c='Salmon', marker='o', ls='None', label='Array to thrust angle (degrees)')
            else:
                DataAxesRight.plot(shortDateVector, CBthrustvector, c='Salmon', marker='o', ls='None')

        #plot mass
        if PlotOptions.PlotMass:
            mass = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    mass.append(event.Mass * 1.0e-3)
            if firstpass:
                DataAxesLeft.plot(date_vector, mass, c='DarkGrey', lw=2, ls='-', label='Mass (1000 kg)')
            else:
                DataAxesLeft.plot(date_vector, mass, c='DarkGrey', lw=2, ls='-')

        #plot number of active thrusters
        if PlotOptions.PlotNumberOfEngines:
            numberofengines = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    numberofengines.append(event.ActivePower)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesLeft.plot(shortDateVector, numberofengines, 'k*', mew=2, markersize=7, label='Number of active thrusters')
            else:
                DataAxesLeft.plot(shortDateVector, numberofengines, 'k*', mew=2, markersize=7)

        #plot power actively used by the thrusters
        if PlotOptions.PlotActivePower:
            activepowervector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    activepowervector.append(event.ActivePower)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesLeft.plot(shortDateVector, activepowervector, c='Navy', lw=2, ls='-', label='Power used by the propulsion system (kW)')
            else:
                DataAxesLeft.plot(shortDateVector, activepowervector, c='Navy', lw=2, ls='-')

        #plot waste heat from the propulsion system
        if PlotOptions.PlotWasteHeat:
            WasteHeatvector = []
            shortDateVector = []

            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    WasteHeatvector.append( (1 - event.AvailableThrust * event.Isp * 9.80665 / (2000 * event.ActivePower)) * event.ActivePower )
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())

            if firstpass:
                DataAxesLeft.plot(shortDateVector, WasteHeatvector, c='Crimson', lw=2, ls='--', label='Waste heat from propulsion system (kW)')
            else:
                DataAxesLeft.plot(shortDateVector, WasteHeatvector, c='Crimson', lw=2, ls='--')

        #plot Earth distance in LU and SPE angle
        if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunSpacecraftEarthAngle or PlotOptions.PlotSpacecraftViewingAngle:
            if not 'sun' in self.central_body.lower():
                print('getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun')
            else:
                import de423
                from jplephem import Ephemeris
                eph = Ephemeris(de423)

                EarthDistanceVector = []
                SunSpacecraftEarthAngle = []
                SpacecraftViewingAngle = []
                for event in self.missionevents:
                    if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    
                        #get the position of the central body relative to the solar system barycenter
                        cb_relative_to_solar_system_barycenter_in_ICRF = eph.position('sun', event.JulianDate)

                        #get the position of the Earth relative to the central body
                        embarycenter_in_ICRF = eph.position('earthmoon', event.JulianDate)
                        moonvector_in_ICRF = eph.position('moon', event.JulianDate)
                        Earth_relative_to_solar_system_barycenter_in_ICRF = embarycenter_in_ICRF - moonvector_in_ICRF * eph.earth_share
                        Earth_relative_to_cb_in_ICRF = Earth_relative_to_solar_system_barycenter_in_ICRF + cb_relative_to_solar_system_barycenter_in_ICRF

                        #rotate the spacecraft state relative to the central body into the ICRF frame
                        spacecraft_state_relative_to_central_body_in_ICRF = AstroFunctions.rotate_from_ecliptic_to_equatorial3(np.array(event.SpacecraftState[0:3]))

                        #get the vector from the Earth to the Spacecraft
                        Earth_Spacecraft_Vector = spacecraft_state_relative_to_central_body_in_ICRF - np.transpose(Earth_relative_to_cb_in_ICRF)[0]

                        #return the magnitude of the Earth-centered position vector
                        EarthDistanceVector.append(np.linalg.norm(Earth_Spacecraft_Vector) / self.LU)

                        #if applicable, compute sun-spacecraft-Earth angle
                        if PlotOptions.PlotSunSpacecraftEarthAngle:
                            cosAngle = np.dot(-Earth_Spacecraft_Vector, -spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(spacecraft_state_relative_to_central_body_in_ICRF)/np.linalg.norm(Earth_Spacecraft_Vector)
                            SunSpacecraftEarthAngle.append(np.arccos(cosAngle) * 180.0/math.pi)
                            
                        if PlotOptions.PlotSpacecraftViewingAngle:
                            tanAngle = Earth_Spacecraft_Vector[2]/math.sqrt(Earth_Spacecraft_Vector[0]*Earth_Spacecraft_Vector[0]+Earth_Spacecraft_Vector[1]*Earth_Spacecraft_Vector[1])
                            SpacecraftViewingAngle.append(np.arctan(tanAngle) * 180.0/math.pi)  
                
                if PlotOptions.PlotEarthDistance:
                    if firstpass:
                        unitstring = 'LU'
                        if 'sun' in self.central_body.lower() and math.fabs(self.LU - 149597870.69100001) < 1.0:
                            unitstring = 'AU'
                        labelstring = 'Distance from Earth (' + unitstring + ')'
                        DataAxesLeft.plot(date_vector, EarthDistanceVector, c='g', lw=2, label=labelstring)
                    else:
                        DataAxesLeft.plot(date_vector, EarthDistanceVector, c='g', lw=2)
                if PlotOptions.PlotSunSpacecraftEarthAngle:
                    if firstpass:
                        DataAxesRight.plot(date_vector, SunSpacecraftEarthAngle, c='orangered', lw=2, ls = '-.', label='Sun-Spacecraft-Earth Angle')
                    else:
                        DataAxesRight.plot(date_vector, SunSpacecraftEarthAngle, c='orangered', lw=2, ls = '-.')
                if PlotOptions.PlotSpacecraftViewingAngle:
                    if firstpass:
                        DataAxesRight.plot(date_vector, SpacecraftViewingAngle, c='orangered', lw=2, ls = '-.', label='Latitude of Earth-Spacecraft Vector')
                    else:
                        DataAxesRight.plot(date_vector, SpacecraftViewingAngle, c='orangered', lw=2, ls = '-.')

        #plot throttle level
        if PlotOptions.PlotThrottleLevel:            
            ThrottleLevelVector = []
            shortDateVector = []
        
            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSBIthrust', 'PSFBthrust', 'LT_spiral']:
                    ThrottleLevelVector.append(event.ThrottleLevel)
                    shortDateVector.append(datetime.datetime.strptime(event.GregorianDate,'%m/%d/%Y').date())
                    
            if firstpass:
                DataAxesLeft.scatter(shortDateVector, ThrottleLevelVector, c='midnightblue', marker='h' , label='Throttle level')
            else:                                                                                   
                DataAxesLeft.scatter(shortDateVector, ThrottleLevelVector, c='midnightblue', marker='h' )
                
        #plot sun-boresight angle
        if PlotOptions.PlotSunBoresightAngle:
            SunBoresightAngle = []
            for event in self.missionevents:
                if event.EventType in ['SFthrust', 'SSFthrust', 'FBLTSthrust', 'FBLTthrust', 'PSFBthrust', "PSBIthrust"]:
                    r = math.sqrt(event.SpacecraftState[0]**2 + event.SpacecraftState[1]**2 + event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 + event.Thrust[2]**2)
                    rdotT = -event.SpacecraftState[0]*event.Thrust[0] - event.SpacecraftState[1]*event.Thrust[1] - event.SpacecraftState[2]*event.Thrust[2]
                    SunBoresightAngle.append(math.acos( rdotT / (r * AppliedThrust) ) * 180.0 / math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby' and event.EventType != 'LT_rndzvs':
                    SunBoresightAngle.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector, SunBoresightAngle, c='purple', marker='o', ls='None', label='Sun-to-Boresight angle (degrees)')
            else:
                DataAxesRight.plot(date_vector, SunBoresightAngle, c='purple', marker='o', ls='None')
Example #32
0
class Tests(TestCase):

    def setUp(self):
        import de421
        self.e = Ephemeris(de421)

    def check0(self, xyz, xyzdot=None):
        eq = partial(self.assertAlmostEqual, delta=1.0)
        x, y, z = xyz
        eq(x, 39705023.28)
        eq(y, 131195345.65)
        eq(z, 56898495.41)
        if xyzdot is None:
            return
        dx, dy, dz = xyzdot
        eq(dx, -2524248.19)
        eq(dy, 619970.11)
        eq(dz, 268928.26)

    def check1(self, xyz, xyzdot=None):
        eq = partial(self.assertAlmostEqual, delta=1.0)
        x, y, z = xyz
        eq(x, -144692624.00)
        eq(y, -32707965.14)
        eq(z, -14207167.26)
        if xyzdot is None:
            return
        dx, dy, dz = xyzdot
        eq(dx, 587334.38)
        eq(dy, -2297419.36)
        eq(dz, -996628.74)

    def test_names(self):
        self.assertEqual(self.e.names,  (
            'earthmoon', 'jupiter', 'librations', 'mars', 'mercury',
            'moon', 'neptune', 'nutations', 'pluto', 'saturn', 'sun',
            'uranus', 'venus',
            ))

    def test_scalar_tdb(self):
        self.check0(self.e.position('earthmoon', 2414994.0))
        self.check1(self.e.position('earthmoon', 2415112.5))

    def test_scalar_tdb2(self):
        self.check0(self.e.position('earthmoon', 2414990.0, 4.0))
        self.check1(self.e.position('earthmoon', 2415110.0, 2.5))

    def test_scalar_tdb_keyword(self):
        self.check0(self.e.position('earthmoon', tdb=2414994.0))
        self.check1(self.e.position('earthmoon', tdb=2415112.5))

    def test_scalar_tdb2_keyword(self):
        self.check0(self.e.position('earthmoon', tdb=2414990.0, tdb2=4.0))
        self.check1(self.e.position('earthmoon', tdb=2415110.0, tdb2=2.5))

    def check_2d_result(self, name, tdb, tdb2):
        p = self.e.position(name, tdb + tdb2)
        self.check0(p[:,0])
        self.check1(p[:,1])

        p = self.e.position(name, tdb, tdb2)
        self.check0(p[:,0])
        self.check1(p[:,1])

        p, v = self.e.position_and_velocity(name, tdb + tdb2)
        self.check0(p[:,0], v[:,0])
        self.check1(p[:,1], v[:,1])

        p, v = self.e.position_and_velocity(name, tdb, tdb2)
        self.check0(p[:,0], v[:,0])
        self.check1(p[:,1], v[:,1])

    def test_array_tdb(self):
        tdb = np.array([2414994.0, 2415112.5])
        tdb2 = 0.0
        self.check_2d_result('earthmoon', tdb, tdb2)

    def test_array_tdb_scalar_tdb2(self):
        tdb = np.array([2414991.5, 2415110.0])
        tdb2 = 2.5
        self.check_2d_result('earthmoon', tdb, tdb2)

    def test_scalar_tdb_array_tdb2(self):
        tdb = 2414990.0
        d = 2415112.5 - tdb
        tdb2 = np.array([4.0, d])
        self.check_2d_result('earthmoon', tdb, tdb2)

    def test_array_tdb_array_tdb2(self):
        tdb = np.array([2414990.0, 2415110.0])
        tdb2 = np.array([4.0, 2.5])
        self.check_2d_result('earthmoon', tdb, tdb2)

    def test_legacy_compute_method(self):
        pv = self.e.compute('earthmoon', 2414994.0)
        self.check0(pv[:3], pv[3:])
        pv = self.e.compute('earthmoon', np.array([2414994.0, 2415112.5]))
        self.check0(pv[:3,0], pv[3:,0])
        self.check1(pv[:3,1], pv[3:,1])

    def test_ephemeris_end_date(self):
        x, y, z = self.e.position('earthmoon', self.e.jomega)
        self.assertAlmostEqual(x, -94189805.73967789, delta=1.0)
        self.assertAlmostEqual(y, 1.05103857e+08, delta=1.0)
        self.assertAlmostEqual(z, 45550861.44383482, delta=1.0)

    def test_too_early_date(self):
        tdb = self.e.jalpha - 0.01
        self.assertRaises(DateError, self.e.position, 'earthmoon', tdb)

    def test_too_late_date(self):
        tdb = self.e.jomega + 16.01
        self.assertRaises(DateError, self.e.position, 'earthmoon', tdb)
Example #33
0
    def GenerateJourneyDataPlot(self, DataAxesLeft, DataAxesRight, PlotOptions,
                                firstpass):

        #generate a vector of dates
        date_string_vector = []
        for event in self.missionevents:
            if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                date_string_vector.append(event.GregorianDate)

        date_vector = [
            datetime.datetime.strptime(d, '%m/%d/%Y').date()
            for d in date_string_vector
        ]

        #dummy line across the bottom so that neither axes object crashes
        DataAxesLeft.plot(date_vector,
                          np.zeros_like(date_vector),
                          c='w',
                          lw=0.1)
        DataAxesRight.plot(date_vector,
                           np.zeros_like(date_vector),
                           c='w',
                           lw=0.1)

        #plot distance from central body
        if PlotOptions.PlotR:
            Rvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Rvector.append(
                        math.sqrt(event.SpacecraftState[0]**2 +
                                  event.SpacecraftState[1]**2 +
                                  event.SpacecraftState[2]**2) / self.LU)
            if firstpass:
                unitstring = 'LU'
                if self.central_body.lower(
                ) == 'sun' and math.fabs(self.LU - 149597870.69100001) < 1.0:
                    unitstring = 'AU'
                labelstring = 'Distance from ' + self.central_body + ' (' + unitstring + ')'
                DataAxesLeft.plot(date_vector,
                                  Rvector,
                                  c='k',
                                  lw=2,
                                  label=labelstring)
            else:
                DataAxesLeft.plot(date_vector, Rvector, c='k', lw=2)

        #plot velocity
        if PlotOptions.PlotV:
            Vvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Vvector.append(
                        math.sqrt(event.SpacecraftState[3]**2 +
                                  event.SpacecraftState[4]**2 +
                                  event.SpacecraftState[5]**2) / self.LU *
                        self.TU)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Vvector,
                                  c='k',
                                  lw=2,
                                  ls='-.',
                                  label='Velocity magnitude (LU/TU)')
            else:
                DataAxesLeft.plot(date_vector, Vvector, c='k', lw=2, ls='-.')

        #plot Thrust
        if PlotOptions.PlotThrust:
            Thrustvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Thrustvector.append(
                        math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 +
                                  event.Thrust[2]**2) * 10.0)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Thrustvector,
                                  c='r',
                                  lw=2,
                                  ls='-',
                                  label='Applied thrust (0.1 N)')
            else:
                DataAxesLeft.plot(date_vector,
                                  Thrustvector,
                                  c='r',
                                  lw=2,
                                  ls='-')

        #plot Isp
        if PlotOptions.PlotIsp:
            Ispvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Ispvector.append(event.Isp / 1000.0)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Ispvector,
                                  c='c',
                                  lw=2,
                                  ls='-',
                                  label='Isp (1000 s)')
            else:
                DataAxesLeft.plot(date_vector, Ispvector, c='c', lw=2, ls='-')

        #plot mass flow rate
        if PlotOptions.PlotMdot:
            Mdotvector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Mdotvector.append(event.MassFlowRate * 1.0e6)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Mdotvector,
                                  c='brown',
                                  lw=2,
                                  ls='-',
                                  label='Mass flow rate (mg/s)')
            else:
                DataAxesLeft.plot(date_vector,
                                  Mdotvector,
                                  c='brown',
                                  lw=2,
                                  ls='-')

        #plot Efficiency
        if PlotOptions.PlotEfficiency:
            Efficiencyvector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    Efficiencyvector.append(event.AvailableThrust * event.Isp *
                                            9.80665 /
                                            (2000 * event.ActivePower))
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Efficiencyvector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Efficiencyvector,
                                  c='DarkGreen',
                                  lw=2,
                                  ls='-',
                                  label='Propulsion system efficiency')
            else:
                DataAxesLeft.plot(date_vector,
                                  Efficiencyvector,
                                  c='DarkGreen',
                                  lw=2,
                                  ls='-')

        #plot Throttle
        if PlotOptions.PlotThrottle:
            Throttlevector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    Throttlevector.append(
                        math.sqrt(event.Thrust[0]**2 + event.Thrust[1]**2 +
                                  event.Thrust[2]**2) /
                        (event.AvailableThrust * self.thruster_duty_cycle))
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    Throttlevector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Throttlevector,
                                  c='r',
                                  lw=2,
                                  ls='--',
                                  label='Throttle')
            else:
                DataAxesLeft.plot(date_vector,
                                  Throttlevector,
                                  c='r',
                                  lw=2,
                                  ls='--')

        #plot power
        if PlotOptions.PlotPower:
            Powervector = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    if event.AvailablePower > 0.0:
                        Powervector.append(event.AvailablePower)
                    else:
                        Powervector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  Powervector,
                                  c='Navy',
                                  lw=2,
                                  ls='-',
                                  label='Power produced by spacecraft (kW)')
            else:
                DataAxesLeft.plot(date_vector,
                                  Powervector,
                                  c='Navy',
                                  lw=2,
                                  ls='-')

        #plot gamma
        if PlotOptions.PlotGamma:
            gammavector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    gammavector.append(
                        math.atan2(event.Thrust[1], event.Thrust[0]) * 180.0 /
                        math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    gammavector.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector,
                                   gammavector,
                                   c='DarkGreen',
                                   lw=2,
                                   ls='--',
                                   label=r'$\gamma$ (radians)')
            else:
                DataAxesRight.plot(date_vector,
                                   gammavector,
                                   c='DarkGreen',
                                   lw=2,
                                   ls='--')

        #plot delta
        if PlotOptions.PlotDelta:
            deltavector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 +
                                              event.Thrust[1]**2 +
                                              event.Thrust[2]**2)
                    deltavector.append(
                        math.asin(event.Thrust[2] / AppliedThrust) * 180.0 /
                        math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    deltavector.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector,
                                   deltavector,
                                   c='LightGreen',
                                   lw=2,
                                   ls='--',
                                   label=r'$\delta$ (radians)')
            else:
                DataAxesRight.plot(date_vector,
                                   deltavector,
                                   c='LightGreen',
                                   lw=2,
                                   ls='--')

        #plot central body to thrust vector angle
        if PlotOptions.PlotCB_thrust_angle:
            CBthrustvector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    r = math.sqrt(event.SpacecraftState[0]**2 +
                                  event.SpacecraftState[1]**2 +
                                  event.SpacecraftState[2]**2)
                    AppliedThrust = math.sqrt(event.Thrust[0]**2 +
                                              event.Thrust[1]**2 +
                                              event.Thrust[2]**2)
                    rdotT = event.SpacecraftState[0] * event.Thrust[
                        0] + event.SpacecraftState[1] * event.Thrust[
                            1] + event.SpacecraftState[2] * event.Thrust[2]
                    CBthrustvector.append(
                        math.acos(rdotT / (r * AppliedThrust)) * 180.0 /
                        math.pi)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    CBthrustvector.append(0.0)
            if firstpass:
                DataAxesRight.plot(date_vector,
                                   CBthrustvector,
                                   c='Salmon',
                                   lw=2,
                                   ls='--',
                                   label='CB-thrust angle (radians)')
            else:
                DataAxesRight.plot(date_vector,
                                   CBthrustvector,
                                   c='Salmon',
                                   lw=2,
                                   ls='--')

        #plot mass
        if PlotOptions.PlotMass:
            mass = []
            for event in self.missionevents:
                if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    mass.append(event.Mass * 1.0e-3)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  mass,
                                  c='DarkGrey',
                                  lw=2,
                                  ls='-',
                                  label='Mass (1000 kg)')
            else:
                DataAxesLeft.plot(date_vector,
                                  mass,
                                  c='DarkGrey',
                                  lw=2,
                                  ls='-')

        #plot number of active thrusters
        if PlotOptions.PlotNumberOfEngines:
            numberofengines = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    numberofengines.append(event.Number_of_Active_Engines)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    numberofengines.append(0)
            if firstpass:
                DataAxesLeft.plot(date_vector,
                                  numberofengines,
                                  c='Orange',
                                  lw=2,
                                  ls='-',
                                  label='Number of active thrusters')
            else:
                DataAxesLeft.plot(date_vector,
                                  numberofengines,
                                  c='Orange',
                                  lw=2,
                                  ls='-')

        #plot power actively used by the thrusters
        if PlotOptions.PlotActivePower:
            activepowervector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    activepowervector.append(event.ActivePower)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    activepowervector.append(0.0)

            if firstpass:
                DataAxesLeft.plot(
                    date_vector,
                    activepowervector,
                    c='Navy',
                    lw=2,
                    ls='--',
                    label='Power used by the propulsion system (kW)')
            else:
                DataAxesLeft.plot(date_vector,
                                  activepowervector,
                                  c='Navy',
                                  lw=2,
                                  ls='--')

        #plot waste heat from the propulsion system
        if PlotOptions.PlotWasteHeat:
            WasteHeatvector = []
            for event in self.missionevents:
                if event.EventType == 'SFthrust' or event.EventType == 'FBLTthrust' or event.EventType == "PSBIthrust":
                    WasteHeatvector.append(
                        (1 - event.AvailableThrust * event.Isp * 9.80665 /
                         (2000 * event.ActivePower)) * event.ActivePower)
                elif event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':
                    WasteHeatvector.append(0.0)
            if firstpass:
                DataAxesLeft.plot(
                    date_vector,
                    WasteHeatvector,
                    c='Crimson',
                    lw=2,
                    ls='--',
                    label='Waste heat from propulsion system (kW)')
            else:
                DataAxesLeft.plot(date_vector,
                                  WasteHeatvector,
                                  c='Crimson',
                                  lw=2,
                                  ls='--')

        #plot Earth distance in LU and SPE angle
        if PlotOptions.PlotEarthDistance or PlotOptions.PlotSunEarthSpacecraftAngle:
            if self.central_body.lower() != 'sun':
                print 'getting Earth distance and Sun-Spacecraft-Earth angle is only supported if the central body is the sun'
            else:
                import de423
                from jplephem import Ephemeris
                eph = Ephemeris(de423)

                EarthDistanceVector = []
                SunEarthSpacecraftAngle = []
                for event in self.missionevents:
                    if event.EventType != 'match_point' and event.EventType != 'upwr_flyby' and event.EventType != 'pwr_flyby':

                        #get the position of the central body relative to the solar system barycenter
                        cb_relative_to_solar_system_barycenter_in_ICRC = eph.position(
                            self.central_body.lower(), event.JulianDate)

                        #get the position of the Earth relative to the central body
                        embarycenter_in_ICRC = eph.position(
                            'earthmoon', event.JulianDate)
                        moonvector_in_ICRC = eph.position(
                            'moon', event.JulianDate)
                        Earth_relative_to_solar_system_barycenter_in_ICRC = embarycenter_in_ICRC - moonvector_in_ICRC * eph.earth_share
                        Earth_relative_to_cb_in_ICRC = Earth_relative_to_solar_system_barycenter_in_ICRC + cb_relative_to_solar_system_barycenter_in_ICRC

                        #rotate the spacecraft state relative to the central body into the ICRF frame
                        spacecraft_state_relative_to_central_body_in_ICRF = AstroFunctions.rotate_from_ecliptic_to_equatorial3(
                            np.array(event.SpacecraftState[0:3]))

                        #get the vector from the Earth to the Spacecraft
                        Earth_Spacecraft_Vector = spacecraft_state_relative_to_central_body_in_ICRF - np.transpose(
                            Earth_relative_to_cb_in_ICRC)[0]

                        #return the magnitude of the Earth-centered position vector
                        EarthDistanceVector.append(
                            np.linalg.norm(Earth_Spacecraft_Vector) / self.LU)

                        #if applicable, compute sun-spacecraft-Earth angle
                        if PlotOptions.PlotSunEarthSpacecraftAngle:
                            cosAngle = np.dot(
                                -Earth_Spacecraft_Vector,
                                -spacecraft_state_relative_to_central_body_in_ICRF
                            ) / np.linalg.norm(
                                spacecraft_state_relative_to_central_body_in_ICRF
                            ) / np.linalg.norm(Earth_Spacecraft_Vector)
                            SunEarthSpacecraftAngle.append(
                                np.arccos(cosAngle) * 180.0 / math.pi)

                if PlotOptions.PlotEarthDistance:
                    if firstpass:
                        unitstring = 'LU'
                        if self.central_body.lower() == 'sun' and math.fabs(
                                self.LU - 149597870.69100001) < 1.0:
                            unitstring = 'AU'
                        labelstring = 'Distance from Earth (' + unitstring + ')'
                        DataAxesLeft.plot(date_vector,
                                          EarthDistanceVector,
                                          c='g',
                                          lw=2,
                                          label=labelstring)
                    else:
                        DataAxesLeft.plot(date_vector,
                                          EarthDistanceVector,
                                          c='g',
                                          lw=2)
                if PlotOptions.PlotSunEarthSpacecraftAngle:
                    if firstpass:
                        DataAxesRight.plot(date_vector,
                                           SunEarthSpacecraftAngle,
                                           c='orangered',
                                           lw=2,
                                           ls='-.',
                                           label='Sun-Spacecraft-Earth Angle')
                    else:
                        DataAxesRight.plot(date_vector,
                                           SunEarthSpacecraftAngle,
                                           c='orangered',
                                           lw=2,
                                           ls='-.')
Example #34
0
 def setUp(self):
     import de421
     self.e = Ephemeris(de421)
Example #35
0
def find_residuals(check_index, decs, ras, JDs, r, r_dot):
    dec_res_total = 0
    ra_res_total = 0
    total_ra = 0
    total_dec = 0

    date = "2018-7-16 01:52"

    for i in range(len(decs)):
        #print str(i + 1) + "/" + str(len(decs))
        k = 0.01720209895
        time_difference = JDs[i] - JDs[check_index]
        tau = 0
        d_tau = 0.001 * is_negative(time_difference)
        end_tau = time_difference * k

        #TEMP INTEGRATOR THINGY HERE (THE NEW ONE BRO)
        sim = rebound.Simulation()
        date = "2018-7-16 01:52"

        #TEST INFO#

        #SUN
        sim.add(m=1.0)

        #ASTEROID
        sim.add(m=0.0, x=r.x, y=r.y, z=r.z, vx=r_dot.x, vy=r_dot.y, vz=r_dot.z)

        #EARTH
        sim.add(m=1.0 / 330000.0,
                x=4.189675889417898E-01,
                y=-8.496104448760934E-01,
                z=-3.683119473905782E-01,
                vx=1.539665060981763E-02 / k,
                vy=6.454046892673179E-03 / k,
                vz=2.797224517462366E-03 / k)
        #sim.add('Earth')

        #JUPITER
        sim.add(m=1.0 / 1000.0,
                x=-3.213494013743870E+00,
                y=-4.009890793133180E+00,
                z=-1.640521133996669E+00,
                vx=5.974697377415830E-03 / k,
                vy=-3.756443410778172E-03 / k,
                vz=-1.755593829452442E-03 / k)
        #sim.add('Jupiter')

        #SATURN
        sim.add(m=1.0 / 3300.0,
                x=1.084878715668408E+00,
                y=-9.231862109791130E+00,
                z=-3.860012135382278E+00,
                vx=5.246951399009119E-03 / k,
                vy=6.191309101028240E-04,
                vz=3.018304002418789E-05 / k)
        #sim.add('Saturn')

        sim.move_to_com()

        ps = sim.particles

        sim.integrate(end_tau)

        r_now = vector(ps[1].x, ps[1].y, ps[1].z)

        AU = 149597870.7  # km/AU
        jd = JDs[i]
        eph = Ephemeris(de421)

        R_geocentric = get_earth_to_sun(JD)
        sun_to_asteroid = r_now
        earth_to_asteroid = norm(
            R_geocentric +
            sun_to_asteroid)  # Gets unit vector from Earth to Asteroid
        RA, Dec = location_to_angles(earth_to_asteroid)
        RA_Residual = abs(ras[i] - RA)
        Dec_Residual = abs(decs[i] - Dec)
        ra_res_total += RA_Residual**2
        dec_res_total += Dec_Residual**2

        tau = 0
        d_tau = 0.000001
        k = 0.01720209895
        mu = 1.0

    sigma = sqrt(ra_res_total + dec_res_total)
    return sigma
Example #36
0
def pertubation(t, orbit_element):
    '''
    :param Orbit_Elements: 轨道六根数,单位为弧度
    :param t: 时间
    :return: 微分方程右边的表达式
    '''
    '''
    d_earth_nonsphericfigure:地球非球型摄动影响
    '''
    t_start_jd = 2458454.0
    R_earth = 6378  #km
    mu = 398600  #km^3/s^(-2)
    J2 = -1.08264 * 10**(-3)
    semi_major_axis = orbit_element[0]
    Eccentricity = orbit_element[1]
    Inclination = orbit_element[2]
    RAAN = orbit_element[3]
    Perigee = orbit_element[4]
    True_Anomaly = orbit_element[5]
    p = semi_major_axis**(1 - Eccentricity**2)
    n = sqrt(mu / (semi_major_axis)**3)
    d_RAAN_earth_nonsphericfigure = (-2 / 3) * (
        R_earth / p)**2 * n * J2 * cos(Inclination)
    d_Perigee_earth_nonsphericfigure = -3 / 4 * (R_earth / p)**2 * n * J2 * (
        1 - 5 * (cos(Inclination)**2))
    d_semi_major_axis_earth_nonsphericfigure = 0
    d_Eccentricity_earth_nonsphericfigure = 0
    d_Inclination_earth_nonsphericfigure = 0
    d_Mean_anomaly_earth_nonsphericfigure = 0
    '''
    d_lunar_solar日,月引力摄动
    '''
    Sun_state = ephemeris('sun', t_start_jd + t / 3600 / 24)  #太阳星历
    barycenter_statement = ephemeris('earthmoon', t_start_jd + t / 3600 / 24)

    import de405
    from jplephem import Ephemeris
    eph = Ephemeris(de405)
    Position_sun = Sun_state[0, :]
    Velocity_sun = Sun_state[1, :]
    Moon_state = ephemeris('moon', t_start_jd + t / 3600 / 24)  #本身就是相对地球的
    Position_moon = Moon_state[0, :]
    Velocity_moon = Moon_state[1, :]
    Earth_state = barycenter_statement - Moon_state * eph.earth_share
    Position_earth = Earth_state[0, :]
    Velocity_earth = Earth_state[1, :]

    # 太阳引力摄动

    G = 6.67259 * 1e-11  #N·m²/kg²
    M_sun = 1.9885 * 1e30  #kg
    R_sun_earth = Position_sun - Position_earth  #地心ICRF参考系下太阳的位置矢量
    V_sun_earth = Velocity_sun - Velocity_earth  #地心ICRF参考系下太阳的速度矢量
    r_sun = np.sqrt(R_sun_earth[0]**2 + R_sun_earth[1]**2 + R_sun_earth[2]**2)
    K_sun = G * M_sun / (r_sun**3)  #r_sun为日地距

    #计算太阳在地心ICRF坐标系下的轨道根数
    import RV_To_Orbit_Elements
    mu_sun_earth = 398600 + G * M_sun / (1e9)  # km^3/s^2
    Sun_Orbit_Elements_ECRF = RV_To_Orbit_Elements.rv_to_orbit_element(
        R_sun_earth, V_sun_earth, mu_sun_earth)
    Inclination_sun = Sun_Orbit_Elements_ECRF[2]
    RAAN_sun = Sun_Orbit_Elements_ECRF[3]
    Perigee_sun = Sun_Orbit_Elements_ECRF[4]
    True_anomaly_sun = Sun_Orbit_Elements_ECRF[5]
    u_sun = True_anomaly_sun + Perigee_sun
    #计算系数
    A_sun = cos(RAAN - RAAN_sun) * cos(u_sun) + sin(RAAN - RAAN_sun) * sin(
        u_sun) * cos(Inclination_sun)
    B1_sun = cos(Inclination)
    B2_sun = B1_sun * (-sin(RAAN - RAAN_sun) * cos(u_sun) + sin(u_sun) *
                       cos(Inclination_sun) * cos(RAAN - RAAN_sun))
    B_sun = B2_sun + sin(Inclination) * sin(Inclination_sun) * sin(u_sun)
    C1_sun = sin(Inclination)
    C2_sun = C1_sun * (sin(RAAN - RAAN_sun) * cos(u_sun) - sin(u_sun) *
                       cos(Inclination_sun) * cos(RAAN - RAAN_sun))
    C_sun = C2_sun + cos(Inclination) * sin(Inclination_sun) * sin(u_sun)
    d_semi_major_axis_solar = 0
    d_Eccentricity_solar = -(15 * K_sun / 2 / n) * Eccentricity * sqrt(
        1 - Eccentricity**2) * (A_sun * B_sun * cos(2 * Perigee) - (1 / 2) *
                                (A_sun**2 - B_sun**2) * sin(2 * Perigee))

    d_Inclination_solar=3*K_sun*C_sun/4/n/sqrt(1-Eccentricity**2)*(A_sun*(2+3*Eccentricity**2+\
                        5*Eccentricity**2*cos(2*Perigee))+5*(B_sun*Eccentricity**2)*sin(2*Perigee))
    d_RAAN_solar = 3*K_sun*C_sun/4/n/sqrt(1-Eccentricity**2)/sin(Inclination)*(B_sun*(2+3*Eccentricity**2+\
                    5*Eccentricity**2*cos(2*Perigee))+5*A_sun*Eccentricity**2*sin(2*Perigee))
    d_Perigee_solar = 3*K_sun/2/n*sqrt(1-Eccentricity**2)*((5*A_sun*B_sun*sin(Perigee*2)+\
                      1/2*(A_sun**2-B_sun**2)*cos(2*Perigee))-1+3/2*(A_sun**2+B_sun**2))\
                      +5*semi_major_axis/2/Eccentricity/r_sun*(1-5/4*(A_sun**2-B_sun**2))*(A_sun*cos(Perigee)\
                      +B_sun*sin(Perigee))-cos(Inclination)*d_RAAN_solar
    d_Mean_anomaly_solar = 0

    # 月球引力摄动

    M_moon = 7.349 * 1e22  #kg
    R_moon_earth = Position_moon  #地心ICRF参考系下太阳的位置矢量
    V_moon_earth = Velocity_moon  #地心ICRF参考系下太阳的速度矢量
    r_moon = np.sqrt(R_moon_earth.dot(R_moon_earth))
    K_moon = G * M_moon / (r_moon**3)  #r_moon为月地距
    mu_moon_earth = 398600 + G * M_moon / (1e9)
    #计算月球在地心ICRF坐标系下的轨道根数
    Moon_Orbit_Elements_ECRF = RV_To_Orbit_Elements.rv_to_orbit_element(
        R_moon_earth, V_moon_earth, mu_moon_earth)
    Inclination_moon = Moon_Orbit_Elements_ECRF[2]
    RAAN_moon = Moon_Orbit_Elements_ECRF[3]
    Perigee_moon = Moon_Orbit_Elements_ECRF[4]
    True_anomaly_moon = Moon_Orbit_Elements_ECRF[5]
    u_moon = True_anomaly_moon + Perigee_moon
    #计算系数
    A_moon = cos(RAAN - RAAN_moon) * cos(u_moon) + sin(RAAN - RAAN_moon) * sin(
        u_moon) * cos(Inclination_moon)
    B1_moon = cos(Inclination)
    B2_moon = B1_moon * (-sin(RAAN - RAAN_moon) * cos(u_moon) + sin(u_moon) *
                         cos(Inclination_moon) * cos(RAAN - RAAN_moon))
    B_moon = B2_moon + sin(Inclination) * sin(Inclination_moon) * sin(u_moon)
    C1_moon = sin(Inclination)
    C2_moon = C1_moon * (sin(RAAN - RAAN_moon) * cos(u_moon) - sin(u_moon) *
                         cos(Inclination_moon) * cos(RAAN - RAAN_moon))
    C_moon = C2_moon + cos(Inclination) * sin(Inclination_moon) * sin(u_moon)
    d_semi_major_axis_lunar = 0
    d_Eccentricity_lunar=-(15*K_moon/2/n)*Eccentricity*sqrt(1-Eccentricity**2)*\
                         (A_moon*B_moon*cos(2*Perigee)-(1/2)*(A_moon**2-B_moon**2)*sin(2*Perigee))

    d_Inclination_lunar=3*K_moon*C_moon/4/n/sqrt(1-Eccentricity**2)*(A_moon*(2+3*Eccentricity**2+\
                        5*Eccentricity**2*cos(2*Perigee))+5*B_moon*Eccentricity**2*sin(2*Perigee))
    d_RAAN_lunar = 3*K_moon*C_moon/4/n/sqrt(1-Eccentricity**2)/sin(Inclination)*(B_moon*(2+3*Eccentricity**2+\
                    5*Eccentricity**2*cos(2*Perigee))+5*A_moon*Eccentricity**2*sin(2*Perigee))
    d_Perigee_lunar = 3*K_moon/2/n*sqrt(1-Eccentricity**2)*((5*A_moon*B_moon*sin(Perigee*2)+\
                      1/2*(A_moon**2-B_moon**2)*cos(2*Perigee))-1+3/2*(A_moon**2+B_moon**2))\
                      +5*semi_major_axis/2/Eccentricity/r_moon*(1-5/4*(A_moon**2-B_moon**2))*(A_moon*cos(Perigee)\
                      +B_moon*sin(Perigee))-cos(Inclination)*d_RAAN_lunar
    d_Mean_anomaly_lunar = 0

    d_semi_major_axis = d_semi_major_axis_earth_nonsphericfigure + d_semi_major_axis_lunar + d_semi_major_axis_solar
    d_Eccentricity = d_Eccentricity_earth_nonsphericfigure + d_Eccentricity_lunar + d_Eccentricity_solar
    d_Inclination = d_Inclination_earth_nonsphericfigure + d_Inclination_solar + d_Inclination_lunar
    d_RAAN = d_RAAN_earth_nonsphericfigure + d_Inclination_lunar + d_RAAN_solar
    d_Perigee = d_Perigee_earth_nonsphericfigure + d_Perigee_lunar + d_Perigee_solar
    d_Mean_anomaly = n

    semi_major_axis_earth_nonsphericfigure = 1
    semi_major_axis_lunar_solar = 0
    Eccentricity_earth_nonsphericfigure = 1
    Eccentricity_lunar_solar = 0
    Inclination_earth_nonsphericfigure = 1
    Inclination_solar_solar = 0
    RAAN_earth_nonsphericfigure = 1
    RAAN_lunar_solar = 0
    Perigee_earth_nonsphericfigure = 1
    Perigee_lunar_solar = 0

    return np.array([
        d_semi_major_axis, d_Eccentricity, d_Inclination, d_RAAN, d_Perigee,
        d_Mean_anomaly
    ])
Example #37
0
RA_measured = array([[20, 56, 08.762], [20, 59, 20.410], [21, 8, 43.156]])

Dec_measured = array([[16, 29, 32.52], [18, 14, 10.95], [22, 28, 36.27]])

t1 = JD[0]
t2 = JD[1]
t3 = JD[2]
list_test = [JD[0], JD[2]]

tau2 = 0
tau1 = k * (t1 - t2)
tau3 = k * (t3 - t2)

R = []
for i in JD:
    eph = Ephemeris(de421)
    barycenter = eph.position('earthmoon', i)
    moonvector = eph.position('moon', i)
    earth = barycenter - moonvector * eph.earth_share
    R0 = vector(
        earth
    ) / AU  # This is the Sun to Earth center vector in Equatorial system

    R_geocentric = -1. * R0
    R.append(array(R_geocentric))
print 'R_geocentric', R
print


def RAconverter(hrs, minutes, seconds):
    return (hrs / 24. + minutes / (24. * 60) + seconds / (24. * 3600)) * 360.
Example #38
0
# import os

from skyfield.api import *
years = range(-9999, 9999, 10)
north_pole = earth.topos('90 N', '0 W')
print(north_pole)
x, y, z = north_pole.gcrs(utc=(years, 1, 1)).position.km
print(x,y,z)
plot(x, y)

exit()

# from skyfield.api import *
import de421
from jplephem import Ephemeris
eph = Ephemeris(de421)
# x, y, z = eph.position('saturn', 2456656.501)
# x, y, z = eph.position('mars', 2456658.500000000);
# x, y, z = eph.position('mercury', 2414992.5);
x,y,z = eph.position('mercury', 2456876) - eph.position('jupiter', 2456876)
print x,y,z


for t in range (2456876,2456876+1000):
    mx,my,mz = eph.position('mercury', t)
    jx,jy,jz = eph.position('jupiter', t)
    eq = -0.0145987218963993*(jx-mx)-0.430326550289791*(jy-my)+0.902555226805917*(jz-mz)
    print "ALPHA",t,eq

exit()