def test_Param(): from roslaunch.core import Param p = Param('key/', 'value') assert p.key == 'key' assert p.value == 'value' assert p == Param('key', 'value') assert p != Param('key2', 'value') assert p != 1 assert 'key' in str(p) assert 'key' in repr(p) assert 'value' in str(p) assert 'value' in repr(p)
def add_param(self, ros_config, param_name, param_value, verbose=True): """ Add L{Param} instances to launch config. Dictionary values are unrolled into individual parameters. @param ros_config: launch configuration @type ros_config: L{ROSLaunchConfig} @param param_name: name of parameter namespace to load values into. If param_name is '/', param_value must be a dictionary @type param_name: str @param param_value: value to assign to param_name. If param_value is a dictionary, it's values will be unrolled into individual parameters. @type param_value: str @raise ValueError: if parameters cannot be processed into valid Params """ # shouldn't ever happen if not param_name: raise ValueError("no parameter name specified") if param_name == '/' and type(param_value) != dict: raise ValueError( "Cannot load non-dictionary types into global namespace '/'") if type(param_value) == dict: # unroll params for k, v in param_value.items(): self.add_param(ros_config, ns_join(param_name, k), v, verbose=verbose) else: ros_config.add_param(Param(param_name, param_value), verbose=verbose)
def _param_tag(self, tag, context, ros_config, force_local=False, verbose=True): """ @param force_local: if True, param must be added to context instead of ros_config @type force_local: bool """ try: self._check_attrs(tag, context, ros_config, XmlLoader.PARAM_ATTRS) # compute name and value ptype = (tag.getAttribute('type') or 'auto').lower().strip() vals = self.opt_attrs(tag, context, ('value', 'textfile', 'binfile', 'command')) if len([v for v in vals if v is not None]) != 1: raise XmlParseException( "<param> tag must have one and only one of value/textfile/binfile." ) # compute name. if name is a tilde name, it is placed in # the context. otherwise it is placed in the ros config. name = self.resolve_args(tag.attributes['name'].value.strip(), context) value = self.param_value(verbose, name, ptype, *vals) if is_private(name) or force_local: p = Param(name, value) context.add_param(p) else: p = Param(ns_join(context.ns, name), value) ros_config.add_param(Param(ns_join(context.ns, name), value), filename=context.filename, verbose=verbose) return p except KeyError, e: raise XmlParseException( "<param> tag is missing required attribute: %s. \n\nParam xml is %s" % (e, tag.toxml()))
def _node_tag(self, tag, context, ros_config, default_machine, is_test=False, verbose=True): """ Process XML <node> or <test> tag @param tag: DOM node @type tag: Node @param context: namespace context @type context: L{LoaderContext} @param params: ROS parameter list @type params: [L{Param}] @param clear_params: list of ROS parameter names to clear before setting parameters @type clear_params: [str] @param default_machine: default machine to assign to node @type default_machine: str @param is_test: if set, will load as L{Test} object instead of L{Node} object @type is_test: bool """ try: if is_test: self._check_attrs(tag, context, ros_config, XmlLoader.TEST_ATTRS) (name,) = self.opt_attrs(tag, context, ('name',)) test_name, time_limit, retry = self._test_attrs(tag, context) if not name: name = test_name else: self._check_attrs(tag, context, ros_config, XmlLoader.NODE_ATTRS) (name,) = self.reqd_attrs(tag, context, ('name',)) if not roslib.names.is_legal_name(name): ros_config.add_config_error("WARN: illegal <node> name '%s'.\nhttp://ros.org/wiki/Names\nThis will likely cause problems with other ROS tools.\nNode xml is %s"%(name, tag.toxml())) child_ns = self._ns_clear_params_attr('node', tag, context, ros_config, node_name=name) param_ns = child_ns.child(name) # required attributes pkg, node_type = self.reqd_attrs(tag, context, ('pkg', 'type')) # optional attributes machine, args, output, respawn, cwd, launch_prefix, required = \ self.opt_attrs(tag, context, ('machine', 'args', 'output', 'respawn', 'cwd', 'launch-prefix', 'required')) if tag.hasAttribute('machine') and not len(machine.strip()): raise XmlParseException("<node> 'machine' must be non-empty: [%s]"%machine) if not machine and default_machine: machine = default_machine.name # validate respawn, required required, respawn = [_bool_attr(*rr) for rr in ((required, False, 'required'),\ (respawn, False, 'respawn'))] # each node gets its own copy of <remap> arguments, which # it inherits from its parent remap_context = context.child('') # nodes can have individual env args set in addition to # the ROS-specific ones. for t in [c for c in tag.childNodes if c.nodeType == DomNode.ELEMENT_NODE]: tag_name = t.tagName.lower() if tag_name == 'remap': r = self._remap_tag(t, context, ros_config) if r is not None: remap_context.add_remap(r) elif tag_name == 'param': self._param_tag(t, param_ns, ros_config, force_local=True, verbose=verbose) elif tag_name == 'rosparam': self._rosparam_tag(t, param_ns, ros_config, verbose=verbose) elif tag_name == 'env': self._env_tag(t, context, ros_config) else: ros_config.add_config_error("WARN: unrecognized '%s' tag in <node> tag. Node xml is %s"%(t.tagName, tag.toxml())) # #1036 evaluate all ~params in context # TODO: can we get rid of force_local (above), remove this for loop, and just rely on param_tag logic instead? for p in itertools.chain(context.params, param_ns.params): pkey = p.key if is_private(pkey): # strip leading ~, which is optional/inferred pkey = pkey[1:] pkey = param_ns.ns + pkey ros_config.add_param(Param(pkey, p.value), verbose=verbose) if not is_test: return Node(pkg, node_type, name=name, namespace=child_ns.ns, machine_name=machine, args=args, respawn=respawn, remap_args=remap_context.remap_args(), env_args=context.env_args, output=output, cwd=cwd, launch_prefix=launch_prefix, required=required, filename=context.filename) else: return Test(test_name, pkg, node_type, name=name, namespace=child_ns.ns, machine_name=machine, args=args, remap_args=remap_context.remap_args(), env_args=context.env_args, time_limit=time_limit, cwd=cwd, launch_prefix=launch_prefix, retry=retry, filename=context.filename) except KeyError, e: raise XmlParseException( "<%s> tag is missing required attribute: %s. Node xml is %s"%(tag.tagName, e, tag.toxml()))