def _update_map_views(self, sat_state): """ Updates the map views of the visualizer with the given satellite data. Parameters ---------- sat_state : SatState The satellite data to use """ sat_pos = np.array([ sat_state.position.x, sat_state.position.y, sat_state.position.z ]) * 1000 # calculate where (latitude and longitude) nadir vector points nadir_ll = None nadir_los = los_to_earth(sat_pos, sat_state.nadir) if nadir_los is not None: nadir_ll = np.hstack( pm.eci2geodetic(nadir_los[0], nadir_los[1], nadir_los[2], sat_state.timestamp)[:2]) # calculate where (latitude and longitude) satellite body minus_z axis points minus_z_ll = None minus_z_normalized = self._sc_body_eci[2] / norm(self._sc_body_eci[2]) minus_z_los = los_to_earth(sat_pos, minus_z_normalized) if minus_z_los is not None: minus_z_ll = np.hstack( pm.eci2geodetic(minus_z_los[0], minus_z_los[1], minus_z_los[2], sat_state.timestamp)[:2]) self._update_flat_map_view(sat_state, nadir_ll, minus_z_ll)
def test_eci2geodetic(use_astropy): pytest.importorskip("numpy") if use_astropy: pytest.importorskip("astropy") eci = [-2981784, 5207055, 3161595] utc = datetime(2019, 1, 4, 12) lla = pm.eci2geodetic(*eci, utc, use_astropy=use_astropy) rel = 0.0001 if use_astropy else 0.01 assert lla == approx([27.881, -163.722, 408850.65], rel=rel)
def plotnav(nav: xarray.DataArray): if not isinstance(nav, xarray.DataArray): return ax = figure().gca() if nav.name == 'S': # WARNING: This conversion isn't verified. lat, lon, alt = eci2geodetic(nav.loc[:, ['X', 'Y', 'Z']] * 1e3, nav.t.to_pandas().tolist()) ax.plot(lon, lat) ax.set_xlabel('glon [deg]') ax.set_ylabel('glat [deg]') print('lat lon', lat, lon) print('altitude [km]', alt / 1e3)
def plotnav(nav: xarray.Dataset): if nav is None: return if not 'X' in nav: return ax = figure().gca() # WARNING: This conversion isn't verified. lat, lon, alt = eci2geodetic(nav[['X', 'Y', 'Z']] * 1e3, nav.time) ax.plot(lon, lat) ax.set_xlabel('glon [deg]') ax.set_ylabel('glat [deg]') print('lat lon', lat, lon) print('altitude [km]', alt / 1e3)
def test_eci(): tlla = (42, -82, 200) teci = (-3.977913815668146e6, -2.582332196263046e6, 4.250818828152067e6) t = datetime(2013, 1, 15, 12, 0, 5, tzinfo=UTC) lla = asarray(pm.eci2geodetic(teci, t)).squeeze() assert_allclose(lla, tlla, rtol=0.2) assert_allclose( pm.eci2ecef(teci, t).squeeze(), [649012.04640917, -4697980.55129606, 4250818.82815207]) assert_allclose( pm.ecef2eci([649012.04640917, -4697980.55129606, 4250818.82815207], t).squeeze(), teci) assert_allclose( asarray(pm.eci2aer(teci, 42, -100, 0, t)).squeeze(), [83.73050, -6.614478, 1.473510e6])
def test_eci_vallado(): t = '2013-01-15T12:00:05' lla = pm.eci2geodetic(eci0, t, useastropy=False) assert lla == approx(lla0, rel=0.2) eci1 = pm.eci2ecef(eci0, t, useastropy=False) assert eci1 == approx( [649012.04640917, -4697980.55129606, 4250818.82815207], rel=0.001) assert pm.ecef2eci(eci1, t, useastropy=False) == approx(eci0, rel=0.001) aer1 = pm.eci2aer(eci0, 42, -100, 0, t, useastropy=False) assert aer1 == approx([83.73050, -6.614478, 1.473510e6], rel=0.001) assert pm.aer2eci(*aer1, 42, -100, 0, t, useastropy=False) == approx(eci0, rel=0.001) with pytest.raises(ValueError): pm.aer2eci(aer1[0], aer1[1], -1, 42, -100, 0, t, useastropy=False)
def test_eci_astropy(): pytest.importorskip('astropy') t = '2013-01-15T12:00:05' lla = pm.eci2geodetic(eci0, t) assert lla == approx(lla0, rel=0.2) eci1 = pm.eci2ecef(eci0, t) assert eci1 == approx( [649012.04640917, -4697980.55129606, 4250818.82815207]) assert pm.ecef2eci(eci1, t) == approx(eci0) aer1 = pm.eci2aer(eci0, 42, -100, 0, t) assert aer1 == approx([83.73050, -6.614478, 1.473510e6]) assert pm.aer2eci(*aer1, 42, -100, 0, t) == approx(eci0) with pytest.raises(ValueError): pm.aer2eci(aer1[0], aer1[1], -1, 42, -100, 0, t)
def iridium_ncdf(fn,day,tlim,ellim, camlla): assert len(ellim) == 2,'must specify elevation limits' fn = Path(fn).expanduser() day = forceutc(day) #%% get all sats psuedo SV number with Dataset(str(fn),'r') as f: #psv_border = nonzero(diff(f['pseudo_sv_num'])!=0)[0] #didn't work because of consequtively reused psv #unique doesn't work because psv's can be recycled psv_border = (diff(f['time'])<0).nonzero()[0] + 1 #note unequal number of samples per satellite, +1 for how diff() is defined #%% iterate over psv, but remember different number of time samples for each sv. # since we are only interested in one satellite at a time, why not just iterate one by one, throwing away uninteresting results # qualified by crossing of FOV. #%% consider only satellites above az,el limits for this location #TODO assumes only one satellite meets elevation and time criteria lind = [0,0] #init for i in psv_border: lind = [lind[1],i] cind = arange(lind[0],lind[1]-1,dtype=int) # all times for this SV #now handle times for this SV t = array([day + timedelta(hours=h) for h in f['time'][cind].astype(float)]) if tlim: mask = (tlim[0] <= t) & (t <= tlim[1]) t = t[mask] cind = cind[mask] #now filter by az,el criteria az,el,r = eci2aer(f['pos_eci'][cind,:], camlla[0], camlla[1], camlla[2],t) if ellim and ((ellim[0] <= el) & (el <= ellim[1])).any(): # print(t) #print('sat psv {}'.format(f['pseudo_sv_num'][i])) eci = f['pos_eci'][cind,:] lat,lon,alt = eci2geodetic(eci,t) x,y,z = eci2ecef(eci,t) #print('ecef {} {} {}'.format(x,y,z)) ecef = DataFrame(index=t, columns=['x','y','z'], data=column_stack((x,y,z))) lla = DataFrame(index=t, columns=['lat','lon','alt'], data=column_stack((lat,lon,alt))) aer = DataFrame(index=t, columns=['az','el','srng'], data=column_stack((az,el,r))) return ecef,lla,aer,eci print('no FOV crossings for your time span were found.') return (None,None)
def test_eci(self): if numpy is None or astropy is None: logging.warning('ECI not tested') return teci = (-3.977913815668146e6, -2.582332196263046e6, 4.250818828152067e6) t = datetime(2013, 1, 15, 12, 0, 5, tzinfo=UTC) lla = numpy.asarray(pm.eci2geodetic(teci, t)).squeeze() assert_allclose(lla, lla0, rtol=0.2) assert_allclose( pm.eci2ecef(teci, t).squeeze(), [649012.04640917, -4697980.55129606, 4250818.82815207]) assert_allclose( pm.ecef2eci([649012.04640917, -4697980.55129606, 4250818.82815207], t).squeeze(), teci) assert_allclose( numpy.asarray(pm.eci2aer(teci, 42, -100, 0, t)).squeeze(), [83.73050, -6.614478, 1.473510e6])
def igrffx(eci_vec, time): #import igrf12 import numpy import pyIGRF import pymap3d from pymap3d import ecef2eci import navpy from navpy import ned2ecef import datetime from datetime import datetime import astropy #eci_vec is a xyz vector in ECI km #output B_ECI is a 3 item array in units of T #get our lat long and alt from ECI geod = pymap3d.eci2geodetic(1000 * eci_vec, time, useastropy=True) latitude = geod[0][0] #degrees longitude = geod[1][0] #degrees altitude = geod[2] #meters #call igrf to get b vector in NED #mag = igrf12.igrf('2019-01-12', glat=latitude, glon=longitude, alt_km=altitude/1000) b = pyIGRF.igrf_value(latitude, longitude, altitude / 1000, 2019) #combine NED components back into an array #NED = numpy.array([b_north,b_east,b_down]) NED = b[3:6] #convert from NED to ECEF ECEF = navpy.ned2ecef(NED, latitude, longitude, altitude) #convert from ECEF to ECI B_ECI = (pymap3d.ecef2eci(ECEF, time, useastropy=True)) * 10**(-9) return B_ECI
def RAY_INTERSECT_WGS84_TERRAIN(point, ray_dir, t, DEM_FILE_LOCATION=None, nom_height=0): lat, lon, height = RAY_INTERSECT_WGS84(point, ray_dir, t) s, height_min = Height_From_DEM(lon, lat, DEM_FILE_LOCATION) if (s == 0): return RAY_INTERSECT_WGS84(point, ray_dir, t) #print(Max_Local_Height_From_DEM(lon,lat,DEM_FILE_LOCATION,scale=(5,5))) s, (max_lat, max_lon, max_height) = Max_Local_Height_From_DEM(lon, lat, DEM_FILE_LOCATION, scale=(5, 5)) if (s == 0): return RAY_INTERSECT_WGS84(point, ray_dir, t) eci_ter = pm.ecef2eci(pm.geodetic2ecef(lat, lon, height), t) #print([(max_lon,max_lat),max_height, t]) eci_ter_lmax = pm.ecef2eci(pm.geodetic2ecef(max_lat, max_lon, max_height), t) #print(mid_llh[2],height_mid xd = ray_dir[0] #-31.46071792#- yd = ray_dir[1] #58.59611618#- zd = ray_dir[2] #27.47631664#- xc = -point[0] yc = -point[1] zc = -point[2] xn = eci_ter_lmax[0] yn = eci_ter_lmax[1] zn = eci_ter_lmax[2] #print(xn,yn,zn) t_par = (((xn)**2 + (yn)**2 + (zn)**2) - (xc * xn) - (yc * yn) - (zc * zn)) / (xd * xn + yd * yn + zd * zn) rez = np.array([xc + t_par * xd, yc + t_par * yd, zc + t_par * zd]) #print(pm.eci2geodetic((rez),t)) #print(eci_ter) height_delta = 9999999999 eci_ter_mid = (eci_ter + rez) / 2 height_delta_old = 9898989898 while (abs(height_delta) > 5 and height_delta_old != height_delta): #print(str(height_delta)+': height delta') mid_llh = pm.eci2geodetic(eci_ter_mid, t) #latlonheight s, height_mid = Height_From_DEM(mid_llh[1], mid_llh[0], DEM_FILE_LOCATION) if (s == 0): return RAY_INTERSECT_WGS84(point, ray_dir, t) #print(mid_llh[2],height_mid[2],mid_llh[2]-height_mid[2]) height_delta_old = height_delta height_delta = mid_llh[2] - height_mid[2] if (height_delta < 0): eci_ter_mid_new = (rez + eci_ter_mid) / 2 eci_ter = eci_ter_mid eci_ter_mid = eci_ter_mid_new else: eci_ter_mid_new = (eci_ter_mid + eci_ter) / 2 rez = eci_ter_mid eci_ter_mid = eci_ter_mid_new #print(mid_llh) return (mid_llh)
def test_eci_geodetic(useastropy): pytest.importorskip("numpy") t = "2013-01-15T12:00:05" lla = pm.eci2geodetic(*eci0, t, useastropy=useastropy) assert lla == approx(lla0, rel=0.2)
def test_eci_geodetic(useastropy): t = '2013-01-15T12:00:05' lla = pm.eci2geodetic(*eci0, t, useastropy=useastropy) assert lla == approx(lla0, rel=0.2)
def test_eci_geodetic(useastropy): t = '2013-01-15T12:00:05' lla = pm.eci2geodetic(*eci0, t, useastropy=useastropy) assert lla == approx(lla0, rel=0.2)