@@ -68,29 +68,31 @@ def get_registered_component_types():
6868ComponentInfo = namedtuple ('Component' , ('uid' , 'name' ))
6969
7070
71- def get_components_in_container (* , node , remote_container_node_name ):
71+ def get_components_in_container (* , node , remote_container_node_name , timeout = 5.0 ):
7272 """
7373 Get information about the components in a container.
7474
7575 :param node: an `rclpy.Node` instance.
7676 :param remote_container_node_names: of the container node to inspect.
77+ :param timeout: maximum time to wait for response in seconds (default: 5.0).
7778 :return: a tuple with either a truthy boolean and a list of `ComponentInfo`
7879 instances containing the unique id and name of each component or a falsy
7980 boolean and a reason string in case of error.
8081 """
8182 return get_components_in_containers (
82- node = node , remote_containers_node_names = [remote_container_node_name ]
83+ node = node , remote_containers_node_names = [remote_container_node_name ], timeout = timeout
8384 )[remote_container_node_name ]
8485
8586
86- def get_components_in_containers (* , node , remote_containers_node_names ):
87+ def get_components_in_containers (* , node , remote_containers_node_names , timeout = 5.0 ):
8788 """
8889 Get information about the components in multiple containers.
8990
9091 Get information about the components in a container.
9192
9293 :param node: an `rclpy.Node` instance.
9394 :param remote_container_node_names: of the container nodes to inspect.
95+ :param timeout: maximum time to wait for response in seconds (default: 5.0).
9496 :return: a dict of tuples, with either a truthy boolean and a list of `ComponentInfo`
9597 instances containing the unique id and name of each component or a falsy boolean and
9698 a reason string in case of error, per container node.
@@ -174,7 +176,7 @@ def _resume(to_completion=False):
174176
175177 timer = node .create_timer (timer_period_sec = 0.1 , callback = resume )
176178 try :
177- rclpy .spin_until_future_complete (node , future , timeout_sec = 5.0 )
179+ rclpy .spin_until_future_complete (node , future , timeout_sec = timeout )
178180 if not future .done ():
179181 resume (to_completion = True )
180182 return dict (future .result ())
@@ -193,7 +195,8 @@ def load_component_into_container(
193195 log_level = None ,
194196 remap_rules = None ,
195197 parameters = None ,
196- extra_arguments = None
198+ extra_arguments = None ,
199+ timeout = None
197200):
198201 """
199202 Load component into a running container synchronously.
@@ -208,6 +211,7 @@ def load_component_into_container(
208211 :param remap_rules: remapping rules for the component node, in the 'from:=to' form
209212 :param parameters: optional parameters for the component node, in the 'name:=value' form
210213 :param extra_arguments: arguments specific to the container node in the 'name:=value' form
214+ :param timeout: maximum time to wait for response in seconds (default: waits indefinitely)
211215 """
212216 load_node_client = node .create_client (
213217 composition_interfaces .srv .LoadNode ,
@@ -244,7 +248,11 @@ def load_component_into_container(
244248 arg_msg .name = name
245249 request .extra_arguments .append (arg_msg )
246250 future = load_node_client .call_async (request )
247- rclpy .spin_until_future_complete (node , future )
251+ rclpy .spin_until_future_complete (node , future , timeout_sec = timeout )
252+ if not future .done ():
253+ raise RuntimeError (
254+ 'Timed out waiting for load_node response from '
255+ f'{ remote_container_node_name !r} container (timeout: { timeout } s)' )
248256 response = future .result ()
249257 if not response .success :
250258 raise RuntimeError ('Failed to load component: ' + response .error_message .capitalize ())
@@ -253,13 +261,15 @@ def load_component_into_container(
253261 node .destroy_client (load_node_client )
254262
255263
256- def unload_component_from_container (* , node , remote_container_node_name , component_uids ):
264+ def unload_component_from_container (
265+ * , node , remote_container_node_name , component_uids , timeout = None ):
257266 """
258267 Unload a component from a running container synchronously.
259268
260269 :param node: an `rclpy.Node` instance
261270 :param remote_container_node_name: of the container node to unload the component from
262271 :param component_uids: list of unique IDs of the components to be unloaded
272+ :param timeout: maximum time to wait for response in seconds (default: waits indefinitely)
263273 """
264274 unload_node_client = node .create_client (
265275 composition_interfaces .srv .UnloadNode ,
@@ -274,7 +284,11 @@ def unload_component_from_container(*, node, remote_container_node_name, compone
274284 request = composition_interfaces .srv .UnloadNode .Request ()
275285 request .unique_id = uid
276286 future = unload_node_client .call_async (request )
277- rclpy .spin_until_future_complete (node , future )
287+ rclpy .spin_until_future_complete (node , future , timeout_sec = timeout )
288+ if not future .done ():
289+ raise RuntimeError (
290+ 'Timed out waiting for unload_node response from '
291+ f'{ remote_container_node_name !r} container (timeout: { timeout } s)' )
278292 response = future .result ()
279293 yield uid , not response .success , response .error_message
280294 finally :
0 commit comments