Browse Source

调试好红外测距传感器的话题输出

corvin 5 years ago
parent
commit
8e85b53333

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 build/
 build/
 devel/
 devel/
+*.pyc

+ 1 - 0
src/ros_arduino_bridge/ros_arduino_msgs/CMakeLists.txt

@@ -9,6 +9,7 @@ add_message_files(FILES
                   ArduinoConstants.msg
                   ArduinoConstants.msg
                   Digital.msg
                   Digital.msg
                   SensorState.msg
                   SensorState.msg
+                  InfraredSensors.msg
                  )
                  )
 
 
 add_service_files(FILES
 add_service_files(FILES

+ 11 - 4
src/ros_arduino_bridge/ros_arduino_msgs/msg/InfraredSensors.msg

@@ -1,6 +1,13 @@
 # Float message from three infrared sensors IO pin.
 # Float message from three infrared sensors IO pin.
-Header header
+std_msgs/Header header
 
 
-float64 front_dist
-float64 left_dist
-float64 right_dist
+uint8 INFRARED=1
+uint8 radiation_type
+
+float32 field_of_view
+float32 min_range
+float32 max_range
+
+float32 front_dist
+float32 left_dist
+float32 right_dist

+ 2 - 5
src/ros_arduino_bridge/ros_arduino_python/config/my_arduino_params.yaml

@@ -12,7 +12,6 @@ i2c_slave_addr: 0x08  #Get arduino due i2c slave addr
 timeout: 0.5
 timeout: 0.5
 
 
 rate: 25
 rate: 25
-sensorstate_rate: 10
 
 
 cmd_topic: cmd_vel
 cmd_topic: cmd_vel
 
 
@@ -50,12 +49,10 @@ CWheel_Kd: 15
 CWheel_Ki: 0
 CWheel_Ki: 0
 CWheel_Ko: 50
 CWheel_Ko: 50
 
 
-# === Sensor definitions.  Examples only - edit for your robot.
-#     Sensor type can be one of the follow (case sensitive!):
-#	  * GP2D12
+# === Sensor definitions.Sensor type can be one of the follow (case sensitive!):
 #	  * Analog
 #	  * Analog
 #	  * Digital
 #	  * Digital
 sensors: {
 sensors: {
-  #antiDropIR_front: {pin: 22, type: Digital, rate: 5, direction: input},
+  GP2Y0A41: {pin: 0, type: GP2Y0A41, rate: 10, direction: input},
 }
 }
 
 

+ 5 - 37
src/ros_arduino_bridge/ros_arduino_python/nodes/arduino_node.py

@@ -7,12 +7,12 @@
 import os
 import os
 import rospy
 import rospy
 import thread
 import thread
-from ros_arduino_python.arduino_driver import Arduino
-from ros_arduino_python.arduino_sensors import *
 from ros_arduino_msgs.srv import *
 from ros_arduino_msgs.srv import *
-from ros_arduino_python.base_controller import BaseController
 from geometry_msgs.msg import Twist
 from geometry_msgs.msg import Twist
 from serial.serialutil import SerialException
 from serial.serialutil import SerialException
+from ros_arduino_python.arduino_sensors import *
+from ros_arduino_python.arduino_driver import Arduino
+from ros_arduino_python.base_controller import BaseController
 
 
 class ArduinoROS():
 class ArduinoROS():
     def __init__(self):
     def __init__(self):
@@ -37,24 +37,12 @@ class ArduinoROS():
         self.rate = int(rospy.get_param("~rate", 20))
         self.rate = int(rospy.get_param("~rate", 20))
         loop_rate = rospy.Rate(self.rate)
         loop_rate = rospy.Rate(self.rate)
 
 
-        # Rate at which summary SensorState message is published. Individual sensors publish
-        # at their own rates.
-        self.sensorstate_rate = int(rospy.get_param("~sensorstate_rate", 10))
-
-        # Set up the time for publishing the next SensorState message
-        now = rospy.Time.now()
-        self.t_delta_sensors = rospy.Duration(1.0 / self.sensorstate_rate)
-        self.t_next_sensors  = now + self.t_delta_sensors
-
         # Initialize a Twist message
         # Initialize a Twist message
         self.cmd_vel = Twist()
         self.cmd_vel = Twist()
 
 
         # A cmd_vel publisher so we can stop the robot when shutting down
         # A cmd_vel publisher so we can stop the robot when shutting down
         self.cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=20)
         self.cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=20)
 
 
