packml.py
Go to the documentation of this file.
1 """
2  Copyright 2017 Shaun Edwards
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 """
16 
17 import os
18 import rospy
19 import rospkg
20 
21 from threading import Thread
22 from qt_gui.plugin import Plugin
23 from python_qt_binding import loadUi
24 from python_qt_binding.QtCore import Qt, QThread, QRunnable, QThreadPool
25 from python_qt_binding.QtWidgets import QWidget
26 from python_qt_binding.QtGui import QPalette
27 from std_srvs.srv import Trigger
28 from packml_msgs.srv import Transition
29 from packml_msgs.srv import TransitionRequest
30 from packml_msgs.msg import Status
31 from packml_msgs.msg import State
32 from packml_msgs.msg import Mode
33 
34 class WorkerThread(QRunnable):
35  def __init__(self, service, req, set_msg):
36  super(WorkerThread, self).__init__()
37  self.service = service
38  self.req = req
39  self.set_msg = set_msg
40 
41  def run(self):
42  res = self.service(self.req)
43  self.set_msg(res.message)
44 
45 class Packml(Plugin):
46 
47  def __init__(self, context):
48  super(Packml, self).__init__(context)
49  self.setObjectName('Packml')
50 
51  from argparse import ArgumentParser
52  parser = ArgumentParser()
53 
54  parser.add_argument("-q", "--quiet", action="store_true",
55  dest="quiet",
56  help="Put plugin in silent mode")
57  args, unknowns = parser.parse_known_args(context.argv())
58  if not args.quiet:
59  print 'arguments: ', args
60  print 'unknowns: ', unknowns
61 
62  # Create QWidget
63  self._widget = QWidget()
64  ui_file = os.path.join(rospkg.RosPack().get_path('packml_gui'), 'resource', 'packml.ui')
65  loadUi(ui_file, self._widget)
66  self._widget.setObjectName('Packml')
67 
68  if context.serial_number() > 1:
69  self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))
70 
71  context.add_widget(self._widget)
72 
73  # Custom code begins here
74  self._widget.reset_button.clicked[bool].connect(self.__handle_reset_clicked)
75  self._widget.start_button.clicked[bool].connect(self.__handle_start_clicked)
76  self._widget.stop_button.clicked[bool].connect(self.__handle_stop_clicked)
77  self._widget.clear_button.clicked[bool].connect(self.__handle_clear_clicked)
78  self._widget.hold_button.clicked[bool].connect(self.__handle_hold_clicked)
79  self._widget.unhold_button.clicked[bool].connect(self.__handle_unhold_clicked)
80  self._widget.suspend_button.clicked[bool].connect(self.__handle_suspend_clicked)
81  self._widget.unsuspend_button.clicked[bool].connect(self.__handle_unsuspend_clicked)
82  self._widget.abort_button.clicked[bool].connect(self.__handle_abort_clicked)
83 
84  self._service_thread = Thread(target=self.wait_for_services, args=())
85  self._service_thread.start()
86 
87  self._status_sub = rospy.Subscriber('packml/status', Status, self.status_callback)
88 
89  self.threadpool = QThreadPool()
90 
92  self._widget.clear_button.setEnabled(False)
93  self._widget.reset_button.setEnabled(False)
94  self._widget.start_button.setEnabled(False)
95  self._widget.stop_button.setEnabled(False)
96  self._widget.hold_button.setEnabled(False)
97  self._widget.suspend_button.setEnabled(False)
98  self._widget.unhold_button.setEnabled(False)
99  self._widget.unsuspend_button.setEnabled(False)
100  self._widget.abort_button.setEnabled(False)
101 
102  def set_message_text(self, text):
103  self._widget.message_box.setText("Message: " + text)
104 
105  def status_callback(self, msg):
106  self.update_button_states(msg.state.val)
107  self.update_status_fields(msg)
108 
109 
110  def update_button_states(self, state):
111  self.disable_all_buttons()
112  if state == State.ABORTED:
113  self._widget.clear_button.setEnabled(True)
114  elif state == State.STOPPED:
115  self._widget.reset_button.setEnabled(True)
116  elif state == State.IDLE:
117  self._widget.start_button.setEnabled(True)
118  elif state == State.EXECUTE:
119  self._widget.hold_button.setEnabled(True)
120  self._widget.suspend_button.setEnabled(True)
121  elif state == State.HELD:
122  self._widget.unhold_button.setEnabled(True)
123  elif state == State.SUSPENDED:
124  self._widget.unsuspend_button.setEnabled(True)
125  elif state == State.COMPLETE:
126  self._widget.reset_button.setEnabled(True)
127 
128  if state != State.STOPPED and \
129  state != State.STOPPING and \
130  state != State.ABORTED and \
131  state != State.ABORTING and \
132  state != State.CLEARING:
133  self._widget.stop_button.setEnabled(True)
134 
135 
136  if state != State.ABORTED and \
137  state != State.ABORTING:
138  self._widget.abort_button.setEnabled(True)
139 
140  def update_status_fields(self, msg):
141  self.update_state_field(msg.state.val)
142  self._widget.substate.setText(str(msg.sub_state))
143  self.update_mode_field(msg.mode.val)
144  self._widget.error_code.setText(str(msg.error))
145  self._widget.suberror_code.setText(str(msg.sub_error))
146 
147 
148  def update_state_field(self, state):
149  if state == State.UNDEFINED:
150  self._widget.state_name.setText("UNDEFINED")
151  elif state == State.OFF:
152  self._widget.state_name.setText("OFF")
153  elif state == State.STOPPED:
154  self._widget.state_name.setText("STOPPED")
155  elif state == State.STARTING:
156  self._widget.state_name.setText("STARTING")
157  elif state == State.IDLE:
158  self._widget.state_name.setText("IDLE")
159  elif state == State.SUSPENDED:
160  self._widget.state_name.setText("SUSPENDED")
161  elif state == State.EXECUTE:
162  self._widget.state_name.setText("EXECUTE")
163  elif state == State.STOPPING:
164  self._widget.state_name.setText("STOPPING")
165  elif state == State.ABORTING:
166  self._widget.state_name.setText("ABORTING")
167  elif state == State.ABORTED:
168  self._widget.state_name.setText("ABORTED")
169  elif state == State.HOLDING:
170  self._widget.state_name.setText("HOLDING")
171  elif state == State.HELD:
172  self._widget.state_name.setText("HELD")
173  elif state == State.RESETTING:
174  self._widget.state_name.setText("RESETTING")
175  elif state == State.SUSPENDING:
176  self._widget.state_name.setText("SUSPENDING")
177  elif state == State.UNSUSPENDING:
178  self._widget.state_name.setText("UNSUSPENDING")
179  elif state == State.CLEARING:
180  self._widget.state_name.setText("CLEARING")
181  elif state == State.UNHOLDING:
182  self._widget.state_name.setText("UNHOLDING")
183  elif state == State.COMPLETING:
184  self._widget.state_name.setText("COMPLETING")
185  elif state == State.COMPLETE:
186  self._widget.state_name.setText("COMPLETE")
187  else:
188  self._widget.state_name.setTest("UNKNOWN")
189 
190 
191 
192  def update_mode_field(self, mode):
193  if mode == Mode.UNDEFINED:
194  self._widget.mode_name.setText("UNDEFINED")
195  elif mode == Mode.AUTOMATIC:
196  self._widget.mode_name.setText("AUTOMATIC")
197  elif mode == Mode.SEMI_AUTOMATIC:
198  self._widget.mode_name.setText("SEMI-AUTOMATIC")
199  elif mode == Mode.MANUAL:
200  self._widget.mode_name.setText("MANUAL")
201  elif mode == Mode.IDLE:
202  self._widget.mode_name.setText("IDLE")
203  elif mode == Mode.SETUP:
204  self._widget.mode_name.setText("SETUP")
205  else:
206  self._widget.mode_name.setText("UNKNOWN")
207 
208 
209 
210  def wait_for_services(self):
211  self._widget.setEnabled(False)
212  transition_service_name = 'packml/transition'
213  rospy.wait_for_service(transition_service_name, 30)
214  self.transition_service = rospy.ServiceProxy(transition_service_name, Transition)
215  self._widget.setEnabled(True)
216 
217  def shutdown_plugin(self):
218  self._status_sub.unregister()
219  pass
220 
221  def save_settings(self, plugin_settings, instance_settings):
222  # TODO save intrinsic configuration, usually using:
223  # instance_settings.set_value(k, v)
224  pass
225 
226  def restore_settings(self, plugin_settings, instance_settings):
227  # TODO restore intrinsic configuration, usually using:
228  # v = instance_settings.value(k)
229  pass
230 
231 
232  def handle_click_thread(self, request):
233  try:
234  service_thread = WorkerThread(self.transition_service, request, self.set_message_text)
235  if self.threadpool.activeThreadCount() >= 1:
236  return
237  else:
238  self.threadpool.start(service_thread)
239  except rospy.ServiceException as exc:
240  rospy.logerror("Service did not process request: " + str(exc))
241 
242  def __handle_start_clicked(self, checked):
243  rospy.loginfo("Start button press")
244  self.handle_click_thread(TransitionRequest.START)
245 
246  def __handle_stop_clicked(self, checked):
247  rospy.loginfo("Stop button press")
248  self.handle_click_thread(TransitionRequest.STOP)
249 
250  def __handle_reset_clicked(self, checked):
251  rospy.loginfo("Reset button press")
252  self.handle_click_thread(TransitionRequest.RESET)
253 
254  def __handle_clear_clicked(self, checked):
255  rospy.loginfo("Clear button press")
256  self.handle_click_thread(TransitionRequest.CLEAR)
257 
258  def __handle_hold_clicked(self, checked):
259  rospy.loginfo("Hold button press")
260  self.handle_click_thread(TransitionRequest.HOLD)
261 
262  def __handle_unhold_clicked(self, checked):
263  rospy.loginfo("Unhold button press")
264  self.handle_click_thread(TransitionRequest.UNHOLD)
265 
266  def __handle_suspend_clicked(self, checked):
267  rospy.loginfo("Suspend button press")
268  self.handle_click_thread(TransitionRequest.SUSPEND)
269 
270  def __handle_unsuspend_clicked(self, checked):
271  rospy.loginfo("Unsuspend button press")
272  self.handle_click_thread(TransitionRequest.UNSUSPEND)
273 
274  def __handle_abort_clicked(self, checked):
275  rospy.loginfo("Abort button press")
276  self.handle_click_thread(TransitionRequest.ABORT)
277 
278  @staticmethod
279  def add_arguments(parser):
280  rospy.loginfo("Add arguments callback")
281  group = parser.add_argument_group('Options for PackML plugin')
282  group.add_argument('--arg1', action='store_true', help='arg1 help')
283 
284  #def trigger_configuration(self):
285  # Comment in to signal that the plugin has a way to configure it
286  # Usually used to open a configuration dialog
def update_button_states(self, state)
Definition: packml.py:110
def set_message_text(self, text)
Definition: packml.py:102
def disable_all_buttons(self)
Definition: packml.py:91
def __handle_suspend_clicked(self, checked)
Definition: packml.py:266
def wait_for_services(self)
Definition: packml.py:210
def __handle_reset_clicked(self, checked)
Definition: packml.py:250
def add_arguments(parser)
Definition: packml.py:279
def update_status_fields(self, msg)
Definition: packml.py:140
def handle_click_thread(self, request)
Definition: packml.py:232
def __handle_unhold_clicked(self, checked)
Definition: packml.py:262
def __handle_stop_clicked(self, checked)
Definition: packml.py:246
def save_settings(self, plugin_settings, instance_settings)
Definition: packml.py:221
def restore_settings(self, plugin_settings, instance_settings)
Definition: packml.py:226
def __handle_start_clicked(self, checked)
Definition: packml.py:242
def __handle_clear_clicked(self, checked)
Definition: packml.py:254
def update_mode_field(self, mode)
Definition: packml.py:192
def shutdown_plugin(self)
Definition: packml.py:217
def __handle_abort_clicked(self, checked)
Definition: packml.py:274
def __handle_unsuspend_clicked(self, checked)
Definition: packml.py:270
def update_state_field(self, state)
Definition: packml.py:148
def __handle_hold_clicked(self, checked)
Definition: packml.py:258
def __init__(self, context)
Definition: packml.py:47
def __init__(self, service, req, set_msg)
Definition: packml.py:35
def status_callback(self, msg)
Definition: packml.py:105


packml_gui
Author(s): Shaun Edwards
autogenerated on Fri Jul 12 2019 03:30:53