diff --git a/tools/roslaunch/src/roslaunch/loader.py b/tools/roslaunch/src/roslaunch/loader.py index 21d11a8a38..025aeba624 100644 --- a/tools/roslaunch/src/roslaunch/loader.py +++ b/tools/roslaunch/src/roslaunch/loader.py @@ -365,7 +365,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_, text, verbose=True, subst_function=None): """ Load rosparam setting @@ -401,6 +401,8 @@ def load_rosparam(self, context, ros_config, cmd, param, file_, text, verbose=Tr with open(file_, 'r') as f: text = f.read() + if subst_function is not None: + text = subst_function(text) # parse YAML text # - lazy import: we have to import rosparam in oder to to configure the YAML constructors global rosparam diff --git a/tools/roslaunch/src/roslaunch/xmlloader.py b/tools/roslaunch/src/roslaunch/xmlloader.py index 5feb0c4155..78a9775542 100644 --- a/tools/roslaunch/src/roslaunch/xmlloader.py +++ b/tools/roslaunch/src/roslaunch/xmlloader.py @@ -235,9 +235,10 @@ def _rosparam_tag(self, tag, context, ros_config, verbose=True): # load is the default command cmd = cmd or 'load' value = _get_text(tag) + subst_function = None if subst_value: - value = self.resolve_args(value, context) - self.load_rosparam(context, ros_config, cmd, param, file, value, verbose=verbose) + subst_function = lambda x: self.resolve_args(x, context) + self.load_rosparam(context, ros_config, cmd, param, file, value, verbose=verbose, subst_function=subst_function) except ValueError as e: raise loader.LoadException("error loading tag: \n\t"+str(e)+"\nXML is %s"%tag.toxml()) diff --git a/tools/roslaunch/test/params_subst.yaml b/tools/roslaunch/test/params_subst.yaml new file mode 100644 index 0000000000..a34c327dd2 --- /dev/null +++ b/tools/roslaunch/test/params_subst.yaml @@ -0,0 +1 @@ +string1: $(anon foo) diff --git a/tools/roslaunch/test/unit/test_xmlloader.py b/tools/roslaunch/test/unit/test_xmlloader.py index 3986815608..ac30189d00 100644 --- a/tools/roslaunch/test/unit/test_xmlloader.py +++ b/tools/roslaunch/test/unit/test_xmlloader.py @@ -242,6 +242,10 @@ def test_rosparam_valid(self): self.assertEquals('bar', p.value) p = [p for p in mock.params if p.key == '/node_rosparam/robots/childparam'][0] self.assertEquals('a child namespace parameter', p.value) + + # test substitution in yaml files + p = [p for p in mock.params if p.key == '/rosparam_subst/string1'][0] + self.assertTrue('$(anon foo)' not in p.value) exes = [e for e in mock.executables if e.command == 'rosparam'] self.assertEquals(len(exes), 2, "expected 2 rosparam exes, got %s"%len(exes)) @@ -274,6 +278,10 @@ def test_rosparam_valid(self): p = [p for p in mock.params if p.key == '/inline_dict2/key4'][0] self.assertEquals('value4', p.value) + # test substitution in inline yaml + p = [p for p in mock.params if p.key == '/inline_subst'][0] + self.assertTrue('$(anon foo)' not in p.value) + # verify that later tags override # - key2 is overriden self.assertEquals(1, len([p for p in mock.params if p.key == '/override/key1'])) diff --git a/tools/roslaunch/test/xml/test-rosparam-valid.xml b/tools/roslaunch/test/xml/test-rosparam-valid.xml index c5d521db3d..2d00435ed7 100644 --- a/tools/roslaunch/test/xml/test-rosparam-valid.xml +++ b/tools/roslaunch/test/xml/test-rosparam-valid.xml @@ -12,6 +12,10 @@ + + + + value1 [1, 2, 3, 4] {key1: value1, key2: value2} @@ -19,6 +23,8 @@ key3: value3 key4: value4 + + $(anon foo) {key1: value1, key2: value2} {key1: override1}