-        # The publisher periodically publishes the values of all sensors on a single topic.
-        self.sensorStatePub = rospy.Publisher('~sensor_state', SensorState, queue_size=5)
-
         # A service to turn set the direction of a digital pin (0 = input, 1 = output)
         # A service to turn set the direction of a digital pin (0 = input, 1 = output)
         rospy.Service('~digital_set_direction', DigitalSetDirection, self.DigitalSetDirectionHandler)
         rospy.Service('~digital_set_direction', DigitalSetDirection, self.DigitalSetDirectionHandler)
 
 
@@ -81,7 +69,6 @@ class ArduinoROS():
 
 
         # Make the connection
         # Make the connection
         self.controller.connect()
         self.controller.connect()
-        #rospy.loginfo("Connected to Arduino on port " + self.serial_port + " at " + str(self.serial_baud) + " serial baud !")
 
 
         # Reserve a thread lock
         # Reserve a thread lock
         mutex = thread.allocate_lock()
         mutex = thread.allocate_lock()
@@ -97,12 +84,10 @@ class ArduinoROS():
             except:
             except:
                 params['direction'] = 'input'
                 params['direction'] = 'input'
 
 
-            if params['type'] == "GP2D12":
-                sensor = GP2D12(self.controller, name, params['pin'], params['rate'], self.base_frame)
+            if params['type'] == "GP2Y0A41":
+                sensor = GP2Y0A41(self.controller, name, params['pin'], params['rate'], self.base_frame)
             elif params['type'] == "IR2Y0A02":
             elif params['type'] == "IR2Y0A02":
                 sensor = IR2Y0A02(self.controller, name, params['pin'], params['rate'], self.base_frame)
                 sensor = IR2Y0A02(self.controller, name, params['pin'], params['rate'], self.base_frame)
-            elif params['type'] == "GP2Y0A41":
-                sensor = GP2Y0A41(self.controller, name, params['pin'], params['rate'], self.base_frame)
             elif params['type'] == 'Digital':
             elif params['type'] == 'Digital':
                 sensor = DigitalSensor(self.controller, name, params['pin'], params['rate'], self.base_frame, direction=params['direction'])
                 sensor = DigitalSensor(self.controller, name, params['pin'], params['rate'], self.base_frame, direction=params['direction'])
             elif params['type'] == 'Analog':
             elif params['type'] == 'Analog':
@@ -123,7 +108,6 @@ class ArduinoROS():
 
 
         # Start polling the sensors and base controller
         # Start polling the sensors and base controller
         while not rospy.is_shutdown():
         while not rospy.is_shutdown():
-            # Base controller
             mutex.acquire()
             mutex.acquire()
             self.myBaseController.poll()
             self.myBaseController.poll()
             mutex.release()
             mutex.release()
@@ -133,22 +117,6 @@ class ArduinoROS():
                 sensor.poll()
                 sensor.poll()
                 mutex.release()
                 mutex.release()
 
 
-            # Publish all sensor values on a single topic for convenience
-            now = rospy.Time.now()
-            if now > self.t_next_sensors:
-                msg = SensorState()
-                msg.header.frame_id = self.base_frame
-                msg.header.stamp    = now
-                for i in range(len(self.mySensors)):
-                    msg.name.append(self.mySensors[i].name)
-                    msg.value.append(self.mySensors[i].value)
-                try:
-                    self.sensorStatePub.publish(msg)
-                except:
-                    pass
-
-                self.t_next_sensors = now + self.t_delta_sensors
-
             loop_rate.sleep()
             loop_rate.sleep()
 
 
     def DigitalSetDirectionHandler(self, req):
     def DigitalSetDirectionHandler(self, req):

