app_manager.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2011, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 #
33 # Revision $Id: app_manager.py 14948 2011-09-07 19:25:54Z pratkanis $
34 
35 # author: leibs
36 import sys
37 
38 if sys.version_info[0] == 3:
39  import _thread as thread # python3 renamed from thread to _thread
40 else:
41  import thread
42 
43 import time
44 import yaml
45 
46 import rosgraph.names
47 import rospy
48 
49 import roslaunch.config
50 import roslaunch.core
51 import roslaunch.parent
52 import roslaunch.pmon
53 import roslaunch.xmlloader
54 
55 import roslaunch.loader
56 from std_srvs.srv import Empty, EmptyResponse
57 
58 from .app import AppDefinition, find_resource, load_AppDefinition_by_name
59 from .exceptions import LaunchException, AppException, InvalidAppException, NotFoundException
60 from .master_sync import MasterSync
61 from .msg import App, AppList, StatusCodes, AppStatus, AppInstallationState, ExchangeApp
62 from .srv import StartApp, StopApp, ListApps, ListAppsResponse, StartAppResponse, StopAppResponse, InstallApp, UninstallApp, GetInstallationState, UninstallAppResponse, InstallAppResponse, GetInstallationStateResponse, GetAppDetails, GetAppDetailsResponse
63 
64 
66  roslaunch_files, port, roslaunch_strs=None, loader=None, verbose=False,
67  assign_machines=True, ignore_unset_args=False
68 ):
69  config = roslaunch.config.ROSLaunchConfig()
70  if port:
71  config.master.uri = rosgraph.network.create_local_xmlrpc_uri(port)
72 
73  loader = loader or roslaunch.xmlloader.XmlLoader()
74  loader.ignore_unset_args = ignore_unset_args
75 
76  # load the roscore file first. we currently have
77  # last-declaration wins rules. roscore is just a
78  # roslaunch file with special load semantics
79  roslaunch.config.load_roscore(loader, config, verbose=verbose)
80 
81  # load the roslaunch_files into the config
82  for f in roslaunch_files:
83  if isinstance(f, tuple):
84  f, args = f
85  else:
86  args = None
87  try:
88  rospy.loginfo('loading config file %s' % f)
89  loader.load(f, config, argv=args, verbose=verbose)
90  except roslaunch.xmlloader.XmlParseException as e:
91  raise roslaunch.core.RLException(e)
92  except roslaunch.loader.LoadException as e:
93  raise roslaunch.core.RLException(e)
94  # we need this for the hardware test systems, which builds up
95  # roslaunch launch files in memory
96  if roslaunch_strs:
97  for launch_str in roslaunch_strs:
98  try:
99  rospy.loginfo('loading config file from string')
100  loader.load_string(launch_str, config)
101  except roslaunch.xmlloader.XmlParseException as e:
102  raise roslaunch.core.RLException(
103  'Launch string: %s\nException: %s' % (launch_str, e))
104  except roslaunch.loader.LoadException as e:
105  raise roslaunch.core.RLException(
106  'Launch string: %s\nException: %s' % (launch_str, e))
107  # choose machines for the nodes
108  if assign_machines:
109  config.assign_machines()
110  return config
111 
112 
113 # overwrite load_config_default function for kinetic
114 # see: https://github.com/ros/ros_comm/pull/1115
115 roslaunch.config.load_config_default = _load_config_default
116 
117 
118 class AppManager(object):
119 
120  def __init__(
121  self, robot_name, interface_master, app_list,
122  exchange, plugins=None, enable_app_replacement=True,
123  ):
124  self._robot_name = robot_name
125  self._interface_master = interface_master
126  self._app_list = app_list
128  self._exchange = exchange
129  self._plugins = plugins
130  self._enable_app_replacement = enable_app_replacement
131 
132  rospy.loginfo("Starting app manager for %s"%self._robot_name)
133 
134  self._app_interface = self.scoped_name('application')
135 
136  # note: we publish into the application namespace
137  self._status_pub = rospy.Publisher(
138  self.scoped_name('application/app_status'), AppStatus,
139  latch=True, queue_size=1)
140  self._list_apps_pub = rospy.Publisher(
141  self.scoped_name('app_list'), AppList,
142  latch=True, queue_size=1)
143 
144  self._list_apps_srv = rospy.Service(self.scoped_name('list_apps'), ListApps, self.handle_list_apps)
145  self._start_app_srv = rospy.Service(self.scoped_name('start_app'), StartApp, self.handle_start_app)
146  self._stop_app_srv = rospy.Service(self.scoped_name('stop_app'), StopApp, self.handle_stop_app)
147  self._reload_app_list_srv = rospy.Service(self.scoped_name('reload_app_list'), Empty, self.handle_reload_app_list)
148  if (self._exchange):
149  self._exchange_list_apps_pub = rospy.Publisher(self.scoped_name('exchange_app_list'), AppInstallationState, latch=True)
150  self._list_exchange_apps_srv = rospy.Service(self.scoped_name('list_exchange_apps'), GetInstallationState, self.handle_list_exchange_apps)
151  self._get_app_details_srv = rospy.Service(self.scoped_name('get_app_details'), GetAppDetails, self.handle_get_app_details)
152  self._install_app_srv = rospy.Service(self.scoped_name('install_app'), InstallApp, self.handle_install_app)
153  self._uninstall_app_srv = rospy.Service(self.scoped_name('uninstall_app'), UninstallApp, self.handle_uninstall_app)
154 
155  pub_names = [x.resolved_name for x in [self._list_apps_pub, self._status_pub, self._exchange_list_apps_pub]]
156  service_names = [x.resolved_name for x in [self._list_apps_srv, self._start_app_srv, self._stop_app_srv, self._get_app_details_srv, self._list_exchange_apps_srv, self._install_app_srv, self._uninstall_app_srv]]
157  else:
158  pub_names = [x.resolved_name for x in [self._list_apps_pub, self._status_pub]]
159  service_names = [x.resolved_name for x in [self._list_apps_srv, self._start_app_srv, self._stop_app_srv]]
160 
161  self._api_sync = MasterSync(self._interface_master,
162  local_service_names=service_names,
163  local_pub_names=pub_names)
164 
165  self._launch = None
166  self._plugin_launch = None
167  self._interface_sync = None
168  self._exit_code = None
169  self._stopped = None
170  self._current_plugins = None
171  self._plugin_context = None
172  self._start_time = None
173 
174  roslaunch.pmon._init_signal_handlers()
175 
176  if (self._exchange):
177  self._exchange.update_local()
178 
179  self._app_list.update()
181  self.publish_list_apps()
182 
183  def shutdown(self):
184  if self._api_sync:
185  self._api_sync.stop()
186  if self._interface_sync:
187  self._interface_sync.stop()
188  self._stopped = True
189  self.__stop_current()
190 
191  def _get_current_app(self):
192  return self._current_app
193 
194  def _set_current_app(self, app, app_definition):
195  self._current_app = app
196  self._current_app_definition = app_definition
197 
198  if self._list_apps_pub:
199  if app is not None:
200  self._list_apps_pub.publish([app], self._app_list.get_app_list())
201  else:
202  self._list_apps_pub.publish([], self._app_list.get_app_list())
203 
204  def scoped_name(self, name):
205  return rosgraph.names.canonicalize_name('/%s/%s'%(self._robot_name, rospy.remap_name(name)))
206 
207  def handle_get_app_details(self, req):
208  return GetAppDetailsResponse(app=self._exchange.get_app_details(req.name))
209 
211  if (self._exchange == None):
212  return None
213  if (req.remote_update):
214  rospy.loginfo("UPDATE")
215  if (not self._exchange.update()):
216  return None
217  i_apps = self._exchange.get_installed_apps()
218  a_apps = self._exchange.get_available_apps()
219  return GetInstallationStateResponse(installed_apps=i_apps, available_apps=a_apps)
220 
221  def publish_list_apps(self):
222  if self._current_app:
223  self._list_apps_pub.publish([self._current_app], self._app_list.get_app_list())
224  else:
225  self._list_apps_pub.publish([], self._app_list.get_app_list())
226 
228  if (self._exchange == None):
229  return
230  i_apps = self._exchange.get_installed_apps()
231  a_apps = self._exchange.get_available_apps()
232  self._exchange_list_apps_pub.publish(i_apps, a_apps)
233 
234  def handle_install_app(self, req):
235  appname = req.name
236  if (self._exchange.install_app(appname)):
237  self._app_list.update()
238  self.publish_list_apps()
240  return InstallAppResponse(installed=True, message="app [%s] installed"%(appname))
241  else:
242  return InstallAppResponse(installed=False, message="app [%s] could not be installed"%(appname))
243 
244  def handle_uninstall_app(self, req):
245  appname = req.name
246  if (self._exchange.uninstall_app(appname)):
247  self._app_list.update()
248  self.publish_list_apps()
250  return UninstallAppResponse(uninstalled=True, message="app [%s] uninstalled"%(appname))
251  else:
252  return UninstallAppResponse(uninstalled=False, message="app [%s] could not be uninstalled"%(appname))
253 
254  def handle_list_apps(self, req):
255  rospy.loginfo("Listing apps")
256  current = self._current_app
257  if current:
258  running_apps = [current]
259  else:
260  running_apps = []
261  self._app_list.update()
262  rospy.loginfo("done listing apps")
263  return ListAppsResponse(running_apps=running_apps, available_apps=self._app_list.get_app_list())
264 
265  def handle_start_app(self, req):
266  rospy.loginfo("start_app: %s"%(req.name))
267  if self._current_app:
268  if self._current_app_definition.name == req.name:
269  return StartAppResponse(started=True, message="app [%s] already started"%(req.name), namespace=self._app_interface)
270  elif not self._enable_app_replacement:
271  return StartAppResponse(
272  started=False,
273  message="app [%s] is denied because app [%s] is already running."
274  % (req.name, self._current_app_definition.name),
275  namespace=self._app_interface,
276  error_code=StatusCodes.MULTIAPP_NOT_SUPPORTED)
277  else:
278  self.stop_app(self._current_app_definition.name)
279 
280  # TODO: the app list has already loaded the App data. We should use that instead for consistency
281 
282  appname = req.name
283  rospy.loginfo("Loading app: %s"%(appname))
284  try:
285  app = load_AppDefinition_by_name(appname)
286  except ValueError as e:
287  return StartAppResponse(started=False, message=str(e), error_code=StatusCodes.BAD_REQUEST)
288  except InvalidAppException as e:
289  return StartAppResponse(started=False, message=str(e), error_code=StatusCodes.INTERNAL_ERROR)
290  except NotFoundException as e:
291  return StartAppResponse(started=False, message=str(e), error_code=StatusCodes.NOT_FOUND)
292 
293  try:
294  self._set_current_app(App(name=appname), app)
295 
296  rospy.loginfo("Launching: %s"%(app.launch))
297  self._status_pub.publish(AppStatus(AppStatus.INFO, 'launching %s'%(app.display_name)))
298 
299  plugin_launch_files = []
300  if app.plugins:
301  self._current_plugins = []
302  if 'start_plugin_order' in app.plugin_order:
303  plugin_names = [p['name'] for p in app.plugins]
304  plugin_order = app.plugin_order['start_plugin_order']
305  if len(set(plugin_names) - set(plugin_order)) > 0:
306  rospy.logwarn(
307  "Some plugins are defined in plugins but not written in start_plugin_order: {}"
308  .format(set(plugin_names) - set(plugin_order)))
309  app_plugins = []
310  for plugin_name in plugin_order:
311  if plugin_name not in plugin_names:
312  rospy.logerr("app plugin '{}' not found in app file.".format(plugin_name))
313  continue
314  app_plugins.append(
315  app.plugins[plugin_names.index(plugin_name)])
316  else:
317  app_plugins = app.plugins
318  for app_plugin in app_plugins:
319  app_plugin_type = app_plugin['type']
320  try:
321  plugin = next(
322  p for p in self._plugins if p['name'] == app_plugin_type)
323  self._current_plugins.append((app_plugin, plugin))
324  if 'launch' in plugin and plugin['launch']:
325  plugin_launch_file = find_resource(plugin['launch'])
326  launch_args = {}
327  if 'launch_args' in app_plugin:
328  launch_args.update(app_plugin['launch_args'])
329  if 'launch_arg_yaml' in app_plugin:
330  with open(app_plugin['launch_arg_yaml']) as yaml_f:
331  yaml_launch_args = yaml.load(yaml_f)
332  for k, v in yaml_launch_args.items():
333  if k in launch_args:
334  rospy.logwarn("'{}' is set both in launch_args and launch_arg_yaml".format(k))
335  rospy.logwarn("'{}' is overwritten: {} -> {}".format(k, launch_args[k], v))
336  launch_args[k] = v
337  plugin_launch_args = []
338  for k, v in launch_args.items():
339  if isinstance(v, list):
340  v = " ".join(map(str, v))
341  plugin_launch_args.append("{}:={}".format(k, v))
342  rospy.loginfo(
343  "Launching plugin: {} {}".format(
344  plugin_launch_file, plugin_launch_args))
345  plugin_launch_files.append(
346  (plugin_launch_file, plugin_launch_args))
347  except StopIteration:
348  rospy.logerr(
349  'There is no available app_manager plugin: {}'
350  .format(app_plugin_type))
351 
352  #TODO:XXX This is a roslaunch-caller-like abomination. Should leverage a true roslaunch API when it exists.
353  self._launch = roslaunch.parent.ROSLaunchParent(
354  rospy.get_param("/run_id"), [app.launch],
355  is_core=False, process_listeners=())
356  if len(plugin_launch_files) > 0:
357  self._plugin_launch = roslaunch.parent.ROSLaunchParent(
358  rospy.get_param("/run_id"), plugin_launch_files,
359  is_core=False, process_listeners=())
360 
361  self._launch._load_config()
362  if self._plugin_launch:
363  self._plugin_launch._load_config()
364 
365  #TODO: convert to method
366  for N in self._launch.config.nodes:
367  for t in app.interface.published_topics.keys():
368  N.remap_args.append((t, self._app_interface + '/' + t))
369  for t in app.interface.subscribed_topics.keys():
370  N.remap_args.append((t, self._app_interface + '/' + t))
371 
372  # run plugin modules first
373  if self._current_plugins:
374  self._plugin_context = {}
375  for app_plugin, plugin in self._current_plugins:
376  if 'module' in plugin and plugin['module']:
377  plugin_args = {}
378  start_plugin_args = {}
379  if 'plugin_args' in app_plugin:
380  plugin_args.update(app_plugin['plugin_args'])
381  if 'plugin_arg_yaml' in app_plugin:
382  with open(app_plugin['plugin_arg_yaml']) as yaml_f:
383  yaml_plugin_args = yaml.load(yaml_f)
384  for k, v in yaml_plugin_args.items():
385  if k in plugin_args:
386  rospy.logwarn("'{}' is set both in plugin_args and plugin_arg_yaml".format(k))
387  rospy.logwarn("'{}' is overwritten: {} -> {}".format(k, plugin_args[k], v))
388  plugin_args[k] = v
389  if 'start_plugin_args' in app_plugin:
390  start_plugin_args.update(app_plugin['start_plugin_args'])
391  if 'start_plugin_arg_yaml' in app_plugin:
392  with open(app_plugin['start_plugin_arg_yaml']) as yaml_f:
393  yaml_plugin_args = yaml.load(yaml_f)
394  for k, v in yaml_plugin_args.items():
395  if k in start_plugin_args:
396  rospy.logwarn("'{}' is set both in start_plugin_args and start_plugin_arg_yaml".format(k))
397  rospy.logwarn("'{}' is overwritten: {} -> {}".format(k, start_plugin_args[k], v))
398  start_plugin_args[k] = v
399  plugin_args.update(start_plugin_args)
400  mod = __import__(plugin['module'].split('.')[0])
401  for sub_mod in plugin['module'].split('.')[1:]:
402  mod = getattr(mod, sub_mod)
403  start_plugin_attr = getattr(
404  mod, 'app_manager_start_plugin')
405  self._plugin_context = start_plugin_attr(
406  app, self._plugin_context, plugin_args)
407  # then, start plugin launches
408  if self._plugin_launch:
409  self._plugin_launch.start()
410 
411  # finally launch main launch
412  self._launch.start()
413  if app.timeout is not None:
414  self._start_time = rospy.Time.now()
415 
416  fp = [self._app_interface + '/' + x for x in app.interface.subscribed_topics.keys()]
417  lp = [self._app_interface + '/' + x for x in app.interface.published_topics.keys()]
418 
419  self._interface_sync = MasterSync(self._interface_master, foreign_pub_names=fp, local_pub_names=lp)
420 
421  thread.start_new_thread(self.app_monitor,())
422 
423  return StartAppResponse(started=True, message="app [%s] started"%(appname), namespace=self._app_interface)
424 
425  except Exception as e:
426  try:
427  # attempt to kill any launched resources
428  self._stop_current()
429  except:
430  pass
431  self._status_pub.publish(AppStatus(AppStatus.INFO, 'app start failed'))
432  rospy.logerr("app start failed")
433  return StartAppResponse(started=False, message="internal error [%s]"%(str(e)), error_code=StatusCodes.INTERNAL_ERROR)
434 
435  def _stop_current(self):
436  try:
437  self.__stop_current()
438  finally:
439  self._launch = None
440  self._plugin_launch = None
441  self._exit_code = None
442  self._stopped = None
443  self._current_plugins = None
444  self._plugin_context = None
445  self._start_time = None
446  try:
447  self._interface_sync.stop()
448  finally:
449  self._interface_sync = None
450 
451  def __stop_current(self):
452  if self._api_sync:
453  self._api_sync.stop()
454  if self._launch:
455  self._launch.shutdown()
456  if (self._exit_code is None
457  and len(self._launch.pm.dead_list) > 0):
458  self._exit_code = self._launch.pm.dead_list[0].exit_code
459  if self._exit_code > 0:
460  rospy.logerr(
461  "App stopped with exit code: {}".format(self._exit_code))
462  if self._plugin_launch:
463  self._plugin_launch.shutdown()
464  if self._current_plugins:
465  self._plugin_context['exit_code'] = self._exit_code
466  self._plugin_context['stopped'] = self._stopped
467  if 'stop_plugin_order' in self._current_app_definition.plugin_order:
468  plugin_names = [p['name'] for p in self._current_app_definition.plugins]
469  plugin_order = self._current_app_definition.plugin_order['stop_plugin_order']
470  if len(set(plugin_names) - set(plugin_order)) > 0:
471  rospy.logwarn(
472  "Some plugins are defined in plugins but not written in stop_plugin_order: {}"
473  .format(set(plugin_names) - set(plugin_order)))
474  current_plugins = []
475  for plugin_name in plugin_order:
476  if plugin_name not in plugin_names:
477  rospy.logerr("app plugin '{}' not found in app file.".format(plugin_name))
478  continue
479  current_plugin_names = [p['name'] for p, _ in self._current_plugins]
480  if plugin_name not in current_plugin_names:
481  rospy.logwarn("app plugin '{}' is not running, so skip stopping".format(plugin_name))
482  continue
483  current_plugins.append(
484  self._current_plugins[current_plugin_names.index(plugin_name)])
485  else:
486  current_plugins = self._current_plugins
487  for app_plugin, plugin in current_plugins:
488  if 'module' in plugin and plugin['module']:
489  plugin_args = {}
490  stop_plugin_args = {}
491  if 'plugin_args' in app_plugin:
492  plugin_args.update(app_plugin['plugin_args'])
493  if 'plugin_arg_yaml' in app_plugin:
494  with open(app_plugin['plugin_arg_yaml']) as yaml_f:
495  yaml_plugin_args = yaml.load(yaml_f)
496  for k, v in yaml_plugin_args.items():
497  if k in plugin_args:
498  rospy.logwarn("'{}' is set both in plugin_args and plugin_arg_yaml".format(k))
499  rospy.logwarn("'{}' is overwritten: {} -> {}".format(k, plugin_args[k], v))
500  plugin_args[k] = v
501  if 'stop_plugin_args' in app_plugin:
502  stop_plugin_args.update(app_plugin['stop_plugin_args'])
503  if 'stop_plugin_arg_yaml' in app_plugin:
504  with open(app_plugin['stop_plugin_arg_yaml']) as yaml_f:
505  yaml_plugin_args = yaml.load(yaml_f)
506  for k, v in yaml_plugin_args.items():
507  if k in stop_plugin_args:
508  rospy.logwarn("'{}' is set both in stop_plugin_args and stop_plugin_arg_yaml".format(k))
509  rospy.logwarn("'{}' is overwritten: {} -> {}".format(k, stop_plugin_args[k], v))
510  stop_plugin_args[k] = v
511  plugin_args.update(stop_plugin_args)
512  mod = __import__(plugin['module'].split('.')[0])
513  for sub_mod in plugin['module'].split('.')[1:]:
514  mod = getattr(mod, sub_mod)
515  stop_plugin_attr = getattr(mod, 'app_manager_stop_plugin')
516  self._plugin_context = stop_plugin_attr(
518  self._plugin_context, plugin_args)
519 
520  def handle_stop_app(self, req):
521  rospy.loginfo("handle stop app: %s"%(req.name))
522  self._stopped = True
523  return self.stop_app(req.name)
524 
525  def handle_reload_app_list(self, req=None):
526  try:
527  self._app_list.update()
528  self.publish_list_apps()
530  rospy.loginfo("app list is reloaded")
531  except Exception as e:
532  rospy.logerr("Failed to reload app list: %s" % e)
533  return EmptyResponse()
534 
535  def app_monitor(self):
536  while self._launch:
537  time.sleep(0.1)
538  launch = self._launch
539  timeout = self._current_app_definition.timeout
540  appname = self._current_app_definition.name
541  now = rospy.Time.now()
542  if launch:
543  pm = launch.pm
544  if pm:
545  procs = pm.procs[:]
546  if len(procs) > 0:
547  if any([p.required for p in procs]):
548  exit_codes = [
549  p.exit_code for p in procs if p.required]
550  self._exit_code = max(exit_codes)
551  if pm.done:
552  time.sleep(1.0)
553  self.stop_app(appname)
554  break
555  if (timeout is not None and
556  self._start_time is not None and
557  (now - self._start_time).to_sec() > timeout):
558  self.stop_app(appname)
559  rospy.logerr(
560  'app {} is stopped because of timeout: {}s'.format(
561  appname, timeout))
562  break
563 
564 
565 
566  def stop_app(self, appname):
567  resp = StopAppResponse(stopped=False)
568  try:
569  app = self._current_app_definition
570 
571  # request to stop all apps.
572  if app is not None and appname == '*':
573  appname = app.name
574 
575  if app is None or app.name != appname:
576  rospy.loginfo("handle stop app: app [%s] is not running [x]"%(appname))
577  resp.error_code = StatusCodes.NOT_RUNNING
578  resp.message = "app %s is not running"%(appname)
579  else:
580  try:
581  if self._launch:
582  rospy.loginfo("handle stop app: stopping app [%s]"%(appname))
583  self._status_pub.publish(AppStatus(AppStatus.INFO, 'stopping %s'%(app.display_name)))
584  self._stop_current()
585  rospy.loginfo("handle stop app: app [%s] stopped"%(appname))
586  resp.stopped = True
587  resp.message = "%s stopped"%(appname)
588  else:
589  rospy.loginfo("handle stop app: app [%s] is not running"%(appname))
590  resp.message = "app [%s] is not running"%(appname)
591  resp.error_code = StatusCodes.NOT_RUNNING
592  finally:
593  self._launch = None
594  self._set_current_app(None, None)
595 
596  except Exception as e:
597  rospy.logerr("handle stop app: internal error %s"%(e))
598  resp.error_code = StatusCodes.INTERNAL_ERROR
599  resp.message = "internal error: %s"%(str(e))
600 
601  return resp
def find_resource(resource)
Definition: app.py:117
def handle_list_exchange_apps(self, req)
Definition: app_manager.py:210
def _set_current_app(self, app, app_definition)
Definition: app_manager.py:194
def _load_config_default(roslaunch_files, port, roslaunch_strs=None, loader=None, verbose=False, assign_machines=True, ignore_unset_args=False)
Definition: app_manager.py:68
def handle_reload_app_list(self, req=None)
Definition: app_manager.py:525
def __init__(self, robot_name, interface_master, app_list, exchange, plugins=None, enable_app_replacement=True)
Definition: app_manager.py:123
def load_AppDefinition_by_name(appname)
Definition: app.py:302


app_manager
Author(s): Jeremy Leibs, Ken Conley, Yuki Furuta
autogenerated on Fri Mar 5 2021 03:07:47