def build_site(jd_span, site_lat, site_lon, site_alt): r"""Create the site dictionary site = build_site(jd_span, site_lat, site_lon, site_alt) Parameters ---------- jd_span : array Array of Julian date times for teh window site_lat : float site latitude in radians site_lon : float site longitude in radians site_alt : float site altitude in kilometers Returns ------- site : dictionary site dicitonary holding data on the observation site Author ------ Shankar Kulumani GWU [email protected] """ site_ecef = geodetic.lla2ecef(site_lat, site_lon, site_alt) # loop over jd span site = defaultdict(list) site['lat'] = site_lat site['lon'] = site_lon site['alt'] = site_alt site['ecef'] = site_ecef for jd in jd_span: gst, lst = time.gstlst(jd, site_lon) # site_eci = geodetic.site2eci(site_lat, site_alt, lst) # site_eci = attitude.rot3(gst).dot(site_ecef) site_eci = transform.dcm_ecef2eci(jd).dot(site_ecef) # test if site is in the dark sun_eci, _, _ = planets.sun_earth_eci(jd) # append site information to list site['eci'].append(site_eci) site['sun_eci'].append(sun_eci) site['gst'].append(gst) site['lst'].append(lst) # turn into numpy arrays for key, item in site.items(): site[key] = np.squeeze(np.array(item)) return site
def dcm_eci2ecef(jd): """Rotation matrix to convert from ECI to ECEF Will gradually improve this function to include all of the Earth motion terms. For now, just use sidereal time to get the rotation matrix """ gst, _ = time.gstlst(jd, 0) dcm = attitude.rot3(gst, 'r') return dcm
class TestTimeGSTValladoEx3_3(): dateexp = (1995, 2, 24, 12, 0, 0) jdexp = 2449773.0 gstexp = np.deg2rad(333.893486) jd, mjd = time.date2jd(dateexp[0], dateexp[1], dateexp[2], dateexp[3], dateexp[4], dateexp[5]) date = time.jd2date(jdexp) gst, _ = time.gstlst(jd, 0) def test_jd(self): np.testing.assert_allclose(self.jd, self.jdexp) def test_date(self): np.testing.assert_allclose(self.date, self.dateexp) def test_gst(self): np.testing.assert_allclose(self.gst, self.gstexp)
def ecef2eci(JD, lon): r"""Computes the updated COEs given the time change Inputs: JD :(time) Julian Date Outputs: ecef2eci :(Rotation Matrix) Unitless Author: Thomas J Susi GWU [email protected] """ gst, lst = time.gstlst(JD, lon) thetag = gst ecef2eci = np.array([[np.cos(thetag),-np.sin(thetag),0],[np.sin(thetag),np.cos(thetag),0],[0,0,1]]) return ecef2eci
class TestECI2ECEF(): """Test to make sure we can convert a location on the earth to the correct ECEF vector """ lonexp = np.deg2rad(72.5529) latgdexp = np.deg2rad(34.352496) latgcexp = np.deg2rad(34.173429) altexp = 5085.22 # kilometer eci_exp = np.array([6524.834, 6862.875, 6448.296]) jd_exp = 2449773.0 _, lst = time.gstlst(jd_exp, lonexp) eci = geodetic.site2eci(latgdexp, altexp, lst) ecef = geodetic.lla2ecef(latgdexp, lonexp, altexp) Reci2ecef = transform.dcm_eci2ecef(jd_exp) eci_from_ecef = Reci2ecef.T.dot(ecef) def test_eci_vallado(self): np.testing.assert_allclose(self.eci, self.eci_exp, rtol=1e-2) def test_eci_from_ecef(self): np.testing.assert_allclose(self.eci_from_ecef, self.eci_exp, rtol=1e-2)
class TestECEF2ECI(): """Example pg.106 in BMW """ lon = np.deg2rad(-57.296) lat = 0 alt = 6.378 # kilometer above equator date = (1970, 1, 2, 6, 0, 0) jd, _ = time.date2jd(date[0], date[1], date[2], date[3], date[4], date[5]) gst0_exp = 1.749333 gst_exp = attitude.normalize(9.6245, 0, 2 * np.pi) lst_exp = attitude.normalize(8.6245, 0, 2 * np.pi) eci_exp = np.array([-0.697 * 6378.137, 0.718 * 6378.137, 0]) gst0 = time.gsttime0(date[0]) gst, lst = time.gstlst(jd, lon) eci = geodetic.site2eci(lat, alt, lst) ecef = geodetic.lla2ecef(lat, lon, alt) Reci2ecef = transform.dcm_eci2ecef(jd) eci_from_ecef = Reci2ecef.T.dot(ecef) def test_gst0(self): np.testing.assert_allclose(self.gst0, self.gst0_exp, rtol=1e-4) def test_gst(self): np.testing.assert_allclose(self.gst, self.gst_exp, rtol=1e-4) def test_lst(self): np.testing.assert_allclose(self.lst, self.lst_exp, rtol=1e-3) def test_eci(self): np.testing.assert_allclose(self.eci, self.eci_exp, rtol=1e-2) def test_eci_from_ecef(self): np.testing.assert_allclose(self.eci_from_ecef, self.eci_exp, rtol=1e-2)
def test_lst_vallado(): expected_lst = 48.578787886 _, actual_lst = time.gstlst(2448855.009722, -104 * deg2rad) np.testing.assert_allclose(actual_lst * rad2deg, expected_lst, rtol=1e-3)
def generate_solution(ifile='./data/example_tle.txt', ofile='./data/SAT_OUT_EXAMPLE.txt'): ifile = os.path.abspath(ifile) ofile = os.path.abspath(ofile) site_lat = np.deg2rad(float(input("Site Latitude (38.925) : ") or "38.925")) site_lon = np.deg2rad(float(input("Site Longitude (-77.057) : ") or "-77.057")) site_alt = float(input("Site Altitude (0.054) : ") or "0.054") site_ecef = geodetic.lla2ecef(site_lat, site_lon, site_alt) # timespan date_start = [float(i) for i in (input('Start Date UTC (2017 12 1 0 0 0) : ') or "2017 12 1 0 0 0").split()] date_end = [float(i) for i in (input('End Date UTC (2017 12 5 0 0 0) : ') or "2017 12 5 0 0 0").split()] jd_start, _ = time.date2jd(date_start[0], date_start[1], date_start[2], date_start[3], date_start[4], date_start[5]) jd_end, _ = time.date2jd(date_end[0], date_end[1], date_end[2], date_end[3], date_end[4], date_end[5]) jd_step = 2 / (24 * 60) # step size in minutes jd_span = np.arange(jd_start, jd_end, jd_step) # echo check some data with open(ofile, 'w') as f: f.write('PREDICT EXAMPLE RESULTS : Shankar Kulumani\n\n') f.write('Check Input Data : \n\n') f.write('Site Latitude = {:9.6f} rad = {:9.6f} deg\n'.format(site_lat, np.rad2deg(site_lat))) f.write('Site Longitude = {:9.6f} rad = {:9.6f} deg\n'.format(site_lon, np.rad2deg(site_lon))) f.write('Site Altitude = {:9.6f} km = {:9.6f} m\n'.format(site_alt, site_alt * 1000)) f.write('\nObservation Window :\n\n') f.write('Start Date : {} UTC\n'.format(datetime.datetime(int(date_start[0]), int(date_start[1]), int(date_start[2]), int(date_start[3]), int(date_start[4]), int(date_start[5])).isoformat())) f.write('End Date : {} UTC\n\n'.format(datetime.datetime(int(date_end[0]),int(date_end[1]),int(date_end[2]),int(date_end[3]),int(date_end[4]),int(date_end[5])).isoformat())) f.write('Start Julian Date = {}\n'.format(jd_start)) f.write('End Julian Date = {}\n\n'.format(jd_end)) # loop over jd span site = defaultdict(list) site['lat'] = site_lat site['lon'] = site_lon site['alt'] = site_alt site['ecef'] = site_ecef for jd in jd_span: gst, lst = time.gstlst(jd, site_lon) # site_eci = geodetic.site2eci(site_lat, site_alt, lst) # site_eci = attitude.rot3(gst).dot(site_ecef) site_eci = transform.dcm_ecef2eci(jd).dot(site_ecef) # test if site is in the dark sun_eci, _, _ = planets.sun_earth_eci(jd) # append site information to list site['eci'].append(site_eci) site['sun_eci'].append(sun_eci) site['gst'].append(gst) site['lst'].append(lst) with open(ofile, 'a') as f: f.write('Site Data:\n\n') f.write('Start GST : {:9.6f} rad\n'.format(site['gst'][0])) f.write('Start LST : {:9.4f} rad\n'.format(site['lst'][0])) f.write('Site ECEF : {:9.6f} x {:9.6f} y {:9.6f} z km\n'.format(site['ecef'][0], site['ecef'][1], site['ecef'][2])) f.write('Sun ECI_0 : {:9.6f} x {:9.6f} y {:9.6f} z km\n\n'.format(site['sun_eci'][0][0], site['sun_eci'][0][1], site['sun_eci'][0][2])) f.write('{}\n\n'.format('*'*80)) # turn into numpy arrays for key, item in site.items(): site[key] = np.squeeze(np.array(item)) # update the downloaded TLEs if necessary # now we have to read the TLE sats = tle.get_tle(ifile) # now propogate and the check if each satellite is visible for sat in sats: sat.tle_update(jd_span) sat.visible(site) sat.output(ofile)
def solution(meas_file='./data/COMFIX_tle_measurement.txt', outfile='./data/COMFIX_tle_solution.txt'): # read in the measurement data fout = open(outfile, 'w') with open(meas_file, 'r') as f: l0 = f.readline().split() l0 = [float(x) for x in l0] while l0: l1 = f.readline().split() l1 = [float(x) for x in l1] latgd, lon, alt, jd = np.deg2rad(l0[0]), np.deg2rad( l0[1]), l0[2] / 1e3, l0[3] satnum, rho, az, el, drho, daz, dele = l1[0], l1[1], np.deg2rad( l1[2]), np.deg2rad(l1[3]), l1[4], np.deg2rad( l1[5]), np.deg2rad(l1[6]) # GST, LST gst, lst = time.gstlst(jd, lon) # find satellite vector in SEZ rho_sez, drho_sez = geodetic.rhoazel2sez(rho, az, el, drho, daz, dele) R_eci2ecef = geodetic.eci2ecef(jd) R_ecef2eci = geodetic.ecef2eci(jd) R_sez2ecef = transform.dcm_sez2ecef(latgd, lon, alt) # find site vector in ECEF/ECI site_ecef = geodetic.lla2ecef(latgd, lon, alt) site_eci = R_ecef2eci.dot(site_ecef) # transform satellite vector from SEZ to ECI rho_ecef = R_sez2ecef.dot(rho_sez) rho_eci = R_ecef2eci.dot(rho_ecef) drho_ecef = R_sez2ecef.dot(drho_sez) drho_eci = R_ecef2eci.dot(drho_ecef) pos_eci = site_eci + rho_eci vel_eci = drho_eci + np.cross( np.array([0, 0, constants.earth.omega]), pos_eci) # find orbital elements p, a, ecc, inc, raan, arg_p, nu, _, _, _, _ = kepler.rv2coe( pos_eci, vel_eci, constants.earth.mu) # compute orbit properties prop_string = kepler.orbit_el(p, ecc, inc, raan, arg_p, nu, constants.earth.mu) l0 = f.readline().split() l0 = [float(x) for x in l0] # output to text file fout.write( '#################### COMFIX SATELLITE {:g} ####################################\n\n' .format(satnum)) fout.write( '------------------------ INPUT DATA -------------------------------------------\n\n' ) fout.write('LAT (deg) LON (deg) ALT (m) JD\n') fout.write( '{:<9.4f} {:<9.4f} {:<9.4f} {:<16.6f}\n\n'.format( np.rad2deg(latgd), np.rad2deg(lon), alt * 1e3, jd)) fout.write( 'RHO (km) AZ (deg) EL (deg) DRHO (km/s) DAZ (deg/s) DEL (deg/s)\n' ) fout.write( '{:<9.4f} {:<6.4f} {:<6.4f} {:<6.4f} {:<6.4f} {:<6.4f}\n' .format(rho, np.rad2deg(az), np.rad2deg(el), drho, np.rad2deg(daz), np.rad2deg(dele))) fout.write( '------------------------- WORKING DATA ----------------------------------------\n\n' ) fout.write('LAT (rad) LON (rad) ALT (m) JD\n') fout.write( '{:<9.4f} {:<9.4f} {:<9.4f} {:<16.6f}\n\n'.format( latgd, lon, alt, jd)) fout.write( 'RHO (km) AZ (rad) EL (rad) DRHO (km/s) DAZ (rad/s) DEL (rad/s)\n' ) fout.write( '{:<9.4f} {:<6.4f} {:<6.4f} {:<6.4f} {:<6.4f} {:<6.4f}\n\n' .format(rho, az, el, drho, daz, dele)) fout.write('GST = {:16.9f} rad = {:16.9f} deg\n'.format( gst, np.rad2deg(gst))) fout.write('LST = {:16.9f} rad = {:16.9f} deg\n\n'.format( lst, np.rad2deg(lst))) fout.write( '---------------------------- VECTORS ------------------------------------------\n' ) fout.write( '{:9s} = {:13.4f} S {:13.4f} E {:13.4f} Z MAG = {:7.4f} km\n'. format('rho_sez', rho_sez[0], rho_sez[1], rho_sez[2], np.linalg.norm(rho_sez))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km\n'. format('rho_ecef', rho_ecef[0], rho_ecef[1], rho_ecef[2], np.linalg.norm(rho_ecef))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km\n'. format('rho_eci', rho_eci[0], rho_eci[1], rho_eci[2], np.linalg.norm(rho_eci))) fout.write( '{:9s} = {:13.4f} S {:13.4f} E {:13.4f} Z MAG = {:7.4f} km/s\n' .format('drho_sez', drho_sez[0], drho_sez[1], drho_sez[2], np.linalg.norm(drho_sez))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km/s\n' .format('drho_ecef', drho_ecef[0], drho_ecef[1], drho_ecef[2], np.linalg.norm(drho_ecef))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km/s\n' .format('drho_eci', drho_eci[0], drho_eci[1], drho_eci[2], np.linalg.norm(drho_eci))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km\n'. format('site_ecef', site_ecef[0], site_ecef[1], site_ecef[2], np.linalg.norm(site_ecef))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km\n'. format('site_eci', site_eci[0], site_eci[1], site_eci[2], np.linalg.norm(site_eci))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km\n'. format('pos_eci', pos_eci[0], pos_eci[1], pos_eci[2], np.linalg.norm(pos_eci))) fout.write( '{:9s} = {:13.4f} I {:13.4f} J {:13.4f} K MAG = {:7.4f} km/s\n' .format('vel_eci', vel_eci[0], vel_eci[1], vel_eci[2], np.linalg.norm(vel_eci))) fout.write(prop_string + '\n') fout.close()
def generate_data(tle_file='./data/COMFIX_tle.txt', outfile='./data/COMFIX_tle_measurement.txt'): # define a time span jd_start, _ = time.date2jd(2017, 12, 1, 0, 0, 0) # time in UTC jd_end, _ = time.date2jd(2017, 12, 11, 0, 0, 0) jd_step = 1 / (24 * 60) jd_span = np.arange(jd_start, jd_end, jd_step) # define the observing site site_lat = np.deg2rad(38.8999), site_lon = np.deg2rad(-77.0490) site_alt = 0.020 site_ecef = geodetic.lla2ecef(site_lat, site_lon, site_alt) # loop over jd span site = defaultdict(list) site['lat'] = site_lat site['lon'] = site_lon site['alt'] = site_alt site['ecef'] = site_ecef for jd in jd_span: gst, lst = time.gstlst(jd, site_lon) # site_eci = geodetic.site2eci(site_lat, site_alt, lst) # site_eci = attitude.rot3(gst).dot(site_ecef) site_eci = geodetic.eci2ecef(jd).T.dot(site_ecef) # test if site is in the dark sun_eci, _, _ = planets.sun_earth_eci(jd) # append site information to list site['eci'].append(site_eci) site['sun_eci'].append(sun_eci) site['gst'].append(gst) site['lst'].append(lst) # turn into numpy arrays for key, item in site.items(): site[key] = np.squeeze(np.array(item)) # read some TLEs and get the state vector and write to a file sats = tle.get_tle(tle_file) f = open(outfile, 'w') for sat in sats: # propogate for several time periods and get the r, v vectors sat.tle_update(jd_span) sat.visible_radar(site) jd_vis = sat.jd_vis rho_vis = sat.rho_vis az_vis = sat.az_vis el_vis = sat.el_vis drho_vis = sat.drho_vis daz_vis = sat.daz_vis dele_vis = sat.dele_vis # write first line - site latgd, lon, alt (meters), JD obs time f.write('{:9.6f} {:9.6f} {:9.6f} {:16.6f}\n'.format( np.rad2deg(site['lat']), np.rad2deg(site['lon']), site['alt'] * 1e3, jd_vis[0])) # write second line rho, az, el, drho, daz, dele f.write( '{:5g} {:16.6f} {:16.6f} {:16.6f} {:16.6f} {:16.6f} {:16.6f}\n'. format(sat.satnum, rho_vis[0], np.rad2deg(az_vis[0][0]), np.rad2deg(el_vis[0]), drho_vis[0], np.rad2deg(daz_vis[0]), np.rad2deg(dele_vis[0]))) f.close()
r_sat_eci_turned, v_sat_eci = PREDICT.coe2rv( n_s, e_s, raan_s, w_s, theta_s, i_s, 398600.5) r_sat_eci = np.array([ float(r_sat_eci_turned[0]), float(r_sat_eci_turned[1]), float(r_sat_eci_turned[2]) ]) """Get Site Info At Time""" ecef2eci = COMFIX.ecef2eci(stp, lon) r_site_eci_turned = np.dot(ecef2eci, r_site_ecef) r_site_eci = np.array([ r_site_eci_turned[0][0], r_site_eci_turned[1][0], r_site_eci_turned[2][0] ]) """Check Visibility At Time""" GST, LST = time.gstlst(stp, lon) import pdb pdb.set_trace() visible_check = PREDICT.visible(r_sat_eci, r_site_eci, lat, lon, LST, stp) """Determine Where to Look At Time""" if (visible_check == 1): print("Y Script") rang, azm, elev = PREDICT.rhoazel(r_sat_eci, r_site_eci, lat, lon, GST) year, month, day, hour, minute, second = time.jd2date(stp) Line_out = [ 'Where to Look at {}/{}/{}\t {}:{}:{} JD:\n\tRange(km): {}\n\tAzmuth(deg): {}\n\tElevation(deg): {}\n' .format(int(month), int(day), int(year), int(hour), int(minute), int(second), rang, np.rad2deg(azm), np.rad2deg(elev))
def test_lst_vallado(): expected_lst = 48.578787886 _, actual_lst = time.gstlst(2448855.009722, -104 * deg2rad) np.testing.assert_allclose(actual_lst * rad2deg, expected_lst, rtol=1e-3)
"""COMFIX practice questions from HW6 2017 """ from astro import constants, geodetic, time, transform import numpy as np # observation lat, lon, alt = np.deg2rad(77.7), np.deg2rad(-68.5), 0.050 jd = 2454154.6376157 rho, az, el, rhodot, azdot, eldot = 2121.418, np.deg2rad(18.9606), np.deg2rad( 35.3507), -3.3204, np.deg2rad(-.07653), np.deg2rad(.20367) gst, lst = time.gstlst(jd, lon) print('JD : {}'.format(jd)) print('GST : {} rad = {} deg'.format(gst, np.rad2deg(gst))) print('LST : {} rad = {} deg'.format(lst, np.rad2deg(lst))) # site location site_ecef = geodetic.lla2ecef(lat, lon, alt) Recef2eci = transform.dcm_ecef2eci(jd) site_eci = Recef2eci.dot(site_ecef) print('Site ECEF : {} km'.format(site_ecef)) print('ECEF TO ECI : \n{}'.format(Recef2eci)) print('Site ECI : {} km'.format(site_eci)) # convert measurement to SEZ then to ECEF then to ECI rho_sez, drho_sez = geodetic.rhoazel2sez(rho, az, el, rhodot, azdot, eldot) R_sez2ecef = transform.dcm_sez2ecef(lat, lon, alt) # transform satellite vector from SEZ to ECI rho_ecef = R_sez2ecef.dot(rho_sez)
var = "False" while var != "True": print("\n\nTest Line {}".format(countl)) #Create 'string' of individual float values readarray1 = [float(n) for n in l1.split()] #Create arrays of 3 values each through numpy lat = np.array(readarray1[0]) * deg2rad longit = np.array(readarray1[1]) * deg2rad alt = np.array(readarray1[2]) * (0.001) t = np.array(readarray1[3]) #print(longit, lat, alt, t) (gst, lst) = time.gstlst(t, longit) #print(gst, lst) N = (eartha)/(1 - (earthe**2 * (np.sin(lat))**2))**.5 #print(N) readarray2 = [float(n) for n in l2.split()] IDN = np.array(readarray2[0]) rho = np.array(readarray2[1]) azm = np.array(readarray2[2]) * deg2rad ele = np.array(readarray2[3]) * deg2rad rhor = np.array(readarray2[4]) azmr = np.array(readarray2[5]) * deg2rad eler = np.array(readarray2[6]) * deg2rad #print(IDN, rho, azm, ele, rhor, azmr, eler) Recef = cf.ela2ecef(lat, longit, alt, N)