Coverage for ion/agents/instrumentagents/simulators/sim_NMEA0183 : 55.41%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
|
#!/usr/bin/env python @file ion/agents/instrumentagents/simulators/sim_NMEA0183.py @brief Base class for GPS simulators that output NMEA0183 GPS to a local virtual serial port. @author Alon Yaari """
# Open a null stream to pipe unwanted console messages to nowhere
""" Converts standard decimal degrees into NMEA's weird degree representation """
# d = degrees(right side of decimal point is fraction of degree) # m = minutes(right side of decimal point is fraction of minute) # Input: ddd.ddddddddd (ex: 34.12341015) # Output: dddmm.mmmmmmm (ex: 3407.404609)
""" Converts a python datetime into DDMMYY """ return '000000'
""" Converts a python datetime into HHMMSS. """ return '000000'
return '999.9', 'X' # TODO: Properly Calculate the magnetic variation
return '00' # Calculate checksum # checksum = 8-bit XOR of all chars in string # checksum is an 8-bit number(0 to 255) # result is a hex byte version of the checksum calcHigh += 7
""" Assemble an outgoing GPGGA sentence from stored configuration values. """ # 0 Sentence header str = ['PGRMC']
# 1 Fix Mode if NMEA0183SimBase.cfg_FIXMODE[0]: str.append(NMEA0183SimBase.cfg_FIXMODE[0]) else: str.append('')
# 2 Alt above/below MSL if NMEA0183SimBase.cfg_ALT: fVal = float(NMEA0183SimBase.cfg_ALT) else: fVal = float(0.0) str.append('%.1f' % fVal)
# 3 Earth Datum Index if NMEA0183SimBase.cfg_DATUMINDEX: iVal = int(NMEA0183SimBase.cfg_DATUMINDEX) else: iVal = int(0) str.append('%d' % iVal)
# 4 User earth datum str.append('0')
# 5 User earth datum inverse flattening factor str.append('0')
# 6 User earth datum delta X str.append('0')
# 7 User earth datum delta Y str.append('0')
# 8 User earth datum delta Z str.append('0')
# 9 Differential mode if NMEA0183SimBase.cfg_DIFFMODE[0]: str.append(NMEA0183SimBase.cfg_DIFFMODE[0]) else: str.append('')
# 10 NMEA 0183 Baud rate if NMEA0183SimBase.cfg_BAUD: iVal = int(NMEA0183SimBase.cfg_BAUD) else: iVal = int(0) str.append('%d' % iVal)
# 11 Velocity Filter if NMEA0183SimBase.cfg_VELFILTER: iVal = int(NMEA0183SimBase.cfg_VELFILTER) else: iVal = int(0) str.append('%d' % iVal)
# 12 Measurement Pulse Output if NMEA0183SimBase.cfg_MPO: iVal = int(NMEA0183SimBase.cfg_MPO) else: iVal = int(0) log.debug('iVal type: %s' % type(iVal)) str.append('%d' % iVal)
# 13 Measurement Pulse Output Length if NMEA0183SimBase.cfg_MPOLEN: iVal = int(NMEA0183SimBase.cfg_MPOLEN) else: iVal = int(0) str.append('%d' % iVal)
coreStr = ','.join(str) cs = CalcChecksum(coreStr)
# 14 Dead reckoning valid time if NMEA0183SimBase.cfg_DEDRECKON: fVal = float(NMEA0183SimBase.cfg_DEDRECKON) else: fVal = float(0.0) str.append('%.1f' % fVal)
coreStr = ','.join(str) return '$' + coreStr + '*' + cs + '\r\n'
""" Assemble an outgoing GPGGA sentence from the given dict info. """
# 0 Sentence header
# 1 UTC time of position fix in format hhmmss except: errFlag = True dt = datetime.min
# 2 Latitude as dd.mmmmmm except: errFlag = True lat = 0.0
# 3 Latitude hemisphere(pos lat = N, neg lat = S)
# 4 Longitude as ddd.mmmmmm except: errFlag = True lon = 0.0
# 5 Longitude hemisphere(pos lat = E, neg lat = W)
# 6 GPS quality info(0=nofix, 1=nondiff, 2=diff, 6=est) str.append('0') else:
# 7 Number of satellites(00 to 12, incl. leading zero) str.append('00') else:
# 8 HDOP(0.5 to 99.9) str.append('99.9') else: ((3.9 + dt.minute % 5.0) +((dt.second % 17.0) / 100.0)))
# 9 Altitude above MSL(-9999.9 to 99999.9)
# 10 Altitude units(always 'M')
# 11 Altitude above geoid(-999.9 to 9999.9)
# 12 Altitude units(always 'M')
# 13 Not used
# 14 Not used
""" Assemble an outgoing GPRMC sentence from the given dict info. """
# 0 Sentence header
# 1 UTC time of position fix in format hhmmss except: errFlag = True dt = datetime.min
# 2 Status(A = valid position, V = NAV receiver warning
# 3 Latitude as dd.mmmmmm except: errFlag = True lat = 0.0
# 4 Latitude hemisphere(pos lat = N, neg lat = S)
# 5 Longitude as ddd.mmmmmm except: errFlag = True lon = 0.0
# 6 Longitude hemisphere(pos lat = E, neg lat = W)
# 7 Speed Over Ground(000.0 to 999.9 knots with leading zeros) except: sogStr = '999.9'
# 8 Course Over Ground(000.0 to 359.9 degrees with leading zeros) except: cogStr = '999.9'
# 9 UTC date of position fix, ddmmyy except: errFlag = True dt = datetime.min
# 10 Magnetic variation(000.0 to 180.0 degrees with leading zeros) # 11 Magnetic variation direction(E or W west adds to true course) str.append('999.9') str.append('X') else:
# 12 Mode indicator(A=Autonomous, D=Differental, E=Estimated, N=invalid)
""" Assemble an outgoing OOIXX sentence from the given dict info. """
errFlag = False
# 0 Sentence header str = ['OOIXX']
# 1 UTC time of position fix in format hhmmss try: dt = n['time'] except: errFlag = True dt = datetime.min str.append(DateTimeToHHMMSS(dt))
# 2 Latitude as dd.mmmmmm try: lat = n['lat'] except: errFlag = True lat = 0.0 str.append(DecDegToNMEAStr(abs(lat)))
# 3 Latitude hemisphere(pos lat = N, neg lat = S) str.append('S' if lat < 0 else 'N')
# 4 Longitude as ddd.mmmmmm try: lon = n['lon'] except: errFlag = True lon = 0.0 str.append(DecDegToNMEAStr(abs(lon)))
# 5 Longitude hemisphere(pos lat = E, neg lat = W) str.append('W' if lon < 0 else 'E')
# 6 GPS quality info(0=nofix, 1=nondiff, 2=diff, 6=est) if errFlag: str.append('0') else: str.append('2')
# 7 Number of satellites(00 to 12, incl. leading zero) if errFlag: str.append('00') else: str.append('%02u' %(5 + dt.minute % 4))
# 8 HDOP(0.5 to 99.9) if errFlag: str.append('99.9') else: str.append('%.1f' % ((3.9 + dt.minute % 5.0) +((dt.second % 17.0) / 100.0)))
# 9 Altitude above MSL(-9999.9 to 99999.9) altMSL = 3.2 +(dt.second % 30.0) / 100.0 str.append('%.1f' % altMSL)
# 10 Altitude units(always 'M') str.append('M' if altMSL else '')
# 11 Course over ground COG (HEADING) in degrees from true north (0.0 to 359.9) str.append(n['cog'])
# 12 Speed over ground SOG (SPEEDMS) in meters per second (0.0 to 999.9) str.append(n['sog'])
# 13 Not used str.append('')
# 14 Not used str.append('')
coreStr = ','.join(str) cs = CalcChecksum(coreStr)
return '$' + coreStr + '*' + cs + '\r\n'
""" Parent class for NMEA0183 GPS simulators """
# Simulator connects to SERPORTMASTER # driver_ NMEA0183 connects to SERPORTSLAVE
# PGRMC CONFIGURATION SETTINGS
# <1> FIX MODE # A = automatic # 2 = 2D(host must supply alt) # 3 = 3D exclusively
# <2> ALT MEAN SEA LEVEL # -1500.0 to 18000.0 meters
# <3> EARTH DATUM INDEX # 0 to 109(IDs of valid earth datum indices) # 96 IS NOT ALLOWED, it is user specified and not supported here # 100 is WGS84 # NOTE Setting to any value except 96 will work but GPS # output will always be in WGS84
# <4> USER EARTH DATUM SEMI-MAJOR AXIS # Always set to 0
# <5> USER EARTH DATUM INVERSE FLATTENING FACTOR # Always set to 0
# <6> USER EARTH DATUM DELTA X # Always set to 0
# <7> USER EARTH DATUM DELTA Y # Always set to 0
# <8> USER EARTH DATUM DELTA Z # Always set to 0
# <9> DIFFERENTIAL MODE # A = automatic(DGPS when available) # D = differential exclusively(no output if not diff fix) # NOTE Setting will store but will make no difference # in GPS output.
# <10> NMEA 0183 BAUD RATE # 1 = 1200 # 2 = 2400 # 3 = 4800 # 4 = 9600 # 5 = 19200 # 6 = 300 # 7 = 600 # 8 = 38400
# <11> VELOCITY FILTER # 0 = No Filter # 1 = Automatic filter # 2-255 = Filter time constant, in seconds # NOTE Setting will store but will make no difference # in GPS output.
# <12> MEASUREMENT PULSE OUTPUT # 1 = Disabled # 2 = Enabled # NOTE Setting will store but will make no difference # in GPS output.
# <13> MEASUREMENT PULSE OUTPUT LENGTH # 0 to 48 # NOTE Setting will store but will make no difference # in GPS output.
# <14> DEAD RECKONING VALID TIME # 1 to 30 # NOTE Setting will store but will make no difference # in GPS output.
""" Initializes the GPS Simulator - Generally best to not override this method - Calls SimGPSSetup() which should have an override """
def SetupSimulator(self): log.error('Serial ports not configured.') return
def SerialPortSetup(self): """ Creates virtual serial ports then Launches the NEMA0183 GPS simulator @param None @retval True if successfully launched, False if not """
# Create the virtual serial ports stdout = nullDesc.fileno(), stderr = nullDesc.fileno()) except OSError, e: log.error('Failure: Could not create virtual serial port(s): %s' % e) return log.error('Failure: Unknown reason.') return % self._vsp.pid)
def SimGPSSetup(self): """ Inits the local simulator or launches external simulator Expects override in child class """ self._workingSim = False
""" Stops the simulator and disconnects serial ports - Generally best not to override this method - Calls SimShutdown() which should have an override @param None @retval None """
# If the process isn't running any more, nothing to stop
# Force the socat app to stop #(Python 2.6 and later would let us send a control-C to stop it)
""" Shuts down the local simulator or stops external simulator Expects override in the child class """ self._workingSim = False
""" Checks if the socat app is still running. @param None @retval True if running, False if not running """
return False
""" Returns status of simulator. - Override in child simulator class """ return False
|