Ejemplo n.º 1
0
def test_read_write_bsp( plot = False ):
	'''
	Propagate a 30 degree inclination orbit (20 periods),
	write BSP kernel, then read back the BSP kernel, ensuring
	that latitudes are within +-30 degrees before and after
	writing kernel
	'''
	spice.furnsh( sd.pck00010 )

	sc = SC( {
		'coes' : [ 8000.0, 0.01, 30.0, 0, 0, 0 ],
		'tspan': '20'
		} )

	'''
	Ensure latitudes are +-30 degrees
	'''
	sc.calc_latlons()
	assert np.all( sc.latlons[ :, 2 ] <=  30.0 )
	assert np.all( sc.latlons[ :, 2 ] >= -30.0 )

	'''
	spice.spkopn will error if a bsp with the requested
	filename already exists
	'''
	filename = 'test_read_write_bsp.bsp'
	if os.path.isfile( filename ):
		os.remove( filename )

	'''
	Write bsp with all the default arguments except filename
	'''
	st.write_bsp( sc.ets, sc.states[ :, :6 ],
		{ 'bsp_fn': filename } )

	'''
	Now read back the bsp and ensure that
	latitudes are still within +-30 degrees
	'''
	spice.furnsh( filename )
	states  = st.calc_ephemeris( -999, sc.ets, 'IAU_EARTH', 399 )
	latlons = nt.cart2lat( states[ :, :3 ] )

	assert np.all( latlons[ :, 2 ] <=  30.0 )
	assert np.all( latlons[ :, 2 ] >= -30.0 )

	os.remove( filename )
Ejemplo n.º 2
0
def test_Spacecraft_minimum_altitude_stop_condition(plot=False):
    sc = SC({
        'coes': [pd.earth['radius'] + 1000.0, 0.5, 0.0, 90.0, 0.0, 0.0],
        'tspan': '1',
        'dt': 100.0,
        'rtol': 1e-9,
        'stop_conditions': {
            'min_alt': 100.0
        }  # km
    })
    assert sc.cb == pd.earth
    '''
	Since inclination is 0, all z-axis components of Spacecraft
	position and velocity should be 0
	'''
    assert np.all(sc.states[:, 2] == 0.0)
    assert np.all(sc.states[:, 5] == 0.0)
    '''
	The orbital elements were set such that minimum altitude
	crossing would occur, triggering the min_alt stop condition
	'''
    assert sc.ode_sol.success
    assert sc.ode_sol.message == 'A termination event occurred.'
    assert sc.ode_sol.status == 1

    assert pytest.approx(
     np.linalg.norm( sc.ode_sol.y_events[ 0 ][ :3 ] ) -\
     sc.cb[ 'radius' ] - 100.0, abs = 6.0e-3 ) == 0.0

    if plot:
        sc.plot_altitudes({
            'hlines': [{
                'val': 100.0,
                'color': 'c'
            }],
            'time_unit': 'hours',
            'title': 'test_Spacecraft_minimum_altitude_stop_condition',
            'show': True
        })
Ejemplo n.º 3
0
def test_Spacecraft_basic_propagation(plot=False):
    sc = SC({
        'coes': [pd.earth['radius'] + 1000.0, 0.0, 0.0, 0.0, 0.0, 0.0],
        'tspan': '1',
        'dt': 100.0,
        'rtol': 1e-8
    })
    assert sc.cb == pd.earth
    '''
	Since inclination is 0, all z-axis components of Spacecraft
	position and velocity should be 0
	'''
    assert np.all(sc.states[:, 2] == 0.0)
    assert np.all(sc.states[:, 5] == 0.0)
    '''
	Since there are no orbital perturbations, all COEs except
	true anomaly should	be close to constant
	(not exactly constant due to numerical error).
	However, since this is a circular orbit, periapsis is loosely
	defined, causing errors in true anomaly (not exactly linear),
	argument of periapsis (bounces back and forth between
	0 and 359.9 degrees), eccentricity (random noise), and
	semi-major axis (drift / random noise)
	'''
    sc.calc_coes()
    assert sc.coes_calculated
    assert pytest.approx(sc.coes[:, 0],
                         abs=1e-3) == pd.earth['radius'] + 1000.0  # sma
    assert pytest.approx(sc.coes[:, 1], abs=1e-6) == 0.0  # ecc
    assert np.all(sc.coes[:, 2] == 0.0)  # inc
    assert np.all(sc.coes[:, 5] == 0.0)  # raan

    sc.calc_apoapses_periapses()
    apse_diffs = sc.apoapses - sc.periapses
    assert pytest.approx(apse_diffs, abs=1e-3) == 0.0

    if plot:
        sc.plot_coes()