+ 38 - 47
src/ros_arduino_bridge/ros_arduino_python/src/ros_arduino_python/arduino_driver.py

@@ -1,14 +1,15 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
+#-*- coding:utf-8 -*-
 
 
 """
 """
-    A Python driver for the Arduino microcontroller running the
-    ROSArduinoBridge firmware.
+    A Python driver for the Arduino microcontroller.
 """
 """
 
 
 from math import pi as PI
 from math import pi as PI
 import sys, traceback
 import sys, traceback
 from serial.serialutil import SerialException
 from serial.serialutil import SerialException
 from serial import Serial
 from serial import Serial
+import numpy as np
 import thread
 import thread
 import smbus
 import smbus
 import rospy
 import rospy
@@ -22,15 +23,16 @@ class Arduino:
     N_ANALOG_PORTS  = 10
     N_ANALOG_PORTS  = 10
     N_DIGITAL_PORTS = 54
     N_DIGITAL_PORTS = 54
 
 
-    def __init__(self, is_use_serial, serial_port="/dev/ttyACM0", baudrate=57600,i2c_smbus_num=1, i2c_slave_addr=8, timeout=0.5):
-        self.PID_RATE = 40 # Do not change this!  It is a fixed property of the Arduino PID controller.
+    def __init__(self, is_use_serial,serial_port="/dev/ttyACM0",baudrate=57600,i2c_smbus_num=1,i2c_slave_addr=8,timeout=0.5):
+        self.PID_RATE = 40   #Don't change this ! It is a fixed property of the Arduino PID controller.
         self.PID_INTERVAL = 25
         self.PID_INTERVAL = 25
 
 
-        self.is_use_serial = is_use_serial
-        self.serial_port   = serial_port
-        self.baudrate = baudrate
+        self.is_use_serial = is_use_serial #与下位机arduino的通信方式是否使用串口还是IIC
 
 
-        self.i2c_smbus_num = i2c_smbus_num
+        self.serial_port = serial_port
+        self.baudrate    = baudrate
+
+        self.i2c_smbus_num  = i2c_smbus_num
         self.i2c_slave_addr = i2c_slave_addr
         self.i2c_slave_addr = i2c_slave_addr
 
 
         self.timeout  = timeout
         self.timeout  = timeout
@@ -64,7 +66,6 @@ class Arduino:
             test = self.get_baud()
             test = self.get_baud()
             if test != self.baudrate:
             if test != self.baudrate:
                 time.sleep(1)
                 time.sleep(1)
-                print "Connecting ..."
                 test = self.get_baud()
                 test = self.get_baud()
                 if test != self.baudrate:
                 if test != self.baudrate:
                     raise SerialException
                     raise SerialException
@@ -82,7 +83,6 @@ class Arduino:
 
 
     def i2c_connect(self):
     def i2c_connect(self):
         try:
         try:
-
             print "Connecting to Arduino on IIC addr ", self.i2c_slave_addr, "..."
             print "Connecting to Arduino on IIC addr ", self.i2c_slave_addr, "..."
             test = self.i2c_get_baud()
             test = self.i2c_get_baud()
             if test != self.baudrate:
             if test != self.baudrate:
@@ -102,18 +102,20 @@ class Arduino:
             print "Cannot connect to Arduino IIC slave addr !"
             print "Cannot connect to Arduino IIC slave addr !"
             os._exit(1)
             os._exit(1)
 
 
-
     def open(self):
     def open(self):
         ''' Open the serial port.
         ''' Open the serial port.
         '''
         '''
         self.serial_port.open()
         self.serial_port.open()
 
 
     def close(self):
     def close(self):
-        ''' Close the serial port.
+        ''' Close the serial port or i2c bus connect.
         '''
         '''
+        print "Now disconnecting ..."
         self.beep_ring(0)
         self.beep_ring(0)
