room_explore.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 
00003 import roslib
00004 roslib.load_manifest('rfid_explore_room')
00005 import rospy
00006 
00007 import tf
00008 from threading import Thread
00009 import actionlib
00010 
00011 from move_base_msgs.msg import MoveBaseGoal, MoveBaseAction
00012 from visualization_msgs.msg import MarkerArray
00013 from visualization_msgs.msg import Marker
00014 from geometry_msgs.msg import Vector3, PoseStamped, Quaternion
00015 from std_msgs.msg import ColorRGBA
00016 
00017 from explore_hrl.msg import ExploreAction, ExploreResult, ExploreGoal
00018 
00019 import yaml
00020 import numpy as np, math
00021 
00022 def retfalse():
00023     return False
00024 
00025 class TFthread( Thread ):
00026     def __init__( self, df ):
00027         Thread.__init__( self )
00028         try:
00029             rospy.init_node( 'TFthread' )
00030         except:
00031             pass # parent probably already initialized node.
00032         self.df = df # yaml dictionary of rooms
00033         self.bc = tf.TransformBroadcaster()
00034         self.should_run = True
00035         self.start()
00036 
00037     def publish_transform( self ):
00038         for room in self.df.keys():
00039             self.bc.sendTransform( ( self.df[room]['position']['x'],
00040                                      self.df[room]['position']['y'],
00041                                      self.df[room]['position']['z'] ),
00042                                    ( self.df[room]['orientation']['x'],
00043                                      self.df[room]['orientation']['y'],
00044                                      self.df[room]['orientation']['z'],
00045                                      self.df[room]['orientation']['w'] ),
00046                                    rospy.Time.now(),
00047                                    room,
00048                                    'map' )
00049 
00050     def run( self ):
00051         rospy.logout( 'TFthread: Starting ' )
00052         r = rospy.Rate( 10 )
00053         while self.should_run and not rospy.is_shutdown():
00054             self.publish_transform()
00055             try:
00056                 r.sleep()
00057             except:
00058                 pass # ROS exception.
00059         rospy.logout( 'TFthread: Starting ')
00060         
00061     def stop( self ):
00062         # Kill off the poller thread.
00063         self.should_run = False
00064         self.join(5)
00065         if (self.isAlive()):
00066             raise RuntimeError('TFthread: Unable to stop thread ' )
00067 
00068 
00069 # if __name__ == '__main__':
00070 #     f = open( room )
00071 #     dat = yaml.load( f )
00072 #     f.close()
00073 
00074 #     TFthread( dat )
00075 #     rospy.spin()
00076 
00077 def standard_rad(t):
00078     if t > 0:
00079         return ((t + np.pi) % (np.pi * 2))  - np.pi
00080     else:
00081         return ((t - np.pi) % (np.pi * -2)) + np.pi
00082 
00083 
00084 class RoomExplore( ):
00085     def __init__( self, df, room, start_rad = 1.5 ):
00086         try:
00087             rospy.init_node( 'RoomExplore' )
00088         except:
00089             pass
00090         self.should_run = True
00091         self.frame = '/' + room
00092         self.old_markers = []
00093         self.mid = 1
00094 
00095         self.height = df[room]['height']
00096         self.width = df[room]['width']
00097 
00098         self.listener = tf.TransformListener()
00099         self.listener.waitForTransform( '/base_link', '/map', rospy.Time(0), timeout = rospy.Duration(100))
00100         self.pub = rospy.Publisher( 'visarr', Marker )
00101 
00102         self.setup_poses( radius = start_rad ) # also initializes radius
00103         print 'Len: ', len(self.poses), ' Publishing.'
00104         self.publish_markers()
00105 
00106         self._as = actionlib.SimpleActionServer( '/explore', ExploreAction, execute_cb = self.action_request )
00107         self._as.start()
00108         self.publish_markers()
00109         rospy.logout('Action should be started.')
00110 
00111     def action_request( self, goal ):
00112         rospy.logout( 'room_explore: action_request received for radius: \'%2.2f\'' % goal.radius )
00113         
00114         def preempt_func():
00115             # self._as should be in scope and bound @ function def. (I think for python...)
00116             check = self._as.is_preempt_requested()
00117             if check:
00118                 rospy.logout( 'room_explore: action_request preempted!' )
00119             return check
00120 
00121         rv = self.begin_explore( goal.radius, preempt_func = preempt_func )
00122         rospy.logout( 'room_explore: action_request received result %d' % int(rv) )
00123 
00124         if rv == True:
00125             self._as.set_succeeded( ExploreResult() )
00126 
00127 
00128     def begin_explore( self, radius, preempt_func = retfalse ):
00129         client = actionlib.SimpleActionClient( 'move_base', MoveBaseAction )
00130         rospy.logout( 'Waiting for move_base server' )
00131         client.wait_for_server()
00132 
00133         rospy.logout( 'room_explore: setting radius' )
00134         all_goals = self.setup_poses( radius )
00135         self.publish_markers()
00136         for goal in all_goals:
00137             #print 'room_explore: sending goal ', goal
00138             goal.target_pose.header.stamp = rospy.Time.now()
00139 
00140             client.send_goal( goal )
00141 
00142             time_last_moving = rospy.Time.now()
00143             goal_time = rospy.Time.now()
00144 
00145             new_pose = self.current_robot_position()
00146             ref_pose = self.current_robot_position()
00147 
00148             r = rospy.Rate( 5 )
00149             while not rospy.is_shutdown():
00150                 state = client.get_state()
00151                 states = { 0: 'WAITING FOR GOAL ACK',
00152                            1: 'PENDING',
00153                            2: 'ACTIVE',
00154                            3: 'WAITING FOR RESULT',
00155                            4: 'WAITING FOR CANCEL ACK',
00156                            5: 'RECALLING',
00157                            6: 'PREEMPTING',
00158                            7: 'DONE' }
00159                 #print 'State: ', state, ' ', states[state]
00160                 #print 'Result: ', client.get_result()
00161                 
00162                 #rospy.logout( 'room_explore: loop' )
00163                 if state == 7 or state == 3:
00164                     rospy.logout( 'room_explore: client no longer active' )
00165                     print 'State: ', state, ' ', states[state]
00166                     time_last_moving = rospy.Time.now()
00167                     break
00168 
00169                 if preempt_func():
00170                     rospy.logout( 'room_explore: preempted at a higher level.' )
00171                     time_last_moving = rospy.Time.now()
00172                     break
00173 
00174                 new_pose = self.current_robot_position()
00175                 dx = new_pose[0] - ref_pose[0]
00176                 dy = new_pose[1] - ref_pose[1]
00177                 da = new_pose[-1] - ref_pose[-1] # yaw
00178                 
00179                 if dx*dx + dy*dy > 0.02 or da*da > math.radians( 5 ):
00180                     time_last_moving = rospy.Time.now()
00181                     ref_pose = self.current_robot_position()
00182                     rospy.logout('WE ARE MOVING')
00183 
00184                 if rospy.Time.now() - time_last_moving > rospy.Duration( 8 ):
00185                     rospy.logout( 'We do not appear to have moved.  Aborting current goal.' )
00186                     client.cancel_all_goals() # Should force a break on GoalState
00187                     time_last_moving = rospy.Time.now()
00188                     break
00189 
00190                 if rospy.Time.now() - goal_time > rospy.Duration( 30 ):
00191                     rospy.logout( 'Goal not achieved after 30 seconds.  Aborting.' )
00192                     client.cancel_all_goals() # Should force a break on GoalState
00193                     time_last_moving = rospy.Time.now()
00194                     break
00195 
00196                 r.sleep()
00197                 
00198             client.cancel_all_goals() # Just in case
00199 
00200             if preempt_func(): # immediately exit if overall action preempted
00201                 break
00202 
00203         return True
00204                         
00205 
00206     def current_robot_position( self ):
00207         ps = PoseStamped()
00208         ps.header.stamp = rospy.Time(0)
00209         ps.header.frame_id = '/base_link'
00210         ps.pose.orientation.w = 1.0
00211 
00212         try:
00213             ps_map = self.listener.transformPose( '/map', ps )
00214         except:
00215             rospy.logout( 'room_explore: Transform failed' )
00216             ps_map = PoseStamped()
00217             ps_map.header.stamp = rospy.Time.now()
00218             ps_map.header.frame_id = '/map'
00219             ps_map.pose.orientation = new_quat
00220 
00221         roll, pitch, yaw = tf.transformations.euler_from_quaternion(( ps_map.pose.orientation.x,
00222                                                                       ps_map.pose.orientation.y,
00223                                                                       ps_map.pose.orientation.z,
00224                                                                       ps_map.pose.orientation.w ))
00225 
00226         rv = [ ps_map.pose.position.x,
00227                ps_map.pose.position.y,
00228                ps_map.pose.position.z,
00229                roll,
00230                pitch,
00231                yaw ]
00232         #print 'RV: ', rv
00233             
00234         return rv
00235         
00236 
00237     def setup_poses( self, radius ):
00238         self.radius = radius
00239         xdir = np.arange( self.radius / 2.0, self.height + self.radius / 2.0, self.radius )
00240         ydir = np.arange( self.radius / 2.0, self.width + self.radius / 2.0, self.radius )
00241 
00242         move_dir = 0.0
00243         self.poses = []
00244         mod = 0
00245         for y in ydir:
00246             if mod == 0:
00247                 xord = xdir
00248             else:
00249                 xord = xdir[::-1]
00250                 
00251             for x in xord:
00252                 goal = MoveBaseGoal()
00253                 goal.target_pose.header.frame_id = self.frame
00254                 goal.target_pose.header.stamp = rospy.Time.now()
00255                 goal.target_pose.pose.position.x = x
00256                 goal.target_pose.pose.position.y = y
00257                 quat = tf.transformations.quaternion_from_euler( 0.0, 0.0, move_dir )
00258                 goal.target_pose.pose.orientation.x = quat[0]
00259                 goal.target_pose.pose.orientation.y = quat[1]
00260                 goal.target_pose.pose.orientation.z = quat[2]
00261                 goal.target_pose.pose.orientation.w = quat[3]
00262 
00263                 self.poses.append( goal )
00264             move_dir = standard_rad( move_dir + np.pi )
00265             mod = ( mod + 1 ) % 2
00266         return self.poses
00267 
00268     def destroy_old_markers( self ):
00269         for m in self.old_markers:
00270             m.action = m.DELETE
00271             self.pub.publish( m )
00272         self.old_markers = []
00273     
00274     def publish_markers( self ):
00275         self.destroy_old_markers()
00276         for i,g in enumerate(self.poses):
00277             self.mid += 1
00278             m = Marker()
00279             m.ns = 'explore_poses'
00280             m.id = self.mid
00281             m.action = m.ADD
00282             m.type = m.ARROW
00283             m.header.frame_id = self.frame
00284             m.header.stamp = rospy.Time.now()
00285             m.scale = Vector3( 0.15, 1.0, 1.0 )
00286             m.color = ColorRGBA( 0.2, 1.0, 0.2, 0.7 )
00287             m.pose = g.target_pose.pose
00288 
00289             self.old_markers.append( m )
00290             self.pub.publish( m )
00291 
00292     def goals( self ):
00293         return self.poses
00294 
00295 
00296 
00297 #self.explore_act = actionlib.SimpleActionClient('explore', explore_hrl.msg.ExploreAction)
00298 
00299 
00300 
00301 if __name__ == '__main__':
00302     import optparse
00303     p = optparse.OptionParser()
00304     p.add_option('--yaml', action='store', type='string', dest='yaml',
00305                  help='Room definition file (required)', default='')
00306     p.add_option('--room', action='store', type='string', dest='room',
00307                  help='Specific room [default \'hrl\']', default='hrl')
00308     opt, args = p.parse_args()
00309 
00310     if opt.yaml == '':
00311         print 'room_explore: YAML FILE REQUIRED.'
00312     else:
00313         print 'Using YAML file: ', opt.yaml
00314     
00315     f = open( opt.yaml )
00316     dat = yaml.load( f )
00317     f.close()
00318 
00319     TFthread( dat )    
00320     
00321     re = RoomExplore( dat, opt.room, 1.5 )
00322     rospy.sleep( 4 )
00323     re.publish_markers()
00324     
00325     rospy.spin()
00326     
00327     # r = rospy.Rate( 2 )
00328     # while not rospy.is_shutdown():
00329     #     re.publish_markers()
00330     #     r.sleep()
00331 
00332     #re.begin_explore( 0.8 )
00333     # rosservice call /explore 0.8
00334     
00335     # explore_act = actionlib.SimpleActionClient('explore', ExploreAction)
00336     # rospy.logout( 'Waiting for explore.' )
00337     # explore_act.wait_for_server()
00338     # rospy.logout( 'Done waiting.' )
00339 
00340     # goal = ExploreGoal( radius = 0.8 )
00341     # explore_act.send_goal(goal)
00342     # rospy.sleep( 0.5 )
00343     # explore_act.wait_for_result()
00344         
00345     
00346         


rfid_explore_room
Author(s): Travis Deyle
autogenerated on Wed Nov 27 2013 12:04:36