PhidgetMotor.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 """Phidgets HC Motor Control ROS service for CoroBot
00003 
00004 A ROS service to request a specific acceleration and individual
00005 side drive wheels speed.
00006 
00007 """
00008 
00009 __author__ = 'Bill Mania <bmania@coroware.com>'
00010 __version__ = '1'
00011 
00012 import roslib; roslib.load_manifest('PhidgetMotor')
00013 from corobot_srvs.srv import *
00014 from corobot_msgs.msg import *
00015 import rospy
00016 from  threading import Timer
00017 from ctypes import *
00018 from Phidgets.Devices.MotorControl import MotorControl
00019 from Phidgets.PhidgetException import PhidgetErrorCodes, PhidgetException
00020 from Phidgets.Events.Events import EncoderPositionUpdateEventArgs
00021 
00022 motors_inverted = False
00023 
00024 phidget1065 = False
00025 motorControl = 0
00026 motorControlRight = 0
00027 leftWheels = 0
00028 rightWheels = 1
00029 minAcceleration = 0
00030 maxAcceleration = 0
00031 minSpeed = -100
00032 maxSpeed = 100
00033 timer = 0
00034 posdataPub = 0
00035 leftPosition = 0
00036 rightPosition = 0
00037 
00038 def stop():
00039     try:
00040         motorControl.setVelocity(leftWheels,0);
00041 
00042         if phidget1065 == True:
00043             motorControlRight.setVelocity(rightWheels,0);
00044         else:
00045                 motorControl.setVelocity(rightWheels, 0);
00046     except PhidgetException as e:
00047         rospy.logerr("Failed in setVelocity() %i: %s", e.code, e.details)
00048         return(False)
00049     return(True)
00050 
00051 
00052 def move(request):
00053     """Cause the CoroBot to move or stop moving
00054 
00055     Request a common acceleration, wheel directions and wheel speeds
00056 
00057     """
00058     global timer
00059     if timer:
00060         timer.cancel();
00061     rospy.logdebug(
00062             "Left: %d:%d, Right: %d:%d, Acceleration: %d", 
00063             leftWheels,
00064             request.leftSpeed,
00065             rightWheels,
00066             request.rightSpeed,
00067             request.acceleration
00068             )
00069     if request.acceleration > maxAcceleration:
00070         acceleration = float(maxAcceleration)
00071     elif request.acceleration < minAcceleration:
00072         acceleration = float(minAcceleration)
00073     else: 
00074         acceleration = float(request.acceleration)
00075 
00076     if request.leftSpeed < minSpeed:
00077         leftSpeed = float(minSpeed)
00078     elif request.leftSpeed > maxSpeed:
00079         leftSpeed = float(maxSpeed)
00080     else:
00081         leftSpeed = float(request.leftSpeed)
00082     if request.rightSpeed < minSpeed:
00083         rightSpeed = float(minSpeed)
00084     elif request.rightSpeed > maxSpeed:
00085         rightSpeed = float(maxSpeed)
00086     else:
00087         rightSpeed = float(request.rightSpeed)
00088 
00089 
00090     if motors_inverted == True:
00091         temp = rightSpeed
00092         rightSpeed = -leftSpeed
00093         leftSpeed = -temp
00094 
00095     rospy.logdebug(
00096             "Left: %d:%d, Right: %d:%d, Acceleration: %d", 
00097             leftWheels,
00098             leftSpeed,
00099             rightWheels,
00100             rightSpeed,
00101             acceleration
00102             )
00103 
00104     try:
00105         motorControl.setAcceleration(leftWheels, acceleration);
00106                 
00107         if phidget1065 == True:
00108             motorControlRight.setAcceleration(rightWheels, acceleration);
00109         else:
00110             motorControl.setAcceleration(rightWheels, acceleration);
00111     except PhidgetException as e:
00112         rospy.logerr("Failed in setAcceleration() %i: %s", e.code, e.details)
00113         return(False)
00114 
00115     try:
00116         motorControl.setVelocity(leftWheels, leftSpeed);
00117 
00118         if phidget1065 == True:
00119             motorControlRight.setVelocity(rightWheels, rightSpeed);
00120         else:
00121             motorControl.setVelocity(rightWheels, rightSpeed);
00122     except PhidgetException as e:
00123         rospy.logerr("Failed in setVelocity() %i: %s", e.code, e.details)
00124         return(False)
00125 
00126     if request.secondsDuration != 0:
00127         timer = Timer(request.secondsDuration, stop)
00128         timer.start()
00129     return(True)
00130 
00131 def mcAttached(e):
00132     return
00133 
00134 def mcDetached(e):
00135     return
00136 
00137 def mcError(e):
00138     return
00139 
00140 def mcCurrentChanged(e):
00141     return
00142 
00143 def mcInputChanged(e):
00144     return
00145 
00146 def mcVelocityChanged(e):
00147     return
00148 
00149 def leftEncoderUpdated(e):
00150 
00151     global leftPosition, rightPosition
00152         
00153     leftPosition += e.positionChange
00154     if motorControlRight:
00155         rightPosition = motorControlRight.getEncoderPosition(rightWheels) # update the right encoder so that we have a correct value of both encoders at a given time.
00156 
00157         # send message on the position topic
00158     msg = PosMsg()
00159     msg.px = leftPosition
00160     msg.py = rightPosition
00161     msg.header.stamp = rospy.Time.now()
00162     posdataPub.publish(msg)
00163 
00164     return
00165 
00166 def rightEncoderUpdated(e):
00167 
00168     global leftPosition, rightPosition
00169 
00170     rightPosition += e.positionChange
00171     if motorControl:
00172         leftPosition = motorControl.getEncoderPosition(leftWheels) # update the left encoder so that we have a correct value of both encoders at a given time.
00173 
00174         # send message on the position topic
00175     msg = PosMsg()
00176     msg.px = leftPosition
00177     msg.py = rightPosition
00178     msg.header.stamp = rospy.Time.now()
00179     posdataPub.publish(msg)
00180 
00181     return
00182 
00183 def setupMoveService():
00184     """Initialize the PhidgetMotor service
00185 
00186     Establish a connection with the Phidget HC Motor Control and
00187     then with the ROS Master as the service PhidgetMotor
00188 
00189     """
00190 
00191     rospy.init_node(
00192             'PhidgetMotor',
00193             log_level = rospy.DEBUG
00194             )
00195 
00196     global motorControl, motorControlRight, minAcceleration, maxAcceleration, timer, motors_inverted, phidget1065, rightWheels, posdataPub
00197     timer = 0
00198     try:
00199         motorControl = MotorControl()
00200     except:
00201         rospy.logerr("Unable to connect to Phidget HC Motor Control")
00202         return
00203 
00204     try:
00205         motorControl.setOnAttachHandler(mcAttached)
00206         motorControl.setOnDetachHandler(mcDetached)
00207         motorControl.setOnErrorhandler(mcError)
00208         motorControl.setOnCurrentChangeHandler(mcCurrentChanged)
00209         motorControl.setOnInputChangeHandler(mcInputChanged)
00210         motorControl.setOnVelocityChangeHandler(mcVelocityChanged)
00211         motorControl.openPhidget()
00212 
00213         #attach the board
00214         motorControl.waitForAttach(10000)
00215         """use the function getMotorCount() to know how many motors the Phidget board can take
00216 
00217         if the result is more than 1, we have a 1064 board and we take care of both motors with one motorControl variable. The corobot_phidgetIK handles the Phidget encoder board that is 
00218         separated of the phidget 1064.
00219         if the result is equal to 1, we have two phidget 1065 boards. The one with serial number that is the lowest will be the left will, the other the right weel. The encoder has to be handled 
00220         in this file as it is part of the 1065 board. 
00221 
00222         """
00223         if motorControl.getMotorCount() == 1:
00224             phidget1065 = True 
00225             rightWheels = 0
00226             motorControlRight.setOnAttachHandler(mcAttached)
00227             motorControlRight.setOnDetachHandler(mcDetached)
00228             motorControlRight.setOnErrorhandler(mcError)
00229             motorControlRight.setOnCurrentChangeHandler(mcCurrentChanged)
00230             motorControlRight.setOnInputChangeHandler(mcInputChanged)
00231             motorControlRight.setOnVelocityChangeHandler(mcVelocityChanged)
00232                         
00233             if motorControl.getSerialNum() > motorControlRight.getSerialNum(): 
00234                 """ As a rule, we need the serial number of the left board to be lower than for the right board. This is for consistancy for all the robots
00235                 """
00236                 motorControlTemp = motorControl
00237                 motorControl = motorControlRight
00238                 motorControlRight = motorControlTemp
00239 
00240                         #Set up the encoders handler
00241             motorControl.setOnPositionUpdateHandler(leftEncoderUpdated)
00242             motorControlRight.setOnPositionUpdateHandler(rightEncoderUpdated)
00243 
00244             #attach the board
00245             motorControlRight.waitForAttach(10000)
00246     except PhidgetException as e:
00247         rospy.logerr("Unable to register the handlers: %i: %s", e.code, e.details)
00248         return
00249     except:
00250         rospy.logerr("Unable to register the handlers")
00251         return
00252      
00253 
00254     if motorControl.isAttached():
00255         rospy.loginfo(
00256                 "Device: %s, Serial: %d, Version: %d",
00257                 motorControl.getDeviceName(),
00258                 motorControl.getSerialNum(),
00259                 motorControl.getDeviceVersion()
00260                 )
00261     if phidget1065 == True:
00262         if motorControlRight.isAttached():
00263             rospy.loginfo(
00264                             "Device: %s, Serial: %d, Version: %d",
00265                             motorControlRight.getDeviceName(),
00266                             motorControlRight.getSerialNum(),
00267                             motorControlRight.getDeviceVersion()
00268                             )
00269 
00270     minAcceleration = motorControl.getAccelerationMin(leftWheels)
00271     maxAcceleration = motorControl.getAccelerationMax(leftWheels)
00272 
00273     motors_inverted = rospy.get_param('~motors_inverted', False)
00274 
00275     phidgetMotorTopic = rospy.Subscriber("PhidgetMotor", MotorCommand ,move)
00276     phidgetMotorService = rospy.Service('PhidgetMotor',Move, move)
00277     if phidget1065 == True:
00278         posdataPub = rospy.Publisher("position_data", PosMsg)
00279     rospy.spin()
00280 
00281 if __name__ == "__main__":
00282     setupMoveService()
00283 
00284     try:
00285         motorControl.closePhidget()
00286         if phidget1065 == True:
00287             motorControlRight.closePhidget()
00288     except:
00289         pass


PhidgetMotor
Author(s): Bill Mania/bmania@coroware.com
autogenerated on Tue Jan 7 2014 11:39:17