-        self.serial_port.close()
-        self.i2c_bus.close()
+        if self.is_use_serial:
+            self.serial_port.close()
+        else:
+            self.i2c_bus.close()
 
 
     def send(self, cmd):
     def send(self, cmd):
         ''' This command should not be used on its own: it is called by the execute commands
         ''' This command should not be used on its own: it is called by the execute commands
@@ -163,7 +165,7 @@ class Arduino:
         '''
         '''
         try:
         try:
             values = self.recv(self.timeout * self.N_ANALOG_PORTS).split()
             values = self.recv(self.timeout * self.N_ANALOG_PORTS).split()
-            return map(int, values)
+            return map(float, values)
         except:
         except:
             return []
             return []
 
 
@@ -179,7 +181,6 @@ class Arduino:
 
 
         ntries   = 1
         ntries   = 1
         attempts = 0
         attempts = 0
-
         try:
         try:
             self.serial_port.write(cmd + '\r')
             self.serial_port.write(cmd + '\r')
             value = self.recv(self.timeout)
             value = self.recv(self.timeout)
@@ -200,7 +201,7 @@ class Arduino:
         return value
         return value
 
 
     def execute_array(self, cmd):
     def execute_array(self, cmd):
-        ''' Thread safe execution of "cmd" on the Arduino returning an array.
+        ''' Thread safe execution of "cmd" on the Arduino returning an float array.
         '''
         '''
         self.mutex.acquire()
         self.mutex.acquire()
         try:
         try:
@@ -228,7 +229,7 @@ class Arduino:
             return []
             return []
 
 
         try:
         try:
-            values = map(int, values)
+            values = map(float, values)
         except:
         except:
             values = []
             values = []
 
 
@@ -247,7 +248,6 @@ class Arduino:
 
 
         ntries   = 1
         ntries   = 1
         attempts = 0
         attempts = 0
-
         try:
         try:
             self.serial_port.write(cmd + '\r')
             self.serial_port.write(cmd + '\r')
             ack = self.recv(self.timeout)
             ack = self.recv(self.timeout)
@@ -271,7 +271,7 @@ class Arduino:
     def update_pid(self, AWheel_Kp, AWheel_Kd, AWheel_Ki, AWheel_Ko,
     def update_pid(self, AWheel_Kp, AWheel_Kd, AWheel_Ki, AWheel_Ko,
                          BWheel_Kp, BWheel_Kd, BWheel_Ki, BWheel_Ko,
                          BWheel_Kp, BWheel_Kd, BWheel_Ki, BWheel_Ko,
                          CWheel_Kp, CWheel_Kd, CWheel_Ki, CWheel_Ko ):
                          CWheel_Kp, CWheel_Kd, CWheel_Ki, CWheel_Ko ):
-        ''' Set the PID parameters on the Arduino
+        ''' Set the PID parameters on the Arduino by serial
         '''
         '''
         print "Updating PID parameters"
         print "Updating PID parameters"
         cmd = 'u '+str(AWheel_Kp)+':'+str(AWheel_Kd)+':'+str(AWheel_Ki)+':'+str(AWheel_Ko)+':'+str(BWheel_Kp)+':'+str(BWheel_Kd)+':'+str(BWheel_Ki)+':'+str(BWheel_Ko)+':'+str(CWheel_Kp)+':'+str(CWheel_Kd)+':'+str(CWheel_Ki)+':'+str(CWheel_Ko)
         cmd = 'u '+str(AWheel_Kp)+':'+str(AWheel_Kd)+':'+str(AWheel_Ki)+':'+str(AWheel_Ko)+':'+str(BWheel_Kp)+':'+str(BWheel_Kd)+':'+str(BWheel_Ki)+':'+str(BWheel_Ko)+':'+str(CWheel_Kp)+':'+str(CWheel_Kd)+':'+str(CWheel_Ki)+':'+str(CWheel_Ko)
@@ -339,7 +339,6 @@ class Arduino:
         else:
         else:
             return values
             return values
 
 
