move_base_server.py
Go to the documentation of this file.
00001 #! /usr/bin/python
00002 import roslib; roslib.load_manifest('simple_move_base')
00003 import rospy
00004 import tf.transformations as tr
00005 import hrl_lib.tf_utils as tfu
00006 import hrl_lib.util as ut
00007 import simple_move_base.msg as hm
00008 import tf
00009 
00010 import geometry_msgs.msg as gm
00011 import sys
00012 import math
00013 import numpy as np
00014 import actionlib
00015 
00016 class MoveBase:
00017 
00018     def __init__(self):
00019         rospy.init_node('odom_move_base')
00020         self.tw_pub = rospy.Publisher('base_controller/command', gm.Twist)
00021         #rospy.Subscriber('simple_move_base', gm.Pose2D, self.pose2d_cb)
00022         self.tl = tf.TransformListener()
00023 
00024         self.go_xy_server = actionlib.SimpleActionServer('go_xy', hm.GoXYAction, self._go_xy_cb, auto_start=False)
00025         self.go_xy_server.start()
00026 
00027         self.go_ang_server = actionlib.SimpleActionServer('go_angle', hm.GoAngleAction, self._go_ang_cb, auto_start=False)
00028         self.go_ang_server.start()
00029 
00030     def _go_xy_cb(self, goal):
00031         rospy.loginfo('received go_xy goal %f %f' % (goal.x, goal.y))
00032         def send_feed_back(error):
00033             feed_back_msg = hm.GoXYFeedback()
00034             feed_back_msg.error = np.linalg.norm(error)
00035             self.go_xy_server.publish_feedback(feed_back_msg)
00036         error = self.go_xy(np.matrix([goal.x, goal.y]).T, func=send_feed_back)
00037         result = hm.GoXYResult()
00038         result.error = np.linalg.norm(error)
00039         self.go_xy_server.set_succeeded(result)
00040 
00041 
00042     def _go_ang_cb(self, goal):
00043         rospy.loginfo('received go_angle goal %f' % (goal.angle))
00044 
00045         def send_feed_back(error):
00046             feed_back_msg = hm.GoAngleFeedback()
00047             feed_back_msg.error = error
00048             self.go_ang_server.publish_feedback(feed_back_msg)
00049 
00050         error = self.go_angle(goal.angle, func=send_feed_back)
00051         result = hm.GoAngleResult()
00052         result.error = error
00053         self.go_ang_server.set_succeeded(result)
00054 
00055 
00056     def go_xy(self, target_base, tolerance=.01, max_speed=.1, func=None):
00057         k = 2.
00058         self.tl.waitForTransform('base_footprint', 'odom_combined', rospy.Time(), rospy.Duration(10))
00059         rate = rospy.Rate(100)
00060 
00061         od_T_bf = tfu.transform('odom_combined', 'base_footprint', self.tl)
00062         target_odom = (od_T_bf * np.row_stack([target_base, np.matrix([0,1.]).T]))[0:2,0]
00063         #print 'target base', target_base.T
00064         #print 'target odom', target_odom.T
00065 
00066         robot_odom = np.matrix(tfu.transform('odom_combined', 'base_footprint', self.tl)[0:2,3])
00067         diff_odom  = target_odom - robot_odom
00068         mag        = np.linalg.norm(diff_odom)
00069         rospy.loginfo('go_xy: error %s' % str(mag))
00070         while not rospy.is_shutdown():
00071             robot_odom = np.matrix(tfu.transform('odom_combined', 'base_footprint', self.tl)[0:2,3])
00072             #rospy.loginfo('go_xy: odom %s' % str(robot_odom.T))
00073 
00074             diff_odom  = target_odom - robot_odom
00075             mag        = np.linalg.norm(diff_odom)
00076             if func != None:
00077                 func(diff_odom)
00078             if mag < tolerance:
00079                 break
00080 
00081             if self.go_xy_server.is_preempt_requested():
00082                 self.go_xy_server.set_preempted()
00083                 break
00084 
00085             direc    = diff_odom / mag
00086             speed = min(mag * k, max_speed)
00087             vel_odom = direc * speed
00088             #vel_odom = direc * mag * k
00089             #print mag*k, max_speed, speed
00090 
00091             bf_T_odom = tfu.transform('base_footprint', 'odom_combined', self.tl)
00092             vel_base = bf_T_odom * np.row_stack([vel_odom, np.matrix([0,0.]).T])
00093             #pdb.set_trace()
00094             #rospy.loginfo('vel_base %f %f' % (vel_base[0,0], vel_base[1,0]))
00095 
00096             tw = gm.Twist()
00097             tw.linear.x = vel_base[0,0]
00098             tw.linear.y = vel_base[1,0]
00099             #rospy.loginfo('commanded %s' % str(tw))
00100             self.tw_pub.publish(tw)
00101             rate.sleep()
00102 
00103         rospy.loginfo('go_xy: finished go_xy %f' % np.linalg.norm(diff_odom))
00104         return diff_odom
00105 
00106     ##
00107     # delta angle
00108     def go_angle(self, target_base, tolerance=math.radians(5.), max_ang_vel=math.radians(20.), func=None):
00109         self.tl.waitForTransform('odom_combined', 'base_footprint', rospy.Time(), rospy.Duration(10))
00110         rate = rospy.Rate(100)
00111         k = math.radians(80)
00112 
00113         od_T_bf = tfu.transform('odom_combined', 'base_footprint', self.tl)
00114         target_odom_mat = od_T_bf * tfu.tf_as_matrix( ([0, 0, 0.], tr.quaternion_from_euler(0, 0, target_base)) )
00115         target_odom = tr.euler_from_quaternion(tfu.matrix_as_tf(target_odom_mat)[1])[2]
00116         #target_odom = (od_T_bf * np.row_stack([target_base, np.matrix([0,1.]).T]))[0:2,0]
00117 
00118         #current_ang_odom = tr.euler_from_matrix(tfu.transform('base_footprint', 'odom_combined', self.tl)[0:3, 0:3], 'sxyz')[2]
00119         #target_odom = current_ang_odom + delta_ang
00120 
00121         robot_odom = tfu.transform('odom_combined', 'base_footprint', self.tl)
00122         current_ang_odom = tr.euler_from_matrix(robot_odom[0:3, 0:3], 'sxyz')[2]
00123         diff = ut.standard_rad(current_ang_odom - target_odom)
00124         rospy.loginfo('go_angle: target %.2f' %  np.degrees(target_odom))
00125         rospy.loginfo('go_angle: current %.2f' %  np.degrees(current_ang_odom))
00126         rospy.loginfo('go_angle: diff %.2f' %  np.degrees(diff))
00127 
00128         while not rospy.is_shutdown():
00129             robot_odom = tfu.transform('odom_combined', 'base_footprint', self.tl)
00130             current_ang_odom = tr.euler_from_matrix(robot_odom[0:3, 0:3], 'sxyz')[2]
00131             diff = ut.standard_rad(target_odom - current_ang_odom)
00132             rospy.loginfo('go_angle: current %.2f diff %.2f' %  (np.degrees(current_ang_odom), np.degrees(diff)))
00133             p = k * diff
00134             if func != None:
00135                 func(diff)
00136             if np.abs(diff) < tolerance:
00137                 break
00138 
00139             if self.go_ang_server.is_preempt_requested():
00140                 self.go_ang_server.set_preempted()
00141                 break
00142 
00143             tw = gm.Twist()
00144             vels = [p, np.sign(p) * max_ang_vel]
00145             tw.angular.z = vels[np.argmin(np.abs(vels))]
00146             #rospy.loginfo('diff %.3f vel %.3f' % (math.degrees(diff), math.degrees(tw.angular.z)))
00147             self.tw_pub.publish(tw)
00148             #rospy.loginfo('commanded %s' % str(tw))
00149             rate.sleep()
00150         rospy.loginfo('go_ang: finished %.3f' % math.degrees(diff))
00151         return diff
00152 
00153 
00154 if __name__ == '__main__':
00155     m = MoveBase()
00156     rospy.loginfo('simple move base server up!')
00157     rospy.spin()
00158 


simple_move_base
Author(s): haidai
autogenerated on Wed Nov 27 2013 12:26:26