Skip to content

Commit bc2ea49

Browse files
saikishormergify[bot]
authored andcommitted
[Spawner] Allow parsing the parameter files parsed from spawner to controllers (#3136)
(cherry picked from commit a583699) # Conflicts: # controller_manager/controller_manager/spawner.py # controller_manager/doc/userdoc.rst # controller_manager/test/test_advanced_spawner.cpp # doc/release_notes.rst
1 parent 06b5989 commit bc2ea49

File tree

5 files changed

+1154
-0
lines changed

5 files changed

+1154
-0
lines changed

controller_manager/controller_manager/spawner.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,55 @@ def main(args=None):
158158
required=False,
159159
)
160160

161+
<<<<<<< HEAD
162+
=======
163+
global_namespace_args = parser.parse_args(args)
164+
165+
controllers_info = []
166+
for controller_name in global_namespace_args.controller_names:
167+
controllers_info.append(
168+
{
169+
"name": controller_name,
170+
"param_files": global_namespace_args.param_file,
171+
"load_only": global_namespace_args.load_only,
172+
"inactive": global_namespace_args.inactive,
173+
"controller_ros_args": global_namespace_args.controller_ros_args,
174+
}
175+
)
176+
177+
return global_namespace_args, controllers_info
178+
179+
180+
def main(args=None):
181+
rclpy.init(args=args, signal_handler_options=SignalHandlerOptions.NO)
182+
183+
def append_unique_preserve_order(base, to_append):
184+
if base is None:
185+
base = []
186+
existing = set(base)
187+
for item in to_append:
188+
if item not in existing:
189+
base.append(item)
190+
existing.add(item)
191+
return base
192+
193+
def get_ros_params_files(argv):
194+
params_files = []
195+
index = 0
196+
while index < len(argv):
197+
if argv[index] == "--params-file":
198+
if index + 1 >= len(argv):
199+
raise ValueError("--params-file requires a path argument")
200+
params_files.append(argv[index + 1])
201+
index += 2
202+
continue
203+
index += 1
204+
return params_files
205+
206+
spawner_ros_params_files = get_ros_params_files(sys.argv[1:])
207+
208+
# Remove ROS args
209+
>>>>>>> a583699 ([Spawner] Allow parsing the parameter files parsed from spawner to controllers (#3136))
161210
command_line_args = rclpy.utilities.remove_ros_args(args=sys.argv)[1:]
162211
args = parser.parse_args(command_line_args)
163212
controller_names = args.controller_names
@@ -171,11 +220,30 @@ def main(args=None):
171220
switch_asap = args.switch_asap
172221
node = None
173222

223+
<<<<<<< HEAD
174224
if param_files:
175225
for param_file in param_files:
176226
if not os.path.isfile(param_file):
177227
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), param_file)
178228
logger = rclpy.logging.get_logger("ros2_control_controller_spawner_" + controller_names[0])
229+
=======
230+
if spawner_ros_params_files:
231+
for controller in controllers:
232+
controller["param_files"] = append_unique_preserve_order(
233+
controller["param_files"], spawner_ros_params_files
234+
)
235+
236+
# Check param files existence
237+
for c in controllers:
238+
if c["param_files"]:
239+
for param_file in c["param_files"]:
240+
if not os.path.isfile(param_file):
241+
raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), param_file)
242+
243+
# Use the first controller name for the logger/lock
244+
first_controller_name = controllers[0]["name"]
245+
logger = rclpy.logging.get_logger("ros2_control_controller_spawner_" + first_controller_name)
246+
>>>>>>> a583699 ([Spawner] Allow parsing the parameter files parsed from spawner to controllers (#3136))
179247

180248
try:
181249
spawner_node_name = "spawner_" + controller_names[0]

controller_manager/doc/userdoc.rst

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,98 @@ There are two scripts to interact with controller manager from launch files:
194194
--controller-ros-args CONTROLLER_ROS_ARGS
195195
The --ros-args to be passed to the controller node, e.g., for remapping topics. Pass multiple times for every argument.
196196
197+
<<<<<<< HEAD
198+
=======
199+
When launching ``spawner`` with ROS parameter files that use substitutions (for example, launch ``allow_substs=True``),
200+
the resolved ``--params-file`` path(s) used by the spawner node are automatically forwarded to each controller along
201+
with any explicit ``--param-file`` arguments passed to the spawner command.
202+
203+
.. note::
204+
If a single parameter file is used for multiple controllers, the spawner will automatically forward the resolved path(s) to each controller. The following methods are recommended:
205+
206+
.. code-block:: console
207+
208+
Node(
209+
package="controller_manager",
210+
executable="spawner",
211+
arguments=[
212+
"my_controller",
213+
"--param-file",
214+
PathSubstitution(FindPackageShare("my_config_pkg"))
215+
/ "config"
216+
/ "controllers.yaml",
217+
],
218+
),
219+
220+
(or)
221+
222+
.. code-block:: console
223+
224+
Node(
225+
package="controller_manager",
226+
executable="spawner",
227+
parameters=[
228+
ParameterFile(
229+
PathSubstitution(FindPackageShare("my_config_pkg"))
230+
/ "config"
231+
/ "controllers.yaml",
232+
),
233+
],
234+
arguments=[
235+
"my_controller"
236+
],
237+
),
238+
239+
The ``spawner`` now supports per controller arguments, while parsing the arguments for multiple controllers using ``--controller`` option. For example, to spawn two controllers with different parameter files and remapping topics, the following command can be used:
240+
241+
.. code-block:: console
242+
243+
$ ros2 run controller_manager spawner --controller position_trajectory_controller \
244+
--param-file /path/to/position_trajectory_controller_params.yaml \
245+
--controller-ros-args "--ros-args --remap /joint_states:=/rrbot/joint_states" \
246+
--controller velocity_trajectory_controller \
247+
--param-file /path/to/velocity_trajectory_controller_params.yaml \
248+
--controller-ros-args "--ros-args --remap /joint_states:=/rrbot/joint_states"
249+
250+
.. code-block:: console
251+
252+
$ ros2 run controller_manager spawner --controller -h
253+
Usage: spawner [global_options] --controller <name> [controller_options] --controller <name> ...
254+
255+
Global Options:
256+
usage: spawner [-c CONTROLLER_MANAGER] [--controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT] [--switch-timeout SWITCH_TIMEOUT] [--service-call-timeout SERVICE_CALL_TIMEOUT] [--activate-as-group]
257+
[--switch-asap | --no-switch-asap] [-u] [-h]
258+
259+
options:
260+
-c CONTROLLER_MANAGER, --controller-manager CONTROLLER_MANAGER
261+
Name of the controller manager
262+
--controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT
263+
Timeout for controller manager services
264+
--switch-timeout SWITCH_TIMEOUT
265+
Timeout for switch controller service
266+
--service-call-timeout SERVICE_CALL_TIMEOUT
267+
Timeout for service calls
268+
--activate-as-group Activate controllers as a group
269+
--switch-asap, --no-switch-asap
270+
Switch controllers as soon as possible
271+
-u, --unload-on-kill Deactivate the active controllers and unload them on kill
272+
-h, --help Show help
273+
274+
Controller Options:
275+
usage: spawner [-p PARAM_FILE] [--load-only] [--inactive] [--controller-ros-args CONTROLLER_ROS_ARGS] controller_name
276+
277+
positional arguments:
278+
controller_name Name of the controller
279+
280+
options:
281+
-p PARAM_FILE, --param-file PARAM_FILE
282+
Parameter files to load for the controller
283+
--load-only Load the controller but do not configure/activate it
284+
--inactive Configure the controller but do not switch it
285+
--controller-ros-args CONTROLLER_ROS_ARGS
286+
ROS arguments to pass to the controller
287+
288+
>>>>>>> a583699 ([Spawner] Allow parsing the parameter files parsed from spawner to controllers (#3136))
197289

198290
The parsed controller config file can follow the same conventions as the typical ROS 2 parameter file format. Now, the spawner can handle config files with wildcard entries and also the controller name in the absolute namespace. See the following examples on the config files:
199291

0 commit comments

Comments
 (0)