def execute( self, context: LaunchContext ) -> Optional[List[Action]]: """Execute the action.""" # resolve target container node name if is_a_subclass(self.__target_container, ComposableNodeContainer): self.__final_target_container_name = self.__target_container.node_name elif isinstance(self.__target_container, SomeSubstitutionsType_types_tuple): subs = normalize_to_list_of_substitutions(self.__target_container) self.__final_target_container_name = perform_substitutions( context, subs) else: self.__logger.error( 'target container is neither a ComposableNodeContainer nor a SubstitutionType') return # Create a client to load nodes in the target container. self.__rclpy_load_node_client = get_ros_node(context).create_client( composition_interfaces.srv.LoadNode, '{}/_container/load_node'.format( self.__final_target_container_name ) ) context.add_completion_future( context.asyncio_loop.run_in_executor( None, self._load_in_sequence, self.__composable_node_descriptions, context ) )
def execute(self, context: LaunchContext) -> Optional[List[Action]]: """Execute the action.""" # resolve target container node name if is_a_subclass(self.__target_container, ComposableNodeContainer): self.__final_target_container_name = self.__target_container.node_name elif isinstance(self.__target_container, SomeSubstitutionsType_types_tuple): subs = normalize_to_list_of_substitutions(self.__target_container) self.__final_target_container_name = perform_substitutions( context, subs) else: self.__logger.error( 'target container is neither a ComposableNodeContainer nor a SubstitutionType' ) return # Create a client to load nodes in the target container. self.__rclpy_load_node_client = get_ros_node(context).create_client( composition_interfaces.srv.LoadNode, '{}/_container/load_node'.format( self.__final_target_container_name)) # Generate load requests before execute() exits to avoid race with context changing # due to scope change (e.g. if loading nodes from within a GroupAction). load_node_requests = [ get_composable_node_load_request(node_description, context) for node_description in self.__composable_node_descriptions ] context.add_completion_future( context.asyncio_loop.run_in_executor(None, self._load_in_sequence, load_node_requests, context))
def _load_in_sequence(self, composable_node_descriptions: List[ComposableNode], context: LaunchContext) -> None: """ Load composable nodes sequentially. :param composable_node_descriptions: descriptions of composable nodes to be loaded :param context: current launch context """ next_composable_node_description = composable_node_descriptions[0] composable_node_descriptions = composable_node_descriptions[1:] self._load_node(next_composable_node_description, context) if len(composable_node_descriptions) > 0: context.add_completion_future( context.asyncio_loop.run_in_executor( None, self._load_in_sequence, composable_node_descriptions, context))
def _load_in_sequence(self, load_node_requests: List[ composition_interfaces.srv.LoadNode.Request], context: LaunchContext) -> None: """ Load composable nodes sequentially. :param composable_node_descriptions: descriptions of composable nodes to be loaded :param context: current launch context """ next_load_node_request = load_node_requests[0] load_node_requests = load_node_requests[1:] self._load_node(next_load_node_request, context) if len(load_node_requests) > 0: context.add_completion_future( context.asyncio_loop.run_in_executor(None, self._load_in_sequence, load_node_requests, context))