Skip to content

Commit 67ed746

Browse files
Roger Strainmlanting
authored andcommitted
Improve node name handling, unit test fixes, more
Distro A; OPSEC #4584 Signed-off-by: Roger Strain <[email protected]>
1 parent ab41ef4 commit 67ed746

File tree

8 files changed

+50
-21
lines changed

8 files changed

+50
-21
lines changed

launch_ros/launch_ros/actions/node.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,6 @@ def __init__(
183183
self.__extensions = get_extensions(self.__logger)
184184
super().__init__(process_description=self.__ros_exec, **kwargs)
185185

186-
def prepare(self, context: LaunchContext):
187-
self.__node_desc.prepare(context, self.__ros_exec, self)
188-
super().prepare(context)
189-
190186
def is_node_name_fully_specified(self):
191187
return self.__node_desc.is_node_name_fully_specified()
192188

@@ -316,6 +312,11 @@ def node_name(self):
316312
"""Getter for node_name."""
317313
return self.__node_desc.node_name
318314

315+
@property
316+
def ros_exec(self):
317+
"""Getter for ros_exec."""
318+
return self.__ros_exec
319+
319320
@property
320321
def expanded_node_namespace(self):
321322
"""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
@@ -88,7 +88,8 @@ def test_launch_node_with_remappings(self):
8888
self._assert_launch_no_errors([node_action])
8989

9090
# Check the expanded parameters.
91-
expanded_remappings = node_action._Node__node_desc.expanded_remappings
91+
for node in node_action.ros_exec.nodes:
92+
expanded_remappings = node.expanded_remappings
9293
assert len(expanded_remappings) == 2
9394
for i in range(2):
9495
assert expanded_remappings[i] == ('chatter', 'new_chatter')
@@ -147,7 +148,8 @@ def test_launch_node_with_parameter_files(self):
147148
self._assert_launch_no_errors([node_action])
148149

149150
# Check the expanded parameters.
150-
expanded_parameter_arguments = node_action._Node__node_desc.expanded_parameter_arguments
151+
for node in node_action.ros_exec.nodes:
152+
expanded_parameter_arguments = node.expanded_parameter_arguments
151153
assert len(expanded_parameter_arguments) == 3
152154
for i in range(3):
153155
assert expanded_parameter_arguments[i] == (str(parameters_file_path), True)
@@ -184,7 +186,8 @@ def test_launch_node_with_parameter_descriptions(self):
184186
)
185187
self._assert_launch_no_errors([node_action])
186188

187-
expanded_parameter_arguments = node_action._Node__node_desc.expanded_parameter_arguments
189+
for node in node_action.ros_exec.nodes:
190+
expanded_parameter_arguments = node.expanded_parameter_arguments
188191
assert len(expanded_parameter_arguments) == 5
189192
parameters = []
190193
for item, is_file in expanded_parameter_arguments:
@@ -221,7 +224,8 @@ def test_launch_node_with_parameter_dict(self):
221224
self._assert_launch_no_errors([node_action])
222225

223226
# Check the expanded parameters (will be written to a file).
224-
expanded_parameter_arguments = node_action._Node__node_desc.expanded_parameter_arguments
227+
for node in node_action.ros_exec.nodes:
228+
expanded_parameter_arguments = node.expanded_parameter_arguments
225229
assert len(expanded_parameter_arguments) == 1
226230
file_path, is_file = expanded_parameter_arguments[0]
227231
assert is_file
@@ -356,5 +360,6 @@ def get_test_node_name_parameters():
356360
)
357361
def test_node_name(node_object, expected_result):
358362
lc = LaunchContext()
359-
node_object._Node__node_desc._perform_substitutions(lc, [])
363+
for node in node_object.ros_exec.nodes:
364+
node._perform_substitutions(lc, [])
360365
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ def test_set_param_with_node():
119119
)
120120
set_param = SetParameter(name='my_param', value='my_value')
121121
set_param.execute(lc)
122-
node._perform_substitutions(lc)
122+
for node_instance in node.ros_exec.nodes:
123+
node_instance._perform_substitutions(lc, [])
123124
actual_command = [perform_substitutions(lc, item) for item in
124125
node.cmd if type(item[0]) == TextSubstitution]
125126
assert actual_command.count('--params-file') == 1

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)