server.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import rospy
4 import actionlib
5 from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
6 from actionlib_msgs.msg import GoalStatus
7 from geometry_msgs.msg import PoseStamped, PoseArray, PolygonStamped
8 from nav_msgs.msg import Path
9 from std_msgs.msg import Bool, Empty
10 from move_base_sequence.srv import *
11 
13  def __init__(self):
14  rospy.init_node('move_base_sequence')
15  #changed this line to get_param every time so that any change in the parameter would be captured without needing to initialize a new object
16  #self._repeating = rospy.get_param("/move_base_sequence/is_repeating",True)
17  self.poses_pub = rospy.Publisher("/move_base_sequence/wayposes",PoseArray,queue_size=10)
18  #self.poly_pub = rospy.Publisher("/poly_path",PolygonStamped,queue_size=10)
19  self.path_pub = rospy.Publisher("/move_base_sequence/path",Path,queue_size=10)
20  _ = rospy.Subscriber("/move_base_sequence/wayposes",PoseArray,self.set_poses)
21  _ = rospy.Subscriber("/move_base_sequence/corner_pose",PoseStamped,self.add_pose)
22  _ = rospy.Service('/move_base_sequence/get_state', get_state, self.get_state)
23  _ = rospy.Service('/move_base_sequence/toggle_state', toggle_state, self.toggle_state)
24  _ = rospy.Service('/move_base_sequence/set_state', set_state, self.set_state)
25  _ = rospy.Service('/move_base_sequence/reset', reset, self.reset)
26  #_ = rospy.Subscriber("/move_base_sequence/state",Bool,self.set_state)#to switch the sending of the sequnce on or off
27  # = rospy.Subscriber("/move_base_sequence/reset",Empty,self.reset)#to reset the whole sequence
28 
29  rospy.set_param("/move_base_sequence/abortion_behaviour","stop")
30  rospy.set_param("/move_base_sequence/is_repeating",True)
31 
32  self.__state__ = True #indicates whether the seq. is running or stopped... edited by /move_base_seq_state topic, should be a service!
33  self._i = 0 #how many goals in the list are done
34  self._sending = False #indicates whether there is a goal thats being served or not
35  self._internal_call = False #this is to prevent infinite loop of calling self.add_pose() when adding poses through pose array
36 
37  self.path = Path()
38  self.path.header.frame_id = "map"
39  self.path.header.stamp = rospy.Time.now()
40 
41  #self.poly_path = PolygonStamped()
42  #self.poly_path.header.frame_id = "map"
43  #self.poly_path.header.stamp = rospy.Time.now()
44  self.poses = PoseArray()
45  self.poses.header.frame_id = "map"
46  self.poses.header.stamp = rospy.Time.now()
47 
48  #Create action client
49  self.client = actionlib.SimpleActionClient('move_base',MoveBaseAction)
50  rospy.loginfo("Waiting for move_base action server...")
51  wait = self.client.wait_for_server(rospy.Duration(5.0))
52  if not wait:
53  rospy.logerr("Action server not available!")
54  #rospy.signal_shutdown("Action server not available!")
55  return
56  rospy.loginfo("Connected to move base server, moving the base "+ ("one way trip" if rospy.get_param("/move_base_sequence/is_repeating",True) == False else "in a repetitive way"))
57  rospy.loginfo("Waiting for goals..")
58 
59 
60  def __del__(self):
61  self.reset(resetRequest())
62  print("move_base_sequence ended successfully!")
63 
64  def reset(self,request):
65  try:
66  self.__state__ = True
67  self._i = 0
68  #self._internal_call = False
69  if self._sending: self.client.cancel_goal()
70  self.path = Path()
71  self.path.header.frame_id = "map"
72  self.path.header.stamp = rospy.Time.now()
73  #self.poly_path = PolygonStamped()
74  #self.poly_path.header.frame_id = "map"
75  #self.poly_path.header.stamp = rospy.Time.now()
76  self.poses = PoseArray()
77  self.poses.header.frame_id = "map"
78  self.poses.header.stamp = rospy.Time.now()
79 
80  self._internal_call = True
81  self.poses_pub.publish(self.poses)
82  #self.poly_pub.publish(self.poly_path)
83  self.path_pub.publish(self.path)
84 
85  rospy.loginfo("Sequence reset done!.. waiting for new goals..")
86  return resetResponse(True)
87  except:
88  #this means a problem happened, may be imporved to add a warning or a log, or even handle the possible errors
89  rospy.logerr("A problem occured during resetting!")
90  return resetResponse(False)
91 
92  def set_state(self,request):
93  if self.__state__ == request.state :
94  rospy.logwarn("the sent state is the same as the internal state! no change is applied.")
95  return set_stateResponse(False)
96  self.__state__ = not self.__state__
97  rospy.loginfo("set_state Success! State now is "+ ("operating" if self.__state__ else "paused."))
98  if self.__state__ == False:
99  if self._sending: self.client.cancel_goal()
100  return set_stateResponse(True)
101 
102  def toggle_state(self,request):
103  try:
104  self.__state__ = not self.__state__
105  if self.__state__ == False:
106  if self._sending: self.client.cancel_goal()
107  rospy.loginfo("toggle_state Success! State now is "+ ("operating" if self.__state__ else "paused."))
108  return toggle_stateResponse(True)
109  except:
110  rospy.logerr("Something went wrong while toggling the state!")
111  return toggle_stateResponse(False)
112 
113 
114  def get_state(self,request):
115  return get_stateResponse("operating" if self.__state__ else "Paused")
116 
117  def add_pose(self,msg):
118  self.poses.poses.append(msg.pose)
119  #self.poly_path.polygon.points.append(self.poses.poses[-1].position)
120  self.path.poses.append(msg)
121  self.poses.header.stamp = rospy.Time.now()
122  #self.poly_path.header.stamp = rospy.Time.now()
123  self.path.header.stamp = rospy.Time.now()
124  if self._internal_call: rospy.loginfo("Adding a goal from a pose array...")
125  else: rospy.loginfo("Adding a new pose to the list.")
126  #updating new visualization topics only if the call was a callback for the topic /corner_pose
127  if not self._internal_call:
128  self._internal_call = True
129  self.poses_pub.publish(self.poses)
130  #self.poly_pub.publish(self.poly_path)
131  self.path_pub.publish(self.path)
132 
133  def set_poses(self,msg):
134  if not self._internal_call:
135  self._internal_call = True
136  temp_posestamped = PoseStamped()
137  temp_posestamped.header = self.poses.header
138  for pose in msg.poses:
139  temp_posestamped.pose = pose
140  self.add_pose(temp_posestamped)
141  self.poses_pub.publish(self.poses)
142  #self.poly_pub.publish(self.poly_path)
143  self.path_pub.publish(self.path)
144  rospy.loginfo("Successfully added goal poses!")
145  else:
146  self._internal_call = False
147 
148  def check_newgoals(self):
149  if not self.__state__:
150  return #state is off, do not send goals!, it won't get here if __state__ is false but as a safety
151  elif self._i <= len(self.poses.poses)-1:
152  self.move_base_client()
153  return
154  else: return # cool, no new goals :)
155 
156 
157  def active_cb(self):
158  rospy.loginfo("Goal pose "+str(self._i)+" is now being processed by the Action Server...")
159 
160 
161  def feedback_cb(self, feedback):
162  #To print current pose at each feedback:
163  #rospy.loginfo("Feedback for goal "+str(self.goal_cnt)+": "+str(feedback))
164  pass
165 
166 
167  def done_cb(self, status, result):
168  # Reference for terminal status values: http://docs.ros.org/diamondback/api/actionlib_msgs/html/msg/GoalStatus.html
169  if status == 2:
170  rospy.loginfo("Goal pose "+str(self._i)+" received a cancel request after it started executing, successfully cancelled!")
171 
172  elif status == 8:
173  rospy.loginfo("Goal pose "+str(self._i)+" received a cancel request before it started executing, successfully cancelled!")
174 
175  elif status == 3:
176  rospy.loginfo("Goal pose "+str(self._i)+" REACHED!")
177  self._set_next_goal()
178 
179  elif status == 4:
180  behav = rospy.get_param("/move_base_sequence/abortion_behaviour","stop")
181  if behav == "stop": self.__state__ = False
182  elif not (behav == "continue"): rospy.logwarn("Param /move_base_sequence/abortion_behaviour is neither 'stop' nor 'continue'! continue is assumed.")
183  rospy.logerr ("Goal pose "+str(self._i)+" aborted," +("stopping sequence execution," if behav=='stop' else "continuing with next goals, ")+ "check any errors!")
184  self._set_next_goal()
185 
186  elif status == 5:
187  rospy.logerr("Goal pose "+str(self._i)+" has been rejected by the Action Server. moving to next goal.")
188  self._set_next_goal()
189 
190  self._sending = False #ended dealing with the goal
191 
192 
193  def _set_next_goal(self):
194  self._i+=1
195  if self._i <= len(self.poses.poses)-1: pass
196  elif self._i > len(self.poses.poses)-1:
197  if rospy.get_param("/move_base_sequence/is_repeating",True):
198  self._i = 0
199  rospy.loginfo("reached the end of the sequence successfully, repeating it again!")
200  else:
201  self._i = 0
202  rospy.loginfo("reached the end of the sequence successfully, waiting another sequence!")
203  #clearing the poses seq., path, and visualisation topics
204  self.path = Path()
205  self.path.header.frame_id = "map"
206  self.path.header.stamp = rospy.Time.now()
207  #self.poly_path = PolygonStamped()
208  #self.poly_path.header.frame_id = "map"
209  #self.poly_path.header.stamp = rospy.Time.now()
210  self.poses = PoseArray()
211  self.poses.header.frame_id = "map"
212  self.poses.header.stamp = rospy.Time.now()
213 
214  self._internal_call = True
215  self.poses_pub.publish(self.poses)
216  #self.poly_pub.publish(self.poly_path)
217  self.path_pub.publish(self.path)
218 
219 
220  def move_base_client(self):
221  if self._sending or not self.__state__: return
222  else:
223  self._sending = True #don't send as it has already sent a goal thats being served
224  goal = MoveBaseGoal()
225  goal.target_pose.header.frame_id = "map"
226  goal.target_pose.header.stamp = rospy.Time.now()
227  goal.target_pose.pose = self.poses.poses[self._i]
228  rospy.loginfo("Sending goal pose "+str(self._i)+" to Action Server")
229  #rospy.loginfo(str(self.poses.poses[self._i]))
230  self.client.send_goal(goal, self.done_cb, self.active_cb, self.feedback_cb)
231 
232 
233 
234 if __name__ == '__main__':
235  move_base_sequence = move_base_sequence()
236  while not rospy.is_shutdown():
237  move_base_sequence.check_newgoals()
238  continue
def move_base_client(self)
Definition: server.py:220
def set_poses(self, msg)
Definition: server.py:133
def _set_next_goal(self)
Definition: server.py:193
def toggle_state(self, request)
Definition: server.py:102
def done_cb(self, status, result)
Definition: server.py:167
def feedback_cb(self, feedback)
Definition: server.py:161
def reset(self, request)
Definition: server.py:64
def add_pose(self, msg)
Definition: server.py:117
def check_newgoals(self)
Definition: server.py:148
def get_state(self, request)
Definition: server.py:114
def set_state(self, request)
Definition: server.py:92


move_base_sequence
Author(s): mark
autogenerated on Thu Mar 4 2021 03:20:45