def __init__(self, naifid, name, orbiting):
        # planets are constructed with their NASA NAIF ID's (int), name (str)
        # and the body they are orbiting (planetary_system instance)

        self.name = name
        self.naifid = naifid

        # not all planets' states are available in spiceypy.spkgeo, so we
        # use their barrycenters' to get state vectors

        self.barrycenter_id = int(str(naifid)[0])
        self.state, self.r_sun = spiceypy.spkgeo(targ=self.barrycenter_id, \
                                                 et=start_date_et, \
                                                 ref="ECLIPJ2000", obs=10)

        _, radii = spiceypy.bodvcd(naifid, "RADII", 3)
        self.radii = np.average(radii) * 1000  # km -> m conv.
        self.vis_area = 2 * self.radii**2 * np.pi
        self.size = int(
            np.ceil(self.vis_area / orbiting.scaling_factor * 50000))
        self.state = self.state * 1000  # km -> m conv.
        self.parent = orbiting
        self.gm = orbiting.G * orbiting.sun_mass
        self.y = []
        self.line = []
        self.anim_data = []
        self.scat = []
        self.color = []
        orbiting.add_planet(self)
Пример #2
0
def calc_ephemeris(target, ets, frame, observer):
    '''
	Convenience wrapper for spkezr and spkgeo
	'''

    if type(target) == str:
        return array(spice.spkezr(target, ets, frame, 'NONE', observer)[0])

    else:
        n_states = len(ets)
        states = zeros((n_states, 6))
        for n in range(n_states):
            states[n] = spice.spkgeo(target, ets[n], frame, observer)[0]
        return states
Пример #3
0
def vinfinity_match( planet0, planet1, v0_sc, et0, tof0, args = {} ):
	'''
	Given an incoming v-infinity vector to planet0, calculate the
	outgoing v-infinity vector that will arrive at planet1 after
	time of flight (tof) where the incoming and outgoing v-infinity
	vectors at planet0 have equal magnitude
	'''
	_args = {
		'et0'       : et0,
		'planet1_ID': planet1,
		'frame'     : 'ECLIPJ2000',
		'center_ID' : 0,
		'mu'        : pd.sun[ 'mu' ],
		'tm'        : 1,
		'diff_step' : 1e-3,
		'tol'       : 1e-4
	}
	for key in args.keys():
		_args[ key ] = args[ key ]

	_args[ 'state0_planet0' ] = spice.spkgeo( planet0, et0,
		_args[ 'frame' ], _args[ 'center_ID' ] )[ 0 ]

	_args[ 'vinf' ] = nt.norm( v0_sc - _args[ 'state0_planet0' ][ 3: ] )

	tof, steps = nt.newton_root_single_fd(
		calc_vinfinity, tof0, _args )

	r1_planet1 = spice.spkgps( planet1, et0 + tof,
		_args[ 'frame' ], _args[ 'center_ID' ] )[ 0 ]

	v0_sc_depart, v1_sc_arrive = lt.lamberts_universal_variables(
		_args[ 'state0_planet0' ][ :3 ], r1_planet1, tof,
		{ 'mu': _args[ 'mu' ], 'tm': _args[ 'tm' ] } )

	return tof, v0_sc_depart, v1_sc_arrive
MAT = spiceypy.sxform(instring='ECLIPJ2000_DE405', \
                      tostring='ECLIPJ2000', \
                      et=DATETIME_ET)

# Let's print the transformation matrix row-wise (spoiler alert: it is the
# identity matrix)
print('Transformation matrix between ECLIPJ2000_DE405 and ECLIPJ2000')
for mat_row in MAT:
    print(f'{np.round(mat_row, 2)}')
print('\n')

#%%

# Compute the state vector of Ceres in ECLIPJ2000 as seen from the Sun
CERES_STATE_VECTOR, _ = spiceypy.spkgeo(targ=2000001, \
                                        et=DATETIME_ET, \
                                        ref='ECLIPJ2000',
                                        obs=10)

#%%

# Get the G*M value for the Sun
_, GM_SUN_PRE = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1)

GM_SUN = GM_SUN_PRE[0]

#%%

