def readOrbit(self, platformPositionRecord): ''' reformat orbit from platformPositionRecord ''' orb=Orbit() orb.setOrbitSource('leaderfile') orb.setOrbitQuality(self.orbitElementsDesignator[platformPositionRecord.metadata['Orbital elements designator']]) t0 = datetime.datetime(year=platformPositionRecord.metadata['Year of data point'], month=platformPositionRecord.metadata['Month of data point'], day=platformPositionRecord.metadata['Day of data point']) t0 = t0 + datetime.timedelta(seconds=platformPositionRecord.metadata['Seconds of day']) #####Read in orbit in inertial coordinates deltaT = platformPositionRecord.metadata['Time interval between data points'] numPts = platformPositionRecord.metadata['Number of data points'] for i in range(numPts): vec = StateVector() t = t0 + datetime.timedelta(seconds=i*deltaT) vec.setTime(t) dataPoints = platformPositionRecord.metadata['Positional Data Points'][i] pos = [dataPoints['Position vector X'], dataPoints['Position vector Y'], dataPoints['Position vector Z']] vel = [dataPoints['Velocity vector X'], dataPoints['Velocity vector Y'], dataPoints['Velocity vector Z']] vec.setPosition(pos) vec.setVelocity(vel) orb.addStateVector(vec) return orb
def extractOrbitFromAnnotation(self): ''' Extract orbit information from xml node. ''' node = self._xml_root.find('generalAnnotation/orbitList') frameOrbit = Orbit() frameOrbit.setOrbitSource('Header') for child in node: timestamp = self.convertToDateTime(child.find('time').text) pos = [] vel = [] posnode = child.find('position') velnode = child.find('velocity') for tag in ['x', 'y', 'z']: pos.append(float(posnode.find(tag).text)) for tag in ['x', 'y', 'z']: vel.append(float(velnode.find(tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) frameOrbit.addStateVector(vec) planet = self.frame.instrument.platform.planet orbExt = OrbitExtender(planet=planet) orbExt.configure() newOrb = orbExt.extendOrbit(frameOrbit) return newOrb
class DOR(BaseEnvisatFile): """A class for parsing Envisat DORIS orbit files""" def __init__(self,fileName=None): BaseEnvisatFile.__init__(self) self.fileName = fileName self.fp = None self.orbit = Orbit() self.orbit.setOrbitSource('DORIS') self.orbit.setReferenceFrame('ECR') def parse(self): orbitDict = {} try: self.fp = open(self.fileName, 'rb') except IOError as errs: errno,strerr = errs print("IOError: %s" % strerr) return self.readMPH() self.readSPH() self.readStateVectors() self.fp.close() if (self.sph['dataSets'][0]['DS_NAME'] == 'DORIS PRELIMINARY ORBIT'): self.orbit.setOrbitQuality('Preliminary') elif (self.sph['dataSets'][0]['DS_NAME'] == 'DORIS PRECISE ORBIT'): self.orbit.setOrbitQuality('Precise') orbitDict.update(self.mph) orbitDict.update(self.sph) return orbitDict def readStateVectors(self): headerLength = self.mphLength + self.sphLength self.fp.seek(headerLength) for line in self.fp.readlines(): vals = line.decode('utf8').split() dateTime = self._parseDateTime(vals[0] + ' ' + vals[1]) position = list(map(float,vals[4:7])) velocity = list(map(float,vals[7:10])) sv = StateVector() sv.setTime(dateTime) sv.setPosition(position) sv.setVelocity(velocity) self.orbit.addStateVector(sv) def _parseDateTime(self,dtString): dateTime = datetime.datetime.strptime(dtString,'%d-%b-%Y %H:%M:%S.%f') return dateTime
def trimOrbit(self, startTime, stopTime): """Trim the list of state vectors to encompass the time span [startTime:stopTime]""" newOrbit = Orbit() newOrbit.setOrbitSource('ODR') newOrbit.setReferenceFrame('ECR') for sv in self._ephemeris: if ((sv.getTime() > startTime) and (sv.getTime() < stopTime)): newOrbit.addStateVector(sv) return newOrbit
def convert(self): ''' Convert ECI orbit to ECEF orbit. ''' ECROrbit = Orbit() ECROrbit.configure() for sv in self.orbit: svtime = sv.getTime() position = sv.getPosition() velocity = sv.getVelocity() ####Compute GMST from GAST - Eq 5.13 dtiff = (svtime - self.referenceEpoch).total_seconds() theta = self.referenceGAST + self.Omega * dtiff costh = np.cos(theta) sinth = np.sin(theta) ###Position transformation A = np.zeros((3, 3)) A[0, 0] = costh A[0, 1] = sinth A[1, 0] = -sinth A[1, 1] = costh A[2, 2] = 1 ###Velocity transformation Adot = np.zeros((3, 3)) Adot[0, 0] = -self.Omega * sinth Adot[0, 1] = self.Omega * costh Adot[1, 0] = -self.Omega * costh Adot[1, 1] = -self.Omega * sinth ###Compute ECR state vector newPos = np.dot(A, position) newVel = np.dot(Adot, position) + np.dot(A, velocity) ####Create state vector object newsv = StateVector() newsv.setTime(svtime) newsv.setPosition(newPos.tolist()) newsv.setVelocity(newVel.tolist()) ###Append to orbit ECROrbit.addStateVector(newsv) ECROrbit.setOrbitSource('Sidereal angle conversion') ECROrbit.setOrbitQuality(self.orbit.getOrbitQuality()) return ECROrbit
def convert(self): '''Convert ECI orbit to ECEF orbit.''' date = self.orbit._stateVectors[0].getTime().date() bspName = 'inertial_orbit_' + date.strftime('%Y%m%d') + '.bsp' ####Convert ISCE orbit to SPICE orbit file sorb = ISCEOrbit(self.orbit) sorb.exportToSPK(bspName, frame=self.eci) ####Convert coordinates with corrections spk = SpiceOrbit(bspName) spk.initSpice() wgsOrbit = Orbit() wgsOrbit.setOrbitSource(self.orbit.getOrbitSource()) wgsOrbit.setOrbitQuality(self.orbit.getOrbitQuality()) for sv in self.orbit: tim = sv.getTime() spksv = spk.interpolateOrbit(tim, frame=self.ecef) wgsOrbit.addStateVector(spksv) return wgsOrbit
class ODR(object): """A class to parse Orbital Data Records (ODR) generated by Delft""" logging_name = 'isceobj.Orbit.ODR' @logged def __init__(self, file=None): self._file = file self._format = None self._satellite = None self._arcNumber = None self._cycleLength = None self._numberOfRecords = None self._version = None self._ephemeris = Orbit() self._ephemeris.setOrbitSource('ODR') self._ephemeris.setReferenceFrame('ECR') self.grs80 = Ellipsoid.Ellipsoid( *AstronomicalHandbook.PlanetsData.ellipsoid['Earth']['GRS-80']) return None #jng added the start and stop time. The computation of the velocities seems pretty time comsuming, so limit the orbit data extraction only to startTime nad stopTime def parseHeader(self, startTime=None, stopTime=None): fp = None try: fp = open(self._file, 'rb') except IOError as strerr: self.logger.error(strerr) buffer = fp.read(16) # Header 1 (format, satellite, dataStartTimeSeconds) = struct.unpack('>4s8si', buffer) buffer = fp.read(16) # Header 2 (cycleLength, number, numberOfRecords, version) = struct.unpack('>4i', buffer) self._format = format.decode('utf-8') self._satellite = satellite.decode('utf-8') self._arcNumber = number self._cycleLength = cycleLength * 1e3 # In cycle length in days self._numberOfRecords = numberOfRecords self._version = version positions = [] for i in range(numberOfRecords): buffer = fp.read(16) if not startTime == None: position = self.parseDataRecords(buffer) if position['time'] < startTime: continue if not stopTime == None: position = self.parseDataRecords(buffer) if position['time'] > stopTime: continue positions.append(self.parseDataRecords(buffer)) self.createStateVectors(positions) fp.close() def parseDataRecords(self, buffer): """Parse the individual data records for this ODR file""" (timeSeconds, latitude, longitude, height) = struct.unpack('>4i', buffer) time = self._utcSecondsToDatetime(timeSeconds) if (self._format == '@ODR'): latitude = latitude * 1e-6 longitude = longitude * 1e-6 elif (self._format == 'xODR'): latitude = latitude * 1e-7 longitude = longitude * 1e-7 height = height * 1e-3 xyz = self._convertToXYZ(latitude, longitude, height) return ({'time': time, 'x': xyz[0], 'y': xyz[1], 'z': xyz[2]}) def createStateVectors(self, positions): """Calculate the satellite velocity from the position data and create StateVector objects""" for i in range(len(positions)): t0 = positions[i]['time'] x0 = positions[i]['x'] y0 = positions[i]['y'] z0 = positions[i]['z'] sv = StateVector() sv.setTime(t0) sv.setPosition([x0, y0, z0]) sv.setVelocity([0.0, 0.0, 0.0]) self._ephemeris.addStateVector(sv) self._calculateVelocities() def _calculateVelocities(self): for sv in self._ephemeris: t0 = sv.getTime() t1 = t0 + datetime.timedelta(seconds=-0.5) t2 = t0 + datetime.timedelta(seconds=0.5) try: sv1 = self._ephemeris.interpolateOrbit(t1, method='legendre') sv2 = self._ephemeris.interpolateOrbit(t2, method='legendre') except ValueError: continue if (not sv1) or (not sv2): continue v1 = sv1.getPosition() v2 = sv2.getPosition() vx = (v2[0] - v1[0]) vy = (v2[1] - v1[1]) vz = (v2[2] - v1[2]) sv.setVelocity([vx, vy, vz]) def trimOrbit(self, startTime, stopTime): """Trim the list of state vectors to encompass the time span [startTime:stopTime]""" newOrbit = Orbit() newOrbit.setOrbitSource('ODR') newOrbit.setReferenceFrame('ECR') for sv in self._ephemeris: if ((sv.getTime() > startTime) and (sv.getTime() < stopTime)): newOrbit.addStateVector(sv) return newOrbit def getEphemeris(self): return self._ephemeris def _convertToXYZ(self, latitude, longitude, height): # The latitude, longitude and height are referenced to the center of mass of the satellite above the GRS80 ellipsoid xyz = self.grs80.llh_to_xyz([latitude, longitude, height]) return xyz def _utcSecondsToDatetime(self, seconds): """All of the ODR records are in UTC seconds from 1 Jan. 1985""" dataTime = datetime.datetime(year=1985, month=1, day=1) dataTime = dataTime + datetime.timedelta(seconds=seconds) return dataTime
def extractResOrbit(self): #read ESA's POD Restituted Orbit by Cunren Liang, APR. 2, 2015. import pathlib useResOrbFlag = 0 ResOrbDir = os.environ.get('RESORB') if ResOrbDir != None: print("Trying to find POD Restituted Orbit...") #get start time and stop time of the SLC data from data xml file dataStartTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productFirstLineUtcTime') ) dataStopTime = self.convertToDateTime( self.grab_from_xml( 'imageAnnotation/imageInformation/productLastLineUtcTime')) #RESORB has an orbit every 10 sec, extend the start and stop time by 50 sec. dataStartTimeExt = dataStartTime - datetime.timedelta(0, 50) dataStopTimeExt = dataStopTime + datetime.timedelta(0, 50) ########################### #deal with orbit directory ########################### orbList = pathlib.Path(ResOrbDir).glob('**/*.EOF') for orb in orbList: #save full path orb = str(orb) orbx = orb #get orbit file name orb = os.path.basename(os.path.normpath(orb)) #print("{0}".format(orb)) #get start and stop time of the orbit file orbStartTime = datetime.datetime.strptime( orb[42:57], "%Y%m%dT%H%M%S") orbStopTime = datetime.datetime.strptime( orb[58:73], "%Y%m%dT%H%M%S") #print("{0}, {1}".format(orbStartTime, orbStopTime)) if dataStartTimeExt >= orbStartTime and dataStopTimeExt <= orbStopTime: try: orbfp = open(orbx, 'r') except IOError as strerr: print("IOError: %s" % strerr) return useResOrbFlag orbxml = ElementTree(file=orbfp).getroot() print('using orbit file: {0}'.format(orbx)) frameOrbit = Orbit() frameOrbit.setOrbitSource('Restituted') #find the orbit data from the file, and use them node = orbxml.find('Data_Block/List_of_OSVs' ) #note upper case and lower case for child in node.getchildren(): timestamp = self.convertToDateTime( child.find('UTC').text[4:]) if timestamp < dataStartTimeExt: continue if timestamp > dataStopTimeExt: break pos = [] vel = [] for tag in ['X', 'Y', 'Z']: pos.append(float(child.find(tag).text)) vel.append(float(child.find('V' + tag).text)) vec = StateVector() vec.setTime(timestamp) vec.setPosition(pos) vec.setVelocity(vel) frameOrbit.addStateVector(vec) #there is no need to extend the orbit any longer #planet = self.frame.instrument.platform.planet #orbExt = OrbitExtender(planet=planet) #orbExt.configure() #newOrb = orbExt.extendOrbit(frameOrbit) self.frame.getOrbit().setOrbitSource('Restituted') for sv in frameOrbit: self.frame.getOrbit().addStateVector(sv) orbfp.close() useResOrbFlag = 1 break return useResOrbFlag
class PDS(object): def __init__(self, file=None): self.filename = file self.firstEpoch = 0 self.lastEpoch = 0 self.orbit = Orbit() self.orbit.configure() self.orbit.setOrbitSource('PDS') def getOrbit(self): return self.orbit def parse(self): fp = open(self.filename, 'r') for line in fp.readlines(): if (line[0].isdigit()): self.__parseStateVectorLine(line) else: self.__parseRecordLine(line) fp.close() def __parseRecordLine(self, line): line = line.strip() if (line.startswith('START_TIME')): values = line.split('=') values[1] = values[1].strip('"') dateTime = values[1].split() self.firstEpoch = self.__parseDateTimeString( dateTime[0], dateTime[1]) elif (line.startswith('STOP_TIME')): values = line.split('=') values[1] = values[1].strip('"') dateTime = values[1].split() self.lastEpoch = self.__parseDateTimeString( dateTime[0], dateTime[1]) elif (line.startswith('LEAP_UTC')): pass elif (line.startswith('LEAP_SIGN')): pass elif (line.startswith('RECORD_SIZE')): pass elif (line.startswith('NUM_REC')): pass def __parseStateVectorLine(self, line): date = line[0:11] time = line[12:27] x = float(line[44:56]) y = float(line[57:69]) z = float(line[70:82]) vx = float(line[83:95]) vy = float(line[96:108]) vz = float(line[109:121]) dt = self.__parseDateTimeString(date, time) sv = StateVector() sv.configure() sv.setTime(dt) sv.setPosition([x, y, z]) sv.setVelocity([vx, vy, vz]) self.orbit.addStateVector(sv) def __parseDateTimeString(self, date, time): """ Fix idiosyncrasies in the date and time strings """ time = time.replace( '-', '0' ) # For some reason, there are occasionally - signs where there should be zeros dt = datetime.datetime.strptime(date + ' ' + time, '%d-%b-%Y %H:%M:%S.%f') return dt
class PRC(object): """A class to parse orbit data from D-PAF""" logging_name = "isce.orbit.PRC.PRC" @logged def __init__(self, file=None): self.filename = file self.firstEpoch = 0 self.lastEpoch = 0 self.tdtOffset = 0 self.orbit = Orbit() self.orbit.configure() self.orbit.setOrbitQuality('Precise') self.orbit.setOrbitSource('PRC') return None def getOrbit(self): return self.orbit def parse(self): #People still seem to be using the old .Z format #Adding support for it - PSA if os.path.splitext(self.filename)[1] == '.Z': from subprocess import Popen, PIPE fp = Popen(["zcat", self.filename], stdout=PIPE).stdout else: fp = open(self.filename, 'r') data = fp.read() fp.close() numLines = int(len(data) / 130) for i in range(numLines): line = data[i * 130:(i + 1) * 130] self.__parseLine(line) def __parseLine(self, line): """Parse a line from a PRC orbit file""" referenceFrame = line[0:6].decode('utf-8') if (referenceFrame == 'STATE '): self.__parseStateLine(line) if (referenceFrame == 'STTERR'): self.__parseTerrestrialLine(line) def __parseTerrestrialLine(self, line): j2000Day = float(line[14:20]) / 10.0 + 0.5 tdt = float(line[20:31]) / 1e6 x = float(line[31:43]) / 1e3 y = float(line[43:55]) / 1e3 z = float(line[55:67]) / 1e3 vx = float(line[67:78]) / 1e6 vy = float(line[78:89]) / 1e6 vz = float(line[89:100]) / 1e6 quality = line[127] tdt = tdt - self.tdtOffset dt = self.__j2000ToDatetime(j2000Day, tdt) sv = StateVector() sv.configure() sv.setTime(dt) sv.setPosition([x, y, z]) sv.setVelocity([vx, vy, vz]) self.orbit.addStateVector(sv) def __parseStateLine(self, line): self.firstEpoch = self.__j2000ToDatetime(float(line[6:12]) / 10.0, 0.0) self.lastEpoch = self.__j2000ToDatetime(float(line[12:18]) / 10.0, 0.0) self.tdtOffset = float(line[47:52]) self.tdtOffset = self.tdtOffset / 1e3 def __j2000ToDatetime(self, j2000Day, tdt): """Convert the number of days since 1 Jan. 2000 to a datetime object""" j2000 = datetime.datetime(year=2000, month=1, day=1) dt = j2000 + datetime.timedelta(days=j2000Day, seconds=tdt) return dt pass