def main(): """Main function of the program.""" main = tk.Tk() # Add Title main.title("Space Craft Creator") # Disable Resizing main.resizable(False, False) data = Data() spacecraft = Spacecraft(data) notebook = Notebook(main) spacecraft_tab = spacecraft.make_tab(notebook) notebook.add(spacecraft_tab, text="Spacecraft") for key, subsystem in spacecraft.subsections.items(): notebook.add(subsystem.make_tab(notebook), text=key) notebook.add(spacecraft.sizes.make_tab(notebook), text="Sizes") notebook.add(spacecraft.velocities.make_tab(notebook), text="Velocity Profiles") notebook.grid(column=0, row=0) notebook.enable_traversal() button = Button(main, text="Caclulate", command=spacecraft.calculate) button.grid(column=0, row=1) main.mainloop()
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 )
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 })
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()
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 })
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()
from Environment import Environment from Spacecraft import Spacecraft from matplotlib import pyplot as plt import numpy as np import pandas as pd import os from models.MATERIAL import MATERIAL environment = Environment("models/spenvisdata.csv") spacecraft = Spacecraft(MATERIAL.ALUMINIUM, 0.0003, environment) masses = [mass * 0.001 for mass in environment.getMasses()][0:112] # gives masses in kg IndividualFluxes = [flux for flux in environment.getFluxes() ][0:112] # gives flux in 1/(m^2 * yr) diameters = [diameter * 0.01 for diameter in environment.getDiameters() ][0:112] # gives diameters in m densities = [density * 1000 for density in environment.getDensities() ][0:112] # gives densities in kg/m^-3 # Give specifications of the run N = 10000 materialType = 'ALUMINIUM' # CARBONFIBER / TITANIUM / ALUMINIUM thickness = 1.0 # milimeter # Get name where file is based basename = 'run_{}_{}_{}'.format(N, materialType, thickness) path = '../Simulation_data/' + basename # Retrieve files and data dataPerRun = pd.read_csv(path + '/' + 'dataPerun.csv', header=0, sep='\t')
from Environment import Environment from Spacecraft import Spacecraft from models.MATERIAL import MATERIAL from matplotlib import pyplot as plt import numpy as np import pandas as pd import os from multiprocessing import Pool import multiprocessing from numba import jit,cuda # Specify variables for the run N = 20000 environment = Environment("models/spenvisdata.csv") spacecraft = Spacecraft(MATERIAL.ALUMINIUM, 0.0010, environment) #Single model run def f(input): if input % np.ceil(N / 10) == 0: print('progress: {}%'.format(input / N * 100)) return spacecraft.getDamage() if __name__ == '__main__': # Calculate data using multiprocessing to speed up the process # with a factor = #number of cpus on the device. Disable if slow computer! pool = Pool(multiprocessing.cpu_count()-1) results = list(zip(*pool.map(f, [i for i in range(N)]))) pool.close()
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, {
''' 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()
# 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)
plt.style.use('dark_background') import matplotlib matplotlib.rcParams['lines.linewidth'] = 2 # Molniya orbital elements raan = 30.0 inc = 63.4 aop = 270.0 a = 26600.0 e = 0.7 coes = [a, e, inc, 0.0, aop, raan] sc_config = {'coes': coes, 'tspan': '2.5', 'dt': 100.0} if __name__ == '__main__': sc = SC(sc_config) sc.plot_3d({ 'colors': ['c'], 'elevation': 13, 'azimuth': -13, 'legend': False, # you are the legend 'show': True }) 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)
''' 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 } )
Acceleration, Velocity and Position subplots script for circular orbit ''' 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') a = 8078.0 coes = [a, 0.0, 0.0, 0.0, 0.0, 0.0] sc_config = {'coes': coes, 'tspan': '1.0', 'dt': 100.0} fn = '/mnt/c/Users/alfon/AWP/foom2_ode_solvers/eq_3d.png' if __name__ == '__main__': sc = SC(sc_config) sc.plot_3d({ 'colors': ['c'], 'elevation': 90, 'azimuth': 270, 'hide_axes': True, 'legend': False, 'filename': fn, 'dpi': 300 })