Ejemplo n.º 4
0
def test_Spacecraft_inclination_latitude(plot=False):
    spice.furnsh(sd.pck00010)

    sc = SC({
        'coes': [pd.earth['radius'] + 1000.0, 0.01, 50.0, 0.0, 0.0, 0.0],
        'tspan': '3',
        'dt': 10.0,
        'rtol': 1e-8
    })
    assert sc.cb == pd.earth
    '''
	Given that this spacecraft has 50 degrees inclination,
	the latitude coordinates should remain in between
	-50 and 50 degrees, since inclination is defined as
	the angle between the orbital plane and Earth's
	equatorial plane
	'''
    sc.calc_latlons()
    assert np.all( sc.latlons[ :, 2 ] <=  50.0 ) and\
        np.all( sc.latlons[ :, 2 ] >= -50.0 )

    if plot:
        sc.plot_groundtracks()
Ejemplo n.º 5
0
def test_Spacecraft_maximum_altitude_stop_condition(plot=False):
    stop_conditions = {'max_alt': pd.earth['SOI'] - pd.earth['radius']}
    sc = SC({
        'coes': [-(pd.earth['radius'] + 1000.0), 1.8, 0.0, 10.0, 0.0, 0.0],
        'tspan': 5 * 24 * 3600.0,
        'rtol': 1e-9,
        'stop_conditions': stop_conditions
    })
    assert sc.cb == pd.earth
    '''
	Since inclination is 0, all z-axis components of Spacecraft
	position and velocity should be 0
	'''
    assert np.all(sc.states[:, 2] == 0.0)
    assert np.all(sc.states[:, 5] == 0.0)
    '''
	The orbital elements were set such that maximum altitude
	crossing would occur, triggering the max_alt stop condition
	'''
    assert sc.ode_sol.success
    assert sc.ode_sol.message == 'A termination event occurred.'
    assert sc.ode_sol.status == 1

    assert pytest.approx(
     np.linalg.norm( sc.ode_sol.y_events[ 1 ][ :3 ] ) -\
     sc.cb[ 'radius' ], abs = 1e-3 ) ==\
     sc.cb[ 'SOI' ] - sc.cb[ 'radius' ]

    if plot:
        hline = {'val': pd.earth['SOI'] - pd.earth['radius'], 'color': 'c'}
        sc.plot_altitudes({
            'hlines': [hline],
            'time_unit': 'hours',
            'title': 'test_Spacecraft_maximum_altitude_stop_condition',
            'show': True
        })
