rplidar_scan.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding:utf-8 -*-
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             # release data
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             # header
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             # rplidar_parameters
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             # _Scan.time_increment = self.duration / 360
00185             # _Scan.scan_time = self.duration
00186             _Scan.range_min = self.range_min
00187             _Scan.range_max = self.range_max
00188             # rplidar_ranges
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)


rplidar_python
Author(s): DinnerHowe
autogenerated on Thu Jun 6 2019 21:53:33