@@ -135,7 +135,7 @@ def is_controller_loaded(node, controller_manager, controller_name):
135135def main (args = None ):
136136 rclpy .init (args = args , signal_handler_options = SignalHandlerOptions .NO )
137137 parser = argparse .ArgumentParser ()
138- parser .add_argument ("controller_name " , help = "Name of the controller " )
138+ parser .add_argument ("controller_names " , help = "List of controllers" , nargs = "+ " )
139139 parser .add_argument (
140140 "-c" ,
141141 "--controller-manager" ,
@@ -184,10 +184,17 @@ def main(args=None):
184184 default = 10 ,
185185 type = int ,
186186 )
187+ parser .add_argument (
188+ "--activate-as-group" ,
189+ help = "Activates all the parsed controllers list together instead of one by one."
190+ " Useful for activating all chainable controllers altogether" ,
191+ action = "store_true" ,
192+ required = False ,
193+ )
187194
188195 command_line_args = rclpy .utilities .remove_ros_args (args = sys .argv )[1 :]
189196 args = parser .parse_args (command_line_args )
190- controller_name = args .controller_name
197+ controller_names = args .controller_names
191198 controller_manager_name = args .controller_manager
192199 controller_namespace = args .namespace
193200 param_file = args .param_file
@@ -197,11 +204,7 @@ def main(args=None):
197204 if param_file and not os .path .isfile (param_file ):
198205 raise FileNotFoundError (errno .ENOENT , os .strerror (errno .ENOENT ), param_file )
199206
200- prefixed_controller_name = controller_name
201- if controller_namespace :
202- prefixed_controller_name = controller_namespace + "/" + controller_name
203-
204- node = Node ("spawner_" + controller_name )
207+ node = Node ("spawner_" + controller_names [0 ])
205208
206209 if not controller_manager_name .startswith ("/" ):
207210 spawner_namespace = node .get_namespace ()
@@ -219,115 +222,142 @@ def main(args=None):
219222 )
220223 return 1
221224
222- if is_controller_loaded (node , controller_manager_name , prefixed_controller_name ):
223- node .get_logger ().warn (
224- bcolors .WARNING
225- + "Controller already loaded, skipping load_controller"
226- + bcolors .ENDC
227- )
228- else :
229- if controller_type :
230- parameter = Parameter ()
231- parameter .name = prefixed_controller_name + ".type"
232- parameter .value = get_parameter_value (string_value = controller_type )
225+ for controller_name in controller_names :
226+ prefixed_controller_name = controller_name
227+ if controller_namespace :
228+ prefixed_controller_name = controller_namespace + "/" + controller_name
233229
234- response = call_set_parameters (
235- node = node , node_name = controller_manager_name , parameters = [parameter ]
230+ if is_controller_loaded (node , controller_manager_name , prefixed_controller_name ):
231+ node .get_logger ().warn (
232+ bcolors .WARNING
233+ + "Controller already loaded, skipping load_controller"
234+ + bcolors .ENDC
236235 )
237- assert len (response .results ) == 1
238- result = response .results [0 ]
239- if result .successful :
240- node .get_logger ().info (
241- bcolors .OKCYAN
242- + 'Set controller type to "'
243- + controller_type
244- + '" for '
245- + bcolors .BOLD
246- + prefixed_controller_name
247- + bcolors .ENDC
236+ else :
237+ if controller_type :
238+ parameter = Parameter ()
239+ parameter .name = prefixed_controller_name + ".type"
240+ parameter .value = get_parameter_value (string_value = controller_type )
241+
242+ response = call_set_parameters (
243+ node = node , node_name = controller_manager_name , parameters = [parameter ]
248244 )
249- else :
245+ assert len (response .results ) == 1
246+ result = response .results [0 ]
247+ if result .successful :
248+ node .get_logger ().info (
249+ bcolors .OKCYAN
250+ + 'Set controller type to "'
251+ + controller_type
252+ + '" for '
253+ + bcolors .BOLD
254+ + prefixed_controller_name
255+ + bcolors .ENDC
256+ )
257+ else :
258+ node .get_logger ().fatal (
259+ bcolors .FAIL
260+ + 'Could not set controller type to "'
261+ + controller_type
262+ + '" for '
263+ + bcolors .BOLD
264+ + prefixed_controller_name
265+ + bcolors .ENDC
266+ )
267+ return 1
268+
269+ ret = load_controller (node , controller_manager_name , controller_name )
270+ if not ret .ok :
250271 node .get_logger ().fatal (
251272 bcolors .FAIL
252- + 'Could not set controller type to "'
253- + controller_type
254- + '" for '
273+ + "Failed loading controller "
255274 + bcolors .BOLD
256275 + prefixed_controller_name
257276 + bcolors .ENDC
258277 )
259278 return 1
260-
261- ret = load_controller (node , controller_manager_name , controller_name )
262- if not ret .ok :
263- node .get_logger ().fatal (
264- bcolors .FAIL
265- + "Failed loading controller "
279+ node .get_logger ().info (
280+ bcolors .OKBLUE
281+ + "Loaded "
266282 + bcolors .BOLD
267283 + prefixed_controller_name
268284 + bcolors .ENDC
269285 )
270- return 1
271- node .get_logger ().info (
272- bcolors .OKBLUE + "Loaded " + bcolors .BOLD + prefixed_controller_name + bcolors .ENDC
273- )
274286
275- if param_file :
276- # load_parameter_file writes to stdout/stderr. Here we capture that and use node logging instead
277- with redirect_stdout (io .StringIO ()) as f_stdout , redirect_stderr (
278- io .StringIO ()
279- ) as f_stderr :
280- load_parameter_file (
281- node = node ,
282- node_name = prefixed_controller_name ,
283- parameter_file = param_file ,
284- use_wildcard = True ,
287+ if param_file :
288+ # load_parameter_file writes to stdout/stderr. Here we capture that and use node logging instead
289+ with redirect_stdout (io .StringIO ()) as f_stdout , redirect_stderr (
290+ io .StringIO ()
291+ ) as f_stderr :
292+ load_parameter_file (
293+ node = node ,
294+ node_name = prefixed_controller_name ,
295+ parameter_file = param_file ,
296+ use_wildcard = True ,
297+ )
298+ if f_stdout .getvalue ():
299+ node .get_logger ().info (bcolors .OKCYAN + f_stdout .getvalue () + bcolors .ENDC )
300+ if f_stderr .getvalue ():
301+ node .get_logger ().error (bcolors .FAIL + f_stderr .getvalue () + bcolors .ENDC )
302+ node .get_logger ().info (
303+ bcolors .OKCYAN
304+ + 'Loaded parameters file "'
305+ + param_file
306+ + '" for '
307+ + bcolors .BOLD
308+ + prefixed_controller_name
309+ + bcolors .ENDC
285310 )
286- if f_stdout .getvalue ():
287- node .get_logger ().info (bcolors .OKCYAN + f_stdout .getvalue () + bcolors .ENDC )
288- if f_stderr .getvalue ():
289- node .get_logger ().error (bcolors .FAIL + f_stderr .getvalue () + bcolors .ENDC )
290- node .get_logger ().info (
291- bcolors .OKCYAN
292- + 'Loaded parameters file "'
293- + param_file
294- + '" for '
295- + bcolors .BOLD
296- + prefixed_controller_name
297- + bcolors .ENDC
298- )
299- # TODO(destogl): use return value when upstream return value is merged
300- # ret =
301- # if ret.returncode != 0:
302- # Error message printed by ros2 param
303- # return ret.returncode
304- node .get_logger ().info ("Loaded " + param_file + " into " + prefixed_controller_name )
305-
306- if not args .load_only :
307- ret = configure_controller (node , controller_manager_name , controller_name )
308- if not ret .ok :
309- node .get_logger ().error (
310- bcolors .FAIL + "Failed to configure controller" + bcolors .ENDC
311+ # TODO(destogl): use return value when upstream return value is merged
312+ # ret =
313+ # if ret.returncode != 0:
314+ # Error message printed by ros2 param
315+ # return ret.returncode
316+ node .get_logger ().info (
317+ "Loaded " + param_file + " into " + prefixed_controller_name
311318 )
312- return 1
313319
314- if not args .inactive :
315- ret = switch_controllers (
316- node , controller_manager_name , [], [controller_name ], True , True , 5.0
317- )
320+ if not args .load_only :
321+ ret = configure_controller (node , controller_manager_name , controller_name )
318322 if not ret .ok :
319323 node .get_logger ().error (
320- bcolors .FAIL + "Failed to activate controller" + bcolors .ENDC
324+ bcolors .FAIL + "Failed to configure controller" + bcolors .ENDC
321325 )
322326 return 1
323327
324- node .get_logger ().info (
325- bcolors .OKGREEN
326- + "Configured and activated "
327- + bcolors .BOLD
328- + prefixed_controller_name
329- + bcolors .ENDC
328+ if not args .inactive and not args .activate_as_group :
329+ ret = switch_controllers (
330+ node , controller_manager_name , [], [controller_name ], True , True , 5.0
331+ )
332+ if not ret .ok :
333+ node .get_logger ().error (
334+ bcolors .FAIL + "Failed to activate controller" + bcolors .ENDC
335+ )
336+ return 1
337+
338+ node .get_logger ().info (
339+ bcolors .OKGREEN
340+ + "Configured and activated "
341+ + bcolors .BOLD
342+ + prefixed_controller_name
343+ + bcolors .ENDC
344+ )
345+
346+ if not args .inactive and args .activate_as_group :
347+ ret = switch_controllers (
348+ node , controller_manager_name , [], controller_names , True , True , 5.0
349+ )
350+ if not ret .ok :
351+ node .get_logger ().error (
352+ bcolors .FAIL + "Failed to activate the parsed controllers list" + bcolors .ENDC
330353 )
354+ return 1
355+
356+ node .get_logger ().info (
357+ bcolors .OKGREEN
358+ + "Configured and activated all the parsed controllers list!"
359+ + bcolors .ENDC
360+ )
331361
332362 if not args .unload_on_kill :
333363 return 0
@@ -339,8 +369,9 @@ def main(args=None):
339369 except KeyboardInterrupt :
340370 if not args .inactive :
341371 node .get_logger ().info ("Interrupt captured, deactivating and unloading controller" )
372+ # TODO(saikishor) we might have an issue in future, if any of these controllers is in chained mode
342373 ret = switch_controllers (
343- node , controller_manager_name , [ controller_name ] , [], True , True , 5.0
374+ node , controller_manager_name , controller_names , [], True , True , 5.0
344375 )
345376 if not ret .ok :
346377 node .get_logger ().error (
0 commit comments