-
     def reset_encoders(self):
     def reset_encoders(self):
         ''' Reset the encoder counts to 0 by serial port
         ''' Reset the encoder counts to 0 by serial port
         '''
         '''
@@ -370,19 +369,6 @@ class Arduino:
         except:
         except:
             return None
             return None
 
 
-    def drive_m_per_s(self, AWheel, BWheel, CWheel):
-        ''' Set the motor speeds in meters per second.
-        '''
-        aWheel_revs_per_second = float(AWheel) / (self.wheel_diameter * PI)
-        bWheel_revs_per_second = float(BWheel) / (self.wheel_diameter * PI)
-        cWheel_revs_per_second = float(CWheel) / (self.wheel_diameter * PI)
-
-        aWheel_ticks_per_loop = int(aWheel_revs_per_second * self.encoder_resolution * self.PID_INTERVAL * self.gear_reduction)
-        bWheel_ticks_per_loop = int(bWheel_revs_per_second * self.encoder_resolution * self.PID_INTERVAL * self.gear_reduction)
-        cWheel_ticks_per_loop = int(cWheel_revs_per_second * self.encoder_resolution * self.PID_INTERVAL * self.gear_reduction)
-
-        self.drive(aWheel_ticks_per_loop , bWheel_ticks_per_loop, cWheel_ticks_per_loop)
-
     def stop(self):
     def stop(self):
         ''' Stop all three motors.
         ''' Stop all three motors.
         '''
         '''
@@ -410,9 +396,6 @@ class Arduino:
     def pin_mode(self, pin, mode):
     def pin_mode(self, pin, mode):
         return self.execute_ack('c %d %d' %(pin, mode))
         return self.execute_ack('c %d %d' %(pin, mode))
 
 
-    def alarm_write(self, value):
-        return self.execute_ack('f %d' %value)
-
     def beep_ring(self, value):
     def beep_ring(self, value):
         return self.execute_ack('p %d' %value)
         return self.execute_ack('p %d' %value)
 
 
@@ -422,6 +405,9 @@ class Arduino:
     def detect_current(self):
     def detect_current(self):
         return self.execute('f')
         return self.execute('f')
 
 
+    def detect_distance(self): #检测三个红外测距传感器的返回值,一共返回三个值,分别为前,左,右三个测距值
+        return self.execute_array('h')
+
     def light_show(self, value):
     def light_show(self, value):
         return self.execute_ack('l %d' %value)
         return self.execute_ack('l %d' %value)
 
 
@@ -463,28 +449,33 @@ class Arduino:
         #else:
         #else:
         #    return values
         #    return values
 
 
-""" Basic test for connectivity """
+""" Basic test for connectivity by serial port or IIC bus"""
 if __name__ == "__main__":
 if __name__ == "__main__":
+    is_use_serial = True
     portName = "/dev/ttyACM0"
     portName = "/dev/ttyACM0"
     baudRate = 57600
     baudRate = 57600
 
 
-    myArduino = Arduino(port=portName, baudrate=baudRate, timeout=0.5)
+    iic_smbus = 1
+    iic_num = 8
+
+    myArduino = Arduino(is_use_serial, serial_port=portName, baudrate=baudRate, i2c_smbus_num=iic_smbus, i2c_slave_addr=iic_num, timeout=0.5)
     myArduino.connect()
     myArduino.connect()
 
 
     print "Sleeping for 1 second..."
     print "Sleeping for 1 second..."
     time.sleep(1)
     time.sleep(1)
 
 
-    print "Reading on analog port 0", myArduino.analog_read(0)
-    print "Reading on digital port 0", myArduino.digital_read(0)
-    print "Blinking the LED 3 times"
+    print "Test Beep ring 3 times..."
     for i in range(3):
     for i in range(3):
