Go to the documentation of this file.00001
00002
00003 """
00004
00005 before run this code pls install parse library and also install construct lib for protocol
00006
00007 Copyright (c) 2016 Xu Zhihao (Howe). All rights reserved.
00008
00009 This program is free software; you can redistribute it and/or modify
00010
00011 This programm is tested on kuboki base turtlebot.
00012 """
00013
00014 from reference import *
00015 import serial
00016 import numpy
00017 import rospy
00018 import getpass
00019 import collections
00020 import math
00021 from sensor_msgs.msg import LaserScan
00022 import function
00023
00024 raw_data = collections.deque(maxlen=360)
00025 para_data = collections.deque(maxlen=360)
00026 compress_data = collections.deque(maxlen=1)
00027 reset = False
00028 start = False
00029 run = True
00030
00031 class ClearParams:
00032 def __init__(self):
00033 rospy.logwarn('clearing parameters')
00034 rospy.delete_param('~rplidar_scan_topic')
00035 rospy.delete_param('~rplidar_port_name')
00036 rospy.delete_param('~rplidar_frame')
00037 rospy.delete_param('~rplidar_range_min')
00038 rospy.delete_param('~rplidar_range_max')
00039
00040 class driver:
00041 def __init__(self):
00042 self.defination()
00043 self.begin()
00044 while run:
00045 self.Read_Data()
00046 self.lidar_publisher()
00047 rospy.signal_shutdown('restart')
00048 self.port.close()
00049
00050 def defination(self):
00051 self.scan_frequency = 0.0001
00052 self.pub_frequency = 0.01
00053
00054 self.ResponseType = {measurement: 'measurement', devinfo: 'devinfo', devhealth: 'devhealth'}
00055 self.ResponseStatus = {status_ok: 'status_ok', status_warning: 'status_warning', status_error: 'status_error'}
00056 self.ResponseMode = {SINGLE: 'SINGLE', MULTI: 'MULTI', UNDEFINED_f: 'UNDEFINED', UNDEFINED_s: 'UNDEFINED'}
00057
00058 self.seq = 0
00059 self.accout = getpass.getuser()
00060
00061 if not rospy.has_param('~rplidar_scan_topic'):
00062 rospy.set_param('~rplidar_scan_topic', '/rplidar_scan')
00063 self.scan_topic = rospy.get_param('~rplidar_scan_topic')
00064
00065 if not rospy.has_param('~rplidar_port_name'):
00066 rospy.set_param('~rplidar_port_name', 'CP2102 USB to UART Bridge Controller')
00067 self.rplidar_port_name = rospy.get_param('~rplidar_port_name')
00068
00069 if not rospy.has_param('~rplidar_frame'):
00070 rospy.set_param('~rplidar_frame', 'laser')
00071 self.rplidar_frame = rospy.get_param('~rplidar_frame')
00072
00073 if not rospy.has_param('~rplidar_range_min'):
00074 rospy.set_param('~rplidar_range_min', 0.15)
00075 self.range_min = rospy.get_param('~rplidar_range_min')
00076
00077 if not rospy.has_param('~rplidar_range_max'):
00078 rospy.set_param('~rplidar_range_max', 6.0)
00079 self.range_max = rospy.get_param('~rplidar_range_max')
00080
00081 finder = function.port_finder(False, self.rplidar_port_name)
00082 self.find_port = finder[1]
00083 if self.find_port:
00084 self.port_name = finder[0][1]
00085 self.port = serial.Serial("%s" % finder[0][0], 115200)
00086
00087 def begin(self):
00088 global start
00089 global run
00090 run = True
00091 if self.find_port:
00092 self.port.setDTR(1)
00093 rospy.logwarn("connect port: %s" %self.port_name)
00094 health = function.device_health(self.port)
00095 try:
00096 rospy.loginfo('health status: %s'%self.ResponseStatus[health.status])
00097 except:
00098 rospy.logwarn('health status: %s restart program' %health)
00099 run = False
00100 if health != None:
00101 if health.status != status_ok:
00102 function.driver_reset(self.port)
00103 else:
00104 self.port.setDTR(0)
00105 cmd = scan
00106 function.send_command(self.port, cmd)
00107 if function.header_check(self.port) == measurement:
00108 start = True
00109 else:
00110 rospy.logerr('header check error,response type not measurement')
00111 start = False
00112 run = False
00113 else:
00114 rospy.logwarn('Can NOT find rplidar please check rplidar connection')
00115 rospy.logwarn('Shut Down Progress')
00116 run = False
00117
00118 def Read_Data(self):
00119 global start
00120 if start:
00121 global raw_data
00122 function.rplidar_points(self.port, raw_data)
00123 self.Resolve_Data()
00124
00125 def Resolve_Data(self):
00126 global raw_data
00127 global reset
00128 global para_data
00129 if len(raw_data)>0:
00130 reset = False
00131 _str = raw_data.pop()
00132 response = response_device_point_format.parse(_str)
00133 synbit = response.quality.syncbit
00134 syncbit_inverse = response.quality.syncbit_inverse
00135
00136 if synbit and not syncbit_inverse:
00137 data_buff = list(para_data)
00138 ranges = function.range_matrix()
00139 intensive = function.intensive_matrix()
00140 for i in range(len(data_buff)):
00141 PolorCoordinate = function.OutputCoordinate(data_buff[i])
00142 if PolorCoordinate[0] >= 360:
00143 angle = PolorCoordinate[0]%360
00144 else:
00145 angle = PolorCoordinate[0]
00146 if not math.isinf(PolorCoordinate[1]):
00147 if math.isinf(ranges[int(angle)]):
00148 ranges[int(angle)] = round(PolorCoordinate[1], 4)
00149 intensive[int(angle)] = PolorCoordinate[2]
00150 else:
00151 ranges[int(angle)] = function.fusion([ranges[int(angle)], intensive[int(angle)]], PolorCoordinate)
00152 intensive[int(angle)] = PolorCoordinate[2] + intensive[int(angle)]
00153 global compress_data
00154 compress_data.append([ranges, intensive])
00155 para_data.clear()
00156 para_data.append(_str)
00157 elif not synbit and syncbit_inverse:
00158 para_data.append(_str)
00159 pass
00160 else:
00161 rospy.logerr('buff error!!')
00162 if not reset:
00163 reset=True
00164 if reset:
00165 global start
00166 start = False
00167 rospy.logwarn('resetting system')
00168 function.stop_device(self.port)
00169 self.begin()
00170
00171 def lidar_publisher(self):
00172 global compress_data
00173 if len(compress_data) > 0:
00174
00175 _Scan = LaserScan()
00176 _Scan.header.stamp = rospy.Time.now()
00177 _Scan.header.seq = self.seq
00178 self.seq += 1
00179 _Scan.header.frame_id = self.rplidar_frame
00180
00181 _Scan.angle_max = numpy.pi - numpy.radians(0.0)
00182 _Scan.angle_min = numpy.pi - numpy.radians(360.0)
00183 _Scan.angle_increment = -numpy.radians(1.0)
00184
00185
00186 _Scan.range_min = self.range_min
00187 _Scan.range_max = self.range_max
00188
00189 [ranges, intensive] = compress_data.pop()
00190 _Scan.ranges = ranges
00191 _Scan.intensities = intensive
00192 if _Scan != LaserScan():
00193 pub_data = rospy.Publisher(self.scan_topic, LaserScan, queue_size=1)
00194 pub_data.publish(_Scan)