Ejemplo n.º 6
0
	'''
    state0 = [
        7.44304239e+03,
        -5.12480267e+02,
        2.37748995e+03,  # km
        5.99287925e+00,
        1.19056063e+01,
        5.17252832e+00
    ]  # km / s

    # 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({
Ejemplo n.º 7
0
from Spacecraft import Spacecraft as SC
import orbit_calculations as oc
import plotting_tools     as pt
import planetary_data     as pd

if __name__ == '__main__':
	periapsis = pd.earth[ 'radius' ] + 4000.0 # km

	coes_circular    = [ periapsis,       0,   0, 0, 0, 0 ]
	coes_elliptical  = [ periapsis / 0.3, 0.7, 0, 0, 0, 0 ]
	state_parabolic  = spice.conics(
		[ periapsis, 1.0, 0, 0, 0, -10.0, 0, pd.earth[ 'mu' ] ], 0 )
	state_hyperbolic = spice.conics(
		[ periapsis, 2.5, 0, 0, 0, -10.0, 0, pd.earth[ 'mu' ] ], 0 )

	sc_circular   = SC( { 'coes': coes_circular,   'tspan': '1' } )
	sc_elliptical = SC( { 'coes': coes_elliptical, 'tspan': '2' } )
	sc_parabolic  = SC( { 'orbit_state': state_parabolic,  'tspan': 70000.0 } )
	sc_hyperbolic = SC( { 'orbit_state': state_hyperbolic, 'tspan': 30000.0 } )
	
	rs = [ sc_circular.states [ :, :3 ], sc_elliptical.states[ :, :3 ],
		   sc_parabolic.states[ :, :3 ], sc_hyperbolic.states[ :, :3 ] ]
	labels = [ 'Circular $(ecc=0.0)$',  'Elliptical $(ecc=0.7)$',
			   'Parabolic $(ecc=1.0)$', 'Hyperbolic $(ecc=3.0)$' ]

	sc_elliptical.plot_states( {
		'time_unit': 'hours',
		'show'     : True
		} )

	pt.plot_orbits( rs,
Ejemplo n.º 8
0
from Spacecraft import Spacecraft as SC
import orbit_calculations as oc

import numpy as np
import matplotlib.pyplot as plt

plt.style.use('dark_background')

# Molniya orbital elements
a = 6778.0
coes = [a, 0.0, 0.0, 0.0, 0.0, 0.0]

sc_config = {'coes': coes, 'tspan': '2.5', 'dt': 100.0}

if __name__ == '__main__':
    sc = SC(sc_config)
    accels = np.zeros((sc.states.shape[0], 3))

    for n in range(sc.states.shape[0]):
        accels[n] = oc.two_body_ode(sc.ets[n], sc.states[n])[3:]

    rnorms = np.linalg.norm(sc.states[:, :3], axis=1)
    vnorms = np.linalg.norm(sc.states[:, 3:6], axis=1)
    anorms = np.linalg.norm(accels, axis=1)

    fig, (ax0, ax1, ax2) = plt.subplots(3, 1, figsize=(20, 10))

    ets = (sc.ets - sc.ets[0]) / 3600.0

    ax0.plot(ets, accels[:, 0], 'r', label=r'$a_x$')
    ax0.plot(ets, accels[:, 1], 'g', label=r'$a_y$')
Ejemplo n.º 9
0
import ode_tools as ot
import plotting_tools as pt
import planetary_data as pd

if __name__ == '__main__':
    r0 = pd.earth['radius'] + 1000.0
    v0_circ = (pd.earth['mu'] / r0)**0.5

    state0_sc0 = [r0, 0, 0, 0, v0_circ, 0.0]
    state0_sc1 = [r0, 0, 0, 2.0, 9.0, 0.0]
    state0_sc2 = [r0, 0, 0, 1.0, 0.0, 8.0]
    state0_sc3 = [r0, 0, 0, 1.0, 6.0, 6.0]

    states0 = [state0_sc0, state0_sc1, state0_sc2, state0_sc3]
    rs = []
    sc_config = {'tspan': '1'}

    for state0 in states0:
        sc_config['orbit_state'] = state0
        rs.append(SC(sc_config).states[:, :3])

    pt.plot_orbits(
        rs, {
            'labels': range(4),
            'colors': ['C3', 'm', 'c', 'lime'],
            'traj_lws': 2,
            'azimuth': -32,
            'elevation': 70,
            'show': True
        })
Ejemplo n.º 10
0
'''
AWP | Astrodynamics with Python by Alfonso Gonzalez
https://github.com/alfonsogonzalez/AWP
https://www.youtube.com/c/AlfonsoGonzalezSpaceEngineering