-        myArduino.digital_write(13, 1)
-        time.sleep(1.0)
-    #print "Current encoder counts", myArduino.encoders()
-    print "Connection test successful.",
+        myArduino.beep_ring(1)
+        time.sleep(2.0)
+
+    print "Did you heard the beep ring ?"
+    print "Now print infrared sensors value:"
+    values = myArduino.detect_distance()
+    distances = np.array([values[0], values[1], values[2]])
+    print distances/100.0
 
 
     myArduino.stop()
     myArduino.stop()
     myArduino.close()
     myArduino.close()
-
     print "Shutting down Arduino."
     print "Shutting down Arduino."
 
 

+ 43 - 57
src/ros_arduino_bridge/ros_arduino_python/src/ros_arduino_python/arduino_sensors.py

@@ -6,10 +6,12 @@
 
 
 import roslib; roslib.load_manifest('ros_arduino_python')
 import roslib; roslib.load_manifest('ros_arduino_python')
 import rospy
 import rospy
+import numpy as np
 from decimal import Decimal
 from decimal import Decimal
 from sensor_msgs.msg import Range
 from sensor_msgs.msg import Range
 from ros_arduino_msgs.msg import *
 from ros_arduino_msgs.msg import *
 
 
+
 LOW = 0
 LOW = 0
 HIGH = 1
 HIGH = 1
 
 
@@ -17,12 +19,13 @@ INPUT = 0
 OUTPUT = 1
 OUTPUT = 1
 
 
 class MessageType:
 class MessageType:
-    ANALOG  = 0
-    DIGITAL = 1
-    RANGE   = 2
-    FLOAT   = 3
-    INT     = 4
-    BOOL    = 5
+    ANALOG   = 0
+    DIGITAL  = 1
+    INFRARED = 2
+    RANGE    = 3
+    FLOAT    = 4
+    INT      = 5
+    BOOL     = 6
 
 
 class Sensor(object):
 class Sensor(object):
     def __init__(self, controller, name, pin, rate, frame_id, direction="input", **kwargs):
     def __init__(self, controller, name, pin, rate, frame_id, direction="input", **kwargs):
@@ -55,6 +58,10 @@ class Sensor(object):
             # For range sensors, assign the value to the range message field
             # For range sensors, assign the value to the range message field
             if self.message_type == MessageType.RANGE:
             if self.message_type == MessageType.RANGE:
                 self.msg.range = self.value
                 self.msg.range = self.value
+            elif self.message_type == MessageType.INFRARED:
+                self.msg.front_dist = self.value[0]
+                self.msg.left_dist  = self.value[1]
+                self.msg.right_dist = self.value[2]
             else:
             else:
                 self.msg.value = self.value
                 self.msg.value = self.value
 
 
@@ -112,7 +119,6 @@ class AnalogFloatSensor(Sensor):
     def write_value(self, value):
     def write_value(self, value):
         return self.controller.analog_write(self.pin, value)
         return self.controller.analog_write(self.pin, value)
 
 
-
 class DigitalSensor(Sensor):
 class DigitalSensor(Sensor):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super(DigitalSensor, self).__init__(*args, **kwargs)
         super(DigitalSensor, self).__init__(*args, **kwargs)
@@ -144,27 +150,54 @@ class RangeSensor(Sensor):
         super(RangeSensor, self).__init__(*args, **kwargs)
         super(RangeSensor, self).__init__(*args, **kwargs)
 
 
         self.message_type = MessageType.RANGE
         self.message_type = MessageType.RANGE
-
         self.msg = Range()
         self.msg = Range()
         self.msg.header.frame_id = self.frame_id
         self.msg.header.frame_id = self.frame_id
-
         self.pub = rospy.Publisher("~sensor/" + self.name, Range, queue_size=5)
         self.pub = rospy.Publisher("~sensor/" + self.name, Range, queue_size=5)
 
 
     def read_value(self):
     def read_value(self):
         self.msg.header.stamp = rospy.Time.now()
         self.msg.header.stamp = rospy.Time.now()
 
 
