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
class Pulsetiming(Component): logging_name = "isce.stdproc.pulsetiming" def __init__(self): super(Pulsetiming, self).__init__() self.frame = None self.orbit = Orbit(source='Pulsetiming') return None def createPorts(self): framePort = Port(name='frame',method=self.addFrame) self._inputPorts.add(framePort) return None def getOrbit(self): return self.orbit def addFrame(self): frame = self.inputPorts['frame'] if frame: if isinstance(frame, Frame): self.frame = frame else: self.logger.error( "Object must be of type Frame, not %s" % (frame.__class__) ) raise TypeError pass return None # @port(Frame) # def addFrame(self): # return None def pulsetiming(self): self.activateInputPorts() numberOfLines = self.frame.getNumberOfLines() prf = self.frame.getInstrument().getPulseRepetitionFrequency() pri = 1.0/prf startTime = self.frame.getSensingStart() thisOrbit = self.frame.getOrbit() self.orbit.setReferenceFrame(thisOrbit.getReferenceFrame()) for i in range(numberOfLines): dt = i*pri time = startTime + datetime.timedelta(seconds=dt) sv = thisOrbit.interpolateOrbit(time,method='hermite') self.orbit.addStateVector(sv)
class Orbit2sch(Component): parameter_list = (ORBIT_POSITION, ORBIT_VELOCITY, PLANET_GM, ELLIPSOID_MAJOR_SEMIAXIS, ELLIPSOID_ECCENTRICITY_SQUARED, COMPUTE_PEG_INFO_FLAG, PEG_LATITUDE, PEG_LONGITUDE, AVERAGE_HEIGHT, PEG_HEADING, SCH_GRAVITATIONAL_ACCELERATION, SCH_POSITION, SCH_VELOCITY) ## An imperative flag? REFACTOR. computePegInfoFlag = -1 #false by default planetGM = CN.EarthGM ellipsoidMajorSemiAxis = CN.EarthMajorSemiAxis ellipsoidEccentricitySquared = CN.EarthEccentricitySquared def __init__(self, averageHeight=None, planet=None, orbit=None, peg=None): super(Orbit2sch, self).__init__() self.averageHeight = averageHeight if planet is not None: self.wireInputPort(name='planet', object=planet) if orbit is not orbit: self.wireInputPort(name='orbit', object=orbit) if peg is not None: self.wireInputPort(name='peg', object=peg) self._time = None self._orbit = None self.dim1_orbitPosition = None self.dim2_orbitPosition = None self.dim1_orbitVelocity = None self.dim2_orbitVelocity = None self.dim1_position = None self.dim2_position = None self.dim1_velocity = None self.dim2_velocity = None self.dim1_acceleration = None self.dim2_acceleration = None self.logger = logging.getLogger('isce.orbit2sch') return def createPorts(self): # Create input ports orbitPort = Port(name='orbit', method=self.addOrbit) planetPort = Port(name='planet', method=self.addPlanet) pegPort = Port(name='peg', method=self.addPeg) # Add the ports self.inputPorts.add(orbitPort) self.inputPorts.add(planetPort) self.inputPorts.add(pegPort) return None def orbit2sch(self): for port in self.inputPorts: port() self.dim1_orbitPosition = len(self.orbitPosition) self.dim2_orbitPosition = len(self.orbitPosition[0]) self.dim1_orbitVelocity = len(self.orbitVelocity) self.dim2_orbitVelocity = len(self.orbitVelocity[0]) self.dim1_position = self.dim1_orbitPosition self.dim2_position = self.dim2_orbitPosition self.dim1_velocity = self.dim1_orbitVelocity self.dim2_velocity = self.dim2_orbitVelocity self.dim1_acceleration = self.dim1_orbitPosition self.dim2_acceleration = self.dim2_orbitPosition self.allocateArrays() self.setState() orbit2sch.orbit2sch_Py() self.getState() self.deallocateArrays() self._orbit = Orbit(source='SCH') # self._orbit.setOrbitSource('Orbit2SCH') self._orbit.setReferenceFrame('SCH') # for i in range(len(self.position)): sv = StateVector() sv.setTime(self._time[i]) sv.setPosition(self.position[i]) sv.setVelocity(self.velocity[i]) self._orbit.addStateVector(sv) return def setState(self): orbit2sch.setStdWriter_Py(int(self.stdWriter)) if self.computePegInfoFlag == -1: orbit2sch.setPegLatitude_Py(float(self.pegLatitude)) orbit2sch.setPegLongitude_Py(float(self.pegLongitude)) orbit2sch.setPegHeading_Py(float(self.pegHeading)) orbit2sch.setAverageHeight_Py(float(self.averageHeight)) orbit2sch.setOrbitPosition_Py(self.orbitPosition, self.dim1_orbitPosition, self.dim2_orbitPosition) orbit2sch.setOrbitVelocity_Py(self.orbitVelocity, self.dim1_orbitVelocity, self.dim2_orbitVelocity) orbit2sch.setPlanetGM_Py(float(self.planetGM)) orbit2sch.setEllipsoidMajorSemiAxis_Py( float(self.ellipsoidMajorSemiAxis)) orbit2sch.setEllipsoidEccentricitySquared_Py( float(self.ellipsoidEccentricitySquared)) orbit2sch.setComputePegInfoFlag_Py(int(self.computePegInfoFlag)) return None def setOrbitPosition(self, var): self.orbitPosition = var return def setOrbitVelocity(self, var): self.orbitVelocity = var return def setPlanetGM(self, var): self.planetGM = float(var) return def setEllipsoidMajorSemiAxis(self, var): self.ellipsoidMajorSemiAxis = float(var) return def setEllipsoidEccentricitySquared(self, var): self.ellipsoidEccentricitySquared = float(var) return def setComputePegInfoFlag(self, var): self.computePegInfoFlag = int(var) return def setPegLatitude(self, var): self.pegLatitude = float(var) return def setPegLongitude(self, var): self.pegLongitude = float(var) return def setPegHeading(self, var): self.pegHeading = float(var) return def setAverageHeight(self, var): self.averageHeight = float(var) return def getState(self): self.position = orbit2sch.getSchPosition_Py(self.dim1_position, self.dim2_position) self.velocity = orbit2sch.getSchVelocity_Py(self.dim1_velocity, self.dim2_velocity) self.acceleration = orbit2sch.getSchGravitationalAcceleration_Py( self.dim1_acceleration, self.dim2_acceleration) return # def getStdWriter(self): # return self.position def getSchVelocity(self): return self.velocity def getSchGravitationalAcceleration(self): return self.acceleration def getOrbit(self): return self._orbit def allocateArrays(self): if self.dim1_orbitPosition is None: self.dim1_orbitPosition = len(self.orbitPosition) self.dim2_orbitPosition = len(self.orbitPosition[0]) if (not self.dim1_orbitPosition) or (not self.dim2_orbitPosition): raise ValueError("Error. Trying to allocate zero size array") orbit2sch.allocate_xyz_Py(self.dim1_orbitPosition, self.dim2_orbitPosition) if self.dim1_orbitVelocity is None: self.dim1_orbitVelocity = len(self.orbitVelocity) self.dim2_orbitVelocity = len(self.orbitVelocity[0]) if (not self.dim1_orbitVelocity) or (not self.dim2_orbitVelocity): raise ValueError("Error. Trying to allocate zero size array") orbit2sch.allocate_vxyz_Py(self.dim1_orbitVelocity, self.dim2_orbitVelocity) if self.dim1_position is None: self.dim1_position = len(self.position) self.dim2_position = len(self.position[0]) if (not self.dim1_position) or (not self.dim2_position): ("Error. Trying to allocate zero size array") raise Exception orbit2sch.allocate_sch_Py(self.dim1_position, self.dim2_position) if self.dim1_velocity is None: self.dim1_velocity = len(self.velocity) self.dim2_velocity = len(self.velocity[0]) if (not self.dim1_velocity) or (not self.dim2_velocity): print("Error. Trying to allocate zero size array") raise Exception orbit2sch.allocate_vsch_Py(self.dim1_velocity, self.dim2_velocity) if self.dim1_acceleration is None: self.dim1_acceleration = len(self.acceleration) self.dim2_acceleration = len(self.acceleration[0]) if (not self.dim1_acceleration) or (not self.dim2_acceleration): print("Error. Trying to allocate zero size array") raise Exception orbit2sch.allocate_asch_Py(self.dim1_acceleration, self.dim2_acceleration) return def deallocateArrays(self): orbit2sch.deallocate_xyz_Py() orbit2sch.deallocate_vxyz_Py() orbit2sch.deallocate_sch_Py() orbit2sch.deallocate_vsch_Py() orbit2sch.deallocate_asch_Py() return @property def orbit(self): return self._orbit @orbit.setter def orbit(self, orbit): self.orbit = orbit return None @property def time(self): return self._time @time.setter def time(self, time): self.time = time return None def addOrbit(self): orbit = self.inputPorts['orbit'] if orbit: try: time, self.orbitPosition, self.orbitVelocity, offset = orbit.to_tuple( ) self._time = [] for t in time: self._time.append(offset + datetime.timedelta(seconds=t)) except AttributeError: self.logger.error( "orbit port should look like an orbit, not: %s" % (orbit.__class__)) raise AttributeError pass return None def addPlanet(self): planet = self._inputPorts.getPort('planet').getObject() if (planet): try: self.planetGM = planet.get_GM() self.ellipsoidMajorSemiAxis = planet.get_elp().get_a() self.ellipsoidEccentricitySquared = planet.get_elp().get_e2() except AttributeError: self.logger.error( "Object %s requires get_GM(), get_elp().get_a() and get_elp().get_e2() methods" % (planet.__class__)) raise AttributeError def addPeg(self): peg = self._inputPorts.getPort('peg').getObject() if (peg): try: self.pegLatitude = math.radians(peg.getLatitude()) self.pegLongitude = math.radians(peg.getLongitude()) self.pegHeading = math.radians(peg.getHeading()) self.logger.debug("Peg Object: %s" % (str(peg))) except AttributeError: self.logger.error( "Object %s requires getLatitude(), getLongitude() and getHeading() methods" % (peg.__class__)) raise AttributeError pass pass pass
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
class Sch2orbit(Component): planetGM = CN.EarthGM ellipsoidMajorSemiAxis = CN.EarthMajorSemiAxis ellipsoidEccentricitySquared = CN.EarthEccentricitySquared def __init__(self, averageHeight=None, planet=None, orbit=None, peg=None): super(Sch2orbit, self).__init__() self.averageHeight = averageHeight if planet is not None: self.wireInputPort(name='planet', object=planet) if orbit is not orbit: self.wireInputPort(name='orbit', object=orbit) if peg is not None: self.wireInputPort(name='peg', object=peg) self._numVectors = None self._time = None self._orbit = None self.position = [] self.velocity = [] self.acceleration = [] self.logger = logging.getLogger('isce.sch2orbit') self.dictionaryOfOutputVariables = { 'XYZ_POSITION': 'self.position', 'XYZ_VELOCITY': 'self.velocity', 'XYZ_GRAVITATIONAL_ACCELERATION': 'self.acceleration' } return def createPorts(self): # Create input ports orbitPort = Port(name='orbit', method=self.addOrbit) planetPort = Port(name='planet', method=self.addPlanet) pegPort = Port(name='peg', method=self.addPeg) # Add the ports self.inputPorts.add(orbitPort) self.inputPorts.add(planetPort) self.inputPorts.add(pegPort) return None def sch2orbit(self): for port in self.inputPorts: port() lens = [len(self.orbitPosition), len(self.orbitVelocity)] if min(lens) != max(lens): raise Exception('Position and Velocity vector lengths dont match') self._numVectors = lens[0] self.allocateArrays() self.setState() sch2orbit.sch2orbit_Py() self.getState() self.deallocateArrays() self._orbit = Orbit(source='XYZ') self._orbit.setReferenceFrame('XYZ') # for i in range(len(self.position)): sv = StateVector() sv.setTime(self._time[i]) sv.setPosition(self.position[i]) sv.setVelocity(self.velocity[i]) self._orbit.addStateVector(sv) return def setState(self): sch2orbit.setStdWriter_Py(int(self.stdWriter)) sch2orbit.setPegLatitude_Py(float(self.pegLatitude)) sch2orbit.setPegLongitude_Py(float(self.pegLongitude)) sch2orbit.setPegHeading_Py(float(self.pegHeading)) sch2orbit.setRadiusOfCurvature_Py(float(self.radiusOfCurvature)) sch2orbit.setOrbitPosition_Py(self.orbitPosition, self._numVectors) sch2orbit.setOrbitVelocity_Py(self.orbitVelocity, self._numVectors) sch2orbit.setPlanetGM_Py(float(self.planetGM)) sch2orbit.setEllipsoidMajorSemiAxis_Py( float(self.ellipsoidMajorSemiAxis)) sch2orbit.setEllipsoidEccentricitySquared_Py( float(self.ellipsoidEccentricitySquared)) return None def setOrbitPosition(self, var): self.orbitPosition = var return def setOrbitVelocity(self, var): self.orbitVelocity = var return def setPlanetGM(self, var): self.planetGM = float(var) return def setEllipsoidMajorSemiAxis(self, var): self.ellipsoidMajorSemiAxis = float(var) return def setEllipsoidEccentricitySquared(self, var): self.ellipsoidEccentricitySquared = float(var) return def setPegLatitude(self, var): self.pegLatitude = float(var) return def setPegLongitude(self, var): self.pegLongitude = float(var) return def setPegHeading(self, var): self.pegHeading = float(var) return def setRadiusOfCurvature(self, var): self.radiusOfCurvature = float(var) return def getState(self): self.position = sch2orbit.getXYZPosition_Py(self._numVectors) self.velocity = sch2orbit.getXYZVelocity_Py(self._numVectors) self.acceleration = sch2orbit.getXYZGravitationalAcceleration_Py( self._numVectors) return def getXYZVelocity(self): return self.velocity def getXYZGravitationalAcceleration(self): return self.acceleration def getOrbit(self): return self._orbit def allocateArrays(self): if (not self._numVectors): raise ValueError("Error. Trying to allocate zero size array") sch2orbit.allocateArrays_Py(self._numVectors) return def deallocateArrays(self): sch2orbit.deallocateArrays_Py() return @property def orbit(self): return self._orbit @orbit.setter def orbit(self, orbit): self.orbit = orbit return None @property def time(self): return self._time @time.setter def time(self): self.time = time return None def addOrbit(self): orbit = self.inputPorts['orbit'] if orbit: try: time, self.orbitPosition, self.orbitVelocity, offset = orbit.to_tuple( ) self._time = [] for t in time: self._time.append(offset + datetime.timedelta(seconds=t)) except AttributeError: self.logger.error( "orbit port should look like an orbit, not: %s" % (orbit.__class__)) raise AttributeError pass return None def addPlanet(self): planet = self._inputPorts.getPort('planet').getObject() if (planet): try: self.planetGM = planet.get_GM() self.ellipsoidMajorSemiAxis = planet.get_elp().get_a() self.ellipsoidEccentricitySquared = planet.get_elp().get_e2() except AttributeError: self.logger.error( "Object %s requires get_GM(), get_elp().get_a() and get_elp().get_e2() methods" % (planet.__class__)) raise AttributeError def addPeg(self): peg = self._inputPorts.getPort('peg').getObject() if (peg): try: self.pegLatitude = math.radians(peg.getLatitude()) self.pegLongitude = math.radians(peg.getLongitude()) self.pegHeading = math.radians(peg.getHeading()) self.logger.debug("Peg Object: %s" % (str(peg))) except AttributeError: self.logger.error( "Object %s requires getLatitude(), getLongitude() and getHeading() methods" % (peg.__class__)) raise AttributeError pass pass pass