Hello world of Spacecraft class
Two-body propagation with J2 perturbation for 100 periods
'''

# Python standard libraries
# AWP libraries
from Spacecraft import Spacecraft as SC
from planetary_data import earth

if __name__ == '__main__':
    coes = [earth['radius'] + 1000, 0.05, 30.0, 0.0, 0.0, 0.0]
    sc = SC({
        'coes': coes,
        'tspan': '100',
        'dt': 100.0,
        'orbit_perts': {
            'J2': True
        }
    })
    sc.plot_3d()
Ejemplo n.º 11
0
# AWP library
from Spacecraft import Spacecraft as SC
import spice_data as sd
import spice_tools as st

# 3rd party libraries
import spiceypy as spice

if __name__ == '__main__':
    spice.furnsh(sd.leapseconds_kernel)
    spice.furnsh(sd.de432)
    spice.furnsh(sd.pck00010)

    sc = SC({
        'date0': '2021-03-03 22:10:35 TDB',
        'coes': [7480.0, 0.09, 5.5, 6.26, 5.95, 0.2],
        'tspan': '40',
    })

    st.write_bsp(sc.ets, sc.states[:, :6], {'bsp_fn': 'leo.bsp'})
    spice.furnsh('leo.bsp')

    et0 = spice.str2et('2021-03-03 22:10:40 TDB')
    etf = spice.str2et('2021-03-04 TDB')

    timecell = spice.utils.support_types.SPICEDOUBLE_CELL(2)
    spice.appndd(et0, timecell)
    spice.appndd(etf, timecell)

    cell = spice.gfoclt('ANY', '399', 'ELLIPSOID', 'IAU_EARTH', '10',
                        'ELLIPSOID', 'IAU_SUN', 'LT', '-999', 120.0, timecell)
Ejemplo n.º 12
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
        })
Ejemplo n.º 13
0
# AWP libraries
from Spacecraft import Spacecraft as SC
from planetary_data import earth
import plotting_tools as pt

# 3rd party libraries
import numpy as np

aops = np.arange(0, 360, 90)
incs = np.arange(0, 90, 20)
tas = [0, 180]
coes = [earth['radius'] + 10000, 0.05, 0.0, 0.0, 0.0, 0.0]
scs = []
config = {'tspan': '1', 'dt': 100.0}

print(len(aops) * len(incs) * len(tas))

if __name__ == '__main__':
    for inc in incs:
        for aop in aops:
            for ta in tas:
                coes[2] = inc
                coes[4] = ta
                coes[5] = aop
                config['coes'] = coes
                sc = SC(config)
                scs.append(sc)

    rs = [sc.states[:, :3] for sc in scs]
    pt.plot_orbits(rs, {'traj_lws': 1, 'show': True})
Ejemplo n.º 14
0
'''
AWP | Astrodynamics with Python by Alfonso Gonzalez
https://github.com/alfonsogonzalez/AWP
https://www.youtube.com/c/AlfonsoGonzalezSpaceEngineering

Sun-synchronous orbit spacecraft eclipse calculations
'''

# AWP library
from Spacecraft import Spacecraft as SC
import spice_data as sd

# 3rd party libraries
import spiceypy as spice

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

	sc = SC( {
		'date0': '2021-01-01',
		'coes' : [ 6378 + 890.0, 0.0, 99.0, 0, 0, 80 ],
		'tspan': '4',
		} )
	sc.calc_eclipses( vv = True )

	sc.plot_eclipse_array( {
		'time_unit': 'days',
		'show'     : True
	} )
Ejemplo n.º 15
0
# 3rd party libraries
import numpy as np

# AWP library
from Spacecraft import Spacecraft as SC
import orbit_calculations as oc
import numerical_tools    as nt
import plotting_tools     as pt
import planetary_data     as pd

if __name__ == '__main__':
	periapsis = pd.earth[ 'radius' ] + 4000.0 # km
	coes      = [ periapsis / 0.3, 0.7, 0, 30.0, 0, 0 ]
	state     = oc.coes2state( coes )
	v_rot     = np.dot( nt.Cz( 40.0 * nt.d2r ), state[ 3: ] )
	state_rot = np.concatenate( ( state[ :3 ], v_rot ) )

	sc0    = SC( { 'orbit_state': state,     'tspan': '1' } )
	sc_rot = SC( { 'orbit_state': state_rot, 'tspan': '1' } )

	pt.plot_orbits( [ sc0.states[ :, :3 ], sc_rot.states[ :, :3 ] ],
		{
		'labels'     : [ 'Before', 'After' ],
		'colors'     : [ 'c', 'm' ],
		'azimuth'    : -90.0,
		'elevation'  :  90.0,
		'axes_custom': 36000.0,
		'traj_lws'   : 2.5,
		'show'       : True
		} )
Ejemplo n.º 16
0
'''
AWP | Astrodynamics with Python by Alfonso Gonzalez
https://github.com/alfonsogonzalez/AWP
https://www.youtube.com/c/AlfonsoGonzalezSpaceEngineering

Geostationary orbit spacecraft eclipse calculations
'''

from Spacecraft import Spacecraft as SC
import spice_data as sd

import spiceypy as spice

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

	sc = SC( {
		'date0': '2021-01-01',
		'coes' : [ 42164, 0, 0, 0, 0, 0 ],
		'tspan': '365',
		} )
	sc.plot_3d()
	sc.calc_eclipses( vv = True )
	sc.plot_eclipse_array( {
		'time_unit': 'days',
		'show'     : True,
	} )