Skip to content

Commit

Permalink
Support "scope" for machine tag default semantics
Browse files Browse the repository at this point in the history
Proposed fix for ros#1884
  • Loading branch information
luisrayas3 committed Sep 24, 2020
1 parent 425fad3 commit 0861b4d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
13 changes: 10 additions & 3 deletions tools/roslaunch/src/roslaunch/loader.py
Expand Up @@ -155,7 +155,8 @@ class LoaderContext(object):
"""

def __init__(self, ns, filename, parent=None, params=None, env_args=None, \
resolve_dict=None, include_resolve_dict=None, arg_names=None):
resolve_dict=None, include_resolve_dict=None, arg_names=None, \
default_machine=None):
"""
@param ns: namespace
@type ns: str
Expand All @@ -169,6 +170,9 @@ def __init__(self, ns, filename, parent=None, params=None, env_args=None, \
@type include_resolve_dict: dict
@param arg_names: name of args that have been declared in this context
@type arg_names: [str]
@param default_machine: name of the machine to use as default only
within this context.
@type default_machine: str
"""
self.parent = parent
self.ns = make_global_ns(ns or '/')
Expand All @@ -184,6 +188,8 @@ def __init__(self, ns, filename, parent=None, params=None, env_args=None, \
self.include_resolve_dict = include_resolve_dict or None
# when this context was created via include, was pass_all_args set?
self.pass_all_args = False
# default machine to use for nodes defined later in this context
self.default_machine = default_machine

def add_param(self, p):
"""
Expand Down Expand Up @@ -323,8 +329,9 @@ def child(self, ns):
return LoaderContext(child_ns, self.filename, parent=self,
params=self.params, env_args=self.env_args[:],
resolve_dict=deepcopy(self.resolve_dict),
arg_names=self.arg_names[:], include_resolve_dict=self.include_resolve_dict)

arg_names=self.arg_names[:], include_resolve_dict=self.include_resolve_dict,
default_machine=self.default_machine)

#TODO: in-progress refactorization. I'm slowly separating out
#non-XML-specific logic from xmlloader and moving into Loader. Soon
#this will mean that it will be easier to write coverage tests for
Expand Down
18 changes: 14 additions & 4 deletions tools/roslaunch/src/roslaunch/xmlloader.py
Expand Up @@ -153,9 +153,12 @@ def _float_attr(v, default, label):


# maps machine 'default' attribute to Machine default property
_is_default = {'true': True, 'false': False, 'never': False }
_is_default = {'true': True, 'scope': False, 'false': False, 'never': False }
# maps machine 'default' attribute to Machine assignable property
_assignable = {'true': True, 'false': True, 'never': False }
_assignable = {'true': True, 'scope': True, 'false': True, 'never': False }
# maps machine 'default' attribute to whether this sets the default_machine in
# the loader context
_is_context_default = {'true': True, 'scope': True, 'false': False, 'never': False }

# NOTE: code is currently in a semi-refactored state. I'm slowly
# migrating common routines into the Loader class in the hopes it will
Expand Down Expand Up @@ -388,8 +391,11 @@ def _node_tag(self, tag, context, ros_config, default_machine, is_test=False, ve
required = self.opt_attrs(tag, context, ('machine', 'args',
'output', 'respawn', 'respawn_delay', 'cwd',
'launch-prefix', 'required'))
if not machine and default_machine:
machine = default_machine.name
if not machine:
if context.default_machine:
machine = context.default_machine.name
elif default_machine:
machine = default_machine.name
# validate respawn, required
required, respawn = [_bool_attr(*rr) for rr in ((required, False, 'required'),\
(respawn, False, 'respawn'))]
Expand Down Expand Up @@ -484,8 +490,12 @@ def _machine_tag(self, tag, context, ros_config, verbose=True):
try:
assignable = _assignable[default]
is_default = _is_default[default]
is_context_default = _is_context_default[default]
except KeyError as e:
raise XmlParseException("Invalid value for 'attribute': %s"%default)
# if the default tag is 'scope' set the default_machine for the current context
if is_context_default:
context.parent.default_machine = m

# load env args
for t in [c for c in tag.childNodes if c.nodeType == DomNode.ELEMENT_NODE]:
Expand Down
9 changes: 8 additions & 1 deletion tools/roslaunch/test/unit/test_xmlloader.py
Expand Up @@ -636,7 +636,14 @@ def test_machines(self):
elif m.name == 'machine9':
self.assertEquals(m.env_loader, '/opt/ros/fuerte/env.sh')


def test_scoped_machine(self):
test_file = os.path.join(self.xml_dir, 'test-machine-scoped.xml')
mock = self._load(test_file)
expect_nodes = {'n1': 'machine2', 'n2': 'machine1'}
self.assertEquals(len(mock.nodes), len(expect_nodes))
for node in mock.nodes:
self.assertEquals(node.machine_name, expect_nodes[node.name])

def test_node_subst(self):
test_file =os.path.join(self.xml_dir, 'test-node-substitution.xml')
keys = ['PACKAGE', 'TYPE', 'OUTPUT', 'RESPAWN']
Expand Down
11 changes: 11 additions & 0 deletions tools/roslaunch/test/xml/test-machine-scoped.xml
@@ -0,0 +1,11 @@
<launch>
<machine name="machine1" address="address1" default="true" />

<group>
<machine name="machine2" address="address2" default="scope" />
<node name="n1" pkg="pack1" type="foo_node" /> <!-- machine2 -->
</group>

<node name="n2" pkg="pack2" type="bar_node" /> <!-- machine1 -->

</launch>

0 comments on commit 0861b4d

Please sign in to comment.