LRO Solar Radiation Pressure with Lookup Table

This example demonstrates how to compute solar radiation pressure (SRP) accelerations using pre-computed lookup tables with the pyRTX library.

lro_srp_with_lut.py
  1### ------------------------------------------------------------------------------------------------------- ###
  2
  3# Example purpose:
  4# Show the object-oriented interface of the pyRTX library
  5#
  6# Example case:
  7# Compute the srp acceleration for LRO spacecraft, using the values stored in a lookup table.
  8
  9### ------------------------------------------------------------------------------------------------------- ###
 10### IMPORTS
 11
 12import sys, os
 13import spiceypy as sp
 14import matplotlib.pyplot as plt
 15import logging, timeit
 16
 17from pyRTX.classes.Spacecraft import Spacecraft
 18from pyRTX.classes.Planet import Planet
 19from pyRTX.classes.SRP import SunShadow, SolarPressure 
 20from pyRTX.classes.Precompute import Precompute
 21from pyRTX.classes.LookUpTable import LookUpTable
 22from pyRTX.core.analysis_utils import epochRange2
 23import logging
 24
 25from numpy import floor, mod
 26
 27import warnings
 28warnings.filterwarnings('ignore')
 29
 30### ------------------------------------------------------------------------------------------------------- ###
 31### INPUTS
 32
 33# NOTE: before running this script you must generate the input file 'luts/lro_accel_lut.nc' by running the 
 34# example 'compute_lut.py' using type = 'accel'.
 35
 36ref_epc 	= "2010 may 10 09:25:00"
 37duration    = 10000  									  # seconds
 38sc_mass		= 2000  									  # can be a float, int or xarray [kg]
 39timestep    = 100
 40METAKR      = '../example_data/LRO/metakernel_lro.tm'     # metakernel
 41obj_path    = '../example_data/LRO/'				      # folder with .obj files
 42lutfile     = 'luts/lro_accel_lut.nc'					  # lookup table file
 43base_flux   =  1361.5
 44ref_radius  =  1737.4
 45
 46if not os.path.exists(lutfile):
 47    print(f"Before running this script you must generate the file '{lutfile}' by running the example 'compute_lut.py' setting type = 'accel'.")
 48    sys.exit()
 49    
 50### ------------------------------------------------------------------------------------------------------- ###
 51### OBJECTS DEFINITION
 52
 53# Time initialization
 54tic = timeit.default_timer()
 55
 56# Load the metakernel containing references to the necessary SPICE frames
 57sp.furnsh(METAKR)
 58
 59# Define a basic epoch
 60epc_et0 =  sp.str2et( ref_epc ) 
 61epc_et1  = epc_et0 + duration
 62epochs   = epochRange2(startEpoch = epc_et0, endEpoch = epc_et1, step = timestep)
 63
 64# Define the Spacecraft Object (Refer to the class documentation for further details)
 65lro = Spacecraft( name = 'LRO',
 66                 
 67				  base_frame = 'LRO_SC_BUS', 					     # Name of the spacecraft body-fixed frame
 68      
 69                  mass = sc_mass,
 70      
 71				  spacecraft_model = {						         # Define a spacecraft model
 72                          
 73					'LRO_BUS': { 
 74							 'file' : obj_path + 'bus_rotated.obj',	 # .obj file of the spacecraft component
 75							 'frame_type': 'Spice',				     # type of frame (can be 'Spice' or 'UD'
 76							 'frame_name': 'LRO_SC_BUS',			 # Name of the frame
 77							 'center': [0.0,0.0,0.0],			     # Origin of the component
 78							 'diffuse': 0.1,				         # Diffuse reflect. coefficient
 79							 'specular': 0.3,				         # Specular reflect. coefficient
 80							 },
 81
 82					'LRO_SA': {	
 83							'file': obj_path + 'SA_recentred.obj',
 84							'frame_type': 'Spice',
 85							'frame_name': 'LRO_SA',
 86							'center': [-1,-1.1, -0.1],
 87							'diffuse': 0,
 88							'specular': 0.3,
 89							},
 90
 91
 92					'LRO_HGA': { 	
 93							'file': obj_path + 'HGA_recentred.obj',
 94							'frame_type': 'Spice',
 95							'frame_name': 'LRO_HGA',
 96							'center':[-0.99,    -0.3,  -3.1],
 97							'diffuse': 0.2,
 98							'specular': 0.1,
 99							},
100					}
101					)
102
103
104# Define the Moon object
105moon = Planet(  fromFile      = None,
106                radius        = ref_radius,
107                name          = 'Moon',
108                bodyFrame     = 'MOON_PA',
109                sunFixedFrame = 'GSE_MOON',
110                units         = 'km',
111                subdivs       = 5,
112                )
113
114
115# Precomputation object. This object performs all the calls to spiceypy before 
116# calculating the acceleration. This is necessary when calculating the acceleration
117# with parallel cores.
118prec = Precompute(epochs = epochs,)
119prec.precomputeSolarPressure(lro, moon, correction='LT+S')
120prec.dump()
121
122# Define the shadow function object
123shadow = SunShadow( spacecraft     = lro,
124				    body           = 'Moon',
125				    bodyShape      = moon,
126				    limbDarkening  = 'Eddington',
127        			precomputation = prec,
128				    )
129
130# Load the Look up table
131LUT  = LookUpTable(lutfile)
132
133# Define the solar pressure object (LUT mode)
134srp = SolarPressure( lro, 
135				     rayTracer      = None,
136				     baseflux       = base_flux,   
137				     shadowObj      = shadow,
138					 precomputation = prec,
139					 lookup         = LUT,
140				     )
141
142# Managing Error messages from trimesh
143# (when concatenating textures, in this case, withouth .mtl definition, trimesh returns a warning that
144#  would fill the stdout. Deactivate it for a clean output)
145log = logging.getLogger('trimesh')
146log.disabled = True
147
148# Compute the SRP acceleration at different epochs and plot it
149accel = srp.lookupCompute(epochs) * 1e3
150        
151log.disabled = False
152
153# Always unload the SPICE kernels
154sp.unload(METAKR)
155
156### ... Elapsed time
157toc = timeit.default_timer()
158time_min = int(floor((toc-tic)/60))
159time_sec = int(mod((toc-tic), 60))
160print("")
161print("\t Elapsed time: %d min, %d sec" %(time_min, time_sec))
162print("")
163
164### ------------------------------------------------------------------------------------------------------- ###
165### PLOT
166
167epochs  = [float( epc - epc_et0)/3600 for epc in epochs]
168
169fig, ax = plt.subplots(3, 1, figsize=(14,8), sharex = True)
170
171ax[0].plot(epochs, accel[:,0], linewidth = 2, color = "tab:blue")
172ax[0].set_ylabel('X [m/s^2]')
173ax[1].plot(epochs, accel[:,1], linewidth = 2, color = "tab:blue")
174ax[1].set_ylabel('Y [m/s^2]')
175ax[2].plot(epochs, accel[:,2], linewidth = 2, color = "tab:blue")
176ax[2].set_ylabel('Z [m/s^2]')
177ax[2].set_xlabel('Hours from t0')
178
179plt.tight_layout()
180plt.show()
181
182### ------------------------------------------------------------------------------------------------------- ###
183
184