def _update_loop(self, stop_when_found=False): self.is_updating = True logger.debug("Starting _update_loop") while self.is_updating: try: result = str(self.serial_port.readline(), "utf-8") logger.debug("Got message from GPS: %s" % result) if result.find("GGA") > 0: msg = pynmea2.parse(result) self.latitude = msg.latitude self.longitude = msg.longitude now = datetime.datetime.now() igrf = pyIGRF.igrf_value(self.latitude, self.longitude, msg.altitude, now.year) self.declination = igrf[0] logger.debug( "Position Update: latitude: %s, longitude: %s, declination: %s" % (self.latitude, self.longitude, self.declination)) self.has_position = True if stop_when_found: # Now we have a lock, just exit to free up resources self.is_updating = False logger.info( "Position found and stop_when_found set. Exiting _update_loop" ) except Exception as ex: logger.error(ex)
def xyz2hdz(x, y, z, Date, lat, lon, alt=0.0): ''' converts X,Y,Z coordinates to H,D,Z using the IGRF model to get the magnetic declination. ''' #get the year year = DateToYear(Date) #find unique year/lat/lon combinations n = np.size(x) dlla = np.zeros((4, n), dtype='float32') dlla[0] = year dlla[1] = lat dlla[2] = lon dlla[3] = alt udlla = np.unique(dlla, axis=1) #get the declination nu = np.size(udlla[0]) dec = np.zeros(n, dtype='float32') for i in range(0, nu): dc, _, _, _, _, _, _ = pyIGRF.igrf_value(udlla[1, i], udlla[2, i], udlla[3, i], udlla[0, i]) comp = (dlla.T == udlla.T[i]).all(axis=1) use = np.where(comp)[0] dec[use] = dc #rotate x and y dec = dec * np.pi / 180.0 h = x * np.cos(dec) + y * np.sin(dec) d = x * np.sin(dec) - y * np.cos(dec) return h, d, z
def igrf_mag_vector_ecef(x_ecef, t_jd): # convert ecef to latitude and longitude xq = u.quantity.Quantity(x_ecef[0], u.km) yq = u.quantity.Quantity(x_ecef[1], u.km) zq = u.quantity.Quantity(x_ecef[2], u.km) loc = EarthLocation(x=xq, y=yq, z=zq) longitude, latitude, altitude = loc.to_geodetic() lon = longitude.value # longitude in degrees lat = latitude.value # latitude in degrees alt = (altitude.value / 1000) - R_e # altitude in km # get decimal date delta = datetime.timedelta( days=t_jd) # convert julian date to delta in days d = datetime.datetime( 2000, 1, 1, 12, 0, 0) + delta # will depend on epoch -- currently using jd2000 decimal_date = (float(d.strftime("%j")) - 1) / 366 + float( d.strftime("%Y")) # get magnetic field in ecef frame r = pyIGRF.igrf_value(lat, lon, alt, decimal_date) # get magnetic field parameters vector = np.array([ r[3], r[4], r[5] ]) # save north, east, and vertical components of magnetic field in nT mag_vector_ecef = vector / np.linalg.norm(vector) # normalize return mag_vector_ecef
def Mag_Dipole(): lat = 0.0 ##right at the equator lon = 0.0 ##right at the prime meridian alt = 500.0 #I'm assuming this is in kilometers above the surface of the Earth date = 2021 ##I'm assuming this is the date in a int format and just the year result = IGRF.igrf_value(lat, lon, alt, date) return result
def get_B_field_at_point(r, year=2019): ''' Find the North-East-Down B-field (in nT) in ECEF coordinates ''' # parse position x = r[0] y = r[1] z = r[2] # Convert ECEF position to geodetic # 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, x, y, z, radians=False) lat, lon, alt = fc.ecef2lla(r) lat = lat * 180 / math.pi lon = lon * 180 / math.pi # Calculate magnetic field properties D, I, H, Bx, By, Bz, F = pyIGRF.igrf_value(lat, lon, alt, year) return Bx, By, Bz
def bfield_arr(lat, lon, alt, date): #This function takes latitude and longitude arrays in degrees #Altitude in units of km above ground level (AGL) and a date in a #int format like 2020 or 2021 if len(lat) != len(lon) or len(lon) != len(alt): print('Array length not correct') return 0, 0, 0, 0 bx_arr = 0 * lat by_arr = 0 * lat bz_arr = 0 * lat btotal_arr = 0 * lat for i in range(0, len(lat)): ##Make the call to the IGRF module (assuming date is a constant) result = IGRF.igrf_value(lat[i], lon[i], alt[i], date) ##Parse out the result (mag field strength is in nT) bx_arr[i] = result[3] by_arr[i] = result[4] bz_arr[i] = result[5] btotal_arr[i] = result[6] return bx_arr, by_arr, bz_arr, btotal_arr
def get_orbit_magnetic(TLE, epoch, sec_past_epoch, wgs=wgs84): ''' determine magnetic field properties from orbit state, in ECEF!!!! ''' r = get_orbit_pos(TLE, epoch, sec_past_epoch, wgs) # parse orbit state x = r[0] y = r[1] z = r[2] epoch = epoch.split('-') year = int(epoch[0]) # Convert ECEF position to geodetic # 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, x, y, z, radians=False) lat, lon, alt = fc.ecef2lla(r) # Calculate magnetic field properties lat = lat * 180 / math.pi lon = lon * 180 / math.pi D, I, H, Bx, By, Bz, F = pyIGRF.igrf_value(lat, lon, alt, year) return Bx, By, Bz
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
& (Fulldata2[' Time LO '] > mintime)] #below was for checking my column headers names #print(list(data2.columns.values)) time2 = data2[' Time LO '] Long = data2[' Longitude '] Lat = data2[' Latitude '] Alt = data2[' Altitude '] #convert ft to km Altkm = Alt * 0.0003048 EarthMagData = np.empty((len(time2), 8)) for i in range(len(time2)): A = pyIGRF.igrf_value(Lat.iloc[i], Long.iloc[i], Altkm.iloc[i], 2018) EarthMagData[i, 0] = time2.iloc[i] EarthMagData[i, 1] = A[0] EarthMagData[i, 2] = A[1] EarthMagData[i, 3] = A[2] EarthMagData[i, 4] = A[3] EarthMagData[i, 5] = A[4] EarthMagData[i, 6] = A[5] EarthMagData[i, 7] = A[6] #saving magnetic field data and time np.savetxt( 'EarthMagdata.csv', EarthMagData, delimiter=', ', header='Time,D(east),I(down), H,X (north),Y (east),Z (down),F(total)')
import pyIGRF if __name__ == '__main__': lat = 40 lon = 116 alt = 300 date = 1999 print(pyIGRF.igrf_value.__doc__) print(pyIGRF.igrf_variation.__doc__) print(pyIGRF.igrf_value(lat, lon, alt, date)) print(pyIGRF.igrf_variation(lat, lon, alt, date)) g, h = pyIGRF.loadCoeffs.get_coeffs(date) print(len(g)) print(len(h))
max_lon = 180 delta = 2 lat_range = np.arange(min_lat, max_lat, delta) lon_range = np.arange(min_lon, max_lon, delta) mag_field_strength_cpp = np.zeros((np.size(lat_range), np.size(lon_range))) mag_field_strength_igrf = np.zeros((np.size(lat_range), np.size(lon_range))) err = np.zeros((np.size(lat_range), np.size(lon_range))) for i, lat in enumerate(lat_range): for j, lon in enumerate(lon_range): B_vec = magnetic_field_cpp.get_magnetic_field(lat, lon, alt, year, 10) mag_field_strength_cpp[i, j] = np.linalg.norm(B_vec) D, I, H, Bx, By, Bz, F = pyIGRF.igrf_value(lat, lon, alt, year) mag_field_strength_igrf[i, j] = F err[i, j] = abs(mag_field_strength_cpp[i, j] - mag_field_strength_igrf[i, j]) X, Y = np.meshgrid(lon_range, lat_range) fig1, ax = plt.subplots() CS = ax.contour(X, Y, mag_field_strength_cpp, 30) CB = fig1.colorbar(CS, shrink=0.8, extend='both') ax.set_title('5th Order IGRF (Our Model)') # plt.show() fig2, ax2 = plt.subplots() CS = ax2.contour(X, Y, mag_field_strength_igrf, 30) CB = fig2.colorbar(CS, shrink=0.8, extend='both')
by_arr[i] = result[4] bz_arr[i] = result[5] btotal_arr[i] = result[6] return bx_arr, by_arr, bz_arr, btotal_arr if __name__ == '__main__': print('Running Example Script') lat = 0.0 ##right at the equator lon = 0.0 ##right at the prime meridian alt = 100.0 #I'm assuming this is in kilometers above the surface of the Earth date = 2021 ##I'm assuming this is the date in a int format and just the year ##Make the call to the IGRF module result = IGRF.igrf_value(lat, lon, alt, date) ##Parse out the result (mag field strength is in nT) bx = result[3] by = result[4] bz = result[5] btotal = result[6] print('B-field = ', bx, by, bz, btotal) ##Plot out B-field as a function of a specific orbit #Using custom Earth_Orbit module rp = 400.0 #km ra = 160000.0 #km orbit = orb.Earth_Orbit(ra, rp)
def Satellite(t, state): x = state[0] y = state[1] z = state[2] q0 = state[6] q1 = state[7] q2 = state[8] q3 = state[9] q0123 = np.array([q0,q1,q2,q3]) p = state[10] q = state[11] r = state[12] pqr = np.array([p,q,r]) # intertia and mass m = globals.m # kg I = globals.I #kg-m^2 invI = globals.invI # Translational Kinematics vel = np.array([state[3],state[4],state[5]]) # Rotational Kinematics PQRMAT = np.array([ [0, -p, -q, -r], [p, 0, r, -q], [q, -r, 0, p], [r, q, -p, 0] ]) q0123dot = 0.5*np.dot(PQRMAT, q0123) # Gravity model r_st = np.array([state[0],state[1],state[2]]) # r = [x,y,z] rho = np.linalg.norm(r_st) rhat = np.divide(r_st,rho) Fgrav = -(G*M*m/np.power(rho,2))*rhat # Magnetic field model (pyIGRF) phiE = 0 thetaE = np.arccos(z/rho) psiE = np.arctan2(y,x) latitude = 90-thetaE*180/np.pi longitude = psiE*180/np.pi igrf_output = pyIGRF.igrf_value(latitude, longitude, altitude, 2020) BN = igrf_output[3] BE = igrf_output[4] BD = igrf_output[5] BNED = np.array([BN,BE,BD]) # Transform to ECI frame BI = np.dot(TIB(phiE, thetaE+np.pi, psiE), BNED) BB = np.dot(TIBquat(q0123),BI) * 1e-9 globals.BB = BB # magnetorquer parameters n_aircore = 195 # turns n_rods = 440 # turns A_aircore = 0.006084 # m^2 A_rod = 0.0001423 # m^2 nA = np.array([n_rods*A_rod, n_rods*A_rod, n_aircore*A_aircore]) # Control Block current = Control(BB,pqr) muB = np.array([current[0]*nA[0], current[1]*nA[1], current[2]*nA[2]]) globals.current = current # Magnetorquer Model LMN_magtorquers = np.cross(muB,BB) #LMN_magtorquers = np.array([0,0,0]) # Translational Dynamics F = Fgrav accel = np.divide(F,m) # Rotational Dynamics H = np.dot(I,pqr) pqrdot = np.dot(invI,(LMN_magtorquers - np.cross(pqr,H))) # Return derivatives vector dstatedt = np.empty((13,)) dstatedt[0] = vel[0] dstatedt[1] = vel[1] dstatedt[2] = vel[2] dstatedt[3] = accel[0] dstatedt[4] = accel[1] dstatedt[5] = accel[2] dstatedt[6] = q0123dot[0] dstatedt[7] = q0123dot[1] dstatedt[8] = q0123dot[2] dstatedt[9] = q0123dot[3] dstatedt[10] = pqrdot[0] dstatedt[11] = pqrdot[1] dstatedt[12] = pqrdot[2] return dstatedt
def mag_vector_ecef(self): value = pyIGRF.igrf_value(self.latitude, self.longitude, self.altitude, self.decimal_date(datetime.datetime.now())) return np.array([value[3], value[4], value[5]])