Skip to content

Commit 2e498f1

Browse files
author
Roger Strain
committed
Improve node name handling, unit test fixes, more
Distro A; OPSEC #4584 Signed-off-by: Roger Strain <[email protected]>
1 parent c648bbc commit 2e498f1

File tree

8 files changed

+51
-22
lines changed

8 files changed

+51
-22
lines changed

launch_ros/launch_ros/actions/node.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,6 @@ def __init__(
125125
nodes=[self.__node_desc], **ros_exec_kwargs)
126126
super().__init__(process_description=self.__ros_exec, **kwargs)
127127

128-
def prepare(self, context: LaunchContext):
129-
self.__node_desc.prepare(context, self.__ros_exec, self)
130-
super().prepare(context)
131-
132128
def is_node_name_fully_specified(self):
133129
return self.__node_desc.is_node_name_fully_specified()
134130

@@ -244,6 +240,11 @@ def node_name(self):
244240
"""Getter for node_name."""
245241
return self.__node_desc.node_name
246242

243+
@property
244+
def ros_exec(self):
245+
"""Getter for ros_exec."""
246+
return self.__ros_exec
247+
247248
@property
248249
def expanded_node_namespace(self):
249250
"""Getter for expanded_node_namespace."""

launch_ros/launch_ros/descriptions/node.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,14 @@ def __init__(
7474
self, *,
7575
node_name: Optional[SomeSubstitutionsType] = None,
7676
node_namespace: Optional[SomeSubstitutionsType] = None,
77+
original_node_name: Optional[SomeSubstitutionsType] = None,
7778
parameters: Optional[SomeParameters] = None,
7879
remappings: Optional[SomeRemapRules] = None,
7980
traits: Optional[Iterable[NodeTrait]] = None,
8081
**kwargs
8182
) -> None:
8283
"""
83-
Construct an Node description.
84-
85-
Many arguments are passed eventually to
86-
:class:`launch.actions.ExecuteProcess`, so see the documentation of
87-
that class for additional details.
84+
Construct a Node description.
8885
8986
If the node name is not given (or is None) then no name is passed to
9087
the node on creation and instead the default name specified within the
@@ -117,6 +114,9 @@ def __init__(
117114
118115
:param: node_name the name of the node
119116
:param: node_namespace the ROS namespace for this Node
117+
:param: original_node_name the name of the node before remapping; if not specified,
118+
remappings/parameters (including node name/namespace changes) may be applied
119+
to all nodes which share a command line executable with this one
120120
:param: parameters list of names of yaml files with parameter rules,
121121
or dictionaries of parameters.
122122
:param: remappings ordered list of 'to' and 'from' string pairs to be
@@ -131,12 +131,14 @@ def __init__(
131131

132132
self.__node_name = node_name
133133
self.__node_namespace = node_namespace
134+
self.__original_node_name = original_node_name
134135
self.__parameters = [] if parameters is None else normalized_params
135136
self.__remappings = [] if remappings is None else list(normalize_remap_rules(remappings))
136137
self.__traits = traits
137138

138139
self.__expanded_node_name = self.UNSPECIFIED_NODE_NAME
139140
self.__expanded_node_namespace = self.UNSPECIFIED_NODE_NAMESPACE
141+
self.__expanded_original_node_name = self.UNSPECIFIED_NODE_NAME
140142
self.__expanded_parameter_arguments = None # type: Optional[List[Tuple[Text, bool]]]
141143
self.__final_node_name = None # type: Optional[Text]
142144
self.__expanded_remappings = None # type: Optional[List[Tuple[Text, Text]]]
@@ -157,6 +159,11 @@ def node_namespace(self):
157159
"""Getter for node_namespace."""
158160
return self.__node_namespace
159161

162+
@property
163+
def original_node_name(self):
164+
"""Getter for original_node_name."""
165+
return self.__original_node_name
166+
160167
@property
161168
def parameters(self):
162169
"""Getter for parameters."""
@@ -245,6 +252,10 @@ def _perform_substitutions(self, context: LaunchContext, cmd: List) -> None:
245252
cmd_ext = ['-r', LocalSubstitution("ros_specific_arguments['ns']")]
246253
cmd.extend([normalize_to_list_of_substitutions(x) for x in cmd_ext])
247254
validate_namespace(self.__expanded_node_namespace)
255+
if self.__original_node_name is not None:
256+
self.__expanded_original_node_name = perform_substitutions(
257+
context, normalize_to_list_of_substitutions(self.__original_node_name))
258+
self.__expanded_node_name.lstrip('/')
248259
except Exception:
249260
self.__logger.error(
250261
"Error while expanding or validating node name or namespace for '{}':"
@@ -310,10 +321,17 @@ def _perform_substitutions(self, context: LaunchContext, cmd: List) -> None:
310321
# Prepare the ros_specific_arguments list and add it to the context so that the
311322
# LocalSubstitution placeholders added to the the cmd can be expanded using the contents.
312323
ros_specific_arguments: Dict[str, Union[str, List[str]]] = {}
324+
original_name_prefix = ""
325+
if self.__expanded_original_node_name is not self.UNSPECIFIED_NODE_NAME:
326+
original_name_prefix = '{}:'.format(self.__expanded_original_node_name)
313327
if self.__node_name is not None:
314-
ros_specific_arguments['name'] = '__node:={}'.format(self.__expanded_node_name)
328+
ros_specific_arguments['name'] = '{}__node:={}'.format(
329+
original_name_prefix, self.__expanded_node_name
330+
)
315331
if self.__expanded_node_namespace != '':
316-
ros_specific_arguments['ns'] = '__ns:={}'.format(self.__expanded_node_namespace)
332+
ros_specific_arguments['ns'] = '{}__ns:={}'.format(
333+
original_name_prefix, self.__expanded_node_namespace
334+
)
317335
context.extend_locals({'ros_specific_arguments': ros_specific_arguments})
318336

319337
if self.is_node_name_fully_specified():
@@ -324,4 +342,4 @@ def _perform_substitutions(self, context: LaunchContext, cmd: List) -> None:
324342
execute_process_logger.warning(
325343
'there are now at least {} nodes with the name {} created within this '
326344
'launch context'.format(node_name_count, self.node_name)
327-
)
345+
)

launch_ros/launch_ros/descriptions/node_trait.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,4 @@ def __init__(self) -> None:
4747

4848
def prepare(self, node: 'Node', context: LaunchContext, action: Action):
4949
"""Perform any actions necessary to prepare the node for execution."""
50+
pass

test_launch_ros/test/test_launch_ros/actions/test_lifecycle_node.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ def test_node_name():
5151
namespace='my_ns',
5252
)
5353
lc = LaunchContext()
54-
node_object._Node__node_desc._perform_substitutions(lc, [])
54+
for node in node_object.ros_exec.nodes:
55+
node._perform_substitutions(lc, [])
5556
assert node_object.is_node_name_fully_specified() is True

test_launch_ros/test/test_launch_ros/actions/test_node.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def test_launch_node_with_remappings(self):
8787
self._assert_launch_no_errors([node_action])
8888

8989
# Check the expanded parameters.
90-
expanded_remappings = node_action._Node__node_desc.expanded_remappings
90+
for node in node_action.ros_exec.nodes:
91+
expanded_remappings = node.expanded_remappings
9192
assert len(expanded_remappings) == 2
9293
for i in range(2):
9394
assert expanded_remappings[i] == ('chatter', 'new_chatter')
@@ -139,7 +140,8 @@ def test_launch_node_with_parameter_files(self):
139140
self._assert_launch_no_errors([node_action])
140141

141142
# Check the expanded parameters.
142-
expanded_parameter_arguments = node_action._Node__node_desc.expanded_parameter_arguments
143+
for node in node_action.ros_exec.nodes:
144+
expanded_parameter_arguments = node.expanded_parameter_arguments
143145
assert len(expanded_parameter_arguments) == 3
144146
for i in range(3):
145147
assert expanded_parameter_arguments[i] == (str(parameters_file_path), True)
@@ -176,7 +178,8 @@ def test_launch_node_with_parameter_descriptions(self):
176178
)
177179
self._assert_launch_no_errors([node_action])
178180

179-
expanded_parameter_arguments = node_action._Node__node_desc.expanded_parameter_arguments
181+
for node in node_action.ros_exec.nodes:
182+
expanded_parameter_arguments = node.expanded_parameter_arguments
180183
assert len(expanded_parameter_arguments) == 5
181184
parameters = []
182185
for item, is_file in expanded_parameter_arguments:
@@ -213,7 +216,8 @@ def test_launch_node_with_parameter_dict(self):
213216
self._assert_launch_no_errors([node_action])
214217

215218
# Check the expanded parameters (will be written to a file).
216-
expanded_parameter_arguments = node_action._Node__node_desc.expanded_parameter_arguments
219+
for node in node_action.ros_exec.nodes:
220+
expanded_parameter_arguments = node.expanded_parameter_arguments
217221
assert len(expanded_parameter_arguments) == 1
218222
file_path, is_file = expanded_parameter_arguments[0]
219223
assert is_file
@@ -348,5 +352,6 @@ def get_test_node_name_parameters():
348352
)
349353
def test_node_name(node_object, expected_result):
350354
lc = LaunchContext()
351-
node_object._Node__node_desc._perform_substitutions(lc, [])
355+
for node in node_object.ros_exec.nodes:
356+
node._perform_substitutions(lc, [])
352357
assert node_object.is_node_name_fully_specified() is expected_result

test_launch_ros/test/test_launch_ros/actions/test_push_ros_namespace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ def test_push_ros_namespace(config):
127127
namespace=config.node_ns,
128128
name=config.node_name
129129
)
130-
node._Node__node_desc._perform_substitutions(lc, [])
130+
for node in node_object.ros_exec.nodes:
131+
node._perform_substitutions(lc, [])
131132
expected_ns = (
132133
config.expected_ns if config.expected_ns is not None else
133134
NodeDescription.UNSPECIFIED_NODE_NAMESPACE

test_launch_ros/test/test_launch_ros/actions/test_set_parameter.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,9 @@ def test_set_param_with_node():
121121
)
122122
set_param = SetParameter(name='my_param', value='my_value')
123123
set_param.execute(lc)
124-
node._Node__node_desc._perform_substitutions(lc, [])
125-
expanded_parameter_arguments = node._Node__node_desc.expanded_parameter_arguments
124+
for node_instance in node.ros_exec.nodes:
125+
node_instance._perform_substitutions(lc, [])
126+
expanded_parameter_arguments = node_instance.expanded_parameter_arguments
126127
assert len(expanded_parameter_arguments) == 2
127128
param_file_path, is_file = expanded_parameter_arguments[0]
128129
assert is_file

test_launch_ros/test/test_launch_ros/actions/test_set_remap.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ def test_set_remap_with_node():
9393
)
9494
set_remap = SetRemap('from1', 'to1')
9595
set_remap.execute(lc)
96-
node._Node__node_desc._perform_substitutions(lc, [])
96+
for node_instance in node.ros_exec.nodes:
97+
node_instance._perform_substitutions(lc, [])
9798
assert len(node.expanded_remapping_rules) == 2
9899
assert node.expanded_remapping_rules == [('from1', 'to1'), ('from2', 'to2')]
99100

0 commit comments

Comments
 (0)