Go to the documentation of this file.00001
00002
00003 """
00004 base_scan.py - A panning sonar sensor used to get a pretend "laser scan" for ROS SLAM
00005 Created for the Pi Robot Project: http://www.pirobot.org
00006 Copyright (c) 2010 Patrick Goebel. All rights reserved.
00007
00008 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016 GNU General Public License for more details at:
00017
00018 http://www.gnu.org/licenses/gpl.html
00019
00020 NOTE: This code borrows heavily from Michael Ferguson's Poor Man's Lidar code.
00021 """
00022
00023 import roslib; roslib.load_manifest('pi_robot')
00024 import rospy
00025 from sensor_msgs.msg import LaserScan
00026 from tf.broadcaster import TransformBroadcaster
00027 from serializer.srv import *
00028 from serializer.msg import *
00029 from math import pi, pow
00030 import time
00031 from threading import Thread, Event
00032
00033 class base_scan(Thread):
00034 def __init__(self, Serializer, name):
00035 Thread.__init__ (self)
00036 self.finished = Event()
00037
00038 self.Serializer = Serializer
00039 self.scanPub = rospy.Publisher('/base_scan', LaserScan)
00040
00041
00042
00043 self.rate = 1
00044 rospy.loginfo("Started base scan at " + str(self.rate) + " Hz")
00045
00046 self.sonar = 0.128
00047
00048
00049 self.servo_id = 2
00050 self.sonar_id = 5
00051 self.ir_id = 3
00052 self.right = 60
00053 self.left = -80
00054
00055
00056 self.sweep_angle = pi * (self.right - self.left) / 200.
00057 self.angle_max = self.sweep_angle / 2.0
00058 self.angle_min = -self.angle_max
00059 self.n_samples = 15
00060 self.angle_increment = self.sweep_angle / self.n_samples
00061 self.servo_increment = (self.right - self.left) / self.n_samples
00062 self.range_min = 0.2
00063 self.range_max = 5.0
00064
00065 self.setServo(self.servo_id, (self.right - self.left) / 2 + self.left)
00066
00067 self.servo_direction = 1
00068 self.count = 0
00069
00070
00071
00072
00073
00074
00075 ir = None
00076 while ir == None:
00077 rospy.loginfo("Getting IR Reading: " + str(ir))
00078 ir = self.SharpGP2Y0A0(self.Serializer.sensor(self.ir_id))
00079 rospy.loginfo("Initial IR Reading: " + str(ir))
00080
00081 def run(self):
00082 rosRate = rospy.Rate(self.rate)
00083 rospy.loginfo("Executing base scan at: " + str(self.rate) + " Hz")
00084
00085 while not rospy.is_shutdown():
00086
00087 ranges = list()
00088
00089 if self.servo_direction > 0:
00090
00091 self.Serializer.servo(self.servo_id, self.left)
00092 else:
00093
00094 self.Serializer.servo(self.servo_id, self.right)
00095
00096
00097
00098 for i in range(self.n_samples):
00099
00100 start = time.time()
00101 ir = self.SharpGP2Y0A0(self.Serializer.sensor(self.ir_id))
00102 ranges.append(ir / 100.0)
00103 delta = time.time() - start
00104
00105 time.sleep(max(0, 0.05 - delta))
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 if self.servo_direction < 0:
00118 ranges.reverse()
00119
00120 scan = LaserScan()
00121 scan.header.stamp = rospy.Time.now()
00122 scan.header.frame_id = "/base_laser"
00123 scan.angle_min = self.angle_min
00124 scan.angle_max = self.angle_max
00125 scan.angle_increment = self.angle_increment
00126 scan.scan_time = self.rate
00127 scan.range_min = self.range_min
00128 scan.range_max = self.range_max
00129 scan.ranges = ranges
00130 self.scanPub.publish(scan)
00131
00132 self.servo_direction *= -1
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 rosRate.sleep()
00147
00148 def stop(self):
00149 print "Shutting down base scan"
00150 self.finished.set()
00151 self.join()
00152
00153 def setServo(self, id, position):
00154 rospy.wait_for_service('SetServo')
00155 try:
00156 servoProxy = rospy.ServiceProxy('SetServo', SetServo)
00157 return servoProxy(id, position)
00158 except rospy.ServiceException, e:
00159 print "Service call failed: %s"%e
00160
00161 def getPing(self, id, cached):
00162 rospy.wait_for_service('Ping')
00163 try:
00164 pingProxy = rospy.ServiceProxy('Ping', Ping)
00165 response = pingProxy(id, cached)
00166 return response.value
00167 except rospy.ServiceException, e:
00168 print "Service call failed: %s"%e
00169
00170 def getVoltage(self, cached):
00171 rospy.wait_for_service('Voltage')
00172 try:
00173 voltageProxy = rospy.ServiceProxy('Voltage', Voltage)
00174 response = voltageProxy(cached)
00175 voltage = response.value
00176 return voltage
00177 except rospy.ServiceException, e:
00178 print "Service call failed: %s"%e
00179
00180 def getAnalog(self, id):
00181 rospy.wait_for_service('GetAnalog')
00182 try:
00183 analogProxy = rospy.ServiceProxy('GetAnalog', GetAnalog)
00184 response = analogProxy(id)
00185 return response.value
00186 except rospy.ServiceException, e:
00187 print "Service call failed: %s"%e
00188
00189 def sensorCallback(self, data):
00190 self.sonar = data.value[0] / 100.
00191
00192
00193 def SharpGP2Y0A0(self, reading):
00194 if reading <= 90:
00195 range = 500
00196 else:
00197 try:
00198 range = (11341 / (reading - 17.562)) - 3
00199 except:
00200 range = 150
00201 return range
00202
00203
00204 if __name__ == '__main__':
00205 try:
00206 myBaseScan = base_scan()
00207 myBaseScan.start()
00208 except rospy.ROSInterruptException:
00209 pass