6 @author: Thorsten Gedicke 9 import roslib; roslib.load_manifest(
'move_base_straight')
14 from geometry_msgs.msg
import PoseStamped, Twist
15 from move_base_msgs.msg
import MoveBaseAction, MoveBaseGoal
16 from sensor_msgs.msg
import LaserScan
26 self.
MIN_SPEED = rospy.get_param(
'~min_speed', 0.05)
54 self.
HOLONOMIC = rospy.get_param(
'~holonomic',
False)
62 self.
cmd_vel_pub = rospy.Publisher(
'base_controller/command', Twist, queue_size=1)
69 rospy.Subscriber(
"/base_scan", LaserScan, self.
laser_cb)
75 self.action_server.start()
76 rospy.loginfo(
'%s: Action server up and running...' % (self.
action_name))
80 self.client.wait_for_server()
86 Uses the laws of sines and cosines to transform range/angle pairs in the 87 base laser frame to range/angle pairs relative to the base footprint frame. 89 gamma = np.pi - angle_laser
91 angle_base = np.arcsin(distance_laser * np.sin(gamma) / distance_base)
92 return (distance_base, angle_base)
100 laser_angle = self.scan.angle_min
101 for laser_distance
in self.scan.ranges:
102 (base_distance, base_angle) = self.
laser_to_base(laser_distance, laser_angle)
103 angle_diff = abs(base_angle - target_angle)
104 will_get_closer = angle_diff < (np.pi / 2.0)
105 is_too_close = (base_distance < self.
RANGE_MINIMUM)
and (laser_distance > self.scan.range_min)
108 if is_too_close
and will_get_closer:
110 block_reason = (base_distance, base_angle, angle_diff)
112 laser_angle += self.scan.angle_increment
114 rospy.logwarn(
'%s: Blocked! Reason: Distance %s at angle %s (%s angle difference to goal direction)' % (self.
action_name, block_reason[0], block_reason[1], block_reason[2]))
121 cmd.linear.x = (x_diff / dist) * drive_speed
122 cmd.linear.y = (y_diff / dist) * drive_speed
123 self.cmd_vel_pub.publish(cmd)
131 self.cmd_vel_pub.publish(cmd)
140 self.cmd_vel_pub.publish(cmd)
145 laser_frame = scan.header.frame_id
146 while not rospy.is_shutdown():
148 self.tf_listener.waitForTransform(self.
footprint_frame, laser_frame, rospy.Time(), rospy.Duration(1.0))
151 except (tf.Exception)
as e:
152 rospy.logwarn(
"MoveBaseBlind tf exception! Message: %s" % e.message)
160 goal = MoveBaseGoal(target_pose=target_pose)
161 self.client.send_goal(goal)
165 rospy.logwarn(
'No messages received yet on topic %s, aborting goal!' % rospy.resolve_name(
'base_scan'))
166 self.action_server.set_aborted()
170 target_pose = goal.target_pose
173 rospy.loginfo(
'%s: Executing, moving to position: (%f, %f)' % (self.
action_name, target_pose.pose.position.x, target_pose.pose.position.y))
175 rate = rospy.Rate(hz = MoveBaseStraightAction.FREQ)
176 while not rospy.is_shutdown():
179 while not rospy.is_shutdown()
and not self.action_server.is_preempt_requested():
183 target_pose.header.stamp = rospy.Time.now()
185 self.tf_listener.waitForTransform(
'/base_footprint',
186 target_pose.header.frame_id,
187 target_pose.header.stamp, rospy.Duration(1.0))
188 target_pose_transformed = self.tf_listener.transformPose(
'/base_footprint', target_pose)
190 except (tf.Exception)
as e:
191 rospy.logwarn(
"MoveBaseBlind tf exception! Message: %s" % e.message)
196 if self.action_server.is_preempt_requested():
198 self.action_server.set_preempted()
201 x_diff = target_pose_transformed.pose.position.x
202 y_diff = target_pose_transformed.pose.position.y
203 dist = np.sqrt(x_diff ** 2 + y_diff ** 2)
205 euler = tf.transformations.euler_from_quaternion([target_pose_transformed.pose.orientation.x,
206 target_pose_transformed.pose.orientation.y, target_pose_transformed.pose.orientation.z,
207 target_pose_transformed.pose.orientation.w])
209 target_angle = np.arctan2(target_pose_transformed.pose.position.y,
210 target_pose_transformed.pose.position.x)
214 if self.
blocked(target_angle, dist):
216 self.cmd_vel_pub.publish(Twist())
218 rospy.loginfo(
'%s: Succeeded (blocked, but closer to goal than acceptable goal threshold)' % self.
action_name)
219 self.action_server.set_succeeded()
222 self.action_server.set_aborted()
247 self.cmd_vel_pub.publish(Twist())
249 self.action_server.set_succeeded()
252 if __name__ ==
'__main__':
253 rospy.init_node(
'move_base_straight')
GOAL_THRESHOLD_ACCEPTABLE
def translate_towards_goal_holonomically(self, x_diff, y_diff, dist)
def manual_cb(self, target_pose)
def blocked(self, target_angle, dist)
def translate_towards_goal(self, target_angle)
def rotate_in_place(self, direction)
def laser_to_base(self, distance_laser, angle_laser)
def execute_cb(self, goal)