00001
00002
00003 """
00004 Sensor class for the arudino_python package
00005
00006 Created for the Pi Robot Project: http://www.pirobot.org
00007 Copyright (c) 2012 Patrick Goebel. All rights reserved.
00008
00009 This program is free software; you can redistribute it and/or modify
00010 it under the terms of the GNU General Public License as published by
00011 the Free Software Foundation; either version 2 of the License, or
00012 (at your option) any later version.
00013
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 GNU General Public License for more details at:
00018
00019 http://www.gnu.org/licenses/gpl.html
00020 """
00021
00022 import roslib; roslib.load_manifest('ros_arduino_python')
00023 import rospy
00024 from sensor_msgs.msg import Range
00025 from ros_arduino_msgs.msg import *
00026
00027 LOW = 0
00028 HIGH = 1
00029
00030 INPUT = 0
00031 OUTPUT = 1
00032
00033 class MessageType:
00034 ANALOG = 0
00035 DIGITAL = 1
00036 RANGE = 2
00037 FLOAT = 3
00038 INT = 4
00039 BOOL = 5
00040
00041 class Sensor(object):
00042 def __init__(self, controller, name, pin, rate, frame_id="/base_link", direction="input", **kwargs):
00043 self.controller = controller
00044 self.name = name
00045 self.pin = pin
00046 self.rate = rate
00047 self.direction = direction
00048
00049 self.frame_id = frame_id
00050 self.value = None
00051
00052 self.t_delta = rospy.Duration(1.0 / self.rate)
00053 self.t_next = rospy.Time.now() + self.t_delta
00054
00055 def poll(self):
00056 now = rospy.Time.now()
00057 if now > self.t_next:
00058 if self.direction == "input":
00059 try:
00060 self.value = self.read_value()
00061 except:
00062 return
00063 else:
00064 try:
00065 self.ack = self.write_value()
00066 except:
00067 return
00068
00069
00070 if self.message_type == MessageType.RANGE:
00071 self.msg.range = self.value
00072 else:
00073 self.msg.value = self.value
00074
00075
00076 self.msg.header.stamp = rospy.Time.now()
00077 self.pub.publish(self.msg)
00078
00079 self.t_next = now + self.t_delta
00080
00081 class AnalogSensor(Sensor):
00082 def __init__(self, *args, **kwargs):
00083 super(AnalogSensor, self).__init__(*args, **kwargs)
00084
00085 self.message_type = MessageType.ANALOG
00086
00087 self.msg = Analog()
00088 self.msg.header.frame_id = self.frame_id
00089
00090 self.pub = rospy.Publisher("~sensor/" + self.name, Analog)
00091
00092 def read_value(self):
00093 return self.controller.analog_read(self.pin)
00094
00095 def write_value(self, value):
00096 return self.controller.analog_write(self.pin, value)
00097
00098 class AnalogFloatSensor(Sensor):
00099 def __init__(self, *args, **kwargs):
00100 super(AnalogFloatSensor, self).__init__(*args, **kwargs)
00101
00102 self.message_type = MessageType.ANALOG
00103
00104 self.msg = AnalogFloat()
00105 self.msg.header.frame_id = self.frame_id
00106
00107 self.pub = rospy.Publisher("~sensor/" + self.name, AnalogFloat)
00108
00109
00110 class DigitalSensor(Sensor):
00111 def __init__(self, *args, **kwargs):
00112 super(DigitalSensor, self).__init__(*args, **kwargs)
00113
00114 self.message_type = MessageType.BOOL
00115
00116 self.msg = Digital()
00117 self.msg.header.frame_id = self.frame_id
00118
00119 self.pub = rospy.Publisher("~sensor/" + self.name, Digital)
00120
00121 if self.direction == "output":
00122 self.controller.pin_mode(self.pin, OUTPUT)
00123 else:
00124 self.controller.pin_mode(self.pin, INPUT)
00125
00126 self.value = LOW
00127
00128 def read_value(self):
00129 return self.controller.digital_read(self.pin)
00130
00131 def write_value(self):
00132
00133 self.value = not self.value
00134 return self.controller.digital_write(self.pin, self.value)
00135
00136
00137 class RangeSensor(Sensor):
00138 def __init__(self, *args, **kwargs):
00139 super(RangeSensor, self).__init__(*args, **kwargs)
00140
00141 self.message_type = MessageType.RANGE
00142
00143 self.msg = Range()
00144 self.msg.header.frame_id = self.frame_id
00145
00146 self.pub = rospy.Publisher("~sensor/" + self.name, Range)
00147
00148 def read_value(self):
00149 self.msg.header.stamp = rospy.Time.now()
00150
00151
00152 class SonarSensor(RangeSensor):
00153 def __init__(self, *args, **kwargs):
00154 super(SonarSensor, self).__init__(*args, **kwargs)
00155
00156 self.msg.radiation_type = Range.ULTRASOUND
00157
00158
00159 class IRSensor(RangeSensor):
00160 def __init__(self, *args, **kwargs):
00161 super(IRSensor, self).__init__(*args, **kwargs)
00162
00163 self.msg.radiation_type = Range.INFRARED
00164
00165 class Ping(SonarSensor):
00166 def __init__(self,*args, **kwargs):
00167 super(Ping, self).__init__(*args, **kwargs)
00168
00169 self.msg.field_of_view = 0.785398163
00170 self.msg.min_range = 0.02
00171 self.msg.max_range = 3.0
00172
00173 def read_value(self):
00174
00175 cm = self.controller.ping(self.pin)
00176
00177
00178 distance = cm / 100.0
00179
00180 return distance
00181
00182
00183 class GP2D12(IRSensor):
00184 def __init__(self, *args, **kwargs):
00185 super(GP2D12, self).__init__(*args, **kwargs)
00186
00187 self.msg.field_of_view = 0.001
00188 self.msg.min_range = 0.10
00189 self.msg.max_range = 0.80
00190
00191 def read_value(self):
00192 value = self.controller.analog_read(self.pin)
00193
00194 if value <= 3.0:
00195 return self.msg.max_range
00196
00197 try:
00198 distance = (6787.0 / (float(value) - 3.0)) - 4.0
00199 except:
00200 return self.msg.max_range
00201
00202
00203 distance /= 100.0
00204
00205
00206 if distance > self.msg.max_range: distance = self.msg.max_range
00207 if distance < self.msg.min_range: distance = self.msg.max_range
00208
00209 return distance
00210
00211 class PololuMotorCurrent(AnalogFloatSensor):
00212 def __init__(self, *args, **kwargs):
00213 super(PololuMotorCurrent, self).__init__(*args, **kwargs)
00214
00215 def read_value(self):
00216
00217 milliamps = self.controller.analog_read(self.pin) * 34
00218 return milliamps / 1000.0
00219
00220 class PhidgetsVoltage(AnalogFloatSensor):
00221 def __init__(self, *args, **kwargs):
00222 super(PhidgetsVoltage, self).__init__(*args, **kwargs)
00223
00224 def read_value(self):
00225
00226 voltage = 0.06 * (self.controller.analog_read(self.pin) - 500.)
00227 return voltage
00228
00229 class PhidgetsCurrent(AnalogFloatSensor):
00230 def __init__(self, *args, **kwargs):
00231 super(PhidgetsCurrent, self).__init__(*args, **kwargs)
00232
00233 def read_value(self):
00234
00235 current = 0.05 * (self.controller.analog_read(self.pin) - 500.)
00236 return current
00237
00238 class MaxEZ1Sensor(SonarSensor):
00239 def __init__(self, *args, **kwargs):
00240 super(MaxEZ1Sensor, self).__init__(*args, **kwargs)
00241
00242 self.trigger_pin = kwargs['trigger_pin']
00243 self.output_pin = kwargs['output_pin']
00244
00245 self.msg.field_of_view = 0.785398163
00246 self.msg.min_range = 0.02
00247 self.msg.max_range = 3.0
00248
00249 def read_value(self):
00250 return self.controller.get_MaxEZ1(self.trigger_pin, self.output_pin)
00251
00252
00253 if __name__ == '__main__':
00254 myController = Controller()
00255 mySensor = SonarSensor(myController, "My Sonar", type=Type.PING, pin=0, rate=10)
00256