# Compute the orbital elements of Ceres using the computed state vector
CERES_ORBITAL_ELEMENTS = spiceypy.oscltx(state=CERES_STATE_VECTOR, \
                                         et=DATETIME_ET, \
                                         mu=GM_SUN)
Пример #5
0
    # propagate until exit Earth SOI
    sc0 = SC({
        'orbit_state': state0,
        'et0': et0,
        'frame': FRAME,
        'tspan': 100000,
        'dt': 10000,
        'stop_conditions': {
            'exit_SOI': True
        }
    })
    '''
	Calculate spacecraft state w.r.t solar system barycenter
	at ephemeris time when spacecraft left Earth SOI
	'''
    state_earth = spice.spkgeo(399, sc0.ets[-1], FRAME, 0)[0]
    state1 = sc0.states[-1, :6] + state_earth
    '''
	Now model the spacecraft as a heliocentric elliptical orbit
	and propagate until enter Jupiter SOI
	'''
    sc1 = SC({
        'orbit_state': state1,
        'et0': sc0.ets[-1],
        'frame': FRAME,
        'tspan': 5 * 365 * 24 * 3600.0,
        'dt': 30000,
        'stop_conditions': {
            'enter_SOI': pd.jupiter
        },
        'cb': pd.sun
kernels = os.path.expanduser('~/git_repos/SpaceScienceTutorial/_kernels')
import spiceypy as sp
sp.furnsh(kernels + '/lsk/naif0012.tls')
sp.furnsh(kernels + '/spk/de432s.bsp')
sp.furnsh(kernels + '/pck/gm_de431.tpc')

DATE_TODAY = datetime.datetime.today()
DATE_TODAY = DATE_TODAY.strftime('%Y-%m-%dT00:00:00')
ET_TODAY_MIDNIGHT = sp.utc2et(DATE_TODAY)

print('ET today midnight')  # what is et exactly??
print(ET_TODAY_MIDNIGHT)

EARTH_STATE_WRT_SUN, EARTH_SUN_LT = sp.spkgeo(targ=399 \
                                                    ,et=ET_TODAY_MIDNIGHT \
                                                    ,ref='ECLIPJ2000' \
                                                    ,obs=10
                                                    )

print("state vector of the earth wrt the sun for \"today\" (midnight): {0}".
      format(EARTH_STATE_WRT_SUN))

# check AU
EARTH_SUN_DISTANCE = math.sqrt(EARTH_STATE_WRT_SUN[0] ** 2 \
                                + EARTH_STATE_WRT_SUN[1] ** 2 \
                                + EARTH_STATE_WRT_SUN[2] ** 2
                                )

EARTH_SUN_DISTANCE_AU = sp.convrt(EARTH_SUN_DISTANCE, 'km', 'AU')

print('CURRENT distance between Earth and Sun in AU: {0}'.format(
Пример #7
0
print(ET_TODAY_MIDNIGHT)

#%%

# Can we compute now the position and velocity (so called state) of the Earth
# with respect to the Sun? We use the following function to determine the
# state vector and the so called light time (travel time of the light between
# the Sun and our home planet). Positions are always given in km, velocities
# in km/s and times in seconds

# targ : Object that shall be pointed at
# et : The ET of the computation
# ref : The reference frame. Here, it is ECLIPJ2000 (so Medium article)
# obs :  The observer respectively the center of our state vector computation
EARTH_STATE_WRT_SUN, EARTH_SUN_LT = spiceypy.spkgeo(targ=399, \
                                                    et=ET_TODAY_MIDNIGHT, \
                                                    ref='ECLIPJ2000', \
                                                    obs=10)

#%%

# An error occured. Again a kernel error. Well, we need to load a so called
# spk to load positional information:
spiceypy.furnsh('../_kernels/spk/de432s.bsp')

#%%

# Let's re-try the computation again
EARTH_STATE_WRT_SUN, EARTH_SUN_LT = spiceypy.spkgeo(targ=399, \
                                                    et=ET_TODAY_MIDNIGHT, \
                                                    ref='ECLIPJ2000', obs=10)
Пример #8
0
_, GM_SUN_PRE = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1)
GM_SUN = GM_SUN_PRE[0]

# Set the G*M value of Jupiter
_, GM_JUPITER_PRE = spiceypy.bodvcd(bodyid=5, item='GM', maxn=1)
GM_JUPITER = GM_JUPITER_PRE[0]

#%%

# Set a sample Ephemeris Time to compute a sample Jupiter state vector and the
# corresponding orbital elements
sample_et = spiceypy.utc2et('2000-001T12:00:00')

# Compute the state vector of Jupiter as seen from the Sun in ECLIPJ2000
JUPITER_STATE, _ = spiceypy.spkgeo(targ=5, \
                                   et=sample_et, \
                                   ref='ECLIPJ2000', \
                                   obs=10)

# Determine the corresponding orbital elements of Jupiter
JUPITER_ORB_ELEM = spiceypy.oscltx(state=JUPITER_STATE, \
                                   et=sample_et, \
                                   mu=GM_SUN)

# Extract the semi-major axis of Jupiter ...
JUPITER_A = JUPITER_ORB_ELEM[-2]

# ... and print the results in AU
print('Semi-major axis of Jupiter in AU: ' \
      f'{spiceypy.convrt(JUPITER_A, inunit="km", outunit="AU")}')
print('\n')
# Import the installed modules
import numpy as np

# Import matplotlib for plotting
from matplotlib import pyplot as plt

#%%

# Create sample Ephemeris Time (ET)
SAMPLE_ET = spiceypy.utc2et('2000-001T00:00:00')

# Compute the state vector of Jupiter's barycentre at the defined ET as seen
# from the Sun
STATE_VEC_JUPITER, _ = spiceypy.spkgeo(targ=5, \
                                       et=SAMPLE_ET, \
                                       ref='ECLIPJ2000', \
                                       obs=10)

# Get the G*M value of the Sun
_, GM_SUN = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1)
GM_SUN = GM_SUN[0]

# Compute the orbital elements of Jupiter ...
ORB_ELEM_JUPITER = spiceypy.oscltx(STATE_VEC_JUPITER, SAMPLE_ET, GM_SUN)

# ... extract the semi-major axis and convert it from km to AU
A_JUPITER_KM = ORB_ELEM_JUPITER[-2]
A_JUPITER_AU = spiceypy.convrt(A_JUPITER_KM, 'km', 'AU')

#%%
# AWP library
import plotting_tools as pt

if __name__ == '__main__':

    spice.furnsh('../../data/spice/lsk/naif0012.tls')
    spice.furnsh('../../data/spice/spk/de432s.bsp')
    spice.furnsh('voyager2_jupiter_flyby.bsp')

    et = spice.str2et('1979-07-09 TDB')
    dt = 10 * 24 * 3600.0
    et0 = et - dt
    et1 = et + dt

    v_arrive = spice.spkgeo(-32, et0, 'ECLIPJ2000', 0)[0][3:]
    v_depart = spice.spkgeo(-32, et1, 'ECLIPJ2000', 0)[0][3:]
    v_jup0 = spice.spkgeo(5, et0, 'ECLIPJ2000', 0)[0][3:]
    v_jup1 = spice.spkgeo(5, et1, 'ECLIPJ2000', 0)[0][3:]
    vinf0 = v_arrive - v_jup0
    vinf1 = v_depart - v_jup1
    vdelta = v_depart - v_arrive

    v0 = {'r': v_arrive, 'label': r'$\vec{v}_{arrive}$', 'color': 'm'}
    v1 = {'r': v_depart, 'label': r'$\vec{v}_{depart}$', 'color': 'm'}
    v2 = {'r': v_jup0, 'label': r'$\vec{v}_{Jupiter}$', 'color': 'C3'}
    v3 = {'r': vinf0, 'label': r'$\vec{v}_{incoming}$', 'color': 'm'}
    v4 = {'r': vinf1, 'label': r'$\vec{v}_{outgoing}$', 'color': 'm'}
    v5 = {'r': vdelta, 'label': r'$\vec{\Delta v}$', 'color': 'lime'}

    pt.plot_orbits(
Пример #11
0
def test_Spacecraft_enter_SOI_voyager2_jupiter(plot=False):
    spice.furnsh(sd.leapseconds_kernel)
    spice.furnsh(sd.de432)
    frame = 'ECLIPJ2000'

    # beginning of coverage for Voyager 2 SPK kernel
    et0 = spice.str2et('1977 AUG 20 15:32:32.182')
    '''
	Voyager 2 initial state w.r.t Earth at et0
	'''
    state0 = [
        7.44304239e+03,
        -5.12480267e+02,
        2.37748995e+03,  # km
        5.99287925e+00,
        1.19056063e+01,
        5.17252832e+00
    ]  # km / s
    '''
	Propagate Voyager 2 trajectory until it exits Earth's sphere of influence,
	where maximum altitude stop condition will be triggered
	'''
    stop_conditions = {'max_alt': pd.earth['SOI'] - pd.earth['radius']}
    sc0 = SC({
        'orbit_state': state0,
        'et0': et0,
        'frame': frame,
        'tspan': 100000,
        'stop_conditions': stop_conditions
    })
    assert sc0.cb == pd.earth
    assert sc0.ode_sol.success
    assert sc0.ode_sol.message == 'A termination event occurred.'
    assert sc0.ode_sol.status == 1
    '''
	Calculate spacecraft state w.r.t solar system barycenter
	at ephemeris time when spacecraft left Earth SOI
	'''
    state_earth = spice.spkgeo(399, sc0.ets[-1], frame, 0)[0]
    state1 = sc0.states[-1, :6] + state_earth
    '''
	Now model the spacecraft as a heliocentric elliptical orbit
	and propagate until enter Jupiter SOI
	'''
    sc1 = SC({
        'orbit_state': state1,
        'et0': sc0.ets[-1],
        'frame': frame,
        'tspan': 5 * 365 * 24 * 3600.0,
        'dt': 30000,
        'stop_conditions': {
            'enter_SOI': pd.jupiter
        },
        'cb': pd.sun
    })
    assert sc1.cb == pd.sun
    assert sc1.ode_sol.success
    assert sc1.ode_sol.message == 'A termination event occurred.'
    assert sc1.ode_sol.status == 1

    if plot:
        ets = np.concatenate((sc0.ets, sc1.ets))
        rs_earth = st.calc_ephemeris(3, ets, frame, 10)[:, :3]
        rs_jupiter = st.calc_ephemeris(5, ets, frame, 10)[:, :3]
        rs0        = sc0.states[ :, :3 ] +\
            st.calc_ephemeris( 3, sc0.ets, frame, 10 )[ :, :3 ]

        labels = [
            '$Voyager2_{EarthSOI}$', '$Voyager2_{SunSOI}$', 'Earth', 'Jupiter'
        ]

        pt.plot_orbits([rs0, sc1.states[:, :3], rs_earth, rs_jupiter], {
            'labels': labels,
            'colors': ['m', 'c', 'b', 'C3'],
            'show': True
        })
Пример #12
0
def main():

    # ** Convert today's time at midnight from UTC to ephemeric time ET **

    #Get today's date
    date_today_utc = dt.datetime.today()
    #Convert datetime to string, replacing time with midnight
    date_today_utc = date_today_utc.strftime('%Y-%m-%dT00:00:00')

    #Get time conversion information from a lsk kernel 'naif0012.tls'
    spiceypy.furnsh(
        'E:\Data Science Projects\Space Science\SpaceScience-P1-EarthStateVectors\data\external\_kernels\lsk/naif0012.tls'
    )
    #Convert UTC to ET using SPICE function 'utc2et'
    et_today = spiceypy.utc2et(date_today_utc)

    # ** Compute the position and velocity of the Earth with respect to the Sun **

    #First load a spk kernel 'de432s.bsp' for positional information of planets.

    #    How to find the relevant kernel?
    #    At https://naif.jpl.nasa.gov/pub/naif/ we navigate to generic_kernels/spk/
    #    planets, since we are trying to find the trajectory of our planet. We
    #    browse the aa_summaries.txt file. The last line of each summary shows the
    #    time range covered in each kernel. The time period of de432s is suitable.

    spiceypy.furnsh(
        'E:\Data Science Projects\Space Science\SpaceScience-P1-EarthStateVectors\data\external/_kernels/spk/de432s.bsp'
    )

    #Use spkgeo function to compute Earth state vectors
    earth_state_wrt_sun, earth_sun_lt = spiceypy.spkgeo(targ=399, \
                                                        et=et_today, \
                                                        ref='ECLIPJ2000', \
                                                        obs=10)

    #Report position vector of Earth
    print(f"Position of Earth wrt Sun on {date_today_utc} is: \n \
          {earth_state_wrt_sun}",
          file=outfile)

    #Check whether computation is correct
    #
    #    We check the veracity of the computed position vectors by using the result
    #    to compute the distance between Earth and Sun. If it is around 1 AU, then
    #    the computation is satisfactory. ("around" 1AU because Earth's orbit is
    #    elliptical, ot perfectly circular)
    #
    #Compute distance between Earth and Sun in km
    earth_sun_distance = math.sqrt(earth_state_wrt_sun[0]**2.0 \
                                 + earth_state_wrt_sun[1]**2.0 \
                                 + earth_state_wrt_sun[2]**2.0)
    #Convert km to AU
    earth_sun_distance_AU = spiceypy.convrt(earth_sun_distance, 'km', 'AU')
    #Report value
    print(f"Current distance between the Earth and the Sun in AU: \
          {earth_sun_distance_AU}",
          file=outfile)

    # ** Compute Orbital Speed of Earth **
    #First we compute actual current orbital speed of Earth around Sun
    earth_orb_speed_wrt_sun = math.sqrt(earth_state_wrt_sun[3]**2.0 \
                                  + earth_state_wrt_sun[4]**2.0 \
                                  + earth_state_wrt_sun[5]**2.0)
    #Report current orbital speed of Earth
    print(f"Current orbital speed of the Earth around the Sun in km/s: \
      {earth_orb_speed_wrt_sun}",
          file=outfile)

    #Now we compute theoretical orbital speed of Earth around Sun
    #
    #    For this, we need the equation to determine the orbital speed. We assume
    #    that the Sun's mass is greater than the mass of the Earth and we assume
    #    that our planet is moving on an almost circular orbit. The orbit velocity
    #    $v_{\text{orb}}$ can be approximated with, where $G$ is the gravitational
    #    constant, $M$ is the mass of the Sun and $r$ is the distance between the
    #    Earth and the Sun:
    #    \begin{align}
    #        v_{\text{orb}}\approx\sqrt{\frac{GM}{r}}
    #    \end{align}
    #
    #    The G*M values for different objects are found in a pck file 'gm_de431.tpc'
    #
    #Load pck kernel for G*M value
    spiceypy.furnsh(
        'E:\Data Science Projects\Space Science\SpaceScience-P1-EarthStateVectors\data\external/_kernels/pck/gm_de431.tpc'
    )
    _, GM_SUN = spiceypy.bodvcd(bodyid=10, item='GM', maxn=1)
    #Compute theoretical orbital speed
    v_orb_func = lambda gm, r: math.sqrt(gm / r)
    earth_orb_speed_wrt_sun_theory = v_orb_func(GM_SUN[0], earth_sun_distance)
    #Report theoretical value
    print(f"Theoretical orbital speed of the Earth around the Sun in km/s: \
      {earth_orb_speed_wrt_sun_theory}",
          file=outfile)
#%%

# Set an initial dataframe for the 67P computations
comet_67p_df = pd.DataFrame([])

# Set the UTC date-times
comet_67p_df.loc[:, 'UTC'] = datetime_range

# Convert the UTC date-time strings to ET
comet_67p_df.loc[:, 'ET'] = comet_67p_df['UTC'].apply(lambda x: \
                              spiceypy.utc2et(x.strftime('%Y-%m-%dT%H:%M:%S')))

# Compute the ET corresponding state vectors
comet_67p_df.loc[:, 'STATE_VEC'] = \
    comet_67p_df['ET'].apply(lambda x: spiceypy.spkgeo(targ=1000012, \
                                                       et=x, \
                                                       ref='ECLIPJ2000', \
                                                       obs=10)[0])

# Compute the state vectors corresponding orbital elements
comet_67p_df.loc[:, 'STATE_VEC_ORB_ELEM'] = \
    comet_67p_df.apply(lambda x: spiceypy.oscltx(state=x['STATE_VEC'], \
                                                 et=x['ET'], \
                                                 mu=GM_SUN), \
                       axis=1)

#%%

# Assign miscellaneous orbital elements as individual columns
# Set the perihelion. Convert km to AU
comet_67p_df.loc[:, 'PERIHELION_AU'] = \
    comet_67p_df['STATE_VEC_ORB_ELEM'].apply(lambda x: \
    atlas_et = spiceypy.datetime2et(atlas_time_step)

    # Compute the ET corresponding state vector of the comet ATLAS
    atlas_state_vec = spiceypy.conics(ATLAS_SPICE_ORB_EL, atlas_et)

    # Store the position vector
    atlas_vecs.append(atlas_state_vec[:3])

# Iterate through the time array (Solar Orbiter)
for so_time_step in TIME_ARRAY:

    # Compute the ET
    so_et = spiceypy.datetime2et(so_time_step)

    # Compute the state vector of the Solar Orbiter (NAIF ID: -144)
    solar_orb_state_vec, _ = spiceypy.spkgeo(targ=-144, et=so_et, \
                                         ref='ECLIPJ2000', obs=10)

    # Store the position vector
    solar_orb_vecs.append(solar_orb_state_vec[:3])

# Convert the lists that contain the vectors to numpy lists
atlas_vecs = np.array(atlas_vecs)
solar_orb_vecs = np.array(solar_orb_vecs)

#%%

# Minimum distance ATLAS - Sun
MIN_DIST_ATLAS_SUN = np.min(np.linalg.norm(atlas_vecs, axis=1))
print('Minimum distance ATLAS - Sun in AU: ' \
      f'{spiceypy.convrt(MIN_DIST_ATLAS_SUN, "km", "AU")}')
Пример #15
0
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('dark_background')
plt.rcParams.update({'font.size': 13})

# AWP library
import orbit_calculations as oc
import numerical_tools as nt
import planetary_data as pd
from EVME_1963 import calc_EVME_1963

if __name__ == '__main__':
    itvim = calc_EVME_1963()
    seq1 = itvim.seq[1]
    v_arrive = seq1['state_sc_arrive'][3:]
    state_venus = spice.spkgeo(2, seq1['et'], 'ECLIPJ2000', 0)[0]
    vinf = nt.norm(v_arrive - state_venus[3:])
    span = 60 * 24 * 3600.0
    dt = 1 * 24 * 3600.0
    tofs = np.arange(seq1['tof'] - span, seq1['tof'] + span, dt)
    n_tofs = len(tofs)
    vinfs = np.zeros(n_tofs)
    args = {
        'planet1_ID': 4,
        'center_ID': 0,
        'et0': seq1['et'],
        'frame': 'ECLIPJ2000',
        'state0_planet0': state_venus,
        'mu': pd.sun['mu'],
        'tm': 1,
        'vinf': vinf
Пример #16
0

# In[11]:


#We need to load it first
spiceypy.furnsh('de432s.bsp')


# In[12]:


# Now compute  the position and velocity
# The first 3 values are the x, y, z components in km. The last 3 values are the corresponding velocity components in km/s.

Earth_State_Sun, Earth_Sun_Light_Time = spiceypy.spkgeo(targ=399, et=ET, 
                                                            ref='ECLIPJ2000', obs=10)


# In[13]:


print(Earth_State_Sun)


# In[14]:


print(Earth_Sun_Light_Time)


# In[15]:
Voyager 2 SPICE kernel is correct. Or you can change the path
to fit your needs
'''

# 3rd party libraries
import spiceypy as spice
import numpy as np

# AWP library
import spice_tools as st
import plotting_tools as pt
import spice_data as sd
from numerical_tools import norm

if __name__ == '__main__':
    spice.furnsh(sd.leapseconds_kernel)
    spice.furnsh('voyager2_jupiter_flyby.bsp')

    et = spice.str2et('1979-07-09 TDB')
    dt = 20 * 24 * 3600.0
    ets = np.arange(et - dt, et + dt, 5000.0)
    states = st.calc_ephemeris(-32, ets, 'ECLIPJ2000', 10)
    state_jup = spice.spkgeo(5, et, 'ECLIPJ2000', 10)[0]
    hline = {'val': norm(state_jup[3:]), 'color': 'C3'}

    pt.plot_velocities(ets, states[:, 3:], {
        'time_unit': 'days',
        'hlines': [hline],
        'show': True,
    })