servo.py
Go to the documentation of this file.
00001 #! /usr/bin/python
00002 import roslib
00003 roslib.load_manifest('rfid_servoing')
00004 import rospy
00005 
00006 import hrl_rfid.ros_M5e_client as rmc
00007 from hrl_rfid.msg import RFIDread
00008 import robotis.ros_robotis as rr
00009 import costmap_services.python_client as costmap
00010 from geometry_msgs.msg import Twist
00011 import actionlib
00012 
00013 from rfid_servoing.srv import ServoSrv
00014 from rfid_servoing.msg import ServoAction, ServoResult, ServoGoal
00015 
00016 
00017 import numpy as np, math
00018 from collections import deque
00019 import os
00020 from threading import Lock
00021 
00022 def ctime():
00023     return rospy.Time.now().to_time()
00024 
00025 def retfalse():
00026     return False
00027 
00028 class ServoNode( ):
00029     def __init__( self ):
00030         rospy.logout('servo_node: Initializing')
00031         try:
00032             rospy.init_node('servo_node')
00033         except: # Node probably already initialized elsewhere
00034             pass
00035 
00036         # Create servos.
00037         self.p_left = rr.ROS_Robotis_Client( 'left_pan' )
00038         self.t_left = rr.ROS_Robotis_Client( 'left_tilt' )
00039         self.p_right = rr.ROS_Robotis_Client( 'right_pan' )
00040         self.t_right = rr.ROS_Robotis_Client( 'right_tilt' )
00041 
00042         # Create Costmap Services obj
00043         self.cs = costmap.CostmapServices( accum = 3 )
00044         # Note: After moving, this will require accum * -1's before stopping.
00045 
00046         # Publish move_base command
00047         self._pub = rospy.Publisher( 'rfid_cmd_vel', Twist )
00048 
00049         # Alterative ways to call servoing using ROS services / actionlib
00050         self._service_servo = rospy.Service( '/rfid_servo/servo', ServoSrv, self.service_request )
00051         self._as = actionlib.SimpleActionServer( '/rfid_servo/servo_act',
00052                                                  ServoAction, execute_cb = self.action_request )
00053         self._as.start()
00054     
00055         rospy.logout( 'servo_node: Service ready and waiting' )
00056 
00057 
00058     def service_request( self, req ):
00059         return self.run( req.tagid )
00060 
00061     def action_request( self, goal ):
00062         rospy.logout( 'servo_node: action_request received for tagid: \'%s\'' % goal.tagid )
00063         
00064         def preempt_func():
00065             # self._as should be in scope and bound @ function def. (I think for python...)
00066             check = self._as.is_preempt_requested()
00067             if check:
00068                 rospy.logout( 'servo_node: action_request preempted!' )
00069             return check
00070 
00071         rv = self.run( goal.tagid, preempt_func = preempt_func )
00072         rospy.logout( 'servo_node: action_request received result %d' % int(rv) )
00073 
00074         if preempt_func():  # this is a relatively new addition
00075             rospy.logout('servo_node: returning actionlib state preempted.')
00076             self._as.set_preempted()
00077         elif rv == True:
00078             self._as.set_succeeded( ServoResult( int(rv) ))
00079             
00080 
00081     def run( self, tag_id, preempt_func = retfalse ):
00082         # tag_id => 12-character tag id
00083         # preempt_func => returns true when a preempt request is received, else false
00084         rospy.logout( 'servo_node: Run called for tagid: \'%s\'' % tag_id )
00085 
00086         # Ears out.
00087         self.robotis_init()
00088         
00089         # Startup RFID reads
00090         zc = ZedCalc( filt_len = 5, tag_id = tag_id ) 
00091                 
00092         rospy.logout('servo_node: Running')
00093 
00094         zed_next = zc.next_pub()
00095         r = rospy.Rate( 10 )
00096         while not rospy.is_shutdown() and self.cs.scoreTraj_PosHyst( 0.1, 0.0, zed_next ) != -1.0 and not preempt_func():
00097             move_command = Twist()
00098             move_command.linear.x = 0.1
00099             move_command.angular.z = zed_next
00100 
00101             self._pub.publish( move_command )
00102             zc.update_last_pub( zed_next )
00103             zed_next = zc.next_pub() 
00104 
00105             # Don't do this too fast (avoid unwanted buffering / rate issues)
00106             try:
00107                 r.sleep()
00108             except rospy.ROSInterruptException: # rospy shutdown request received
00109                 pass
00110 
00111         self._pub.publish( Twist() ) # Stop moving.
00112 
00113         # Tuck ears
00114         # self.robotis_end()
00115 
00116         zc.stop() # Stop the RFID reader...
00117 
00118         if preempt_func():
00119             rospy.logout( 'servo_node: Preempt was requested. May not have finished.' )
00120             rospy.logout( 'servo_node: Exiting' )
00121             return False
00122         else:
00123             rospy.logout( 'servo_node: Exiting' )
00124             return True
00125         
00126 
00127     def robotis_init( self ):
00128         # Move Antennas into Servo mode
00129         self.t_left.move_angle( 0.0, math.radians(30), blocking = False )
00130         self.t_right.move_angle( 0.0, math.radians(30), blocking = False )
00131         self.p_left.move_angle( math.radians(40), math.radians(30), blocking = False )
00132         self.p_right.move_angle( math.radians(-40), math.radians(30), blocking = True )
00133 
00134         while self.p_left.is_moving() or self.p_right.is_moving():
00135             rospy.sleep( 0.05 )
00136 
00137     def robotis_end( self ):
00138         # Return servos to home position
00139         self.t_left.move_angle( 0.0, math.radians(10), blocking = False )
00140         self.t_right.move_angle( 0.0, math.radians(10), blocking = False )
00141         self.p_left.move_angle( 1.350, math.radians(10), blocking = False )
00142         if not (os.environ.has_key('ROBOT') and os.environ['ROBOT'] == 'sim'):
00143             self.p_right.move_angle( -1.350, math.radians(10), blocking = False )
00144         else:
00145             self.p_right.move_angle( -1.350, math.radians(10), blocking = True )
00146 
00147 
00148 
00149 class ZedCalc( ):
00150     ### WARNING: Do not instantiate in init's.  This object queries the RFID reader!
00151     def __init__( self, tag_id, sub_name = '/rfid/ears_reader', filt_len = 5 ):
00152         rospy.logout( 'ZedCalc: Initializing' )
00153         # We will process the reads ourself
00154         self.values = { 'EleLeftEar': 75.0,
00155                         'EleRightEar': 75.0 }
00156 
00157         self.lock = Lock()
00158         self.buff_len = filt_len * 2 # two antennas' worth
00159         self.zed_buff = deque( np.zeros( self.buff_len ))  # Angle filter length
00160 
00161         self.last_zed = 0.0 # last published command
00162         self.new_zed = 0.0  # projected new command
00163 
00164         self._sub = rospy.Subscriber( sub_name, RFIDread, self.callback)
00165         self.reader = rmc.ROS_M5e_Client('ears')
00166         self.reader.track_mode( tag_id )
00167 
00168         rospy.logout( 'ZedCalc: Ready.' )
00169 
00170     def stop( self ):
00171         rospy.logout( 'ZedCalc: Stopping RFID reader' )
00172         self.reader.stop() # Stop RFID reads
00173 
00174 
00175     def callback( self, msg ):
00176         self.values[ msg.antenna_name ] = np.clip( msg.rssi, 75.0, 110.0 )
00177         left = self.values[ 'EleLeftEar' ]
00178         right = self.values[ 'EleRightEar' ]
00179 
00180         self.lock.acquire() # lock on buff 
00181         self.zed_buff.append( 0.10 * (left - right)/5.0 )
00182         if len( self.zed_buff ) > self.buff_len:
00183             self.zed_buff.popleft()
00184         self.lock.release()
00185 
00186     def next_pub( self, angle_slew = math.radians( 10 )):
00187         self.lock.acquire() # lock on buff
00188         target = np.mean( self.zed_buff )
00189         self.lock.release()
00190         
00191         lz = self.last_zed
00192         return lz + np.clip( target - lz, -1.0 * angle_slew, angle_slew )
00193 
00194     def update_last_pub( self, pub_val ):
00195         self.last_zed = pub_val
00196         
00197 
00198 
00199 if __name__ == '__main__':
00200 
00201     sn = ServoNode()
00202     rospy.spin()
00203     
00204     # There are (at least) three ways to call this code.
00205     # 1) Python:
00206     
00207     # print sn.run( 'person      ' )
00208     # rospy.spin()
00209 
00210     # 2) ROS service:
00211 
00212     # rosservice call /rfid_servo/servo "'person      '"
00213 
00214     # 3) ROS actionlib:
00215 
00216     # try:
00217     #     client = actionlib.SimpleActionClient( '/rfid_servo/servo_act', ServoAction )
00218     #     client.wait_for_server()
00219     #     client.send_goal( ServoGoal( 'person      ' ))
00220     #     client.wait_for_result()
00221     #     print client.get_result()
00222     # except rospy.ROSInterruptException:
00223     #     print 'Program interrupted before completion'
00224 
00225     # rospy.spin()
00226 
00227     
00228 


rfid_servoing
Author(s): Travis Deyle
autogenerated on Wed Nov 27 2013 11:49:30