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 import math, numpy as np
00031 import sys, time
00032
00033 NAME = 'utm_python_listener'
00034 import roslib; roslib.load_manifest('hrl_hokuyo')
00035 import rospy
00036 from sensor_msgs.msg import LaserScan
00037 from threading import RLock
00038
00039 import hokuyo_processing as hp
00040 import copy
00041
00042 import numpy as np
00043
00044 class HokuyoScan():
00045 ''' This class has the data of a laser scan.
00046 '''
00047 def __init__(self,hokuyo_type,angular_res,max_range,min_range,start_angle,end_angle):
00048 ''' hokuyo_type - 'urg', 'utm'
00049 angular_res - angle (radians) between consecutive points in the scan.
00050 min_range, max_range - in meters
00051 ranges,angles,intensities - 1xn_points numpy matrix.
00052 '''
00053 self.hokuyo_type = hokuyo_type
00054 self.angular_res = angular_res
00055 self.max_range = max_range
00056 self.min_range = min_range
00057 self.start_angle = start_angle
00058 self.end_angle = end_angle
00059 self.n_points = int((end_angle-start_angle)/angular_res)+1
00060
00061 self.ranges = None
00062 self.intensities = None
00063 self.angles = []
00064
00065 for i in xrange(self.n_points):
00066 self.angles.append(hp.index_to_angle(self,i))
00067 self.angles = np.matrix(self.angles)
00068
00069
00070 class Urg():
00071 ''' get a scan from urg using player.
00072 '''
00073 def __init__(self, urg_number,start_angle=None,end_angle=None, host='localhost', port=6665):
00074 ''' host, port - hostname and port of the player server
00075 '''
00076 import player_functions as pf
00077 import playerc as pl
00078
00079 self.player_client = pf.player_connect(host,port)
00080 self.laser = pl.playerc_laser(self.player_client, urg_number)
00081 if self.laser.subscribe(pl.PLAYERC_OPEN_MODE) != 0:
00082 raise RuntimeError("hokuyo_scan.Urg.__init__: Unable to connect to urg!\n")
00083
00084 for i in range(10):
00085 self.player_client.read()
00086
00087 start_angle_fullscan = -math.radians(654./2*0.36)
00088 end_angle_fullscan = math.radians(654./2*0.36)
00089 if start_angle == None or start_angle<start_angle_fullscan:
00090 start_angle_subscan = start_angle_fullscan
00091 else:
00092 start_angle_subscan = start_angle
00093
00094 if end_angle == None or end_angle>end_angle_fullscan:
00095 end_angle_subscan = end_angle_fullscan
00096 else:
00097 end_angle_subscan = end_angle
00098
00099 ang_res = math.radians(0.36)
00100 self.start_index_fullscan=(start_angle_subscan-start_angle_fullscan)/ang_res
00101 self.end_index_fullscan=(end_angle_subscan-start_angle_fullscan)/ang_res
00102
00103 self.hokuyo_scan = HokuyoScan(hokuyo_type = 'urg', angular_res = math.radians(0.36),
00104 max_range = 4.0, min_range = 0.2,
00105 start_angle=start_angle_subscan,
00106 end_angle=end_angle_subscan)
00107
00108 def get_scan(self, avoid_duplicate=False):
00109 ''' avoid_duplicate - avoids duplicates caused by querying player faster than it
00110 can get new scans.
00111 '''
00112 curr_ranges = self.hokuyo_scan.ranges
00113 for i in range(10):
00114 if self.player_client.read() == None:
00115 raise RuntimeError('hokuyo_scan.Urg.get_scan: player_client.read() returned None.\n')
00116 sub_ranges = np.matrix(self.laser.ranges[self.start_index_fullscan:self.end_index_fullscan+1])
00117 if avoid_duplicate == False or np.any(curr_ranges != sub_ranges):
00118
00119 break
00120 self.hokuyo_scan.ranges = sub_ranges
00121 return copy.copy(self.hokuyo_scan)
00122
00123
00124 class Utm():
00125 ''' get a scan from a UTM using ROS
00126 '''
00127 def __init__(self, utm_number,start_angle=None,end_angle=None,ros_init_node=True):
00128
00129 hokuyo_node_name = '/utm%d'%utm_number
00130
00131
00132
00133
00134
00135
00136
00137 max_ang_degrees = rospy.get_param(hokuyo_node_name+'/max_ang_degrees')
00138 min_ang_degrees = rospy.get_param(hokuyo_node_name+'/min_ang_degrees')
00139 start_angle_fullscan = math.radians(min_ang_degrees)
00140 end_angle_fullscan = math.radians(max_ang_degrees)
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 if start_angle == None or start_angle<start_angle_fullscan:
00151 start_angle_subscan = start_angle_fullscan
00152 else:
00153 start_angle_subscan = start_angle
00154
00155 if end_angle == None or end_angle>end_angle_fullscan:
00156 end_angle_subscan = end_angle_fullscan
00157 else:
00158 end_angle_subscan = end_angle
00159
00160 ang_res = math.radians(0.25)
00161 self.start_index_fullscan=int(round((start_angle_subscan-start_angle_fullscan)/ang_res))
00162 self.end_index_fullscan=int(round((end_angle_subscan-start_angle_fullscan)/ang_res))
00163
00164 self.hokuyo_scan = HokuyoScan(hokuyo_type = 'utm', angular_res = math.radians(0.25),
00165 max_range = 10.0, min_range = 0.1,
00166 start_angle=start_angle_subscan,
00167 end_angle=end_angle_subscan)
00168
00169 self.lock = RLock()
00170 self.lock_init = RLock()
00171 self.connected_to_ros = False
00172
00173 self.ranges,self.intensities = None,None
00174
00175 if ros_init_node:
00176 try:
00177 print 'Utm: init ros node.'
00178 rospy.init_node(NAME, anonymous=True)
00179 except rospy.ROSException, e:
00180 print 'Utm: rospy already initialized. Got message', e
00181 pass
00182
00183 rospy.Subscriber("utm%d_scan"%(utm_number), LaserScan,
00184 self.callback, queue_size = 1)
00185
00186 def callback(self, scan):
00187 self.lock.acquire()
00188 self.connected_to_ros = True
00189 self.ranges = np.matrix(scan.ranges[self.start_index_fullscan:self.end_index_fullscan+1])
00190 self.intensities = np.matrix(scan.intensities[self.start_index_fullscan:self.end_index_fullscan+1])
00191 self.lock.release()
00192
00193 def get_scan(self, avoid_duplicate=False):
00194 while self.connected_to_ros == False:
00195 pass
00196 while not rospy.is_shutdown():
00197 self.lock.acquire()
00198 if avoid_duplicate == False or np.any(self.hokuyo_scan.ranges!=self.ranges):
00199
00200 self.hokuyo_scan.ranges = copy.copy(self.ranges)
00201 self.hokuyo_scan.intensities = copy.copy(self.intensities)
00202 self.lock.release()
00203 break
00204 self.lock.release()
00205 time.sleep(0.001)
00206
00207 return copy.copy(self.hokuyo_scan)
00208
00209
00210 class Hokuyo():
00211 ''' common class for getting scans from both urg and utm.
00212 '''
00213
00214 def __init__(self, hokuyo_type, hokuyo_number, start_angle=None,
00215 end_angle=None, flip=False, ros_init_node=True):
00216 ''' hokuyo_type - 'urg', 'utm'
00217 - 'utm' requires ros revision 2536
00218 ros-kg revision 5612
00219 hokuyo_number - 0,1,2 ...
00220 start_angle, end_angle - unoccluded part of the scan. (radians)
00221 flip - whether to flip the scans (hokuyo upside-down)
00222 '''
00223 self.hokuyo_type = hokuyo_type
00224 self.flip = flip
00225
00226 if hokuyo_type == 'urg':
00227 self.hokuyo = Urg(hokuyo_number,start_angle,end_angle)
00228 elif hokuyo_type == 'utm':
00229 self.hokuyo = Utm(hokuyo_number,start_angle,end_angle,ros_init_node=ros_init_node)
00230 else:
00231 raise RuntimeError('hokuyo_scan.Hokuyo.__init__: Unknown hokuyo type: %s\n'%(hokuyo_type))
00232
00233 def get_scan(self, avoid_duplicate=False, avg=1, remove_graze=True):
00234 ''' avoid_duplicate - prevent duplicate scans which will happen if get_scan is
00235 called at a rate faster than the scanning rate of the hokuyo.
00236 avoid_duplicate == True, get_scan will block till new scan is received.
00237 (~.2s for urg and 0.05s for utm)
00238 '''
00239 l = []
00240 l2 = []
00241 for i in range(avg):
00242 hscan = self.hokuyo.get_scan(avoid_duplicate)
00243 l.append(hscan.ranges)
00244 l2.append(hscan.intensities)
00245
00246 ranges_mat = np.row_stack(l)
00247 ranges_mat[np.where(ranges_mat==0)] = -1000.
00248 ranges_avg = (ranges_mat.sum(0)/avg)
00249 if self.flip:
00250 ranges_avg = np.fliplr(ranges_avg)
00251 hscan.ranges = ranges_avg
00252
00253 intensities_mat = np.row_stack(l2)
00254 if self.hokuyo_type == 'utm':
00255 hscan.intensities = (intensities_mat.sum(0)/avg)
00256
00257 if remove_graze:
00258 if self.hokuyo_type=='utm':
00259 hp.remove_graze_effect_scan(hscan)
00260 else:
00261 print 'hokuyo_scan.Hokuyo.get_scan: hokuyo type is urg, but remove_graze is True'
00262
00263 return hscan
00264
00265
00266
00267 if __name__ == '__main__':
00268 import pylab as pl
00269
00270
00271 h = Hokuyo('utm', 0, flip=True)
00272 print 'getting first scan'
00273 scan1 = h.get_scan(avoid_duplicate=True)
00274
00275 t_list = []
00276 for i in range(200):
00277 t0 = time.time()
00278 scan2 = h.get_scan(avoid_duplicate=True,avg=1,remove_graze=False)
00279
00280 t1 = time.time()
00281 print t1-t0, scan1==scan2
00282 t_list.append(t1-t0)
00283 scan1=scan2
00284 print scan1.ranges.shape
00285 print scan1.angles.shape
00286
00287
00288
00289
00290
00291
00292 pl.plot(t_list)
00293 pl.show()
00294
00295
00296
00297
00298
00299
00300