Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import roslib
00036 roslib.load_manifest('nmea_gps_driver')
00037 import rospy
00038 from sensor_msgs.msg import NavSatFix
00039 from sensor_msgs.msg import NavSatStatus
00040 from sensor_msgs.msg import TimeReference
00041 from geometry_msgs.msg import TwistStamped
00042
00043 import serial, string, math, time, calendar
00044
00045
00046 def convertNMEATimeToROS(nmea_utc):
00047
00048 utc_struct = time.gmtime()
00049 utc_list = list(utc_struct)
00050 hours = int(nmea_utc[0:2])
00051 minutes = int(nmea_utc[2:4])
00052 seconds = int(nmea_utc[4:6])
00053 utc_list[3] = hours
00054 utc_list[4] = minutes
00055 utc_list[5] = seconds
00056 unix_time = calendar.timegm(tuple(utc_list))
00057 return rospy.Time.from_sec(unix_time)
00058
00059
00060 def addTFPrefix(frame_id):
00061 prefix = ""
00062 prefix_param = rospy.search_param("tf_prefix")
00063 if prefix_param:
00064 prefix = rospy.get_param(prefix_param)
00065 if prefix[0] != "/":
00066 prefix = "/%s" % prefix
00067
00068 return "%s/%s" % (prefix, frame_id)
00069
00070
00071 def check_checksum(nmea_sentence):
00072 split_sentence = nmea_sentence.split('*')
00073 transmitted_checksum = split_sentence[1].strip()
00074
00075
00076 data_to_checksum = split_sentence[0][1:]
00077 checksum = 0
00078 for c in data_to_checksum:
00079 checksum ^= ord(c)
00080
00081 return ("%02X" % checksum) == transmitted_checksum.upper()
00082
00083 if __name__ == "__main__":
00084
00085 rospy.init_node('nmea_gps_driver')
00086 gpspub = rospy.Publisher('fix', NavSatFix)
00087 gpsVelPub = rospy.Publisher('vel',TwistStamped)
00088 gpstimePub = rospy.Publisher('time_reference', TimeReference)
00089
00090 GPSport = rospy.get_param('~port','/dev/ttyUSB0')
00091 GPSrate = rospy.get_param('~baud',4800)
00092 frame_id = rospy.get_param('~frame_id','gps')
00093 if frame_id[0] != "/":
00094 frame_id = addTFPrefix(frame_id)
00095
00096 time_ref_source = rospy.get_param('~time_ref_source', frame_id)
00097 useRMC = rospy.get_param('~useRMC', False)
00098
00099
00100 navData = NavSatFix()
00101 gpsVel = TwistStamped()
00102 gpstime = TimeReference()
00103 gpstime.source = time_ref_source
00104 navData.header.frame_id = frame_id
00105 gpsVel.header.frame_id = frame_id
00106 GPSLock = False
00107 try:
00108 GPS = serial.Serial(port=GPSport, baudrate=GPSrate, timeout=2)
00109
00110 while not rospy.is_shutdown():
00111
00112 data = GPS.readline()
00113
00114 if not check_checksum(data):
00115 rospy.logerr("Received a sentence with an invalid checksum. Sentence was: %s" % data)
00116 continue
00117
00118 timeNow = rospy.get_rostime()
00119 fields = data.split(',')
00120 for i in fields:
00121 i = i.strip(',')
00122 try:
00123 if useRMC:
00124
00125 if 'GSA' in fields[0]:
00126 lockState = int(fields[2])
00127
00128 if lockState == 3:
00129 GPSLock = True
00130 else:
00131 GPSLock = False
00132
00133 else:
00134 if GPSLock == True:
00135 if 'RMC' in fields[0]:
00136
00137 gpsVel.header.stamp = timeNow
00138 gpsVel.twist.linear.x = float(fields[7])*0.514444444444*math.sin(float(fields[8]))
00139 gpsVel.twist.linear.y = float(fields[7])*0.514444444444*math.cos(float(fields[8]))
00140 gpsVelPub.publish(gpsVel)
00141
00142 navData.status.status = NavSatStatus.STATUS_FIX
00143 navData.header.stamp = gpsVel.header.stamp
00144 navData.status.service = NavSatStatus.SERVICE_GPS
00145
00146 gpstime.header.stamp = gpsVel.header.stamp
00147 gpstime.time_ref = convertNMEATimeToROS(fields[1])
00148
00149 longitude = float(fields[5][0:3]) + float(fields[5][3:])/60
00150 if fields[6] == 'W':
00151 longitude = -longitude
00152
00153 latitude = float(fields[3][0:2]) + float(fields[3][2:])/60
00154 if fields[4] == 'S':
00155 latitude = -latitude
00156
00157
00158 navData.latitude = latitude
00159 navData.longitude = longitude
00160 navData.altitude = float('NaN')
00161 navData.position_covariance_type = NavSatFix.COVARIANCE_TYPE_UNKNOWN
00162 gpspub.publish(navData)
00163 gpstimePub.publish(gpstime)
00164 else:
00165 pass
00166
00167 else:
00168
00169
00170 if 'GGA' in fields[0]:
00171 gps_quality = int(fields[6])
00172 if gps_quality == 0:
00173 navData.status.status = NavSatStatus.STATUS_NO_FIX
00174 elif gps_quality == 1:
00175 navData.status.status = NavSatStatus.STATUS_FIX
00176 elif gps_quality == 2:
00177 navData.status.status = NavSatStatus.STATUS_SBAS_FIX
00178 elif gps_quality in (4,5):
00179
00180
00181 navData.status.status = NavSatStatus.STATUS_GBAS_FIX
00182 else:
00183 navData.status.status = NavSatStatus.STATUS_NO_FIX
00184 navData.status.service = NavSatStatus.SERVICE_GPS
00185
00186 navData.header.stamp = timeNow
00187
00188 latitude = float(fields[2][0:2]) + float(fields[2][2:])/60
00189 if fields[3] == 'S':
00190 latitude = -latitude
00191 navData.latitude = latitude
00192
00193 longitude = float(fields[4][0:3]) + float(fields[4][3:])/60
00194 if fields[5] == 'W':
00195 longitude = -longitude
00196 navData.longitude = longitude
00197
00198 hdop = float(fields[8])
00199 navData.position_covariance[0] = hdop**2
00200 navData.position_covariance[4] = hdop**2
00201 navData.position_covariance[8] = (2*hdop)**2
00202 navData.position_covariance_type = NavSatFix.COVARIANCE_TYPE_APPROXIMATED
00203
00204
00205 altitude = float(fields[9]) + float(fields[11])
00206 navData.altitude = altitude
00207
00208
00209 gpstime.header.stamp = timeNow
00210 gpstime.time_ref = convertNMEATimeToROS(fields[1])
00211
00212 gpspub.publish(navData)
00213 gpstimePub.publish(gpstime)
00214 except ValueError as e:
00215 rospy.logwarn("Value error, likely due to missing fields in the NMEA messages. Error was: %s" % e)
00216
00217 except rospy.ROSInterruptException:
00218 GPS.close()