00001
00002
00003 """
00004 Copyright (c) 2014, Robotnik Automation
00005 All rights 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
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00020 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026 POSSIBILITY OF SUCH DAMAGE.
00027 """
00028
00029
00030 import roslib; roslib.load_manifest("interactive_markers")
00031 import rospy
00032 import copy
00033
00034 from interactive_markers.interactive_marker_server import *
00035 from visualization_msgs.msg import InteractiveMarker
00036 from interactive_markers.menu_handler import *
00037
00038 import actionlib
00039 from geometry_msgs.msg import Pose2D
00040 from purepursuit_planner.msg import goal, GoToGoal, GoToAction
00041
00042
00043 class PurepursuitClient():
00044
00045 def __init__(self, planner_name):
00046 self.planner_name = planner_name
00047
00048
00049 self.client = actionlib.SimpleActionClient(planner_name, GoToAction)
00050
00051
00052
00053 def goTo(self, goal_list):
00054
00055
00056 if self.client.wait_for_server(timeout = rospy.Duration(3.0) ):
00057
00058
00059
00060
00061 g = GoToGoal(target = goal_list)
00062 rospy.loginfo('PurepursuitClient: Sendig %d waypoints'%(len(goal_list)))
00063 self.client.send_goal(g)
00064 return 0
00065 else:
00066 rospy.logerr('PurepursuitClient: Error waiting for server')
00067 return -1
00068
00069
00070 def cancel(self):
00071 rospy.loginfo('PurepursuitClient: cancelling the goal')
00072 self.client.cancel_goal()
00073
00074
00075
00076
00077
00078
00079
00080
00081 def getState(self):
00082 return self.client.get_state()
00083
00084
00085 def getResult(self):
00086 ret = self.client.get_result()
00087 if not ret:
00088 return -1
00089
00090 else:
00091 return ret
00092
00093
00094 class PointPath(InteractiveMarker):
00095
00096 def __init__(self, frame_id, name, description, is_manager = False):
00097 InteractiveMarker.__init__(self)
00098
00099 self.header.frame_id = frame_id
00100 self.name = name
00101 self.description = description
00102
00103 self.marker = Marker()
00104 self.marker.type = Marker.CYLINDER
00105 self.marker.scale.x = 0.1
00106 self.marker.scale.y = 0.1
00107 self.marker.scale.z = 0.4
00108 self.marker.pose.position.z = 0.20
00109 if is_manager:
00110 self.marker.color.r = 0.8
00111 self.marker.color.g = 0.0
00112 self.marker.color.b = 0.0
00113 self.marker.color.a = 0.5
00114 else:
00115 self.marker.color.r = 0.0
00116 self.marker.color.g = 0.8
00117 self.marker.color.b = 0.0
00118 self.marker.color.a = 0.5
00119
00120 self.marker_control = InteractiveMarkerControl()
00121 self.marker_control.always_visible = True
00122 self.marker_control.orientation.w = 1
00123 self.marker_control.orientation.x = 0
00124 self.marker_control.orientation.y = 1
00125 self.marker_control.orientation.z = 0
00126 self.marker_control.markers.append( self.marker )
00127 self.marker_control.interaction_mode = InteractiveMarkerControl.MOVE_PLANE
00128
00129 self.controls.append( self.marker_control )
00130
00131
00132 def processFeedback(self, feedback):
00133
00134 self.pose = feedback.pose
00135
00136
00137
00138
00139 class PointPathManager(InteractiveMarkerServer):
00140
00141 def __init__(self, name, frame_id, planner):
00142 InteractiveMarkerServer.__init__(self, name)
00143 self.list_of_points = []
00144 self.frame_id = frame_id
00145 self.counter_points = 0
00146
00147
00148 self.menu_handler = MenuHandler()
00149 h_first_entry = self.menu_handler.insert( "Waypoints" )
00150 entry = self.menu_handler.insert( "Create New", parent=h_first_entry, callback=self.newPointCB)
00151 entry = self.menu_handler.insert( "Delete last", parent=h_first_entry, callback=self.deletePointCB );
00152 entry = self.menu_handler.insert( "Delete all", parent=h_first_entry, callback=self.deleteAllPointsCB );
00153 h_second_entry = self.menu_handler.insert( "Path" )
00154 entry = self.menu_handler.insert( "Go", parent=h_second_entry, callback=self.startRouteCB)
00155 entry = self.menu_handler.insert( "Stop", parent=h_second_entry, callback=self.stopRouteCB)
00156 entry = self.menu_handler.insert( "Go back", parent=h_second_entry, callback=self.reverseRouteCB)
00157
00158
00159
00160 self.initial_point = PointPath(frame_id, 'PointManager', 'PointManager', True)
00161 self.insert(self.initial_point, self.initial_point.processFeedback)
00162
00163 self.menu_handler.apply( self, self.initial_point.name )
00164 self.applyChanges()
00165
00166 self.planner_client = PurepursuitClient(planner)
00167
00168
00169
00170
00171
00172 def createNewPoint(self):
00173
00174
00175 new_point = PointPath(self.frame_id, 'p%d'%(self.counter_points), 'p%d'%(self.counter_points))
00176
00177
00178 if len(self.list_of_points) > 1:
00179 new_point.pose.position.x = self.list_of_points[self.counter_points-1].pose.position.x
00180 new_point.pose.position.y = self.list_of_points[self.counter_points-1].pose.position.y
00181 elif len(self.list_of_points) == 1:
00182 new_point.pose.position.x = self.list_of_points[0].pose.position.x
00183 new_point.pose.position.y = self.list_of_points[0].pose.position.y
00184
00185 new_point.pose.position.x = new_point.pose.position.x + 1.0
00186
00187
00188
00189
00190 self.list_of_points.append(new_point)
00191 self.insert(new_point, new_point.processFeedback)
00192 self.menu_handler.apply( self, 'p%d'%(self.counter_points) )
00193 self.applyChanges()
00194 self.counter_points = self.counter_points + 1
00195
00196
00197
00198
00199 return
00200
00201
00202 def newPointCB(self, feedback):
00203
00204 self.createNewPoint()
00205
00206
00207 def deletePointCB(self, feedback):
00208 if self.counter_points > 0:
00209 p = self.list_of_points.pop()
00210 self.counter_points = self.counter_points - 1
00211 self.erase(p.name)
00212 self.applyChanges()
00213
00214
00215
00216
00217 def deleteAllPointsCB(self, feedback):
00218 for i in range(len(self.list_of_points)):
00219 p = self.list_of_points.pop()
00220 self.counter_points = self.counter_points - 1
00221 self.erase(p.name)
00222
00223 self.applyChanges()
00224
00225
00226
00227
00228 def startRouteCB(self, feedback):
00229 goals = self.convertListOfPointPathIntoGoal()
00230 print 'goals: %s'%(goals)
00231 self.planner_client.goTo(goals)
00232 return
00233
00234
00235 def reverseRouteCB(self, feedback):
00236 goals = self.convertListOfPointPathIntoGoal(inverse = True)
00237
00238 self.planner_client.goTo(goals)
00239 return
00240
00241
00242 def stopRouteCB(self, feedback):
00243 self.planner_client.cancel()
00244 return
00245
00246
00247 def convertListOfPointPathIntoGoal(self, inverse = False):
00248 converted_list = []
00249 if inverse:
00250 for i in reversed(self.list_of_points):
00251 converted_list.append(goal(pose = Pose2D(i.pose.position.x, i.pose.position.y, 0.0), speed = 0.4))
00252 else:
00253 for i in self.list_of_points:
00254
00255 converted_list.append(goal(pose = Pose2D(i.pose.position.x, i.pose.position.y, 0.0), speed = 0.4))
00256
00257 return converted_list
00258
00259 if __name__=="__main__":
00260 rospy.init_node("agvs_path_maker")
00261
00262 server = PointPathManager('agvs_path_maker', frame_id = '/map', planner = 'purepursuit_planner')
00263
00264 rospy.spin()
00265