diff --git a/tools/roslaunch/src/roslaunch/loader.py b/tools/roslaunch/src/roslaunch/loader.py index 8b884b6bd9..3d2a0d4bda 100644 --- a/tools/roslaunch/src/roslaunch/loader.py +++ b/tools/roslaunch/src/roslaunch/loader.py @@ -364,7 +364,7 @@ def add_param(self, ros_config, param_name, param_value, verbose=True): else: ros_config.add_param(Param(param_name, param_value), verbose=verbose) - def load_rosparam(self, context, ros_config, cmd, param, file_, text, verbose=True): + def load_rosparam(self, context, ros_config, cmd, param, file_, execute, text, verbose=True): """ Load rosparam setting @@ -376,7 +376,9 @@ def load_rosparam(self, context, ros_config, cmd, param, file_, text, verbose=Tr @type cmd: str @param file_: filename for rosparam to use or None @type file_: str - @param text: text for rosparam to load. Ignored if file_ is set. + @param execute: command to execute for rosparam load or None + @type execute: str + @param text: text for rosparam to load. Ignored if file_ or execute are set. @type text: str @raise ValueError: if parameters cannot be processed into valid rosparam setting """ @@ -387,7 +389,12 @@ def load_rosparam(self, context, ros_config, cmd, param, file_, text, verbose=Tr raise ValueError("file does not exist [%s]"%file_) if cmd == 'delete': raise ValueError("'file' attribute is invalid with 'delete' command.") - + elif execute is not None: + if cmd == 'delete': + raise ValueError("'execute' attribute is invalid with 'delete' command.") + if cmd == 'dump': + raise ValueError("'execute' attribute is invalid with 'dump' command.") + full_param = ns_join(context.ns, param) if param else context.ns if cmd == 'dump': @@ -399,6 +406,28 @@ def load_rosparam(self, context, ros_config, cmd, param, file_, text, verbose=Tr if file_: with open(file_, 'r') as f: text = f.read() + elif execute: + try: + if type(execute) == unicode: + execute = execute.encode('utf-8') #attempt to force to string for shlex/subprocess + except NameError: + pass + if verbose: + print("... executing command param [%s]" % execute) + import subprocess, shlex #shlex rocks + try: + p = subprocess.Popen(shlex.split(execute), stdout=subprocess.PIPE) + text = p.communicate()[0] + if not isinstance(text, str): + text = text.decode('utf-8') + if p.returncode != 0: + raise ValueError("Cannot load command parameter [%s]: command [%s] returned with code [%s]"%(name, execute, p.returncode)) + except OSError as e: + if e.errno == 2: + raise ValueError("Cannot load command parameter [%s]: no such command [%s]"%(name, execute)) + raise + if text is None: + raise ValueError("parameter: unable to get output of command [%s]"%execute) # parse YAML text # - lazy import: we have to import rosparam in oder to to configure the YAML constructors diff --git a/tools/roslaunch/src/roslaunch/xmlloader.py b/tools/roslaunch/src/roslaunch/xmlloader.py index 9136f09ee1..cfb2a085c2 100644 --- a/tools/roslaunch/src/roslaunch/xmlloader.py +++ b/tools/roslaunch/src/roslaunch/xmlloader.py @@ -222,12 +222,12 @@ def _check_attrs(self, tag, context, ros_config, attrs): # 'ns' attribute is now deprecated and is an alias for # 'param'. 'param' is required if the value is a non-dictionary # type - ROSPARAM_OPT_ATTRS = ('command', 'ns', 'file', 'param', 'subst_value') + ROSPARAM_OPT_ATTRS = ('command', 'ns', 'file', 'execute', 'param', 'subst_value') @ifunless def _rosparam_tag(self, tag, context, ros_config, verbose=True): try: self._check_attrs(tag, context, ros_config, XmlLoader.ROSPARAM_OPT_ATTRS) - cmd, ns, file, param, subst_value = self.opt_attrs(tag, context, (XmlLoader.ROSPARAM_OPT_ATTRS)) + cmd, ns, file, execute, param, subst_value = self.opt_attrs(tag, context, (XmlLoader.ROSPARAM_OPT_ATTRS)) subst_value = _bool_attr(subst_value, False, 'subst_value') # ns atribute is a bit out-moded and is only left in for backwards compatibility param = ns_join(ns or '', param or '') @@ -237,7 +237,7 @@ def _rosparam_tag(self, tag, context, ros_config, verbose=True): value = _get_text(tag) if subst_value: value = self.resolve_args(value, context) - self.load_rosparam(context, ros_config, cmd, param, file, value, verbose=verbose) + self.load_rosparam(context, ros_config, cmd, param, file, execute, value, verbose=verbose) except ValueError as e: raise loader.LoadException("error loading tag: \n\t"+str(e)+"\nXML is %s"%tag.toxml())