def calc_vinfinity( tof, args ): r1_planet1 = spice.spkgps( args[ 'planet1_ID' ], args[ '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' ] } ) vinf = nt.norm( v0_sc_depart - args[ 'state0_planet0' ][ 3: ] ) return args[ 'vinf' ] - vinf
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
def f_calc_position(time_et): SSB_position, _ = spiceypy.spkgps(targ=0,et=time_et,\ ref="ECLIPJ2000",obs=10) return (SSB_position)
print('Calculated time diff: {calculated_difference}s'.format( calculated_difference=delta_seconds)) print('Computational time diff: {computational_difference}s'.format( computational_difference=end_time_et - initial_time_et)) print() ### grid with 1 day intervals between initial time and end time time_interval_et = np.linspace(initial_time_et, end_time_et, delta_days) ### ssb is solar system barycenter ssb_wrt_sun_position = [] for interval_et in time_interval_et: _position, _ = sp.spkgps(targ=0 \ ,et=interval_et \ ,ref='ECLIPJ2000' \ ,obs=10 ) ssb_wrt_sun_position.append(_position) ssb_wrt_sun_position_array = np.array(ssb_wrt_sun_position) initial_position = np.round(ssb_wrt_sun_position[0]) ### First Position print('Position (components) of the Solar System Barycentre w.r.t the\n' \ 'centre of the Sun (at inital time): \n' \ 'X = {x} km\n' \ 'Y = {y} km\n' \ 'Z = {z} km\n'.format(x = initial_position[0] \ ,y = initial_position[1] \
from scipy.spatial.distance import cdist DIST_MAT = cdist(np.array(list(ast_2020_jx1_df['POS_VEC_KM'].values)), \ np.array(list(ast_2020_jx1_df['POS_VEC_KM'].values))) # Print the maximum distance of all position solution space / domain print('Maximum distance of the predicted positions of 2020 JX1 in km: ' \ f'{np.max(DIST_MAT)}') print('\n') #%% # We want to compute the ecliptic coordinates of the asteroid as seen from # Earth ... or let's say: the solution space # First, we need to compute the position vector of our home planet ... EARTH_POSITION_KM, _ = spiceypy.spkgps(targ=399, et=SAMPLE_ET, \ ref='ECLIPJ2000', obs=10) #%% # ... to determine the asteroid's position as seen from Earth ast_2020_jx1_df.loc[:, 'POS_VEC_WRT_EARTH_KM'] = \ ast_2020_jx1_df['POS_VEC_KM'].apply(lambda x: x - EARTH_POSITION_KM) #%% # Now let's compute the ecliptic longitude and latitude values ast_2020_jx1_df.loc[:, 'ECLIP_LONG_DEG'] = \ ast_2020_jx1_df['POS_VEC_WRT_EARTH_KM'] \ .apply(lambda x: np.degrees(spiceypy.recrad(x)[1])) ast_2020_jx1_df.loc[:, 'ECLIP_LAT_DEG'] = \ ast_2020_jx1_df['POS_VEC_WRT_EARTH_KM'] \
# We see that 5.0012845 seconds are added in this time period (leap-seconds) # Create a numpy array that covers a time interval in delta = 1 day step TIME_INTERVAL_ET = np.linspace(INIT_TIME_ET, END_TIME_ET, DELTA_DAYS) #%% # Now we compute the position of the Solar System's barycentre w.r.t. our Sun: # First we set an empty list that stores later all x, y, z components for each # time step SSB_WRT_SUN_POSITION = [] # Each time step is used in this for-loop to compute the position of the SSB # w.r.t. the Sun. We use the function spkgps. for TIME_INTERVAL_ET_f in TIME_INTERVAL_ET: _position, _ = spiceypy.spkgps(targ=0, et=TIME_INTERVAL_ET_f, \ ref='ECLIPJ2000', obs=10) # Append the result to the final list SSB_WRT_SUN_POSITION.append(_position) # Convert the list to a numpy array SSB_WRT_SUN_POSITION = np.array(SSB_WRT_SUN_POSITION) #%% # Let's have a look at the first entry and ... print('Position (components) of the Solar System Barycentre w.r.t the\n' \ 'centre of the Sun (at initial time): \n' \ 'X = %s km\n' \ 'Y = %s km\n' \ 'Z = %s km\n' % tuple(np.round(SSB_WRT_SUN_POSITION[0])))
ceres_df.loc[:, 'UTC_PARSED'] = DATETIME_RANGE.strftime('%Y-%j') # Convert the date-time to Ephemeris Time ceres_df.loc[:, 'ET_TIME'] = ceres_df['UTC_TIME'] \ .apply(lambda x: spiceypy.utc2et(str(x))) #%% # Compute the distance between Ceres and the Sun and convert the resulting # distance value given in km to AU ceres_df.loc[:, 'DIST_SUN_AU'] = \ ceres_df['ET_TIME'].apply(lambda x: \ spiceypy.convrt( \ spiceypy.vnorm( \ spiceypy.spkgps(targ=CERES_ID, \ et=x, \ ref='ECLIPJ2000', \ obs=10)[0]), \ 'km', 'AU')) # # Compute the distance between Ceres and the Earth and convert the resulting # distance value given in km to AU ceres_df.loc[:, 'DIST_EARTH_AU'] = \ ceres_df['ET_TIME'].apply(lambda x: \ spiceypy.convrt( \ spiceypy.vnorm( \ spiceypy.spkgps(targ=CERES_ID, \ et=x, \ ref='ECLIPJ2000', \ obs=399)[0]), \ 'km', 'AU'))
# Set the column ET that stores all ETs SOLAR_SYSTEM_DF.loc[:, 'ET'] = TIME_INTERVAL_ET # The column UTC transforms all ETs back to a UTC format. The function # spicepy.et2datetime is NOT an official part of SPICE (there you can find # et2utc). # However this function returns immediately a datetime object SOLAR_SYSTEM_DF.loc[:, 'UTC'] = \ SOLAR_SYSTEM_DF['ET'].apply(lambda x: spiceypy.et2datetime(et=x).date()) # Here, the position of the SSB, as seen from the Sun, is computed. Since # spicepy.spkgps returns the position and the corresponding light time, # we add the index [0] to obtain only the position array SOLAR_SYSTEM_DF.loc[:, 'POS_SSB_WRT_SUN'] = \ SOLAR_SYSTEM_DF['ET'].apply(lambda x: spiceypy.spkgps(targ=0, \ et=x, \ ref='ECLIPJ2000', \ obs=10)[0]) # Now the SSB position vector is scaled with the Sun's radius SOLAR_SYSTEM_DF.loc[:, 'POS_SSB_WRT_SUN_SCALED'] = \ SOLAR_SYSTEM_DF['POS_SSB_WRT_SUN'].apply(lambda x: x / RADIUS_SUN) # Finally the distance between the Sun and the SSB is computed. The length # (norm) of the vector needs to be determined with the SPICE function vnorm(). # numpy provides an identical function in: numpy.linalg.norm() SOLAR_SYSTEM_DF.loc[:, 'SSB_WRT_SUN_SCALED_DIST'] = \ SOLAR_SYSTEM_DF['POS_SSB_WRT_SUN_SCALED'].apply(lambda x: \ spiceypy.vnorm(x)) #%%
print('Init time in UTC: %s' % initial_UTC) print('End time in UTC: %s\n' % end_UTC) # Convert to Ephemeris Time (ET) using the SPICE function utc2et initial_et = spiceypy.utc2et(initial_UTC) end_et = spiceypy.utc2et(end_UTC) print('Covered time interval in seconds: %s\n' % (end_et - initial_et)) # We see that 5.0012845 seconds are added in this time period (leapseconds) # Create a numpy array that covers a time interval in delta = 1 day step delta_time = np.linspace(initial_et, end_et, delta) for i in delta_time: position, _ = spiceypy.spkgps(targ=0, et = i, ref='ECLIPJ2000', obs=10) barycenter.append(position) barycenter = np.array(barycenter) print('Position (components) of the Solar System Barycentre w.r.t the\n' \ 'centre of the Sun (at inital time): \n' \ 'X = %s km\n' \ 'Y = %s km\n' \ 'Z = %s km\n' % tuple(np.round(barycenter[0]))) # ... let's determine and print the corresponding distance using the numpy # function linalg.norm() print('Distance between the Solar System Barycentre w.r.t the\n' \ 'centre of the Sun (at initial time): \n' \ 'd = %s km\n' % round(np.linalg.norm(barycenter[0])))