LRO Albedo and Thermal IR (Simple)
This example demonstrates how to compute albedo and thermal infrared accelerations using the object-oriented interface of the pyRTX library.
In this simplified case, we use single uniform values for:
Planet emissivity
Planet albedo
Planet surface temperature
This provides a quick way to compute planetary radiation pressure effects without requiring detailed surface property maps.
lro_alb_ir_simple.py
1### ------------------------------------------------------------------------------------------------------- ###
2
3# Example purpose:
4# Show the object-oriented interface of the pyRTX library
5#
6# Example case:
7# Show how to compute albedo and thermal-ir accelerations
8# Here we use a single value for the emissivity, albedo and temperature for the planet.
9
10### ------------------------------------------------------------------------------------------------------- ###
11### IMPORTS
12
13import sys, os
14import numpy as np
15import spiceypy as sp
16import matplotlib.pyplot as plt
17import timeit
18
19from pyRTX.classes.Spacecraft import Spacecraft
20from pyRTX.classes.Planet import Planet
21from pyRTX.classes.Radiation import Albedo, Emissivity
22from pyRTX.classes.Precompute import Precompute
23from pyRTX.classes.LookUpTable import LookUpTable
24from pyRTX.core.analysis_utils import epochRange2
25
26from numpy import floor, mod
27
28### ------------------------------------------------------------------------------------------------------- ###
29### INPUTS
30
31# NOTE: before running this script you must generate the input file 'luts/lro_accel_lut.nc' by running the
32# example 'compute_lut.py' using type = 'accel'.
33
34ref_epc = "2010 may 10 09:25:00"
35duration = 10000 # seconds
36timestep = 100
37METAKR = '../example_data/LRO/metakernel_lro.tm' # metakernel
38obj_path = '../example_data/LRO/' # folder with .obj files
39lutfile = 'luts/lro_accel_lut.nc' # lookup table file
40base_flux = 1361.5
41ref_radius = 1737.4
42n_cores = 10
43sc_mass = 2000 # can be a float, int or xarray [kg]
44
45if not os.path.exists(lutfile):
46 print(f"Before running this script you must generate the file '{lutfile}' by running the example 'compute_lut.py' setting type = 'accel'.")
47 sys.exit()
48
49### ------------------------------------------------------------------------------------------------------- ###
50### OBJECTS DEFINITION
51
52# Time initialization
53tic = timeit.default_timer()
54
55# Load the metakernel containing references to the necessary SPICE frames
56sp.furnsh(METAKR)
57
58# Define epochs
59epc_et0 = sp.str2et( ref_epc )
60epc_et1 = epc_et0 + duration
61epochs = epochRange2(startEpoch = epc_et0, endEpoch = epc_et1, step = timestep)
62
63# Define the Spacecraft Object (Refer to the class documentation for further details)
64lro = Spacecraft( name = 'LRO',
65
66 base_frame = 'LRO_SC_BUS', # Name of the spacecraft body-fixed frame
67
68 mass = sc_mass,
69
70 spacecraft_model = { # Define a spacecraft model
71
72 'LRO_BUS': {
73 'file' : obj_path + 'bus_rotated.obj', # .obj file of the spacecraft component
74 'frame_type': 'Spice', # type of frame (can be 'Spice' or 'UD'
75 'frame_name': 'LRO_SC_BUS', # Name of the frame
76 'center': [0.0,0.0,0.0], # Origin of the component
77 'diffuse': 0.1, # Diffuse reflect. coefficient
78 'specular': 0.3, # Specular reflect. coefficient
79 },
80
81 'LRO_SA': {
82 'file': obj_path + 'SA_recentred.obj',
83 'frame_type': 'Spice',
84 'frame_name': 'LRO_SA',
85 'center': [-1,-1.1, -0.1],
86 'diffuse': 0,
87 'specular': 0.3,
88 },
89
90
91 'LRO_HGA': {
92 'file': obj_path + 'HGA_recentred.obj',
93 'frame_type': 'Spice',
94 'frame_name': 'LRO_HGA',
95 'center':[-0.99, -0.3, -3.1],
96 'diffuse': 0.2,
97 'specular': 0.1,
98 },
99 }
100 )
101
102# Define the Moon object
103moon = Planet( fromFile = None,
104 radius = ref_radius,
105 name = 'Moon',
106 bodyFrame = 'MOON_PA',
107 sunFixedFrame = 'GSE_MOON',
108 units = 'km',
109 subdivs = 5,
110 )
111
112# Set the albedo and emissivity values
113# Here we use dummy values and assume that
114# albedo and emissivity are constant over the whole planet
115# and set a different dayside and nightside temperature
116# pyRTX supports also gridded values for albedo and emissivity (see examples/lro_alb_ir_grid.py)
117
118moon.albedo = 0.3
119moon.emissivity = 0.8
120moon.dayside_temperature = 300
121moon.nightside_temperature = 200
122
123# Load the Look up table
124LUT = LookUpTable(lutfile)
125
126# Precomputation object
127prec = Precompute(epochs = epochs,)
128prec.precomputePlanetaryRadiation(lro, moon, LUT.moving_frames, correction='CN')
129prec.dump()
130
131# Create the albedo object
132albedo = Albedo(lro, LUT, moon, precomputation = prec, baseflux = base_flux,)
133
134# Create the thermal infrared object
135thermal_ir = Emissivity(lro, LUT, moon, precomputation = prec, baseflux = base_flux,)
136
137### ------------------------------------------------------------------------------------------------------- ###
138### COMPUTATIONS
139
140# Both the albedo and emissivity objects have a .compute() method.
141# This method returns the normalized fluxes, direction and albedo values
142# for each of the planet faces contributing to the computation
143# The general formula for computing the acceleration of an elementary face is:
144#
145# acc_i = L * albedo_value/mass * norm_flux
146#
147# where L is the normalized optical response of the spacecraft which can be computed
148# with raytracing setting a unitary radiance of the impacting rays
149# Due to the very high number of rays involved in these computations
150# it is mandatory to precompute L in the form of a lookup table.
151# Here we import the lookup table for LRO which can be computed using the example script
152# 'compute_lut.py'
153
154# Parallel computations
155alb_accel = albedo.compute(epochs, n_cores = n_cores)[0] * 1e3
156ir_accel = thermal_ir.compute(epochs, n_cores = n_cores)[0] * 1e3
157
158# Always unload the SPICE kernels
159sp.unload(METAKR)
160
161### ... Elapsed time
162toc = timeit.default_timer()
163time_min = int(floor((toc-tic)/60))
164time_sec = int(mod((toc-tic), 60))
165print("")
166print("\t Elapsed time: %d min, %d sec" %(time_min, time_sec))
167print("")
168
169### ------------------------------------------------------------------------------------------------------- ###
170### PLOT
171
172epochs = [float( epc - epc_et0 )/3600 for epc in epochs]
173
174# ALBEDO
175fig, ax = plt.subplots(3, 1, figsize=(14,8), sharex = True)
176
177ax[0].plot(epochs, alb_accel[:,0], linewidth = 2, color = "tab:blue")
178ax[0].set_ylabel('X [m/s^2]')
179ax[1].plot(epochs, alb_accel[:,1], linewidth = 2, color = "tab:blue")
180ax[1].set_ylabel('Y [m/s^2]')
181ax[2].plot(epochs, alb_accel[:,2], linewidth = 2, color = "tab:blue")
182ax[2].set_ylabel('Z [m/s^2]')
183ax[2].set_xlabel('Hours from CA')
184fig.suptitle('Albedo in S/C body frame')
185plt.tight_layout()
186
187# IR
188fig, ax = plt.subplots(3, 1, figsize=(14,8), sharex = True)
189
190ax[0].plot(epochs, ir_accel[:,0], linewidth = 2, color = "tab:blue")
191ax[0].set_ylabel('X [m/s^2]')
192ax[1].plot(epochs, ir_accel[:,1], linewidth = 2, color = "tab:blue")
193ax[1].set_ylabel('Y [m/s^2]')
194ax[2].plot(epochs, ir_accel[:,2], linewidth = 2, color = "tab:blue")
195ax[2].set_ylabel('Z [m/s^2]')
196ax[2].set_xlabel('Hours from CA')
197fig.suptitle('IR in S/C body frame')
198plt.tight_layout()
199
200plt.show()
201
202### ------------------------------------------------------------------------------------------------------- ###