@@ -68,13 +68,13 @@ def __init__(
68
68
69
69
def _load_node (
70
70
self ,
71
- composable_node_description : ComposableNode ,
71
+ request : composition_interfaces . srv . LoadNode . Request ,
72
72
context : LaunchContext
73
73
) -> None :
74
74
"""
75
75
Load node synchronously.
76
76
77
- :param composable_node_description: description of composable node to be loaded
77
+ :param request: service request to load a node
78
78
:param context: current launch context
79
79
"""
80
80
while not self .__rclpy_load_node_client .wait_for_service (timeout_sec = 1.0 ):
@@ -85,45 +85,14 @@ def _load_node(
85
85
)
86
86
)
87
87
return
88
- request = composition_interfaces .srv .LoadNode .Request ()
89
- request .package_name = perform_substitutions (
90
- context , composable_node_description .package
91
- )
92
- request .plugin_name = perform_substitutions (
93
- context , composable_node_description .node_plugin
94
- )
95
- if composable_node_description .node_name is not None :
96
- request .node_name = perform_substitutions (
97
- context , composable_node_description .node_name
98
- )
99
- if composable_node_description .node_namespace is not None :
100
- request .node_namespace = perform_substitutions (
101
- context , composable_node_description .node_namespace
88
+
89
+ self .__logger .debug (
90
+ "Calling the '{}' service with request '{}'" .format (
91
+ self .__rclpy_load_node_client .srv_name , request
102
92
)
103
- # request.log_level = perform_substitutions(context, node_description.log_level)
104
- if composable_node_description .remappings is not None :
105
- for from_ , to in composable_node_description .remappings :
106
- request .remap_rules .append ('{}:={}' .format (
107
- perform_substitutions (context , list (from_ )),
108
- perform_substitutions (context , list (to )),
109
- ))
110
- if composable_node_description .parameters is not None :
111
- request .parameters = [
112
- param .to_parameter_msg () for param in to_parameters_list (
113
- context , evaluate_parameters (
114
- context , composable_node_description .parameters
115
- )
116
- )
117
- ]
118
- if composable_node_description .extra_arguments is not None :
119
- request .extra_arguments = [
120
- param .to_parameter_msg () for param in to_parameters_list (
121
- context , evaluate_parameters (
122
- context , composable_node_description .extra_arguments
123
- )
124
- )
125
- ]
93
+ )
126
94
response = self .__rclpy_load_node_client .call (request )
95
+ self .__logger .debug ("Received response '{}'" .format (response ))
127
96
if not response .success :
128
97
self .__logger .error (
129
98
"Failed to load node '{}' of type '{}' in container '{}': {}" .format (
@@ -137,7 +106,7 @@ def _load_node(
137
106
138
107
def _load_in_sequence (
139
108
self ,
140
- composable_node_descriptions : List [ComposableNode ],
109
+ load_node_requests : List [composition_interfaces . srv . LoadNode . Request ],
141
110
context : LaunchContext
142
111
) -> None :
143
112
"""
@@ -146,13 +115,13 @@ def _load_in_sequence(
146
115
:param composable_node_descriptions: descriptions of composable nodes to be loaded
147
116
:param context: current launch context
148
117
"""
149
- next_composable_node_description = composable_node_descriptions [0 ]
150
- composable_node_descriptions = composable_node_descriptions [1 :]
151
- self ._load_node (next_composable_node_description , context )
152
- if len (composable_node_descriptions ) > 0 :
118
+ next_load_node_request = load_node_requests [0 ]
119
+ load_node_requests = load_node_requests [1 :]
120
+ self ._load_node (next_load_node_request , context )
121
+ if len (load_node_requests ) > 0 :
153
122
context .add_completion_future (
154
123
context .asyncio_loop .run_in_executor (
155
- None , self ._load_in_sequence , composable_node_descriptions , context
124
+ None , self ._load_in_sequence , load_node_requests , context
156
125
)
157
126
)
158
127
@@ -168,8 +137,61 @@ def execute(
168
137
)
169
138
)
170
139
140
+ # Generate load requests before execute() exits to avoid race with context changing
141
+ # due to scope change (e.g. if loading nodes from within a GroupAction).
142
+ load_node_requests = [
143
+ get_composable_node_load_request (node_description , context )
144
+ for node_description in self .__composable_node_descriptions
145
+ ]
146
+
171
147
context .add_completion_future (
172
148
context .asyncio_loop .run_in_executor (
173
- None , self ._load_in_sequence , self . __composable_node_descriptions , context
149
+ None , self ._load_in_sequence , load_node_requests , context
174
150
)
175
151
)
152
+
153
+
154
+ def get_composable_node_load_request (
155
+ composable_node_description : ComposableNode ,
156
+ context : LaunchContext
157
+ ):
158
+ """Get the request that will be send to the composable node container."""
159
+ request = composition_interfaces .srv .LoadNode .Request ()
160
+ request .package_name = perform_substitutions (
161
+ context , composable_node_description .package
162
+ )
163
+ request .plugin_name = perform_substitutions (
164
+ context , composable_node_description .node_plugin
165
+ )
166
+ if composable_node_description .node_name is not None :
167
+ request .node_name = perform_substitutions (
168
+ context , composable_node_description .node_name
169
+ )
170
+ if composable_node_description .node_namespace is not None :
171
+ request .node_namespace = perform_substitutions (
172
+ context , composable_node_description .node_namespace
173
+ )
174
+ if composable_node_description .remappings is not None :
175
+ for from_ , to in composable_node_description .remappings :
176
+ request .remap_rules .append ('{}:={}' .format (
177
+ perform_substitutions (context , list (from_ )),
178
+ perform_substitutions (context , list (to )),
179
+ ))
180
+ if composable_node_description .parameters is not None :
181
+ request .parameters = [
182
+ param .to_parameter_msg () for param in to_parameters_list (
183
+ context , evaluate_parameters (
184
+ context , composable_node_description .parameters
185
+ )
186
+ )
187
+ ]
188
+ if composable_node_description .extra_arguments is not None :
189
+ request .extra_arguments = [
190
+ param .to_parameter_msg () for param in to_parameters_list (
191
+ context , evaluate_parameters (
192
+ context , composable_node_description .extra_arguments
193
+ )
194
+ )
195
+ ]
196
+
197
+ return request
0 commit comments