def process(data_file, error_apriori, units): ''' Given a .csv data file in the format of (time, x, y, z) applies both filters, generates a filtered.csv data file, prints out the final keplerian elements computed from both Lamberts and Interpolation and finally plots the initial, filtered data set and the final orbit. Args: data_file (string): The name of the .csv file containing the positional data error_apriori (float): apriori estimation of the measurements error in km Returns: Runs the whole process of the program ''' # First read the csv file called "orbit" with the positional data data = read_data.load_data(data_file) if (units == 'm'): # Transform m to km data[:, 1:4] = data[:, 1:4] / 1000 print( "***********Choose filter(s) in desired order of application***********" ) print( "(SPACE to toggle, UP/DOWN to navigate, RIGHT/LEFT to select/deselect and ENTER to submit)" ) print( "*if nothing is selected, Triple Moving Average followed by Savitzky Golay will be applied" ) questions = [ inquirer.Checkbox( 'filter', message="Select filter(s)", choices=['Savitzky Golay Filter', 'Triple Moving Average Filter'], ), ] choices = inquirer.prompt(questions) data_after_filter = data if (len(choices['filter']) == 0): print("Applying Triple Moving Average followed by Savitzky Golay...") # Apply the Triple moving average filter with window = 3 data_after_filter = triple_moving_average.generate_filtered_data( data_after_filter, 3) # Use the golay_window.py script to find the window for the Savitzky Golay filter based on the error you input window = golay_window.window(error_apriori, data_after_filter) # Apply the Savitzky Golay filter with window = window (51 for orbit.csv) and polynomial order = 3 data_after_filter = sav_golay.golay(data_after_filter, window, 3) else: for index, choice in enumerate(choices['filter']): if (choice == 'Savitzky Golay Filter'): print("Applying Savitzky Golay Filter...") # Use the golay_window.py script to find the window for the Savitzky Golay filter based on the error you input window = golay_window.window(error_apriori, data_after_filter) # Apply the Savitzky Golay filter with window = window (51 for orbit.csv) and polynomial order = 3 data_after_filter = sav_golay.golay(data_after_filter, window, 3) else: print("Applying Triple Moving Average Filter...") # Apply the Triple moving average filter with window = 3 data_after_filter = triple_moving_average.generate_filtered_data( data_after_filter, 3) # Compute the residuals between filtered data and initial data and then the sum and mean values of each axis res = data_after_filter[:, 1:4] - data[:, 1:4] sums = np.sum(res, axis=0) print("\nDisplaying the sum of the residuals for each axis") print(sums, "\n") means = np.mean(res, axis=0) print("Displaying the mean of the residuals for each axis") print(means, "\n") # Save the filtered data into a new csv called "filtered" np.savetxt("filtered.csv", data_after_filter, delimiter=",") print("***********Choose Method(s) for Orbit Determination***********") print( "(SPACE to toggle, UP/DOWN to navigate, RIGHT/LEFT to select/deselect and ENTER to submit)" ) print( "*if nothing is selected, Cubic Spline Interpolation will be used for Orbit Determination" ) questions = [ inquirer.Checkbox( 'method', message="Select Method(s)", choices=[ 'Lamberts Kalman', 'Cubic Spline Interpolation', 'Ellipse Best Fit', 'Gibbs 3 Vector' ], ), ] choices = inquirer.prompt(questions) kep_elements = {} if (len(choices['method']) == 0): # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_final_inter = np.transpose(kep_final_inter) kep_final_inter = np.resize(kep_final_inter, ((7, 1))) kep_final_inter[6, 0] = sgp4.rev_per_day(kep_final_inter[0, 0]) kep_elements['Cubic Spline Interpolation'] = kep_final_inter else: for index, choice in enumerate(choices['method']): if (choice == 'Lamberts Kalman'): # Apply Lambert Kalman method for the filtered data set kep_lamb = lamberts_kalman.create_kep(data_after_filter) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_lamb = lamberts_kalman.kalman(kep_lamb, 0.01**2) kep_final_lamb = np.transpose(kep_final_lamb) kep_final_lamb = np.resize(kep_final_lamb, ((7, 1))) kep_final_lamb[6, 0] = sgp4.rev_per_day(kep_final_lamb[0, 0]) kep_elements['Lamberts Kalman'] = kep_final_lamb elif (choice == 'Cubic Spline Interpolation'): # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_final_inter = np.transpose(kep_final_inter) kep_final_inter = np.resize(kep_final_inter, ((7, 1))) kep_final_inter[6, 0] = sgp4.rev_per_day(kep_final_inter[0, 0]) kep_elements['Cubic Spline Interpolation'] = kep_final_inter elif (choice == 'Ellipse Best Fit'): # Apply the ellipse best fit method kep_ellip = ellipse_fit.determine_kep(data_after_filter[:, 1:])[0] kep_final_ellip = np.transpose(kep_ellip) kep_final_ellip = np.resize(kep_final_ellip, ((7, 1))) kep_final_ellip[6, 0] = sgp4.rev_per_day(kep_final_ellip[0, 0]) kep_elements['Ellipse Best Fit'] = kep_final_ellip else: # Apply the Gibbs method kep_gibbs = gibbs_method.gibbs_get_kep(data_after_filter[:, 1:]) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_gibbs = lamberts_kalman.kalman(kep_gibbs, 0.01**2) kep_final_gibbs = np.transpose(kep_final_gibbs) kep_final_gibbs = np.resize(kep_final_gibbs, ((7, 1))) kep_final_gibbs[6, 0] = sgp4.rev_per_day(kep_final_gibbs[0, 0]) kep_elements['Gibbs 3 Vector'] = kep_final_gibbs kep_final = np.zeros((7, len(kep_elements))) order = [] for index, key in enumerate(kep_elements): kep_final[:, index] = np.ravel(kep_elements[key]) order.append(str(key)) # Print the final orbital elements for all solutions kep_elements = [ "Semi major axis (a)(km)", "Eccentricity (e)", "Inclination (i)(deg)", "Argument of perigee (ω)(deg)", "Right acension of ascending node (Ω)(deg)", "True anomaly (v)(deg)", "Frequency (f)(rev/day)" ] for i in range(0, len(order)): print("\n******************Output for %s Method******************\n" % order[i]) for j in range(0, 7): print("%s: %.16f" % (kep_elements[j], kep_final[j, i])) print("\nShow plots? [y/n]") user_input = input() if (user_input == "y" or user_input == "Y"): for j in range(0, len(order)): # Plot the initial data set, the filtered data set and the final orbit # First we transform the set of keplerian elements into a state vector state = kep_state.kep_state(np.resize(kep_final[:, j], (7, 1))) # Then we produce more state vectors at varius times using a Runge Kutta algorithm keep_state = np.zeros((6, 150)) ti = 0.0 tf = 1.0 t_hold = np.zeros((150, 1)) x = state h = 0.1 tetol = 1e-04 for i in range(0, 150): keep_state[:, i] = np.ravel(rkf78.rkf78(6, ti, tf, h, tetol, x)) t_hold[i, 0] = tf tf = tf + 1 positions = keep_state[0:3, :] ## Finally we plot the graph mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() ax = fig.gca(projection='3d') ax.plot(data[:, 1], data[:, 2], data[:, 3], ".", label='Initial data ') ax.plot(data_after_filter[:, 1], data_after_filter[:, 2], data_after_filter[:, 3], "k", linestyle='-', label='Filtered data') ax.plot(positions[0, :], positions[1, :], positions[2, :], "r-", label='Orbit after %s method' % order[j]) ax.legend() ax.can_zoom() ax.set_xlabel('x (km)') ax.set_ylabel('y (km)') ax.set_zlabel('z (km)') plt.show()
def process(data_file, error_apriori, name): ''' Perform filtering and orbit determination methods. Applies filters and orbit determination techniques on the input data and saves the output in dst folder. Args: data_file (numpy array): Raw orbit data error_apriori (float): apriori estimation of the measurements error in km name (str): name of the file being processed ''' # Get positional data data = data_file # Units is km by default # Apply the Triple moving average filter with window = 3 data_after_filter = triple_moving_average.generate_filtered_data(data, 3) # Use the golay_window.py script to find the window for the savintzky golay filter based on the error you input window = golay_window.window(error_apriori, data_after_filter) # Apply the Savintzky - Golay filter with window = 31 and polynomail parameter = 6 data_after_filter = sav_golay.golay(data_after_filter, window, 3) # Compute the residuals between filtered data and initial data and then the sum and mean values of each axis res = data_after_filter[:, 1:4] - data[:, 1:4] sums = np.sum(res, axis=0) print("Displaying the sum of the residuals for each axis") print(sums) print(" ") means = np.mean(res, axis=0) print("Displaying the mean of the residuals for each axis") print(means) print(" ") # Save the filtered data into a new csv called "filtered" np.savetxt(os.path.join(os.getcwd(), "example_data", "DestinationCSV", "%s_filtered.csv" % (name)), data_after_filter, delimiter=",") # Apply Lambert's solution for the filtered data set kep_lamb = lamberts_kalman.create_kep(data_after_filter) # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply the Gibbs method kep_gibbs = gibbsMethod.gibbs_get_kep(data_after_filter[:, 1:]) # Apply the ellipse best fit method kep_ellip = ellipse_fit.determine_kep(data_after_filter[:, 1:])[0] # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # set we a estimate of measurement vatiance R = 0.01 ** 2 kep_final_lamb = lamberts_kalman.kalman(kep_lamb, 0.01**2) kep_final_lamb = np.transpose(kep_final_lamb) kep_final_lamb = np.resize(kep_final_lamb, ((7, 1))) kep_final_lamb[6, 0] = sgp4.rev_per_day(kep_final_lamb[0, 0]) kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_final_inter = np.transpose(kep_final_inter) kep_final_inter = np.resize(kep_final_inter, ((7, 1))) kep_final_inter[6, 0] = sgp4.rev_per_day(kep_final_inter[0, 0]) kep_final_ellip = np.transpose(kep_ellip) kep_final_ellip = np.resize(kep_final_ellip, ((7, 1))) kep_final_ellip[6, 0] = sgp4.rev_per_day(kep_final_ellip[0, 0]) kep_final_gibbs = lamberts_kalman.kalman(kep_gibbs, 0.01**2) kep_final_gibbs = np.transpose(kep_final_gibbs) kep_final_gibbs = np.resize(kep_final_gibbs, ((7, 1))) kep_final_gibbs[6, 0] = sgp4.rev_per_day(kep_final_gibbs[0, 0]) kep_final = np.zeros((7, 4)) kep_final[:, 0] = np.ravel(kep_final_lamb) kep_final[:, 1] = np.ravel(kep_final_inter) kep_final[:, 2] = np.ravel(kep_final_ellip) kep_final[:, 3] = np.ravel(kep_final_gibbs) # Print the final orbital elements for all solutions kep_elements = [ "Semi major axis (a)(km)", "Eccentricity (e)", "Inclination (i)(deg)", "Argument of perigee (omega)(deg)", "Right acension of ascending node (Omega)(deg)", "True anomaly (v)(deg)", "Frequency (f)(rev/day)" ] det_methods = [ "Lamberts Kalman", "Spline Interpolation", "Ellipse Best Fit", "Gibbs 3 Vector" ] method_name = ["lamb", "inter", "ellip", "gibb"] for i in range(0, 4): print("\n******************Output for %s Method******************\n" % det_methods[i]) j = 0 for j in range(0, 7): print("%s: %.16f\n" % (kep_elements[j], kep_final[j, i])) print("\nSave plots? [y/n]") user_input = input() if (user_input == "y" or user_input == "Y"): for j in range(0, 4): # Plot the initial data set, the filtered data set and the final orbit # First we transform the set of keplerian elements into a state vector state = kep_state.kep_state(np.resize(kep_final[:, j], (7, 1))) # Then we produce more state vectors at varius times using a Runge Kutta algorithm keep_state = np.zeros((6, 150)) ti = 0.0 tf = 1.0 t_hold = np.zeros((150, 1)) x = state h = 0.1 tetol = 1e-04 for i in range(0, 150): keep_state[:, i] = np.ravel(rkf78.rkf78(6, ti, tf, h, tetol, x)) t_hold[i, 0] = tf tf = tf + 1 positions = keep_state[0:3, :] ## Finally we plot the graph mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() ax = fig.gca(projection='3d') ax.plot(data[:, 1], data[:, 2], data[:, 3], ".", label='Initial data ') ax.plot(data_after_filter[:, 1], data_after_filter[:, 2], data_after_filter[:, 3], "k", linestyle='-', label='Filtered data') ax.plot(positions[0, :], positions[1, :], positions[2, :], "r-", label='Orbit after %s method' % det_methods[j]) ax.legend() ax.can_zoom() ax.set_xlabel('x (km)') ax.set_ylabel('y (km)') ax.set_zlabel('z (km)') plt.savefig(os.path.join(os.getcwd(), "example_data", "DestinationSVG", '%s_%s.svg' % (name, method_name[j])), format="svg") print("saved %s_%s.svg" % (name, method_name[j]))
# Earth's mass parameter in appropriate units: mu_Earth = 398600.435436E9 # m^3/seg^2 #Earth's radius in appropriate units: # R_Earth = 6378136.3 #m #minimal acceptable altitude for satellites (150 km)?? #maximal acceptable altitude for satellites (150 km)?? #write file name of data: fname = '../orbit.csv' # load observational data: data = np.loadtxt(fname, skiprows=1, usecols=(0, 1, 2, 3)) # generate vector of initial guess of orbital elements: # values written below correspond to solution of ellipse_fit.py for the same file data0 = __read_file(fname) kep0, res0 = determine_kep(data0) a_ = kep0[0][0] # m e_ = kep0[1][0] I_ = np.deg2rad(kep0[2][0]) #deg omega_ = np.deg2rad(kep0[3][0]) #deg Omega_ = np.deg2rad(kep0[4][0]) #deg f_ = np.deg2rad(kep0[5][0]) #deg #estimate time of pericenter passage from true anomaly at epoch E_ = truean2eccan(e_, f_) #ecc. anomaly M_ = E_ - e_ * np.sin(E_) #mean anomaly n_ = meanmotion(mu_Earth, a_) #mean motion taup_ = data[0, 0] - M_ / n_ #time of pericenter passage # this is the vector of initial guess of orbital elements:
def test_ellipse_fit(): """Tests ellipse fit with 8 satellites: * NOAA-1 * GPS-23 * Cryosat-2 * NOAA-15 * NOAA-18 * NOAA-19 * MOLNIYA 2-10 * ISS To add your own test copy the template, put the 2nd row of the TLE of the satellite in place of kep. In the rkf5 line put the final time and time step such that 700±200 points are generated. Now, put the actual orbital parameters in the assert statements. Args: NIL Returns: NIL """ #noaa-1 tle = np.array( [101.7540, 195.7370, 0.0031531, 352.8640, 117.2610, 12.53984625169364]) r = tle_to_state(tle) _, vecs = rkf5(0, 7200, 10, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(7826.006538, 0.1) # sma assert kep[1] == pytest.approx(0.0031531, 0.01) # ecc assert kep[2] == pytest.approx(101.7540, 0.1) # inc assert kep[3] == pytest.approx(352.8640, 1.0) # argp assert kep[4] == pytest.approx(195.7370, 0.1) # raan assert kep[5] == pytest.approx(117.2610, 0.5) # true_anom #gps-23 tle = np.array( [54.4058, 84.8417, 0.0142955, 74.4543, 193.5934, 2.00565117179872]) r = tle_to_state(tle) _, vecs = rkf5(0, 43080, 50, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(26560.21419, 0.1) # sma assert kep[1] == pytest.approx(0.0142955, 0.01) # ecc assert kep[2] == pytest.approx(54.4058, 0.1) # inc assert kep[3] == pytest.approx(74.4543, 1.0) # argp assert kep[4] == pytest.approx(84.8417, 0.1) # raan assert kep[5] == pytest.approx(193.5934, 0.5) # true_anom #cryosat-2 tle = np.array( [92.0287, 282.8216, 0.0005088, 298.0188, 62.0505, 14.52172969429489]) r = tle_to_state(tle) _, vecs = rkf5(0, 5950, 10, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(7096.69719, 0.1) # sma assert kep[1] == pytest.approx(0.0005088, 0.01) # ecc assert kep[2] == pytest.approx(92.0287, 0.1) # inc assert kep[3] == pytest.approx(298.0188, 1.0) # argp assert kep[4] == pytest.approx(282.8216, 0.1) # raan assert kep[5] == pytest.approx(62.0505, 0.5) # true_anom #noaa-15 tle = np.array( [98.7705, 158.2195, 0.0009478, 307.8085, 52.2235, 14.25852803]) r = tle_to_state(tle) _, vecs = rkf5(0, 6120, 10, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(7183.76381, 0.1) # sma assert kep[1] == pytest.approx(0.0009478, 0.01) # ecc assert kep[2] == pytest.approx(98.7705, 0.1) # inc assert kep[3] == pytest.approx(307.8085, 1.0) # argp assert kep[4] == pytest.approx(158.2195, 0.1) # raan assert kep[5] == pytest.approx(52.2235, 0.5) # true_anom #noaa-18 tle = np.array( [99.1472, 176.6654, 0.0014092, 197.4778, 162.5909, 14.12376102669957]) r = tle_to_state(tle) _, vecs = rkf5(0, 6120, 10, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(7229.38911, 0.1) # sma assert kep[1] == pytest.approx(0.0014092, 0.01) # ecc assert kep[2] == pytest.approx(99.1472, 0.1) # inc assert kep[3] == pytest.approx(197.4778, 1.0) # argp assert kep[4] == pytest.approx(176.6654, 0.1) # raan assert kep[5] == pytest.approx(162.5909, 0.5) # true_anom #noaa-19 tle = np.array( [99.1401, 119.3629, 0.0014753, 44.0001, 316.2341, 14.12279464478196]) r = tle_to_state(tle) _, vecs = rkf5(0, 6120, 10, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(7229.71889, 0.1) # sma assert kep[1] == pytest.approx(0.0014753, 0.01) # ecc assert kep[2] == pytest.approx(99.1401, 0.1) # inc assert kep[3] == pytest.approx(44.0001, 1.0) # argp assert kep[4] == pytest.approx(119.3629, 0.1) # raan assert kep[5] == pytest.approx(316.2341, 0.5) # true_anom #molniya 2-10 tle = np.array( [63.2749, 254.2968, 0.7151443, 294.4926, 9.2905, 2.01190064320534]) r = tle_to_state(tle) _, vecs = rkf5(0, 43000, 50, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(26505.1836, 0.1) # sma assert kep[1] == pytest.approx(0.7151443, 0.01) # ecc assert kep[2] == pytest.approx(63.2749, 0.1) # inc assert kep[3] == pytest.approx(294.4926, 1.0) # argp assert kep[4] == pytest.approx(254.2968, 0.1) # raan assert kep[5] == pytest.approx(65.56742, 0.5) # true_anom #ISS tle = np.array( [51.6402, 150.4026, 0.0004084, 108.2140, 238.0528, 15.54082454114406]) r = tle_to_state(tle) _, vecs = rkf5(0, 5560, 10, r) r = np.reshape(r, (1, 6)) vecs = np.insert(vecs, 0, r, axis=0) vecs = vecs[:, 0:3] kep, _ = determine_kep(vecs) assert kep[0] == pytest.approx(6782.95812, 0.1) # sma assert kep[1] == pytest.approx(0.0004084, 0.01) # ecc assert kep[2] == pytest.approx(51.6402, 0.1) # inc assert kep[3] == pytest.approx(108.2140, 1.0) # argp assert kep[4] == pytest.approx(150.4026, 0.1) # raan assert kep[5] == pytest.approx(238.0528, 0.5) # true_anom
def process(data_file, error_apriori, units): ''' Given a .csv data file in the format of (time, x, y, z) applies both filters, generates a filtered.csv data file, prints out the final keplerian elements computed from both Lamberts and Interpolation and finally plots the initial, filtered data set and the final orbit. Args: data_file (string): The name of the .csv file containing the positional data error_apriori (float): apriori estimation of the measurements error in km Returns: Runs the whole process of the program ''' # First read the csv file called "orbit" with the positional data data = read_data.load_data(data_file) if (units == 'm'): # Transform m to km data[:, 1:4] = data[:, 1:4] / 1000 print("Choose filter(s) in the order you want to apply them") print( "(SPACE to change, UP/DOWN to navigate, RIGHT/LEFT to Select/Deselect and ENTER to Submit)" ) print("*if nothing is selected program will run without applying filters") questions = [ inquirer.Checkbox( 'filter', message="Select filters", choices=[ 'Savintzky Golay Filter', 'Tripple Moving Average Filter' ], ), ] choices = inquirer.prompt(questions) data_after_filter = data if (len(choices['filter']) == 0): print("No filter selected, continuing without applying filter") else: for index, choice in enumerate(choices['filter']): if (choice == 'Savintzky Golay Filter'): print("Applying Savintzky Golay Filter") # Use the golay_window.py script to find the window for the savintzky golay filter based on the error you input window = golay_window.window(error_apriori, data_after_filter) # Apply the Savintzky - Golay filter with window = 31 and polynomail parameter = 6 data_after_filter = sav_golay.golay(data_after_filter, window, 3) else: print("Applying Triple Moving Average Filter") # Apply the Triple moving average filter with window = 3 data_after_filter = triple_moving_average.generate_filtered_data( data_after_filter, 3) # Compute the residuals between filtered data and initial data and then the sum and mean values of each axis res = data_after_filter[:, 1:4] - data[:, 1:4] sums = np.sum(res, axis=0) print("\nDisplaying the sum of the residuals for each axis") print(sums) means = np.mean(res, axis=0) print("Displaying the mean of the residuals for each axis") print(means, "\n") # Save the filtered data into a new csv called "filtered" np.savetxt("filtered.csv", data_after_filter, delimiter=",") print("Choose Methods for Orbit Determination") print( "(SPACE to change, UP/DOWN to navigate, RIGHT/LEFT to Select/Deselect and ENTER to Submit)" ) print( "*if nothing is selected program will determine orbit using Cubic Spline Interpolation" ) questions = [ inquirer.Checkbox( 'method', message="Select Methods", choices=[ 'Lamberts Kalman Solutions', 'Cubic Spline Interpolation', 'Ellipse Best Fit' ], ), ] choices = inquirer.prompt(questions) kep_elements = {} if (len(choices['method']) == 0): # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply Kalman filters, estimate of measurement variance R = 0.01 ** 2 kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_elements['Interpolation'] = np.transpose(kep_final_inter) else: for index, choice in enumerate(choices['method']): if (choice == 'Lamberts Kalman Solutions'): # Apply Lambert's solution for the filtered data set kep_lamb = lamberts_kalman.create_kep(data_after_filter) # Apply Kalman filters, estimate of measurement variance R = 0.01 ** 2 kep_final_lamb = lamberts_kalman.kalman(kep_lamb, 0.01**2) kep_elements['Lambert'] = np.transpose(kep_final_lamb) elif (choice == 'Cubic Spline Interpolation'): # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply Kalman filters, estimate of measurement variance R = 0.01 ** 2 kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_elements['Interpolation'] = np.transpose(kep_final_inter) elif (choice == 'Ellipse Best Fit'): # Fitting an ellipse on filtered data kep_elements['Ellipse-Fit'] = (ellipse_fit.determine_kep( data_after_filter[:, 1:]))[0] kep_final = np.zeros((6, len(kep_elements))) order = [] for index, key in enumerate(kep_elements): kep_final[:, index] = np.ravel(kep_elements[key]) order.append(str(key)) # Print the final orbital elements for both solutions print( "Displaying the final keplerian elements with methods in column order: {}" .format(", ".join(order))) print(kep_final) print("\n") # Plot the initial data set, the filtered data set and the final orbit # First we transform the set of keplerian elements into a state vector state = kep_state.kep_state(kep_elements[order[0]]) # Then we produce more state vectors at varius times using a Runge Kutta algorithm keep_state = np.zeros((6, 150)) ti = 0.0 tf = 1.0 t_hold = np.zeros((150, 1)) x = state h = 0.1 tetol = 1e-04 for i in range(0, 150): keep_state[:, i] = np.ravel(rkf78.rkf78(6, ti, tf, h, tetol, x)) t_hold[i, 0] = tf tf = tf + 1 positions = keep_state[0:3, :] ## Finally we plot the graph mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() ax = fig.gca(projection='3d') ax.plot(data[:, 1], data[:, 2], data[:, 3], ".", label='Initial data ') ax.plot(data_after_filter[:, 1], data_after_filter[:, 2], data_after_filter[:, 3], "k", linestyle='-', label='Filtered data') ax.plot(positions[0, :], positions[1, :], positions[2, :], "r-", label='Orbit after {} method'.format(order[0])) ax.legend() ax.can_zoom() ax.set_xlabel('x (km)') ax.set_ylabel('y (km)') ax.set_zlabel('z (km)') plt.show()
def process(data_file, error_apriori, units): ''' Given a .csv data file in the format of (time, x, y, z) applies both filters, generates a filtered.csv data file, prints out the final keplerian elements computed from both Lamberts and Interpolation and finally plots the initial, filtered data set and the final orbit. Args: data_file (string): The name of the .csv file containing the positional data error_apriori (float): apriori estimation of the measurements error in km Returns: Runs the whole process of the program ''' # First read the csv file called "orbit" with the positional data print("Imported file format is:", read_data.detect_file_format(data_file)["file"]) print("") data = read_data.load_data(data_file) if (units == 'm'): # Transform m to km data[:, 1:4] = data[:, 1:4] / 1000 print( "***********Choose filter(s) in desired order of application***********" ) print( "(SPACE to toggle, UP/DOWN to navigate, RIGHT/LEFT to select/deselect and ENTER to submit)" ) print( "*if nothing is selected, Triple Moving Average followed by Savitzky Golay will be applied" ) questions = [ inquirer.Checkbox( 'filter', message="Select filter(s)", choices=[ 'None', 'Savitzky Golay Filter', 'Triple Moving Average Filter', 'Wiener Filter' ], ), ] choices = inquirer.prompt(questions) data_after_filter = data if (len(choices['filter']) == 0): print("Applying Triple Moving Average followed by Savitzky Golay...") # Apply the Triple moving average filter with window = 3 data_after_filter = triple_moving_average.generate_filtered_data( data_after_filter, 3) # Use the golay_window.py script to find the window for the Savitzky Golay filter based on the error you input window = golay_window.window(error_apriori, data_after_filter) polyorder = 3 if polyorder < window: # Apply the Savitzky Golay filter with window = window (51 for example_data/orbit.csv) and polynomial order = 3 data_after_filter = sav_golay.golay(data_after_filter, window, polyorder) else: for index, choice in enumerate(choices['filter']): if (choice == 'None'): print("Using the original data...") # no filter is applied data_after_filter = data_after_filter elif (choice == 'Savitzky Golay Filter'): print("Applying Savitzky Golay Filter...") # Use the golay_window.py script to find the window for the Savitzky Golay filter # based on the error you input window = golay_window.window(error_apriori, data_after_filter) polyorder = 3 if polyorder < window: # Apply the Savitzky Golay filter with window = window (51 for example_data/orbit.csv) and polynomial order = 3 data_after_filter = sav_golay.golay( data_after_filter, window, polyorder) elif (choice == 'Wiener Filter'): print("Applying Wiener Filter...") # Apply the Wiener filter data_after_filter = wiener.wiener_new(data_after_filter, 3) else: print("Applying Triple Moving Average Filter...") # Apply the Triple moving average filter with window = 3 data_after_filter = triple_moving_average.generate_filtered_data( data_after_filter, 3) # Compute the residuals between filtered data and initial data and then the sum and mean values of each axis res = data_after_filter[:, 1:4] - data[:, 1:4] sums = np.sum(res, axis=0) print("\nDisplaying the sum of the residuals for each axis") print(sums, "\n") means = np.mean(res, axis=0) print("Displaying the mean of the residuals for each axis") print(means, "\n") # Save the filtered data into a new csv called "filtered" np.savetxt("filtered.csv", data_after_filter, delimiter=",") print("***********Choose Method(s) for Orbit Determination***********") print( "(SPACE to toggle, UP/DOWN to navigate, RIGHT/LEFT to select/deselect and ENTER to submit)" ) print( "*if nothing is selected, Cubic Spline Interpolation will be used for Orbit Determination" ) questions = [ inquirer.Checkbox( 'method', message="Select Method(s)", choices=[ 'Lamberts Kalman', 'Cubic Spline Interpolation', 'Ellipse Best Fit', 'Gibbs 3 Vector', 'Gauss 3 Vector', 'MCMC (exp.)' ], ), ] choices = inquirer.prompt(questions) kep_elements = {} if (len(choices['method']) == 0): # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_final_inter = np.transpose(kep_final_inter) kep_final_inter = np.resize(kep_final_inter, ((7, 1))) kep_final_inter[6, 0] = sgp4.rev_per_day(kep_final_inter[0, 0]) kep_elements['Cubic Spline Interpolation'] = kep_final_inter else: for index, choice in enumerate(choices['method']): if (choice == 'Lamberts Kalman'): # Apply Lambert Kalman method for the filtered data set #previously, all data... #kep_lamb = lamberts_kalman.create_kep(data_after_filter) # only three (3) observations from half an orbit. # also just two (2) observations are fine for lamberts. data = np.array([ data_after_filter[:, :][0], data_after_filter[:, :][len(data_after_filter) // 2], data_after_filter[:, :][-1] ]) kep_lamb = lamberts_kalman.create_kep(data) # Determination of orbit period semimajor_axis = kep_lamb[0][0] timestamps = data_after_filter[:, 0] index = get_timestamp_index_by_orbitperiod( semimajor_axis, timestamps) # enough data for half orbit data = np.array([ data_after_filter[:, :][0], data_after_filter[:, :][index // 2], data_after_filter[:, :][index] ]) kep_lamb = lamberts_kalman.create_kep(data) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_lamb = lamberts_kalman.kalman(kep_lamb, 0.01**2) kep_final_lamb = np.transpose(kep_final_lamb) kep_final_lamb = np.resize(kep_final_lamb, ((7, 1))) kep_final_lamb[6, 0] = sgp4.rev_per_day(kep_final_lamb[0, 0]) kep_elements['Lamberts Kalman'] = kep_final_lamb elif (choice == 'Cubic Spline Interpolation'): # Apply the interpolation method kep_inter = interpolation.main(data_after_filter) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_inter = lamberts_kalman.kalman(kep_inter, 0.01**2) kep_final_inter = np.transpose(kep_final_inter) kep_final_inter = np.resize(kep_final_inter, ((7, 1))) kep_final_inter[6, 0] = sgp4.rev_per_day(kep_final_inter[0, 0]) kep_elements['Cubic Spline Interpolation'] = kep_final_inter elif (choice == 'Ellipse Best Fit'): # Apply the ellipse best fit method kep_ellip = ellipse_fit.determine_kep(data_after_filter[:, 1:])[0] kep_final_ellip = np.transpose(kep_ellip) kep_final_ellip = np.resize(kep_final_ellip, ((7, 1))) kep_final_ellip[6, 0] = sgp4.rev_per_day(kep_final_ellip[0, 0]) kep_elements['Ellipse Best Fit'] = kep_final_ellip elif (choice == 'Gibbs 3 Vector'): # Apply the Gibbs method # first only with first, middle and last measurement R = np.array([ data_after_filter[:, 1:][0], data_after_filter[:, 1:][len(data_after_filter) // 2], data_after_filter[:, 1:][-1] ]) kep_gibbs = gibbs_method.gibbs_get_kep(R) # Determination of orbit period semimajor_axis = kep_gibbs[0][0] timestamps = data_after_filter[:, 0] index = get_timestamp_index_by_orbitperiod( semimajor_axis, timestamps) # enough data for half orbit R = np.array([ data_after_filter[:, 1:][0], data_after_filter[:, 1:][index // 2], data_after_filter[:, 1:][index] ]) kep_gibbs = gibbs_method.gibbs_get_kep(R) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_gibbs = lamberts_kalman.kalman(kep_gibbs, 0.01**2) kep_final_gibbs = np.transpose(kep_final_gibbs) kep_final_gibbs = np.resize(kep_final_gibbs, ((7, 1))) kep_final_gibbs[6, 0] = sgp4.rev_per_day(kep_final_gibbs[0, 0]) kep_elements['Gibbs 3 Vector'] = kep_final_gibbs elif (choice == 'Gauss 3 Vector'): # Apply the Gauss method # first only with first, middle and last measurement R = np.array([ data_after_filter[:, 1:][0], data_after_filter[:, 1:][len(data_after_filter) // 2], data_after_filter[:, 1:][-1] ]) t1 = data_after_filter[:, 0][0] t2 = data_after_filter[:, 0][len(data_after_filter) // 2] t3 = data_after_filter[:, 0][-1] v2 = gauss_method.gauss_method_get_velocity( R[0], R[1], R[2], t1, t2, t3) # Determination of orbit period semimajor_axis = oe.semimajor_axis(R[0], v2) timestamps = data_after_filter[:, 0] index = get_timestamp_index_by_orbitperiod( semimajor_axis, timestamps) # enough data for half orbit R = np.array([ data_after_filter[:, 1:][0], data_after_filter[:, 1:][index // 2], data_after_filter[:, 1:][index] ]) t1 = data_after_filter[:, 0][0] t2 = data_after_filter[:, 0][index // 2] t3 = data_after_filter[:, 0][index] v2 = gauss_method.gauss_method_get_velocity( R[0], R[1], R[2], t1, t2, t3) semimajor_axis = oe.semimajor_axis(R[0], v2) ecc = oe.eccentricity_v(R[1], v2) ecc = np.linalg.norm(ecc) inc = oe.inclination(R[1], v2) * 180.0 / np.pi AoP = oe.AoP(R[1], v2) * 180.0 / np.pi raan = oe.raan(R[1], v2) * 180.0 / np.pi true_anomaly = oe.true_anomaly(R[1], v2) * 180.0 / np.pi T_orbitperiod = oe.T_orbitperiod(semimajor_axis=semimajor_axis) n_mean_motion_perday = oe.n_mean_motion_perday(T_orbitperiod) kep_gauss = np.array([[ semimajor_axis, ecc, inc, AoP, raan, true_anomaly, n_mean_motion_perday ]]) # Apply Kalman filters to find the best approximation of the keplerian elements for all solutions # We set an estimate of measurement variance R = 0.01 ** 2 kep_final_gauss = lamberts_kalman.kalman(kep_gauss, 0.01**2) kep_final_gauss = np.transpose(kep_final_gauss) kep_final_gauss = np.resize(kep_final_gauss, ((7, 1))) kep_final_gauss[6, 0] = sgp4.rev_per_day(kep_final_gauss[0, 0]) kep_elements['Gauss 3 Vector'] = kep_final_gauss else: # apply mcmc method, a real optimizer # all data timestamps = data_after_filter[:, 0] R = np.array(data_after_filter[:, 1:]) # all data can make the MCMC very slow. so we just pick a few in random, but in order. timestamps_short = [] R_short = [] if len(timestamps) > 25: print( "Too many positions for MCMC. Just 25 positons are selected" ) # pick randomly, but in order and no duplicates l = list( np.linspace(0, len(timestamps) - 1, num=len(timestamps))) select_index = sorted(random.sample(list(l)[1:-1], k=23)) print(select_index) timestamps_short.append(timestamps[0]) R_short.append(R[0]) for select in range(len(select_index)): timestamps_short.append(timestamps[int( select_index[select])]) R_short.append(R[int(select_index[select])]) timestamps_short.append(timestamps[-1]) R_short.append(R[-1]) else: timestamps_short = timestamps R_short = R parameters = with_mcmc.fromposition(timestamps_short, R_short) r_a = parameters["r_a"] r_p = parameters["r_p"] AoP = parameters["AoP"] inc = parameters["inc"] raan = parameters["raan"] tp = parameters["tp"] semimajor_axis = (r_p + r_a) / 2.0 ecc = (r_a - r_p) / (r_a + r_p) T_orbitperiod = oe.T_orbitperiod(semimajor_axis=semimajor_axis) true_anomaly = tp / T_orbitperiod * 360.0 n_mean_motion_perday = oe.n_mean_motion_perday(T_orbitperiod) kep_mcmc = np.array([[ semimajor_axis, ecc, inc, AoP, raan, true_anomaly, n_mean_motion_perday ]]) kep_elements['MCMC (exp.)'] = kep_mcmc kep_final = np.zeros((7, len(kep_elements))) order = [] for index, key in enumerate(kep_elements): kep_final[:, index] = np.ravel(kep_elements[key]) order.append(str(key)) # Print the final orbital elements for all solutions kep_elements = [ "Semi major axis (a)(km)", "Eccentricity (e)", "Inclination (i)(deg)", "Argument of perigee (ω)(deg)", "Right acension of ascending node (Ω)(deg)", "True anomaly (v)(deg)", "Frequency (f)(rev/day)" ] for i in range(0, len(order)): print("\n******************Output for %s Method******************\n" % order[i]) for j in range(0, 7): print("%s: %.16f" % (kep_elements[j], kep_final[j, i])) print("\nShow plots? [y/n]") user_input = input() if (user_input == "y" or user_input == "Y"): for j in range(0, len(order)): # Plot the initial data set, the filtered data set and the final orbit # First we transform the set of keplerian elements into a state vector state = kep_state.kep_state(np.resize(kep_final[:, j], (7, 1))) # Then we produce more state vectors at varius times using a Runge Kutta algorithm keep_state = np.zeros((6, 150)) ti = 0.0 tf = 1.0 t_hold = np.zeros((150, 1)) x = state h = 0.1 tetol = 1e-04 for i in range(0, 150): keep_state[:, i] = np.ravel(rkf78.rkf78(6, ti, tf, h, tetol, x)) t_hold[i, 0] = tf tf = tf + 1 positions = keep_state[0:3, :] ## Finally we plot the graph mpl.rcParams['legend.fontsize'] = 10 fig = plt.figure() ax = plt.axes(projection='3d') ax.plot(data[:, 1], data[:, 2], data[:, 3], ".", label='Initial data ') ax.plot(data_after_filter[:, 1], data_after_filter[:, 2], data_after_filter[:, 3], "k", linestyle='-', label='Filtered data') ax.plot(positions[0, :], positions[1, :], positions[2, :], "r-", label='Orbit after %s method' % order[j]) ax.legend() ax.can_zoom() ax.set_xlabel('x (km)') ax.set_ylabel('y (km)') ax.set_zlabel('z (km)') plt.show()