def test_array_ecef2geodetic(): """ tests ecef2geodetic can handle numpy array data in addition to singular floats """ np = pytest.importorskip("numpy") # test values with no points inside ellipsoid lla0_array = ( np.array([lla0[0], lla0[0]]), np.array([lla0[1], lla0[1]]), np.array([lla0[2], lla0[2]]), ) xyz = pm.geodetic2ecef(*lla0_array) lats, lons, alts = pm.ecef2geodetic(*xyz) assert lats == approx(lla0_array[0]) assert lons == approx(lla0_array[1]) assert alts == approx(lla0_array[2]) # test values with some (but not all) points inside ellipsoid lla0_array_inside = ( np.array([lla0[0], lla0[0]]), np.array([lla0[1], lla0[1]]), np.array([lla0[2], -lla0[2]]), ) xyz = pm.geodetic2ecef(*lla0_array_inside) lats, lons, alts = pm.ecef2geodetic(*xyz) assert lats == approx(lla0_array_inside[0]) assert lons == approx(lla0_array_inside[1]) assert alts == approx(lla0_array_inside[2])
def test_geodetic(): xyz = pm.geodetic2ecef(*lla0) assert xyz == approx(xyz0) assert pm.geodetic2ecef(*rlla0, deg=False) == approx(xyz) with pytest.raises(ValueError): pm.geodetic2ecef(lla0[0], lla0[1], -1) with pytest.raises(ValueError): pm.geodetic2ecef(-100, lla0[1], lla0[2]) with pytest.raises(ValueError): pm.geodetic2ecef(lla0[0], -200, lla0[2]) assert pm.ecef2geodetic(*xyz) == approx(lla0) assert pm.ecef2geodetic(*xyz, deg=False) == approx(rlla0) lla2 = pm.aer2geodetic(*aer0, *lla0) rlla2 = pm.aer2geodetic(*raer0, *rlla0, deg=False) with pytest.raises(ValueError): pm.aer2geodetic(aer0[0], aer0[1], -1, *lla0) assert lla2 == approx(lla1) assert rlla2 == approx(rlla1) assert pm.geodetic2aer(*lla2, *lla0) == approx(aer0) assert pm.geodetic2aer(*rlla2, *rlla0, deg=False) == approx(raer0) anan = np.empty((10, 10)) anan.fill(np.nan) assert np.isnan(pm.geodetic2aer(anan, anan, anan, *lla0)).all() assert np.isnan(pm.aer2geodetic(anan, anan, anan, *lla0)).all()
def geodetic_to_ecef(lla_point: Union[np.ndarray, Sequence[float]]) -> np.ndarray: """Convert given latitude, longitude, and optionally altitude into ECEF coordinates. If no altitude is given, altitude 0 is assumed. Args: lla_point (Union[np.ndarray, Sequence[float]]): Latitude, Longitude and optionally Altitude Returns: np.ndarray: 3D ECEF coordinate """ if len(lla_point) == 2: return np.array(pm.geodetic2ecef(lla_point[0], lla_point[1], 0), dtype=np.float64) else: return np.array(pm.geodetic2ecef(lla_point[0], lla_point[1], lla_point[2]), dtype=np.float64)
def test_ecef(): xyz = pm.geodetic2ecef(*lla0) assert xyz == approx(xyz0) assert pm.geodetic2ecef(*rlla0, deg=False) == approx(xyz) with pytest.raises(ValueError): pm.geodetic2ecef(-100, lla0[1], lla0[2]) assert pm.ecef2geodetic(*xyz) == approx(lla0) assert pm.ecef2geodetic(*xyz, deg=False) == approx(rlla0) assert pm.ecef2geodetic((A - 1) / np.sqrt(2), (A - 1) / np.sqrt(2), 0) == approx([0, 45, -1])
def test_pandas(): pandas = pytest.importorskip("pandas") pd_lla = pandas.Series(lla0) xyz = pm.geodetic2ecef(*pd_lla) assert xyz == approx(xyz0) # %% dataframe degenerates to series pd_lla = pandas.DataFrame([[*lla0], [*lla0]], columns=["lat", "lon", "alt_m"]) xyz = pm.geodetic2ecef(pd_lla["lat"], pd_lla["lon"], pd_lla["alt_m"]) assert xyz[0].values == approx(xyz0[0]) assert xyz[1].values == approx(xyz0[1]) assert xyz[2].values == approx(xyz0[2])
def test_pandas(): pandas = pytest.importorskip('pandas') pd_lla = pandas.Series(lla0) xyz = pm.geodetic2ecef(*pd_lla) assert xyz == approx(xyz0) assert isinstance(xyz[0], float) # series degenerates to scalars by pandas itself # %% dataframe degenerates to series pd_lla = pandas.DataFrame([[*lla0], [*lla0]], columns=['lat', 'lon', 'alt_m']) xyz = pm.geodetic2ecef(pd_lla['lat'], pd_lla['lon'], pd_lla['alt_m']) assert xyz[0].values == approx(xyz0[0]) assert xyz[1].values == approx(xyz0[1]) assert xyz[2].values == approx(xyz0[2]) assert isinstance(xyz[0], pandas.Series)
def test_scalar_geodetic2ecef(lla): """ verify we can handle the wide variety of input data type users might use """ x0, y0, z0 = pm.geodetic2ecef(*lla) assert (x0, y0, z0) == approx(xyz0)
def main(header_to_test, modelnames, dates, heights, lats, lons, bns, bes, bds, margin): """create and write catch2 tests as a c++ source file to test header_to_test defining the WMM coefficents and model The file created has the name header_to_test[:-4]+'_test.cpp' Args: header_to_test(str ending in .hpp): the c++ header file with the model and coefficents modelnames(list of str): The list of model names for each test dates(numpy array): decimal test years heights(numpy array): test heights (km) with respect to wgs 84 ellipsoid lats(numpy array): test lat (deg) lons(numpy array): test lon (deg) bns(numpy array): test X(local north) magnetic field (nT) bes(numpy array): test Y(local east) magnetic field (nT) bds(numpy array): test Z(local down) magnetic field (nT) margin(float or int): Acceptable error in each component (nT)""" xs, ys, zs = pm.geodetic2ecef(lats, lons, heights * 1000) bxs, bys, bzs = pm.enu2uvw(bes * 1E-9, bns * 1E-9, -bds * 1E-9, lats, lons) file_name = header_to_test[:-4] + '_test.cpp' with open(file_name, 'w') as f: outstr = """ // %s Generated by python script wmmcodeupdate.py /** \\file * \\author Nathan Zimmerberg ([email protected]) * \\date 24 OCT 2019 * \\brief c++ catch2 tests for magnetic field header only library. * \\details Compile with g++ %s -std=c++1z */ #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file #include "catch.hpp" #include "../%s" """ % (file_name, file_name, header_to_test) for i in range(len(xs)): testcase = """ TEST_CASE( "geomag test %s of %s model", "[GeoMag]" ) { geomag::Vector in; in.x= %s; in.y= %s; in.z= %s; geomag::Vector out; geomag::Vector truth; truth.x= %s; truth.y= %s; truth.z= %s; out= geomag::GeoMag(%s,in,geomag::%s); CHECK( out.x*1E9 == Approx(truth.x*1E9).margin(%s) ); CHECK( out.y*1E9 == Approx(truth.y*1E9).margin(%s) ); CHECK( out.z*1E9 == Approx(truth.z*1E9).margin(%s) ); } """ % (i, modelnames[i], repr(xs[i]), repr(ys[i]), repr( zs[i]), repr(bxs[i]), repr(bys[i]), repr( bzs[i]), dates[i], modelnames[i], margin, margin, margin) outstr = outstr + testcase f.write(outstr)
def check_hull(self, lat0, lon0, alt0): """ Check if the input points R0 are within the convex hull of the original data. Parameters: lat0: [ndarray] geodetic latitude (can be multidimensional array) lon0: [ndarray] geodetic longitude (can be multidimensional array) alt0: [ndarray] geodetic altitude (can be multidimensional array) """ # this is horribly inefficient, but mostly nessisary? hull = ConvexHull(self.hull_vert) check = [] for lat, lon, alt in zip(lat0.ravel(), lon0.ravel(), alt0.ravel()): value = False x, y, z = pm.geodetic2ecef(lat, lon, alt) pnts = np.append(self.hull_vert, np.array([[x, y, z]]), axis=0) new_hull = ConvexHull(pnts) if np.array_equal(hull.vertices, new_hull.vertices): value = True check.append(value) return np.array(check).reshape(alt0.shape)
def iridium_tle(fn,T,sitella,svn): assert isinstance(svn,int) assert len(sitella)==3 assert isinstance(T[0],datetime),'parse your date' fn = Path(fn).expanduser() #%% read tle with fn.open('r') as f: for l1 in f: if int(l1[2:7]) == svn: l2 = f.readline() break sat = readtle('n/a',l1,l2) #%% comp sat position obs = Observer() obs.lat = str(sitella[0]); obs.lon = str(sitella[1]); obs.elevation=float(sitella[2]) ecef = DataFrame(index=T,columns=['x','y','z']) lla = DataFrame(index=T,columns=['lat','lon','alt']) aer = DataFrame(index=T,columns=['az','el','srng']) for t in T: obs.date = t sat.compute(obs) lat,lon,alt = degrees(sat.sublat), degrees(sat.sublong), sat.elevation az,el,srng = degrees(sat.az), degrees(sat.alt), sat.range x,y,z = geodetic2ecef(lat,lon,alt) ecef.loc[t,:] = column_stack((x,y,z)) lla.loc[t,:] = column_stack((lat,lon,alt)) aer.loc[t,:] = column_stack((az,el,srng)) return ecef,lla,aer
def test_geodetic(): assert_allclose(pm.ecef2geodetic(tx, ty, tz), (ec2la, ec2lo, ec2a), rtol=0.01, err_msg='ecef2geodetic: ' + str(pm.ecef2geodetic(tx, ty, tz))) assert_allclose(pm.geodetic2aer(lat2, lon2, alt2, tlat, tlon, talt), (g2az, g2el, g2rn), rtol=0.05, err_msg='geodetic2aer: {}'.format( pm.geodetic2aer(lat2, lon2, alt2, tlat, tlon, talt))) assert_allclose(pm.geodetic2ecef(tlat, tlon, talt), (g2x, g2y, g2z), rtol=0.01, err_msg='geodetic2ecef: {}'.format( pm.geodetic2ecef(tlat, tlon, talt)))
def transform_coords(self, lat, lon, alt): """ Transform from spherical coordinates to something friendlier for calculating the basis fit. This involves a rotation so that the data is centered around the north pole and a trasformation of the radial component such that z = 100*(r/RE-1). Parameters: R0: [ndarray(3,npoints)] array of input points in geocentric coordinates R = [[r coordinates (m)],[theta coordinates (rad)],[phi coordinates (rad)]] if input points are expressed as a list of r,t,p points, eg. points = [[r1,t1,p1],[r2,t2,p2],...], R = np.array(points).T Returns: R_trans: [ndarray(3,npoints)] array of input points transformed into model coordinates R_trans = [[z coordinates],[theta coordinates (rad)],[phi coordinates (rad)]] cp: [ndarray(2)] center point of the input coordinates R0 Notes: """ x, y, z = pm.geodetic2ecef(lat, lon, alt) R_trans = np.array([x, y, z]) return R_trans
def sunlocate(time): #inputs # time: time in MJD #outputs #Sun2Earth - unit vector from sun2earth in ECI import astropy import astropy.coordinates import datetime import julian from astropy.time import Time import pymap3d from pymap3d import geodetic2ecef import decimal from astropy import units as u from astropy.coordinates import Angle import numpy as np #get the time in MJD #mjd = 58562 t2 = Time(time, format='mjd') #print(t2) #get the location of the sun in lat long sun_GEOD = astropy.coordinates.get_sun(t2) #print(sun_GEOD) lon_extra = Angle(sun_GEOD.ra) lat_extra = Angle(sun_GEOD.dec) #get it as a float lon = 1 * lon_extra.degree lat = 1 * lat_extra.degree #print(lon) #print(lat) #print(type(lon)) #a = Angle(lat) #print(a.degree) here = type(lon) #print(here) #convert the geodetic coordinates to ECEF sun_ECEF = geodetic2ecef(lat, lon, 0, ell=None, deg=True) #Convert ECEF to ECI sun_ECI = pymap3d.ecef2eci(sun_ECEF, t2, useastropy=True) #get the norm to normalize it norm_sun_ECI = np.linalg.norm(sun_ECI) #print(norm_sun_ECI) Sun2Earth = 1.496e8 * sun_ECI / norm_sun_ECI return Sun2Earth
def __get_line(lat, lon, alt, bearing, pitch): p = pymap3d.geodetic2ecef(lat, lon, alt) d = numpy.array([ math.cos(math.radians(pitch)) * math.sin(math.radians(bearing)), math.cos(math.radians(pitch)) * math.cos(math.radians(bearing)), math.sin(math.radians(pitch)) ]) m = numpy.array([ [ -1 * math.sin(math.radians(lon)), -1 * math.sin(math.radians(lat)) * math.cos(math.radians(lon)), math.cos(math.radians(lat)) * math.cos(math.radians(lon)) ], [ math.cos(math.radians(lon)), -1 * math.sin(math.radians(lat)) * math.sin(math.radians(lon)), math.cos(math.radians(lat)) * math.sin(math.radians(lon)) ], [0, math.cos(math.radians(lat)), math.sin(math.radians(lat))] ]) d = m.dot(d) d = Geographic.__normalize(d) return p, d
def convert_to_ECEF(self): self.X, self.Y, self.Z = pm.geodetic2ecef(self.latitude, self.longitude, self.altitude * 1000.) self.Vx, self.Vy, self.Vz = pm.enu2uvw(self.field[:, 0], self.field[:, 1], self.field[:, 2], self.latitude, self.longitude)
def get_ground_station_postion_ICRF(t, lat, lon, alt, MJD_UTC_Start): ''' :param t:相对仿真起始点的时间/s :param r_ITRS: 地固坐标系 m :return: 地心惯性坐标系 m ''' x, y, z = pm.geodetic2ecef(lat, lon, alt) #默认为WGS84椭球体 r_ITRS = np.array([x, y, z]) const = Const() MJD_UTC = MJD_UTC_Start + t / 86400 # JD = MJD_UTC + 2400000.5 x_pole, y_pole, UT1_UTC, LOD, dpsi, deps, dx_pole, dy_pole, TAI_UTC = IERS( Global_parameters.eopdata, MJD_UTC, 'l') UT1_TAI, UTC_GPS, UT1_GPS, TT_UTC, GPS_UTC = timediff(UT1_UTC, TAI_UTC) JD = MJD_UTC + 2400000.5 year, month, day, hour, minute, sec = invjday(JD) DJMJD0, DATE = iauCal2jd(year, month, day) TIME = (60 * (60 * hour + minute) + sec) / 86400 UTC = DATE + TIME TT = UTC + TT_UTC / 86400 #Terrestrial Time (TT) Terrestrial Time (TT) # used to be known as Terrestrial Dynamical Time (TDT) TUT = TIME + UT1_UTC / 86400 UT1 = DATE + TUT #Polar motion matrix (TIRS->ITRS, IERS 2003) Pi = iauPom00(x_pole, y_pole, iauSp00(DJMJD0, TT)) #Form bias-precession-nutation matrix NPB = iauPnm06a(DJMJD0, TT) #% Form Earth rotation matrix gast = iauGst06(DJMJD0, UT1, DJMJD0, TT, NPB) Theta = iauRz(gast, np.eye(3)) #ICRS to ITRS transformation E = np.dot(np.dot(Pi, Theta), NPB) #ITRS to ICRS transformation E_1 = np.linalg.inv(E) r_ICRF = np.dot(E_1, r_ITRS) return r_ICRF
def extract_gps_cordinate(lats=[], lons=[], alts=[]): x_arr = [] y_arr = [] z_arr = [] for lat, lon, alt in zip(lats, lons, alts): x, y, z = pm.geodetic2ecef(lat, lon, alt) x_arr.append(x) y_arr.append(y) z_arr.append(z) return (x_arr, y_arr, z_arr)
def test_compare_geodetic(): pyproj = pytest.importorskip('pyproj') xyz = pm.geodetic2ecef(*lla0) ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84') lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84') assert pyproj.transform(lla, ecef, lla0[1], lla0[0], lla0[2]) == approx(xyz) assert pyproj.transform(ecef, lla, *xyz) == approx((lla0[1], lla0[0], lla0[2]))
def test_scalar_geodetic2ecef(lla): """ verify we can handle the wide variety of input data type users might use """ if isinstance(lla[0], list): pytest.importorskip("numpy") x0, y0, z0 = pm.geodetic2ecef(*lla) assert (x0, y0, z0) == approx(xyz0)
def test_compare_geodetic(): pyproj = pytest.importorskip("pyproj") xyz = pm.geodetic2ecef(*lla0) ecef = pyproj.Proj(proj="geocent", ellps="WGS84", datum="WGS84") lla = pyproj.Proj(proj="latlong", ellps="WGS84", datum="WGS84") assert pyproj.transform(lla, ecef, lla0[1], lla0[0], lla0[2]) == approx(xyz) assert pyproj.transform(ecef, lla, *xyz) == approx((lla0[1], lla0[0], lla0[2]))
def getIonosphericPiercingPoints(rx_xyz, sv, obstimes, ipp_alt, navfn, cs='wsg84', rx_xyz_coords='xyz', el0=0): """ Sebastijan Mrak Function returns a list of Ionospheric Piersing Point (IPP) trajectory in WSG84 coordinate system (CS). Function takes as parameter a receiver location in ECEF CS, satellite number, times ob observation and desired altitude of a IPP trajectory. You also have to specify a full path to th navigation data file. It returns IPP location in either WSG84 or AER coordinate system. """ ipp_alt = ipp_alt * 1E3 if rx_xyz_coords == 'xyz': rec_lat, rec_lon, rec_alt = ecef2geodetic(rx_xyz[0], rx_xyz[1], rx_xyz[2]) else: if not isinstance(rx_xyz, list): rx_xyz = list(rx_xyz) if len(rx_xyz) == 2: rx_xyz.append(0) assert len(rx_xyz) == 3 rec_lat = rx_xyz[0] rec_lon = rx_xyz[1] rec_alt = rx_xyz[2] rx_xyz = geodetic2ecef(lat = rec_lon, lon = rec_lat, alt = rec_alt) if sv[0] == 'G': if navfn.endswith('n'): xyz = gpsSatPosition(navfn, obstimes, sv=sv, rx_position=rx_xyz, coords='xyz') elif navfn.endswith('sp3'): xyz = gpsSatPositionSP3(navfn, obstimes, sv=sv, rx_position=rx_xyz, coords='xyz') az,el,r = ecef2aer(xyz[0,:],xyz[1,:],xyz[2,:],rec_lat, rec_lon, rec_alt) aer_vector = np.array([az, el, r]) r_new = [] for i in range(len(el)): if el[i] > el0: fm = np.sin(np.radians(el[i])) r_new.append(ipp_alt / fm) else: r_new.append(np.nan) lla_vector = np.array(aer2geodetic(az, el, r_new, rec_lat, rec_lon, rec_alt)) elif sv[0] == 'R': aer_vector = gloSatPosition(navfn=navfn, sv=sv, obstimes=obstimes, rx_position=[rec_lon, rec_lat, rec_alt], cs='aer') fm = np.sin(np.radians(aer_vector[1])) r_new = ipp_alt / fm lla_vector = np.array(aer2geodetic(aer_vector[0], aer_vector[1], r_new, rec_lat, rec_lon, rec_alt)) else: print ('Type in valid sattype initial. "G" for GPS and "R" for GLONASS') if (cs == 'wsg84'): return lla_vector elif (cs == 'aer'): return aer_vector else: print ('Enter either "wsg84" or "aer" as coordinate system. "wsg84" is default one.')
def placemark_to_component(placemark, origin): point = placemark.geometry if origin is None: origin = np.array([point.y, point.x, point.z]) ecef_x, ecef_y, ecef_z = pm.geodetic2ecef(point.y, point.x, point.z) x, y, z = pm.ecef2enu(ecef_x, ecef_y, ecef_z, origin[0], origin[1], origin[2]) pos = np.array([x, y, z]) name = placemark.description return WellpadComponent(pos, name), origin
def test_xarray(): xarray = pytest.importorskip("xarray") xr_lla = xarray.DataArray(list(lla0)) xyz = pm.geodetic2ecef(*xr_lla) assert xyz == approx(xyz0) # %% xr_xyz = xarray.DataArray(list(xyz0)) lla = pm.ecef2geodetic(*xr_xyz) assert lla == approx(lla0)
def __init__(self, config): self.read_config(config) bc = np.loadtxt(self.beamcode_filename) idx = np.where(np.in1d(bc[:, 0], self.beamcodes))[0] self.beam_codes = bc[idx, :] self.X0, self.Y0, self.Z0 = pm.geodetic2ecef( self.site_coords[0], self.site_coords[1], self.site_coords[2] * 1000.) self.get_gate_locations(self.beam_codes[:, 1], self.beam_codes[:, 2], float(self.range_step)) self.geodetic_locations()
def transform_coord(self, gdlat, gdlon, gdalt): """ Transform from spherical coordinates to something friendlier for calculating the basis fit. This involves a rotation so that the data is centered around the north pole and a trasformation of the radial component such that z = 100*(r/RE-1). Parameters: R0: [ndarray(3,npoints)] array of input points in geocentric coordinates R = [[r coordinates (m)],[theta coordinates (rad)],[phi coordinates (rad)]] if input points are expressed as a list of r,t,p points, eg. points = [[r1,t1,p1],[r2,t2,p2],...], R = np.array(points).T Returns: R_trans: [ndarray(3,npoints)] array of input points transformed into model coordinates R_trans = [[z coordinates],[theta coordinates (rad)],[phi coordinates (rad)]] cp: [ndarray(2)] center point of the input coordinates R0 Notes: """ x0, y0, z0 = pm.geodetic2ecef(self.latcp,self.loncp,0.) theta0 = np.arccos(z0/np.sqrt(x0**2+y0**2+z0**2)) phi0 = np.arctan2(y0,x0) k = np.array([np.cos(phi0+np.pi/2.),np.sin(phi0+np.pi/2.),0.]) x, y, z = pm.geodetic2ecef(gdlat, gdlon, gdalt) Rp = np.array([x,y,z]) Rr = np.array([R*np.cos(theta0)+np.cross(k,R)*np.sin(theta0)+k*np.dot(k,R)*(1-np.cos(theta0)) for R in Rp.T]).T r = np.sqrt(Rr[0]**2+Rr[1]**2+Rr[2]**2) t = np.arccos(Rr[2]/r) p = np.arctan2(Rr[1],Rr[0]) return 100*(r/RE-1), t, p
def test_ecef(): xyz = pm.geodetic2ecef(*lla0) assert xyz == approx(xyz0) assert pm.geodetic2ecef(*rlla0, deg=False) == approx(xyz) with pytest.raises(ValueError): pm.geodetic2ecef(lla0[0], lla0[1], -1) with pytest.raises(ValueError): pm.geodetic2ecef(-100, lla0[1], lla0[2]) with pytest.raises(ValueError): pm.geodetic2ecef(lla0[0], -200, lla0[2]) assert pm.ecef2geodetic(*xyz) == approx(lla0) assert pm.ecef2geodetic(*xyz, deg=False) == approx(rlla0)
def getGGA_userPOS(line): if 'GGA' in line: record = pynmea2.parse(line) x, y, z = pm.geodetic2ecef(record.latitude, record.longitude, record.altitude) lat = record.latitude lon = record.longitude #ecef_x.append(x) #ecef_y.append(y) #ecef_z.append(z) #error=getDistance(record.latitude, record.longitude,True_Lat, True_Lon) #Distance_2Derror.append(error) return (lat, lon, x, y, z)
def test_xarray(): xarray = pytest.importorskip('xarray') xr_lla = xarray.DataArray(list(lla0)) xyz = pm.geodetic2ecef(*xr_lla) assert xyz == approx(xyz0) assert isinstance(xyz[0], xarray.DataArray) # %% xr_xyz = xarray.DataArray(list(xyz0)) lla = pm.ecef2geodetic(*xr_xyz) assert lla == approx(lla0) assert isinstance(lla[0], float) # xarrayness is lost, possibly expensive to keep due to isinstance()
def __init__(self, config_file): self.read_config(config_file) lat, lon, alt = np.meshgrid( np.linspace(self.latrange[0], self.latrange[1], self.numgridpnt), np.linspace(self.lonrange[0], self.lonrange[1], self.numgridpnt), np.linspace(self.altrange[0], self.altrange[1], self.numgridpnt) * 1000.) X, Y, Z = pm.geodetic2ecef(lat.flatten(), lon.flatten(), alt.flatten()) self.centers = np.array([X, Y, Z]).T self.nbasis = self.centers.shape[0] self.eval_reg_matricies = {}
def get_satelite(filename, user): """ Devuelve una lista de objetos Satelite obtenidos del fichero "filename" @param filename Fichero .txt de satelites activos @return Lista de objetos Satelite """ with open(filename) as fobj: # Se obtiene la fecha y hora actual now = datetime.datetime.now(tz=pytz.UTC) # Se itera sobre el fichero for line in fobj: with suppress(StopIteration): # Leer nombre y dos líneas name = line line1 = next(fobj) line2 = next(fobj) # Obtener latitud/longitud como tipo ephem.Angle (tipo interno, representacion HH:MM:SS.SS) # https://rhodesmill.org/pyephem/angle.html # tle_rec.elevation devuelve la altitud tle_rec = ephem.readtle(name, line1, line2) tle_rec.compute(now) # Convertir ephem.Angle a grados sat_lat = tle_rec.sublat * 180.0 / math.pi sat_lon = tle_rec.sublong * 180.0 / math.pi sat_alt = tle_rec.elevation # metros # Convertir LLA (lat/lon/alt) a ECEF (earth-centered, earth-fixed) sat_x, sat_y, sat_z = pm.geodetic2ecef(sat_lat, sat_lon, sat_alt) # Conversion a KM sat_x = sat_x / 1000 sat_y = sat_y / 1000 sat_z = sat_z / 1000 # Se parte la segunda linea para obtener el identificador y # anyadirlo a la url fields = line2.split() # Se construye y devuelve un objeto Satelite con la posicion # , el nombre, las coordenadas del usuario y la url yield Satelite( sat_x, sat_y, sat_z, name.strip(), user, 'https://www.n2yo.com/satellite/?s=' + fields[1])
def convert_point(point, config): """ Convert Point to geodetic coordinates to ECEF coordinates to ENU coordinates and return camera perspective coordinates """ # Convert point geodetic coordinates (lat, lon, alt) to ECEF coordinates (x, y, z) x_ecef, y_ecef, z_ecef = pymap3d.geodetic2ecef(point[0], point[1], point[2]) # Convert point ECEF coordinates (x, y, z) to ENU coordinates (East, North, Up) # pymap3d.ecef2enuv(x, y, z, lat0, lon0, h0) where 0 is camera coordinates u_east, v_north, w_up = pymap3d.ecef2enu(x_ecef, y_ecef, z_ecef, config[0], config[1], config[2]) # Convert ENU coordinates to camera perspective camera_x, camera_y, camera_z = enu_to_camera_coords( u_east, v_north, w_up, config) return camera_x, camera_y, camera_z
def test_geodetic2ecef(lla, xyz): assert pm.geodetic2ecef(*lla) == approx(xyz, abs=atol_dist)