complex_action_server.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 # Copyright (c) 2009, Willow Garage, Inc.
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above copyright
11 # notice, this list of conditions and the following disclaimer in the
12 # documentation and/or other materials provided with the distribution.
13 # * Neither the name of the Willow Garage, Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
28 #
29 # Author: Brian Wright.
30 # Based on C++ simple_action_server.h by Eitan Marder-Eppstein
31 
32 import rospy
33 
34 import threading
35 import traceback
36 
37 import six
38 
39 import actionlib_msgs
40 from actionlib import ActionServer
41 from actionlib.server_goal_handle import ServerGoalHandle;
42 
43 def nop_cb(goal_handle):
44  pass
45 
46 
47 
51 
57  def __init__(self, name, ActionSpec, execute_cb = None, auto_start = True):
58 
59  self.goals_received_ = 0;
60  self.goal_queue_ = six.moves.queue.Queue()
61 
62  self.new_goal = False
63 
64  self.execute_callback = execute_cb;
65  self.goal_callback = None;
66 
67  self.need_to_terminate = False
68  self.terminate_mutex = threading.RLock();
69 
70  # since the internal_goal/preempt_callbacks are invoked from the
71  # ActionServer while holding the self.action_server.lock
72  # self.lock must always be locked after the action server lock
73  # to avoid an inconsistent lock acquisition order
74  self.lock = threading.RLock();
75 
76  self.execute_condition = threading.Condition(self.lock);
77 
80 
81  if self.execute_callback:
82  self.execute_thread = threading.Thread(None, self.executeLoop);
83  self.execute_thread.start();
84  else:
85  self.execute_thread = None
86 
87 
88  #create the action server
89  self.action_server = ActionServer(name, ActionSpec, self.internal_goal_callback,self.internal_preempt_callback,auto_start);
90 
91 
92  def __del__(self):
93  if hasattr(self, 'execute_callback') and self.execute_callback:
94  with self.terminate_mutex:
95  self.need_to_terminate = True;
96 
97  assert(self.execute_thread);
98  self.execute_thread.join();
99 
100 
101 
103  def accept_new_goal(self):
104  with self.action_server.lock, self.lock:
105 
106  rospy.logdebug("Accepting a new goal");
107 
108  self.goals_received_ -= 1;
109 
110  #get from queue
111  current_goal = self.goal_queue_.get()
112 
113  #set the status of the current goal to be active
114  current_goal.set_accepted("This goal has been accepted by the simple action server");
115 
116  return current_goal#.get_goal();
117 
118 
119 
122  return self.goals_received_ > 0
123 
124 
125 
127  def is_active(self):
128  if not self.current_goal.get_goal():
129  return False;
130 
131  status = self.current_goal.get_goal_status().status;
132  return status == actionlib_msgs.msg.GoalStatus.ACTIVE #or status == actionlib_msgs.msg.GoalStatus.PREEMPTING;
133 
134 
136  def set_succeeded(self,result=None, text="", goal_handle=None):
137  with self.action_server.lock, self.lock:
138  if not result:
139  result=self.get_default_result();
140  #self.current_goal.set_succeeded(result, text);
141  goal_handle.set_succeeded(result,text)
142 
143 
145  def set_aborted(self, result = None, text="" , goal_handle=None):
146  with self.action_server.lock, self.lock:
147  if not result:
148  result=self.get_default_result();
149  #self.current_goal.set_aborted(result, text);
150  goal_handle.set_aborted(result,text)
151 
152 
154  def publish_feedback(self,feedback):
155  self.current_goal.publish_feedback(feedback);
156 
157 
159  return self.action_server.ActionResultType();
160 
161 
164  if self.execute_callback:
165  rospy.logwarn("Cannot call ComplexActionServer.register_goal_callback() because an executeCallback exists. Not going to register it.");
166  else:
167  self.goal_callback = cb;
168 
169 
170 
171  def start(self):
172  self.action_server.start();
173 
174 
175 
176  def internal_goal_callback(self, goal):
177  self.execute_condition.acquire();
178 
179  try:
180  rospy.logdebug("A new goal %shas been recieved by the single goal action server",goal.get_goal_id().id);
181 
182 
183  print("got a goal")
184  self.next_goal = goal;
185  self.new_goal = True;
186  self.goals_received_ += 1
187 
188  #add goal to queue
189  self.goal_queue_.put(goal)
190 
191  #Trigger runLoop to call execute()
192  self.execute_condition.notify();
193  self.execute_condition.release();
194 
195  except Exception as e:
196  rospy.logerr("ComplexActionServer.internal_goal_callback - exception %s",str(e))
197  self.execute_condition.release();
198 
199 
200 
201  def internal_preempt_callback(self,preempt):
202  return
203 
204 
205  def executeLoop(self):
206  loop_duration = rospy.Duration.from_sec(.1);
207 
208  while (not rospy.is_shutdown()):
209  rospy.logdebug("SAS: execute");
210 
211  with self.terminate_mutex:
212  if (self.need_to_terminate):
213  break;
214 
215  if (self.is_new_goal_available()):
216  # accept_new_goal() is performing its own locking
217  goal_handle = self.accept_new_goal();
218  if not self.execute_callback:
219  rospy.logerr("execute_callback_ must exist. This is a bug in ComplexActionServer");
220  return
221 
222  try:
223 
224  print("run new executecb")
225  thread = threading.Thread(target=self.run_goal,args=(goal_handle.get_goal(),goal_handle));
226  thread.start()
227 
228  except Exception as ex:
229  rospy.logerr("Exception in your execute callback: %s\n%s", str(ex),
230  traceback.format_exc())
231  self.set_aborted(None, "Exception in execute callback: %s" % str(ex))
232 
233  with self.execute_condition:
234  self.execute_condition.wait(loop_duration.to_sec());
235 
236 
237 
238 
239  def run_goal(self,goal, goal_handle):
240  print('new thread')
241  self.execute_callback(goal,goal_handle);
242 
243 
244 
flexbe_input.complex_action_server.nop_cb
def nop_cb(goal_handle)
Definition: complex_action_server.py:43
flexbe_input.complex_action_server.ComplexActionServer.accept_new_goal
def accept_new_goal(self)
Accepts a new goal when one is available The status of this goal is set to active upon acceptance,...
Definition: complex_action_server.py:103
flexbe_input.complex_action_server.ComplexActionServer.__del__
def __del__(self)
Definition: complex_action_server.py:92
actionlib::server_goal_handle
actionlib::ActionServer
flexbe_input.complex_action_server.ComplexActionServer.publish_feedback
def publish_feedback(self, feedback)
Publishes feedback for a given goal.
Definition: complex_action_server.py:154
flexbe_input.complex_action_server.ComplexActionServer.goals_received_
goals_received_
Definition: complex_action_server.py:59
flexbe_input.complex_action_server.ComplexActionServer.is_active
def is_active(self)
Allows polling implementations to query about the status of the current goal.
Definition: complex_action_server.py:127
flexbe_input.complex_action_server.ComplexActionServer.terminate_mutex
terminate_mutex
Definition: complex_action_server.py:68
flexbe_input.complex_action_server.ComplexActionServer.lock
lock
Definition: complex_action_server.py:74
flexbe_input.complex_action_server.ComplexActionServer.internal_goal_callback
def internal_goal_callback(self, goal)
Callback for when the ActionServer receives a new goal and passes it on.
Definition: complex_action_server.py:176
flexbe_input.complex_action_server.ComplexActionServer.internal_preempt_callback
def internal_preempt_callback(self, preempt)
Callback for when the ActionServer receives a new preempt and passes it on.
Definition: complex_action_server.py:201
flexbe_input.complex_action_server.ComplexActionServer
The ComplexActionServer Operate with concurrent goals in a multi-threaded fashion.
Definition: complex_action_server.py:50
flexbe_input.complex_action_server.ComplexActionServer.__init__
def __init__(self, name, ActionSpec, execute_cb=None, auto_start=True)
Constructor for a ComplexActionServer.
Definition: complex_action_server.py:57
actionlib::server_goal_handle::ServerGoalHandle
flexbe_input.complex_action_server.ComplexActionServer.run_goal
def run_goal(self, goal, goal_handle)
Definition: complex_action_server.py:239
flexbe_input.complex_action_server.ComplexActionServer.goal_queue_
goal_queue_
Definition: complex_action_server.py:60
flexbe_input.complex_action_server.ComplexActionServer.get_default_result
def get_default_result(self)
Definition: complex_action_server.py:158
flexbe_input.complex_action_server.ComplexActionServer.execute_callback
execute_callback
Definition: complex_action_server.py:64
flexbe_input.complex_action_server.ComplexActionServer.set_succeeded
def set_succeeded(self, result=None, text="", goal_handle=None)
Sets the status of the active goal to succeeded.
Definition: complex_action_server.py:136
flexbe_input.complex_action_server.ComplexActionServer.executeLoop
def executeLoop(self)
Called from a separate thread to call blocking execute calls.
Definition: complex_action_server.py:205
flexbe_input.complex_action_server.ComplexActionServer.set_aborted
def set_aborted(self, result=None, text="", goal_handle=None)
Sets the status of the active goal to aborted.
Definition: complex_action_server.py:145
flexbe_input.complex_action_server.ComplexActionServer.next_goal
next_goal
Definition: complex_action_server.py:79
flexbe_input.complex_action_server.ComplexActionServer.need_to_terminate
need_to_terminate
Definition: complex_action_server.py:67
flexbe_input.complex_action_server.ComplexActionServer.register_goal_callback
def register_goal_callback(self, cb)
Allows users to register a callback to be invoked when a new goal is available.
Definition: complex_action_server.py:163
flexbe_input.complex_action_server.ComplexActionServer.is_new_goal_available
def is_new_goal_available(self)
Allows polling implementations to query about the availability of a new goal.
Definition: complex_action_server.py:121
flexbe_input.complex_action_server.ComplexActionServer.new_goal
new_goal
Definition: complex_action_server.py:62
flexbe_input.complex_action_server.ComplexActionServer.goal_callback
goal_callback
Definition: complex_action_server.py:65
flexbe_input.complex_action_server.ComplexActionServer.execute_thread
execute_thread
Definition: complex_action_server.py:82
flexbe_input.complex_action_server.ComplexActionServer.current_goal
current_goal
Definition: complex_action_server.py:78
flexbe_input.complex_action_server.ComplexActionServer.start
def start(self)
Explicitly start the action server, used it auto_start is set to false.
Definition: complex_action_server.py:171
flexbe_input.complex_action_server.ComplexActionServer.action_server
action_server
Definition: complex_action_server.py:89
flexbe_input.complex_action_server.ComplexActionServer.execute_condition
execute_condition
Definition: complex_action_server.py:76


flexbe_input
Author(s): Philipp Schillinger, Philipp Schillinger
autogenerated on Fri Jul 21 2023 02:26:08