1616
1717from typing import List
1818from typing import Optional
19+ from typing import Text
20+ from typing import Union
1921
2022import composition_interfaces .srv
2123
2224from launch .action import Action
2325from launch .launch_context import LaunchContext
2426import launch .logging
27+ from launch .some_substitutions_type import SomeSubstitutionsType
28+ from launch .some_substitutions_type import SomeSubstitutionsType_types_tuple
2529from launch .utilities import ensure_argument_type
30+ from launch .utilities import is_a_subclass
31+ from launch .utilities import normalize_to_list_of_substitutions
2632from launch .utilities import perform_substitutions
2733
2834from .composable_node_container import ComposableNodeContainer
@@ -39,7 +45,7 @@ def __init__(
3945 self ,
4046 * ,
4147 composable_node_descriptions : List [ComposableNode ],
42- target_container : ComposableNodeContainer ,
48+ target_container : Union [ SomeSubstitutionsType , ComposableNodeContainer ] ,
4349 ** kwargs ,
4450 ) -> None :
4551 """
@@ -57,13 +63,15 @@ def __init__(
5763 """
5864 ensure_argument_type (
5965 target_container ,
60- ComposableNodeContainer ,
66+ list (SomeSubstitutionsType_types_tuple ) +
67+ [ComposableNodeContainer ],
6168 'target_container' ,
6269 'LoadComposableNodes'
6370 )
6471 super ().__init__ (** kwargs )
6572 self .__composable_node_descriptions = composable_node_descriptions
6673 self .__target_container = target_container
74+ self .__final_target_container_name = None # type: Optional[Text]
6775 self .__logger = launch .logging .get_logger (__name__ )
6876
6977 def _load_node (
@@ -128,11 +136,11 @@ def _load_node(
128136 self .__logger .error (
129137 "Failed to load node '{}' of type '{}' in container '{}': {}" .format (
130138 response .full_node_name if response .full_node_name else request .node_name ,
131- request .plugin_name , self .__target_container . node_name , response .error_message
139+ request .plugin_name , self .__final_target_container_name , response .error_message
132140 )
133141 )
134142 self .__logger .info ("Loaded node '{}' in container '{}'" .format (
135- response .full_node_name , self .__target_container . node_name
143+ response .full_node_name , self .__final_target_container_name
136144 ))
137145
138146 def _load_in_sequence (
@@ -161,10 +169,23 @@ def execute(
161169 context : LaunchContext
162170 ) -> Optional [List [Action ]]:
163171 """Execute the action."""
172+ # resolve target container node name
173+
174+ if is_a_subclass (self .__target_container , ComposableNodeContainer ):
175+ self .__final_target_container_name = self .__target_container .node_name
176+ elif isinstance (self .__target_container , SomeSubstitutionsType_types_tuple ):
177+ subs = normalize_to_list_of_substitutions (self .__target_container )
178+ self .__final_target_container_name = perform_substitutions (
179+ context , subs )
180+ else :
181+ self .__logger .error (
182+ 'target container is neither a ComposableNodeContainer nor a SubstitutionType' )
183+ return
184+
164185 # Create a client to load nodes in the target container.
165186 self .__rclpy_load_node_client = context .locals .launch_ros_node .create_client (
166187 composition_interfaces .srv .LoadNode , '{}/_container/load_node' .format (
167- self .__target_container . node_name
188+ self .__final_target_container_name
168189 )
169190 )
170191 # Assume user has configured `LoadComposableNodes` to happen after container action
0 commit comments