+class MyRangeSensor(Sensor):
+    def __init__(self, *args, **kwargs):
+        super(MyRangeSensor, self).__init__(*args, **kwargs)
+
+        self.message_type = MessageType.INFRARED
+        self.msg = InfraredSensors()
+        self.msg.header.frame_id = self.frame_id
+
+        self.pub = rospy.Publisher("~sensor/" + self.name, InfraredSensors, queue_size=2)
+
+    def read_value(self):
+        self.msg.header.stamp = rospy.Time.now()
+
 class SonarSensor(RangeSensor):
 class SonarSensor(RangeSensor):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super(SonarSensor, self).__init__(*args, **kwargs)
         super(SonarSensor, self).__init__(*args, **kwargs)
-
         self.msg.radiation_type = Range.ULTRASOUND
         self.msg.radiation_type = Range.ULTRASOUND
 
 
 class IRSensor(RangeSensor):
 class IRSensor(RangeSensor):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super(IRSensor, self).__init__(*args, **kwargs)
         super(IRSensor, self).__init__(*args, **kwargs)
+        self.msg.radiation_type = Range.INFRARED
 
 
+class MyIRSensor(MyRangeSensor):
+    def __init__(self, *args, **kwargs):
+        super(MyIRSensor, self).__init__(*args, **kwargs)
         self.msg.radiation_type = Range.INFRARED
         self.msg.radiation_type = Range.INFRARED
 
 
+class GP2Y0A41(MyIRSensor):
+    def __init__(self, *args, **kwargs):
+        super(GP2Y0A41, self).__init__(*args, **kwargs)
+
+        self.msg.field_of_view = 0.01
+        self.msg.min_range = 0.04
+        self.msg.max_range = 0.30
+
+    def read_value(self):
+        values = self.controller.detect_distance()
+        distances = np.array([values[0], values[1], values[2]])
+        return distances/100.0
+
 class IR2Y0A02(IRSensor):
 class IR2Y0A02(IRSensor):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super(IR2Y0A02, self).__init__(*args, **kwargs)
         super(IR2Y0A02, self).__init__(*args, **kwargs)
@@ -192,53 +225,6 @@ class IR2Y0A02(IRSensor):
 
 
         return dist
         return dist
 
 
-class GP2Y0A41(IRSensor):
-    def __init__(self, *args, **kwargs):
-        super(GP2Y0A41, self).__init__(*args, **kwargs)
-
-        self.msg.field_of_view = 0.001
-        self.msg.min_range = 0.04
-        self.msg.max_range = 0.30
-
-    def read_value(self):
-        value = self.controller.analog_read(self.pin)
-
-        dist = 20.76/(value - 11.0)
-
-        # If we get a spurious reading, set it to the max_range
-        if dist > self.msg.max_range: dist = self.msg.max_range
-        if dist < self.msg.min_range: dist = self.msg.min_range
-
-        return Decimal(dist).quantize(Decimal('0.000'))
-
-class GP2D12(IRSensor):
-    def __init__(self, *args, **kwargs):
-        super(GP2D12, self).__init__(*args, **kwargs)
-
-        self.msg.field_of_view = 0.001
-        self.msg.min_range = 0.10
-        self.msg.max_range = 0.80
-
-    def read_value(self):
-        value = self.controller.analog_read(self.pin)
-
-        if value <= 3.0:
-            return self.msg.max_range
-
-        try:
-            distance = (6787.0 / (float(value) - 3.0)) - 4.0
-        except:
-            return self.msg.max_range
-
-        # Convert to meters
-        distance /= 100.0
-
-        # If we get a spurious reading, set it to the max_range
-        if distance > self.msg.max_range: distance = self.msg.max_range
-        if distance < self.msg.min_range: distance = self.msg.max_range
-
-        return distance
-
 class MotorTotalCurrent(AnalogFloatSensor):
 class MotorTotalCurrent(AnalogFloatSensor):
     def __init__(self, *args, **kwargs):
     def __init__(self, *args, **kwargs):
         super(MotorTotalCurrent, self).__init__(*args, **kwargs)
         super(MotorTotalCurrent, self).__init__(*args, **kwargs)