2424 AppendEnvironmentVariable ,
2525 DeclareLaunchArgument ,
2626 ExecuteProcess ,
27+ ForEach ,
2728 GroupAction ,
2829 IncludeLaunchDescription ,
2930 LogInfo ,
3031 OpaqueFunction ,
3132 RegisterEventHandler ,
3233)
34+
3335from launch .conditions import IfCondition
3436from launch .event_handlers import OnShutdown
37+ from launch .launch_context import LaunchContext
3538from launch .launch_description_sources import PythonLaunchDescriptionSource
3639from launch .substitutions import LaunchConfiguration , TextSubstitution
37- from nav2_common .launch import ParseMultiRobotPose
3840
41+ import yaml
42+
43+
44+ def count_robots (context : LaunchContext ) -> list [LogInfo ]:
45+ """Count the number of robots from the 'robots' launch argument."""
46+ robots_str = LaunchConfiguration ('robots' ).perform (context ).strip ()
47+ log_msg = ''
48+
49+ if not robots_str :
50+ log_msg = 'No robots provided in the launch argument.'
51+
52+ try :
53+ robots_list = [yaml .safe_load (robot .strip ()) for robot in
54+ robots_str .split (';' ) if robot .strip ()]
55+ log_msg = f'number_of_robots={ len (robots_list )} '
56+ except yaml .YAMLError as e :
57+ log_msg = f'Error parsing the robots launch argument: { e } '
58+
59+ return [LogInfo (msg = [log_msg ])]
3960
40- def generate_robot_actions (context , * args , ** kwargs ):
61+
62+ def generate_robot_actions (name : str = '' , pose : dict = {}) -> list [GroupAction ]:
63+ """Generate the actions to launch a robot with the given name and pose."""
4164 bringup_dir = get_package_share_directory ('nav2_bringup' )
4265 launch_dir = os .path .join (bringup_dir , 'launch' )
4366 use_rviz = LaunchConfiguration ('use_rviz' )
@@ -47,25 +70,19 @@ def generate_robot_actions(context, *args, **kwargs):
4770 map_yaml_file = LaunchConfiguration ('map' )
4871 use_robot_state_pub = LaunchConfiguration ('use_robot_state_pub' )
4972
50- robots_substitution = ParseMultiRobotPose (LaunchConfiguration ('robots' ))
51- robots_list = robots_substitution .perform (context )
52-
5373 # Define commands for launching the navigation instances
54- bringup_cmd_group = []
55- for robot_name in robots_list :
56- init_pose = robots_list [robot_name ]
57- group = GroupAction (
74+ group = GroupAction (
5875 [
5976 LogInfo (
60- msg = ['Launching namespace=' , robot_name , ' init_pose=' , str (init_pose ),]
77+ msg = ['Launching namespace=' , name , ' init_pose=' , str (pose ),]
6178 ),
6279 IncludeLaunchDescription (
6380 PythonLaunchDescriptionSource (
6481 os .path .join (launch_dir , 'rviz_launch.py' )
6582 ),
6683 condition = IfCondition (use_rviz ),
6784 launch_arguments = {
68- 'namespace' : TextSubstitution (text = robot_name ),
85+ 'namespace' : TextSubstitution (text = name ),
6986 'rviz_config' : rviz_config_file ,
7087 }.items (),
7188 ),
@@ -74,7 +91,7 @@ def generate_robot_actions(context, *args, **kwargs):
7491 os .path .join (bringup_dir , 'launch' , 'tb3_simulation_launch.py' )
7592 ),
7693 launch_arguments = {
77- 'namespace' : robot_name ,
94+ 'namespace' : name ,
7895 'map' : map_yaml_file ,
7996 'use_sim_time' : 'True' ,
8097 'params_file' : params_file ,
@@ -83,21 +100,18 @@ def generate_robot_actions(context, *args, **kwargs):
83100 'use_simulator' : 'False' ,
84101 'headless' : 'False' ,
85102 'use_robot_state_pub' : use_robot_state_pub ,
86- 'x_pose' : TextSubstitution (text = str (init_pose [ 'x' ] )),
87- 'y_pose' : TextSubstitution (text = str (init_pose [ 'y' ] )),
88- 'z_pose' : TextSubstitution (text = str (init_pose [ 'z' ] )),
89- 'roll' : TextSubstitution (text = str (init_pose [ 'roll' ] )),
90- 'pitch' : TextSubstitution (text = str (init_pose [ 'pitch' ] )),
91- 'yaw' : TextSubstitution (text = str (init_pose [ 'yaw' ] )),
92- 'robot_name' : TextSubstitution (text = robot_name ),
103+ 'x_pose' : TextSubstitution (text = str (pose . get ( 'x' , 0.0 ) )),
104+ 'y_pose' : TextSubstitution (text = str (pose . get ( 'y' , 0.0 ) )),
105+ 'z_pose' : TextSubstitution (text = str (pose . get ( 'z' , 0.0 ) )),
106+ 'roll' : TextSubstitution (text = str (pose . get ( 'roll' , 0.0 ) )),
107+ 'pitch' : TextSubstitution (text = str (pose . get ( 'pitch' , 0.0 ) )),
108+ 'yaw' : TextSubstitution (text = str (pose . get ( 'yaw' , 0.0 ) )),
109+ 'robot_name' : TextSubstitution (text = name ),
93110 }.items (),
94111 ),
95112 ]
96113 )
97-
98- bringup_cmd_group .append (group )
99- bringup_cmd_group .append (LogInfo (msg = ['number_of_robots=' , str (len (robots_list ))]))
100- return bringup_cmd_group
114+ return [group ]
101115
102116
103117def generate_launch_description ():
@@ -106,9 +120,13 @@ def generate_launch_description():
106120
107121 Launch arguments consist of robot name(which is namespace) and pose for initialization.
108122 Keep general yaml format for pose information.
109- ex) robots:='robot1={x: 1.0, y: 1.0, yaw: 1.5707}; robot2={x: 1.0, y: 1.0, yaw: 1.5707}'
110- ex) robots:='robot3={x: 1.0, y: 1.0, z: 1.0, roll: 0.0, pitch: 1.5707, yaw: 1.5707};
111- robot4={x: 1.0, y: 1.0, z: 1.0, roll: 0.0, pitch: 1.5707, yaw: 1.5707}'
123+
124+ ex) robots:='{name: 'robot1', pose: {x: 1.0, y: 1.0, yaw: 1.5707}};
125+ {name: 'robot2', pose: {x: 1.0, y: 1.0, yaw: 1.5707}}'
126+ ex) robots:='{name: 'robot3', pose: {x: 1.0, y: 1.0, z: 1.0,
127+ roll: 0.0, pitch: 1.5707, yaw: 1.5707}};
128+ {name: 'robot4', pose: {x: 1.0, y: 1.0, z: 1.0,
129+ roll: 0.0, pitch: 1.5707, yaw: 1.5707}}'
112130 """
113131 # Get the launch directory
114132 bringup_dir = get_package_share_directory ('nav2_bringup' )
@@ -134,8 +152,10 @@ def generate_launch_description():
134152
135153 declare_robots_cmd = DeclareLaunchArgument (
136154 'robots' ,
137- default_value = """robot1={x: 0.5, y: 0.5, yaw: 0};
138- robot2={x: -0.5, y: -0.5, z: 0, roll: 0, pitch: 0, yaw: 1.5707}""" ,
155+ default_value = (
156+ "{name: 'robot1', pose: {x: 0.5, y: 0.5, yaw: 0}};"
157+ "{name: 'robot2', pose: {x: -0.5, y: -0.5, z: 0, roll: 0, pitch: 0, yaw: 1.5707}}"
158+ ),
139159 description = 'Robots and their initialization poses in YAML format' ,
140160 )
141161
@@ -237,6 +257,8 @@ def generate_launch_description():
237257 ld .add_action (
238258 LogInfo (condition = IfCondition (log_settings ), msg = ['autostart: ' , autostart ])
239259 )
240- ld .add_action (OpaqueFunction (function = generate_robot_actions ))
260+
261+ ld .add_action (OpaqueFunction (function = count_robots ))
262+ ld .add_action (ForEach (LaunchConfiguration ('robots' ), function = generate_robot_actions ))
241263
242264 return ld
0 commit comments