axserver.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # Software License Agreement (BSD License)
3 #
4 # Copyright (c) 2009, Willow Garage, Inc.
5 # All rights reserved.
6 #
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions
9 # are met:
10 #
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above
14 # copyright notice, this list of conditions and the following
15 # disclaimer in the documentation and/or other materials provided
16 # with the distribution.
17 # * Neither the name of Willow Garage, Inc. nor the names of its
18 # contributors may be used to endorse or promote products derived
19 # from this software without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 # POSSIBILITY OF SUCH DAMAGE.
33 
34 """
35 usage: %prog /action_name action_type
36 """
37 
38 PKG = 'actionlib'
39 
40 from optparse import OptionParser
41 import roslib.message
42 import wx
43 import rospy
44 import actionlib
45 import threading
46 from cStringIO import StringIO
47 from library import to_yaml, yaml_msg_str
48 from dynamic_action import DynamicAction
49 
50 SEND_FEEDBACK = 0
51 SUCCEED = 1
52 ABORT = 2
53 PREEMPT = 3
54 
55 
56 class AXServerApp(wx.App):
57  def __init__(self, action_type, action_name):
58  self.action_type = action_type
59  self.action_name = action_name
60  wx.App.__init__(self)
61 
63  self.action_name,
64  self.action_type.action,
65  self.execute
66  )
67  self.condition = threading.Condition()
68  self.feedback_msg = None
69  self.result_msg = None
70  self.execute_type = None
71 
72  def set_goal(self, goal):
73  if goal is None:
74  self.status_bg.SetBackgroundColour(wx.Colour(200, 0, 0))
75  self.status.SetLabel("Waiting For Goal...")
76  self.send_feedback.Disable()
77  self.succeed.Disable()
78  self.abort.Disable()
79  self.preempt.Disable()
80 
81  self.goal.SetValue("")
82 
83  else:
84  self.status_bg.SetBackgroundColour(wx.Colour(0, 200, 0))
85  self.status.SetLabel("Received Goal. Send feedback, succeed, or abort.")
86  self.send_feedback.Enable()
87  self.succeed.Enable()
88  self.abort.Enable()
89  self.preempt.Enable()
90 
91  try:
92  self.goal.SetValue(to_yaml(goal))
93  except UnicodeDecodeError:
94  self.goal.SetValue("Cannot display goal due to unprintable characters")
95 
97  self.status_bg.SetBackgroundColour(wx.Colour(0, 200, 200))
98  self.status.SetLabel("Preempt requested...")
99 
100  def execute(self, goal):
101 
102  wx.CallAfter(self.set_goal, goal)
103  self.condition.acquire()
104 
105  self.result_msg = None
106  self.feedback_msg = None
107  self.execute_type = None
108 
109  while self.execute_type is None or self.execute_type == SEND_FEEDBACK:
110  self.result_msg = None
111  self.feedback_msg = None
112  self.execute_type = None
113 
114  while self.execute_type is None:
115  if self.server.is_preempt_requested():
116  wx.CallAfter(self.set_preempt_requested)
117  self.condition.wait(1.0)
118 
119  if self.execute_type == SEND_FEEDBACK:
120  if self.feedback_msg is not None:
121  self.server.publish_feedback(self.feedback_msg)
122 
123  if self.execute_type == SUCCEED:
124  self.server.set_succeeded(self.result_msg)
125 
126  if self.execute_type == ABORT:
127  self.server.set_aborted()
128 
129  if self.execute_type == PREEMPT:
130  self.server.set_preempted()
131 
132  wx.CallAfter(self.set_goal, None)
133 
134  self.condition.release()
135 
136  def on_feedback(self, event):
137  self.condition.acquire()
138 
139  try:
140  self.feedback_msg = yaml_msg_str(self.action_type.feedback,
141  self.feedback.GetValue())
142  buff = StringIO()
143  self.feedback_msg.serialize(buff)
144 
145  self.execute_type = SEND_FEEDBACK
146  self.condition.notify()
147  except roslib.message.SerializationError as e:
148  self.feedback_msg = None
149  wx.MessageBox(str(e), "Error serializing feedback", wx.OK)
150 
151  self.condition.release()
152 
153  def on_succeed(self, event):
154  self.condition.acquire()
155 
156  try:
157  self.result_msg = yaml_msg_str(self.action_type.result, self.result.GetValue())
158  buff = StringIO()
159  self.result_msg.serialize(buff)
160 
161  self.execute_type = SUCCEED
162  self.condition.notify()
163  except roslib.message.SerializationError as e:
164  self.result_msg = None
165  wx.MessageBox(str(e), "Error serializing result", wx.OK)
166 
167  self.condition.release()
168 
169  def on_abort(self, event):
170  self.condition.acquire()
171 
172  self.execute_type = ABORT
173  self.condition.notify()
174 
175  self.condition.release()
176 
177  def on_preempt(self, event):
178  self.condition.acquire()
179 
180  self.execute_type = PREEMPT
181  self.condition.notify()
182 
183  self.condition.release()
184 
185  def OnInit(self):
186 
187  self.frame = wx.Frame(
188  None, -1,
189  self.action_name + ' - ' + self.action_type.name + ' - Standin'
190  )
191 
192  self.sz = wx.BoxSizer(wx.VERTICAL)
193 
194  tmp_feedback = self.action_type.feedback()
195  tmp_result = self.action_type.result()
196 
197  self.goal = wx.TextCtrl(self.frame, -1, style=(wx.TE_MULTILINE | wx.TE_READONLY))
198  self.goal_st_bx = wx.StaticBox(self.frame, -1, "Goal")
199  self.goal_st = wx.StaticBoxSizer(self.goal_st_bx, wx.VERTICAL)
200  self.goal_st.Add(self.goal, 1, wx.EXPAND)
201 
202  self.feedback = wx.TextCtrl(self.frame, -1, style=wx.TE_MULTILINE)
203  self.feedback.SetValue(to_yaml(tmp_feedback))
204  self.feedback_st_bx = wx.StaticBox(self.frame, -1, "Feedback")
205  self.feedback_st = wx.StaticBoxSizer(self.feedback_st_bx, wx.VERTICAL)
206  self.feedback_st.Add(self.feedback, 1, wx.EXPAND)
207 
208  self.result = wx.TextCtrl(self.frame, -1, style=wx.TE_MULTILINE)
209  self.result.SetValue(to_yaml(tmp_result))
210  self.result_st_bx = wx.StaticBox(self.frame, -1, "Result")
211  self.result_st = wx.StaticBoxSizer(self.result_st_bx, wx.VERTICAL)
212  self.result_st.Add(self.result, 1, wx.EXPAND)
213 
214  self.send_feedback = wx.Button(self.frame, -1, label="SEND FEEDBACK")
215  self.send_feedback.Bind(wx.EVT_BUTTON, self.on_feedback)
216 
217  self.succeed = wx.Button(self.frame, -1, label="SUCCEED")
218  self.succeed.Bind(wx.EVT_BUTTON, self.on_succeed)
219 
220  self.abort = wx.Button(self.frame, -1, label="ABORT")
221  self.abort.Bind(wx.EVT_BUTTON, self.on_abort)
222 
223  self.preempt = wx.Button(self.frame, -1, label="PREEMPT")
224  self.preempt.Bind(wx.EVT_BUTTON, self.on_preempt)
225 
226  self.status_bg = wx.Panel(self.frame, -1)
227  self.status_bg.SetBackgroundColour(wx.Colour(200, 0, 0))
228  self.status = wx.StaticText(self.status_bg, -1, label="Waiting For Goal...")
229 
230  self.sz.Add(self.goal_st, 1, wx.EXPAND)
231  self.sz.Add(self.feedback_st, 1, wx.EXPAND)
232  self.sz.Add(self.result_st, 1, wx.EXPAND)
233  self.sz.Add(self.send_feedback, 0, wx.EXPAND)
234  self.sz.Add(self.succeed, 0, wx.EXPAND)
235  self.sz.Add(self.abort, 0, wx.EXPAND)
236  self.sz.Add(self.preempt, 0, wx.EXPAND)
237  self.sz.Add(self.status_bg, 0, wx.EXPAND)
238 
239  self.frame.SetSizer(self.sz)
240 
241  self.set_goal(None)
242 
243  self.sz.Layout()
244  self.frame.Show()
245 
246  return True
247 
248 
249 if __name__ == '__main__':
250  rospy.init_node('axserver', anonymous=True)
251 
252  parser = OptionParser(__doc__.strip())
253 # parser.add_option("-t","--test",action="store_true", dest="test",default=False,
254 # help="A testing flag")
255 # parser.add_option("-v","--var",action="store",type="string", dest="var",default="blah")
256 
257  (options, args) = parser.parse_args(rospy.myargv())
258 
259  if (len(args) != 3):
260  parser.error("You must specify the action name and type. Eg: ./axserver.py my_action actionlib/Test")
261 
262  action = DynamicAction(args[2])
263 
264  app = AXServerApp(action, args[1])
265  app.MainLoop()
266  rospy.signal_shutdown('GUI shutdown')
def on_preempt(self, event)
Definition: axserver.py:177
def __init__(self, action_type, action_name)
Definition: axserver.py:57
def on_succeed(self, event)
Definition: axserver.py:153
def execute(self, goal)
Definition: axserver.py:100
def on_feedback(self, event)
Definition: axserver.py:136
def on_abort(self, event)
Definition: axserver.py:169
def set_preempt_requested(self)
Definition: axserver.py:96
def OnInit(self)
Definition: axserver.py:185
def set_goal(self, goal)
Definition: axserver.py:72
def yaml_msg_str(type_, yaml_str, filename=None)
Definition: library.py:85
def to_yaml(obj)
Definition: library.py:77


actionlib
Author(s): Eitan Marder-Eppstein, Vijay Pradeep, Mikael Arguedas
autogenerated on Mon Aug 24 2020 03:40:47