nmea_gps.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 import math, time, serial
00004 
00005 import roslib; roslib.load_manifest('clearpath_sensors')
00006 import rospy
00007 
00008 from clearpath_sensors.msg import GPSFix
00009 
00010 
00011 METERS_PER_SEC_PER_KNOT = 0.514444444
00012 FIRST_TIMEOUT_SECS = 3.0
00013 TIMEOUT_SECS = 1.2
00014 RETRY_OPEN_SECS = 1.0
00015 
00016 STATE_UNKNOWN = 0
00017 STATE_NOFIX = 1
00018 STATE_FIX = 2
00019 
00020 
00021 class GPS:
00022     def __init__(self):
00023         rospy.init_node('nmea_gps')
00024         self.port = rospy.get_param('~port', '/dev/ttyUSB0')
00025         self.baud = rospy.get_param('~baud', 4800)
00026         self.serial = None
00027 
00028         self.start_serial()
00029         self.state = STATE_UNKNOWN;
00030         self.pub = rospy.Publisher('fix', GPSFix)
00031         
00032 
00033     def start_serial(self):
00034         if self.serial:
00035             self.serial.close()
00036             self.serial = None
00037 
00038         error = None
00039         while True:
00040             try:
00041                 self.serial = serial.Serial(self.port, self.baud, timeout=0)
00042                 self.timeout = time.clock() + FIRST_TIMEOUT_SECS
00043                 rospy.loginfo("Opened GPS on port: %s" % self.port)
00044                 break;
00045 
00046             except serial.SerialException as e:
00047                 if not error:
00048                     error = e
00049                     rospy.logerr("Error opening GPS serial port: %s" % error)
00050                     rospy.logerr("Will retry opening GPS every second.")
00051                 time.sleep(RETRY_OPEN_SECS)
00052 
00053 
00054     def run(self):
00055         buffer = "";
00056         while not rospy.is_shutdown():
00057             time.sleep(0.01)
00058             raw = self.serial.read(255)
00059             if len(raw) > 0:
00060                 self.timeout = time.clock() + TIMEOUT_SECS
00061                 chunks = raw.split('\n')
00062                 buffer += chunks.pop(0)
00063                 while len(chunks) > 0:
00064                     self.process(buffer)
00065                     buffer = chunks.pop(0)
00066             else:
00067                 if time.clock() > self.timeout:
00068                     rospy.logerr("GPS timed out. Attempting to reopen serial port.")
00069                     self.start_serial()
00070                     
00071 
00072     def process(self, buffer):
00073         fields = buffer.split(',')
00074         if fields[0] == '$GPRMC':
00075             if fields[2] == 'A':
00076                 if self.state != STATE_FIX:
00077                     rospy.loginfo("GPS fix acquired. Publishing to %sfix." % rospy.get_namespace())
00078                     self.state = STATE_FIX
00079                 fix_msg = GPSFix()
00080                 fix_msg.latitude = self._lat(fields)
00081                 fix_msg.longitude = self._lon(fields)
00082                 if fields[8]: fix_msg.track = float(fields[8])
00083                 if fields[7]: fix_msg.speed = float(fields[7]) * METERS_PER_SEC_PER_KNOT
00084                 self.pub.publish(fix_msg)
00085             else:
00086                 if self.state != STATE_NOFIX:
00087                     rospy.loginfo("GPS has no fix.")
00088                     self.state = STATE_NOFIX
00089 
00090 
00091     @staticmethod
00092     def _lat(fields):
00093         inp = float(fields[3])
00094         out = math.floor(inp / 100) + (inp % 100) / 60
00095         if fields[4] == 'S':
00096             out =- out
00097         return out
00098 
00099         
00100     @staticmethod
00101     def _lon(fields):
00102         inp = float(fields[5])
00103         out = math.floor(inp / 100) + (inp % 100) / 60
00104         if fields[6] == 'W':
00105             out =- out
00106         return out
00107 
00108 
00109 GPS().run()


clearpath_sensors
Author(s): Ryan Gariepy
autogenerated on Sun Oct 5 2014 22:52:23