Skip to content

Commit f8da14d

Browse files
saikishormergify[bot]
authored andcommitted
[Spawner] Allow arguments per controller instead of global args (#2895)
(cherry picked from commit cb9a983)
1 parent 0a81bfc commit f8da14d

File tree

6 files changed

+1319
-75
lines changed

6 files changed

+1319
-75
lines changed

controller_manager/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,19 @@ if(BUILD_TESTING)
236236
test_spawner_unspawner
237237
PRIVATE PARAMETERS_FILE_PATH="${CMAKE_CURRENT_LIST_DIR}/test/")
238238

239+
ament_add_gmock(test_advanced_spawner
240+
test/test_advanced_spawner.cpp
241+
TIMEOUT 180
242+
)
243+
target_link_libraries(test_advanced_spawner
244+
controller_manager
245+
test_controller
246+
ros2_control_test_assets::ros2_control_test_assets
247+
)
248+
target_compile_definitions(
249+
test_advanced_spawner
250+
PRIVATE PARAMETERS_FILE_PATH="${CMAKE_CURRENT_LIST_DIR}/test/")
251+
239252
ament_add_gmock(test_hardware_spawner
240253
test/test_hardware_spawner.cpp
241254
TIMEOUT 120

controller_manager/controller_manager/launch_utils.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,91 @@ def generate_load_controller_launch_description(
148148
controller_params_files=controller_params_files,
149149
extra_spawner_args=extra_spawner_args,
150150
)
151+
152+
153+
def generate_spawner_launch_description(controller_info_dict: dict, extra_spawner_args=[]):
154+
"""
155+
Generate launch description for loading a controller using spawner.
156+
157+
controller_info_dict: dict
158+
A dictionary with the following info:
159+
- controller_name: str
160+
The name of the controller to load as the key
161+
- controller_specific_args: dict
162+
A dictionary of extra arguments to pass to the controller spawner
163+
The supported keys are:
164+
- param_file: str or list or None
165+
The path to the controller parameter file or a list of paths to multiple parameter files
166+
or None if no parameter file is needed as the value of the key
167+
If a list is passed, the controller parameters will be overloaded in same order
168+
- load_only: bool
169+
Whether to load the controller but not start it
170+
- inactive: bool
171+
Whether to configure the controller but not activate it
172+
- ros_args: str
173+
Extra arguments to pass to the controller spawner
174+
extra_spawner_args: list
175+
A list of extra arguments to pass to the controller.
176+
Supported items are only the global arguments supported by the spawner.
177+
"""
178+
if not type(controller_info_dict) is dict:
179+
raise ValueError(f"Invalid controller_info_dict type parsed {controller_info_dict}")
180+
controller_names = list(controller_info_dict.keys())
181+
spawner_arguments = []
182+
for controller_name in controller_names:
183+
controller_specific_args = ["--controller", controller_name]
184+
185+
controller_params_file = controller_info_dict[controller_name].get("param_file", None)
186+
if controller_params_file:
187+
if type(controller_params_file) is list:
188+
for param_file in controller_params_file:
189+
controller_specific_args.append("--param-file")
190+
controller_specific_args.append(param_file)
191+
elif type(controller_params_file) is str:
192+
controller_specific_args.append("--param-file")
193+
controller_specific_args.append(controller_params_file)
194+
else:
195+
raise ValueError(
196+
f"Invalid controller_params_file type parsed in the dict {controller_params_file}. Expected str or list, got {type(controller_params_file)}."
197+
)
198+
if "load_only" in controller_info_dict[controller_name]:
199+
load_only_arg = controller_info_dict[controller_name]["load_only"]
200+
if type(load_only_arg) is not bool:
201+
raise ValueError(
202+
f"Invalid load_only type parsed in the dict {load_only_arg}. Expected bool, got {type(load_only_arg)}."
203+
)
204+
if load_only_arg:
205+
controller_specific_args.append("--load-only")
206+
if "inactive" in controller_info_dict[controller_name]:
207+
inactive_arg = controller_info_dict[controller_name]["inactive"]
208+
if type(inactive_arg) is not bool:
209+
raise ValueError(
210+
f"Invalid inactive type parsed in the dict {inactive_arg}. Expected bool, got {type(inactive_arg)}."
211+
)
212+
if inactive_arg:
213+
controller_specific_args.append("--inactive")
214+
if "ros_args" in controller_info_dict[controller_name]:
215+
ros_args = controller_info_dict[controller_name]["ros_args"]
216+
if type(ros_args) is not str:
217+
raise ValueError(
218+
f"Invalid ros_args type parsed in the dict {ros_args}. Expected str, got {type(ros_args)}."
219+
)
220+
controller_specific_args.append("--controller-ros-args")
221+
controller_specific_args.append(ros_args)
222+
spawner_arguments.extend(controller_specific_args)
223+
224+
spawner_arguments.extend(extra_spawner_args)
225+
226+
spawner = Node(
227+
package="controller_manager",
228+
executable="spawner",
229+
arguments=spawner_arguments,
230+
shell=True,
231+
output="screen",
232+
)
233+
234+
return LaunchDescription(
235+
[
236+
spawner,
237+
]
238+
)

0 commit comments

Comments
 (0)