def test_eci_times_astropy(): pytest.importorskip('astropy') with pytest.raises(AssertionError): pm.eci2ecef(eci0, [t0, t0]) with pytest.raises(AssertionError): pm.ecef2eci(eci0, [t0, t0]) eci0s = np.stack((eci0, eci0)) assert pm.ecef2eci(pm.eci2ecef(eci0s, [t0] * 2), [t0] * 2) == approx(eci0s)
def test_eci_times_vallado(): with pytest.raises(AssertionError): pm.eci2ecef(eci0, [t0, t0], useastropy=False) with pytest.raises(AssertionError): pm.ecef2eci(eci0, [t0, t0], useastropy=False) eci0s = np.stack((eci0, eci0)) assert pm.ecef2eci(pm.eci2ecef(eci0s, [t0] * 2, useastropy=False), [t0] * 2, useastropy=False) == approx(eci0s, rel=0.001)
def test_eci_times(useastropy): with pytest.raises(ValueError): pm.eci2ecef(*eci0, [t0, t0], useastropy=useastropy) with pytest.raises(ValueError): pm.ecef2eci(*eci0, [t0, t0], useastropy=useastropy) x = [eci0[0]] * 2 y = [eci0[1]] * 2 z = [eci0[2]] * 2 t = [t0] * 2 assert pm.ecef2eci(*pm.eci2ecef(x, y, z, t, useastropy=useastropy), t, useastropy=useastropy) == approx(eci0, rel=0.001)
def test_eciecef(useastropy): pytest.importorskip("numpy") ecef = pm.eci2ecef(*eci0, t1, useastropy=useastropy) assert ecef == approx( [649012.04640917, -4697980.55129606, 4250818.82815207], rel=0.001) assert pm.ecef2eci(*ecef, t1, useastropy=useastropy) == approx(eci0, rel=0.001)
def RAY_INTERSECT_WGS84(point, ray_dir, t): #-----WGS 84 -------------- dat_a = 6378137 #Meters dat_f = 1 / 298.257223563 #flat scale for oblateness dat_ep = 1 / ((1 - dat_f) * (1 - dat_f)) 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] qa = xd**2 + yd**2 + (zd**2) * dat_ep qb = 2 * (xc * xd + yc * yd + zc * zd * dat_ep) qc = xc**2 + yc**2 + ((zc**2) * dat_ep) - (dat_a**2) ray_roots = np.roots([qa, qb, qc]) earth_point = [] earth_point.append([ xc + ray_roots[0] * xd, yc + ray_roots[0] * yd, zc + ray_roots[0] * zd ]) earth_point.append([ xc + ray_roots[1] * xd, yc + ray_roots[1] * yd, zc + ray_roots[1] * zd ]) #print(earth_point) #6371e3 * np.vstack(ecef) #print('--NORMS '+str(np.linalg.norm(earth_point[0]))+'--:--'+str(np.linalg.norm(earth_point[1]))+'\n') #print('\n\n ---------- STATE VECTOR 2 NORMAL PROJECTION -------------- \n') #print(earth_point) #print(6371e3*np.vstack(earth_point[0])) earth_point[0] = pm.eci2ecef((earth_point[1]), t) #earth_point[0]=6371e3*np.array(earth_point[0]) # 6371e3 * np.vstack(ecef) ecx = -1 * earth_point[0][0] ecy = -1 * earth_point[0][1] ecz = -1 * earth_point[0][2] #print((ecx**2+ecy**2+ecz**2)**0.5) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(pm.ecef2geodetic(ecx,ecy,ecz))) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(ECI_TO_WGS84LLH(-1*np.array(earth_point[0]),t ))) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(ECEF_TO_WGS84LLH(-1*np.array(earth_point[0])))) #earth_point[0]=np.array([ecx,ecy,ecz))/1000 #llh=pm.ecef2geodetic(ecx,ecy,ecz) # ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84') # lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84') # lon, lat, alt = pyproj.transform(ecef, lla, ecx, ecy, ecz, radians=False) llh = pm.ecef2geodetic(ecx, ecy, ecz) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(llh)) #print('---------- ------------------------------- -------------- \n') #print(llh) return (llh)
def test_eci2ecef(use_astropy): pytest.importorskip("numpy") if use_astropy: pytest.importorskip("astropy") # this example from Matlab eci2ecef docs eci = [-2981784, 5207055, 3161595] utc = datetime(2019, 1, 4, 12) ecef = pm.eci2ecef(*eci, utc, use_astropy=use_astropy) rel = 0.0001 if use_astropy else 0.02 assert ecef == approx([-5.7627e6, -1.6827e6, 3.1560e6], rel=rel)
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 RAY_INTERSECT_WGS84_PYGAC(point, ray_dir, t): centre = -point a__ = 6378137 # km # b__ = 6356.75231414 # km, GRS80 b__ = 6356752.314245 # km, WGS84 radius = np.array([[1 / a__, 1 / a__, 1 / b__]]).T shape = ray_dir.shape xr_ = ray_dir.reshape([3, -1]) * radius print(xr_) cr_ = centre.reshape([3, -1]) * radius print(cr_) ldotc = np.einsum("ij,ij->j", xr_, cr_) print(ldotc) lsq = np.einsum("ij,ij->j", xr_, xr_) print(lsq) csq = np.einsum("ij,ij->j", cr_, cr_) print(csq) #print(ldotc**2-(csq*lsq+lsq)) #print((ldotc**2-csq*lsq+lsq)**0.5) d1_ = (ldotc - np.sqrt(ldotc**2 - csq * lsq + lsq)) / lsq #print(d1_) #print(ray_dir * d1_.reshape(shape[1:]) - centre) # return the actual pixel positions earth_point = [] earth_point.append(ray_dir * d1_.reshape(shape[1:]) - centre) earth_point[0] = pm.eci2ecef((earth_point[0]), t) #earth_point[0]=6371e3*np.array(earth_point[0]) # 6371e3 * np.vstack(ecef) ecx = -1 * earth_point[0][0] ecy = -1 * earth_point[0][1] ecz = -1 * earth_point[0][2] llh = pm.ecef2geodetic(ecx, ecy, ecz) #print((ecx**2+ecy**2+ecz**2)**0.5) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(pm.ecef2geodetic(ecx,ecy,ecz))) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(ECI_TO_WGS84LLH(-1*np.array(earth_point[0]),t ))) #print("LAT(deg) LON(deg) HEIGHT(m) :"+str(ECEF_TO_WGS84LLH(-1*np.array(earth_point[0])))) #earth_point[0]=np.array([ecx,ecy,ecz))/1000 return llh
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 interp_ira(sat, ts): # (linear) interpolate sat position global satidx, osatidx """ # Option to interpolate based on TLEs geocentric = by_name[iridium_next.sv_map[sat]].at(timescale.utc(datetime.datetime.utcfromtimestamp(ts).replace(tzinfo=utc))) xyz = geocentric.position.m xyz[0], xyz[1], xyz[2] = pymap3d.eci2ecef(xyz[0], xyz[1], xyz[2], datetime.datetime.utcfromtimestamp(ts)) return xyz """ if ts > ira_xyzt[sat][satidx[sat]][3]: satidx[sat] = 0 if True or satidx[sat] == 0: #print("Searching for sat %d..."%sat) osatidx[sat] = 0 for x in range(len(ira_xyzt[sat])): if osatidx[sat] == 0 and ts - ira_xyzt[sat][x][3] < tmax: #print("` old=%d"%x, end=' ') osatidx[sat] = x if ira_xyzt[sat][x][3] - ts > tmax: #print("` new_exit=%d"%x) break satidx[sat] = x xyz = [None, None, None] idx = satidx[sat] idxo = osatidx[sat] tn = ira_xyzt[sat][idx][3] to = ira_xyzt[sat][idxo][3] delta = tn - to #print("Borders: %d -> %d"%(idxo, idx)) #print("time %f -> %f: Δt: %f"%(to,tn,tn-to)) # refuse to extrapolate if delta > 2000: raise InterpException("Too inaccurate (Δ=%d)" % (delta)) if ts < to: raise InterpException("In the past") if ts > tn: raise InterpException("In the future") if idxo == idx: raise InterpException("Not enough data") step = 1 T = [t for x, y, z, t in ira_xyzt[sat][idxo:idx + 1:step]] X = [x for x, y, z, t in ira_xyzt[sat][idxo:idx + 1:step]] Y = [y for x, y, z, t in ira_xyzt[sat][idxo:idx + 1:step]] Z = [z for x, y, z, t in ira_xyzt[sat][idxo:idx + 1:step]] if len(T) < 2: raise InterpException("Not enough data") xyz[0], xyz[1], xyz[2] = interp_circ.interp([X, Y, Z], T, ts, debug) xyz[0], xyz[1], xyz[2] = pymap3d.eci2ecef( xyz[0], xyz[1], xyz[2], datetime.datetime.utcfromtimestamp(ts)) return xyz