00001
00002
00003 """
00004 A ROS Node for the Arduino microcontroller
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 rospy
00023 from ros_arduino_python.arduino_driver import Arduino
00024 from ros_arduino_python.arduino_sensors import *
00025 from ros_arduino_msgs.srv import *
00026 from ros_arduino_python.base_controller import BaseController
00027 from geometry_msgs.msg import Twist
00028 import os, time
00029 import thread
00030
00031 class ArduinoROS():
00032 def __init__(self):
00033 rospy.init_node('Arduino', log_level=rospy.DEBUG)
00034
00035
00036 rospy.on_shutdown(self.shutdown)
00037
00038 self.port = rospy.get_param("~port", "/dev/ttyACM0")
00039 self.baud = int(rospy.get_param("~baud", 57600))
00040 self.timeout = rospy.get_param("~timeout", 0.5)
00041 self.base_frame = rospy.get_param("~base_frame", 'base_link')
00042
00043
00044 self.rate = int(rospy.get_param("~rate", 50))
00045 r = rospy.Rate(self.rate)
00046
00047
00048
00049 self.sensorstate_rate = int(rospy.get_param("~sensorstate_rate", 10))
00050
00051 self.use_base_controller = rospy.get_param("~use_base_controller", False)
00052
00053
00054 now = rospy.Time.now()
00055 self.t_delta_sensors = rospy.Duration(1.0 / self.sensorstate_rate)
00056 self.t_next_sensors = now + self.t_delta_sensors
00057
00058
00059 self.cmd_vel = Twist()
00060
00061
00062 self.cmd_vel_pub = rospy.Publisher('cmd_vel', Twist)
00063
00064
00065
00066 self.sensorStatePub = rospy.Publisher('~sensor_state', SensorState)
00067
00068
00069 rospy.Service('~servo_write', ServoWrite, self.ServoWriteHandler)
00070
00071
00072 rospy.Service('~servo_read', ServoRead, self.ServoReadHandler)
00073
00074
00075 rospy.Service('~digital_set_direction', DigitalSetDirection, self.DigitalSetDirectionHandler)
00076
00077
00078 rospy.Service('~digital_write', DigitalWrite, self.DigitalWriteHandler)
00079
00080
00081 rospy.Service('~analog_write', AnalogWrite, self.AnalogWriteHandler)
00082
00083
00084 self.controller = Arduino(self.port, self.baud, self.timeout)
00085
00086
00087 self.controller.connect()
00088
00089 rospy.loginfo("Connected to Arduino on port " + self.port + " at " + str(self.baud) + " baud")
00090
00091
00092 mutex = thread.allocate_lock()
00093
00094
00095 self.mySensors = list()
00096
00097 sensor_params = rospy.get_param("~sensors", dict({}))
00098
00099 for name, params in sensor_params.iteritems():
00100
00101 try:
00102 params['direction']
00103 except:
00104 params['direction'] = 'input'
00105
00106 if params['type'] == "Ping":
00107 sensor = Ping(self.controller, name, params['pin'], params['rate'], self.base_frame)
00108 elif params['type'] == "GP2D12":
00109 sensor = GP2D12(self.controller, name, params['pin'], params['rate'], self.base_frame)
00110 elif params['type'] == 'Digital':
00111 sensor = DigitalSensor(self.controller, name, params['pin'], params['rate'], self.base_frame, direction=params['direction'])
00112 elif params['type'] == 'Analog':
00113 sensor = AnalogSensor(self.controller, name, params['pin'], params['rate'], self.base_frame, direction=params['direction'])
00114 elif params['type'] == 'PololuMotorCurrent':
00115 sensor = PololuMotorCurrent(self.controller, name, params['pin'], params['rate'], self.base_frame)
00116 elif params['type'] == 'PhidgetsVoltage':
00117 sensor = PhidgetsVoltage(self.controller, name, params['pin'], params['rate'], self.base_frame)
00118 elif params['type'] == 'PhidgetsCurrent':
00119 sensor = PhidgetsCurrent(self.controller, name, params['pin'], params['rate'], self.base_frame)
00120
00121
00122
00123
00124
00125 self.mySensors.append(sensor)
00126 rospy.loginfo(name + " " + str(params))
00127
00128
00129 if self.use_base_controller:
00130 self.myBaseController = BaseController(self.controller, self.base_frame)
00131
00132
00133 while not rospy.is_shutdown():
00134 for sensor in self.mySensors:
00135 mutex.acquire()
00136 sensor.poll()
00137 mutex.release()
00138
00139 if self.use_base_controller:
00140 mutex.acquire()
00141 self.myBaseController.poll()
00142 mutex.release()
00143
00144
00145 now = rospy.Time.now()
00146
00147 if now > self.t_next_sensors:
00148 msg = SensorState()
00149 msg.header.frame_id = self.base_frame
00150 msg.header.stamp = now
00151 for i in range(len(self.mySensors)):
00152 msg.name.append(self.mySensors[i].name)
00153 msg.value.append(self.mySensors[i].value)
00154 try:
00155 self.sensorStatePub.publish(msg)
00156 except:
00157 pass
00158
00159 self.t_next_sensors = now + self.t_delta_sensors
00160
00161 r.sleep()
00162
00163
00164 def ServoWriteHandler(self, req):
00165 self.controller.servo_write(req.id, req.value)
00166 return ServoWriteResponse()
00167
00168 def ServoReadHandler(self, req):
00169 self.controller.servo_read(req.id)
00170 return ServoReadResponse()
00171
00172 def DigitalSetDirectionHandler(self, req):
00173 self.controller.pin_mode(req.pin, req.direction)
00174 return DigitalSetDirectionResponse()
00175
00176 def DigitalWriteHandler(self, req):
00177 self.controller.digital_write(req.pin, req.value)
00178 return DigitalWriteResponse()
00179
00180 def AnalogWriteHandler(self, req):
00181 self.controller.analog_write(req.pin, req.value)
00182 return AnalogWriteResponse()
00183
00184 def shutdown(self):
00185
00186 try:
00187 rospy.loginfo("Stopping the robot...")
00188 self.cmd_vel_pub.Publish(Twist())
00189 rospy.sleep(2)
00190 except:
00191 pass
00192 rospy.loginfo("Shutting down Arduino Node...")
00193
00194 if __name__ == '__main__':
00195 myArduino = ArduinoROS()