tilt_head.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright (c) 2015 Fetch Robotics Inc.
00004 # Copyright (c) 2013-2014 Unbounded Robotics Inc. 
00005 # All right reserved.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions are met:
00009 #
00010 #   * Redistributions of source code must retain the above copyright
00011 #     notice, this list of conditions and the following disclaimer.
00012 #   * Redistributions in binary form must reproduce the above copyright
00013 #     notice, this list of conditions and the following disclaimer in the
00014 #     documentation and/or other materials provided with the distribution.
00015 #   * Neither the name of Unbounded Robotics Inc. nor the names of its 
00016 #     contributors may be used to endorse or promote products derived 
00017 #     from this software without specific prior written permission.
00018 #
00019 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00020 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022 # DISCLAIMED. IN NO EVENT SHALL UNBOUNDED ROBOTICS INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
00023 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00025 # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00026 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00027 # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00028 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030 #
00031 # Tilt head for navigation obstacle avoidance.
00032 #
00033 
00034 from threading import Lock
00035 
00036 import rospy
00037 import actionlib
00038 
00039 from tf.listener import TransformListener
00040 from tf.transformations import quaternion_matrix
00041 
00042 from actionlib_msgs.msg import GoalStatus, GoalStatusArray
00043 from control_msgs.msg import PointHeadAction, PointHeadGoal
00044 from geometry_msgs.msg import PointStamped
00045 from nav_msgs.msg import Path
00046 
00047 class NavHeadController:
00048 
00049     def __init__(self):
00050         self.has_goal = False
00051 
00052         # pose and lock
00053         self.x = 1.0
00054         self.y = 0.0
00055         self.mutex = Lock()
00056 
00057         self.listener = TransformListener()
00058 
00059         self.client = actionlib.SimpleActionClient("head_controller/point_head", PointHeadAction)
00060         self.client.wait_for_server()
00061 
00062         self.plan_sub = rospy.Subscriber("move_base/TrajectoryPlannerROS/local_plan", Path, self.planCallback)
00063         self.stat_sub = rospy.Subscriber("move_base/status", GoalStatusArray, self.statCallback)
00064 
00065     def statCallback(self, msg):
00066         goal = False
00067         for status in msg.status_list:
00068             if status.status == GoalStatus.ACTIVE:
00069                 goal = True
00070                 break
00071         self.has_goal = goal
00072 
00073     def planCallback(self, msg):
00074         # get the goal
00075         pose_stamped = msg.poses[-1]
00076         pose = pose_stamped.pose
00077 
00078         # look ahead one meter
00079         R = quaternion_matrix([pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w])
00080         point = [1, 0, 0, 1]
00081         M = R*point
00082 
00083         p = PointStamped()
00084         p.header.frame_id = pose_stamped.header.frame_id
00085         p.header.stamp = rospy.Time(0)
00086         p.point.x += pose_stamped.pose.position.x + M[0,0]
00087         p.point.y += pose_stamped.pose.position.y + M[1,0]
00088         p.point.z += pose_stamped.pose.position.z + M[2,0]
00089 
00090         # transform to base_link
00091         p = self.listener.transformPoint("base_link", p)
00092 
00093         # update
00094         with self.mutex:
00095             if p.point.x < 0.65:
00096                 self.x = 0.65
00097             else:
00098                 self.x = p.point.x
00099             if p.point.y > 0.5:
00100                 self.y = 0.5
00101             elif p.point.y < -0.5:
00102                 self.y = -0.5
00103             else:
00104                 self.y = p.point.y
00105 
00106     def loop(self):
00107         while not rospy.is_shutdown():
00108             if self.has_goal:
00109                 goal = PointHeadGoal()
00110                 goal.target.header.stamp = rospy.Time.now()
00111                 goal.target.header.frame_id = "base_link"
00112                 with self.mutex:
00113                     goal.target.point.x = self.x
00114                     goal.target.point.y = self.y
00115                     self.x = 1
00116                     self.y = 0
00117                 goal.target.point.z = 0.0
00118                 goal.min_duration = rospy.Duration(1.0)
00119 
00120                 self.client.send_goal(goal)
00121                 self.client.wait_for_result()
00122 
00123                 with self.mutex:
00124                     goal.target.point.x = self.x
00125                     goal.target.point.y = self.y
00126                     self.x = 1
00127                     self.y = 0
00128                 goal.target.point.z = 0.75
00129 
00130                 self.client.send_goal(goal)
00131                 self.client.wait_for_result()
00132             else:
00133                 rospy.sleep(1.0)
00134 
00135 if __name__=="__main__":
00136     rospy.init_node("tilt_head_node")
00137     h = NavHeadController()
00138     h.loop()


fetch_navigation
Author(s): Michael Ferguson
autogenerated on Sat Aug 5 2017 04:00:40