OMPL Plannification
Path planning with OMPL
controller_quadrotor.py
1 #!/usr/bin/env python
2 
3 # ROS imports
4 import roslib; roslib.load_manifest('control_turtlebot')
5 import rospy
6 import tf
7 import math
8 
9 #ROS messages
10 from geometry_msgs.msg import Twist
11 from nav_msgs.msg import Odometry
12 from control_turtlebot.srv import GotoWaypoint, GotoWaypointResponse, FindPathToGoal, FindPathToGoalResponse, FindPathToGoalRequest
13 
14 #Numpy
15 import numpy as np
16 
17 class Controller(object):
18 
19  def __init__(self):
20  self.odometry_sub_ = rospy.Subscriber("/ground_truth/state", Odometry, self.odomCallback, queue_size = 1)
21  self.control_input_pub_ = rospy.Publisher("/cmd_vel", Twist, queue_size = 1)
22 
23  self.serv_ = rospy.Service('/controller_turtlebot/goto',
24  GotoWaypoint,
26 
27  self.current_position_ = np.zeros(3)
28  self.current_orientation_ = 0.0
29 
30  self.desired_position_ = np.zeros(3)
31  self.desired_orientation_ = 0.0
32 
33 
34  rospy.wait_for_service('/controller_turtlebot/find_path_to_goal')
35  try:
36  self.find_path_to_goal_serv_ = rospy.ServiceProxy('/controller_turtlebot/find_path_to_goal', FindPathToGoal)
37  except rospy.ServiceException, e:
38  print "Service call failed: %s"%e
39 
40  return
41 
42  def calculateControlInput(self, req):
43 
44  planner_request = FindPathToGoalRequest()
45  planner_request.new_goal = True
46  planner_request.goal_state_x = req.goal_state_x
47  planner_request.goal_state_y = req.goal_state_y
48  planner_request.goal_state_z = req.goal_state_z
49 
50  planner_response = self.find_path_to_goal_serv_(planner_request)
51 
52  for pose in planner_response.poses:
53  print pose
54  control_input = Twist()
55  self.desired_position_[0] = pose.position.x
56  self.desired_position_[1] = pose.position.y
57  self.desired_position_[2] = pose.position.z
58 
59  loop_rate = rospy.Rate(100) # 10Hz
60  orientation_approach = False
61  while not rospy.is_shutdown():
62  inc_x = self.desired_position_[0] - self.current_position_[0]
63  inc_y = self.desired_position_[1] - self.current_position_[1]
64  inc_z = self.desired_position_[2] - self.current_position_[2]
65 
66  self.desired_orientation_ = wrapAngle(math.atan2(inc_y, inc_x))
67  yaw_error = wrapAngle(self.desired_orientation_ - self.current_orientation_)
68  distance_to_goal = math.sqrt(math.pow(inc_x, 2.0) + math.pow(inc_y, 2.0))
69 
70  if abs(yaw_error) > 0.04 and not orientation_approach:
71  control_input.angular.x = 0.0
72  control_input.angular.y = 0.0
73  control_input.angular.z = yaw_error * 1.0
74 
75  control_input.linear.x = 0.0
76  control_input.linear.y = 0.0
77  control_input.linear.z = 0.0
78  else:
79  control_input.angular.x = 0.0
80  control_input.angular.y = 0.0
81  control_input.angular.z = 0.0
82 
83  orientation_approach = True
84  liner_speed = abs(distance_to_goal) * 0.5
85  altitude_speed = inc_z * 0.5
86 
87  if liner_speed < 0.1:
88  control_input.linear.x = 0.1
89  elif liner_speed > 0.2:
90  control_input.linear.x = 0.2
91  else :
92  control_input.linear.x = liner_speed
93 
94  if abs(altitude_speed) < 0.1:
95  if altitude_speed ==0 :
96  control_input.linear.z = 0
97  elif altitude_speed > 0 :
98  control_input.linear.z = 0.1
99  else:
100  control_input.linear.z = -0.1
101 
102  elif abs(altitude_speed) > 0.2:
103  if altitude_speed > 0 :
104  control_input.linear.z = 0.2
105  else:
106  control_input.linear.z = - 0.2
107  else:
108  control_input.linear.z = altitude_speed
109 
110  control_input.linear.y = 0.0
111 
112 
113  self.control_input_pub_.publish(control_input)
114 
115  rospy.logdebug("%s: current position: [%f, %f]\n", rospy.get_name(), self.current_position_[0], self.current_position_[1])
116  rospy.logdebug("%s: desired position: [%f, %f]\n", rospy.get_name(), self.desired_position_[0], self.desired_position_[1])
117  rospy.logdebug("%s: yaw_error: %f\n", rospy.get_name(), yaw_error)
118  rospy.logdebug("%s: current orientation: %f\n", rospy.get_name(), self.current_orientation_)
119  rospy.logdebug("%s: desired orientation: %f\n", rospy.get_name(), self.desired_orientation_)
120  rospy.logdebug("%s: distance_to_goal: %f\n", rospy.get_name(), distance_to_goal)
121  rospy.logdebug("%s: control_input.linear.x %f\n", rospy.get_name(), control_input.linear.x)
122  rospy.logdebug("%s: control_input.angular.z %f\n", rospy.get_name(), control_input.angular.z)
123 
124  if distance_to_goal <= 0.2:
125  break
126  loop_rate.sleep()
127 
128  return GotoWaypointResponse()
129 
130  def odomCallback(self, odometry_msg):
131  self.current_position_[0] = odometry_msg.pose.pose.position.x
132  self.current_position_[1] = odometry_msg.pose.pose.position.y
133  self.current_position_[2] = odometry_msg.pose.pose.position.z
134  (r, p, y) = tf.transformations.euler_from_quaternion([odometry_msg.pose.pose.orientation.x, odometry_msg.pose.pose.orientation.y, odometry_msg.pose.pose.orientation.z, odometry_msg.pose.pose.orientation.w])
135  self.current_orientation_ = wrapAngle(y)
136  return
137 
138 def wrapAngle(angle):
139  """wrapAngle
140 
141  Calculates angles values between 0 and 2pi"""
142  return (angle + ( 2.0 * math.pi * math.floor( ( math.pi - angle ) / ( 2.0 * math.pi ) ) ) )
143 
144 if __name__ == '__main__':
145  rospy.init_node('control_quadrotor', log_level=rospy.INFO)
146  rospy.loginfo("%s: starting quadrotor controller", rospy.get_name())
147 
148  controller = Controller()
149  rospy.spin()
def odomCallback(self, odometry_msg)