16 Example for spawning multiple robots in Gazebo.
18 This is an example on how to create a launch file for spawning multiple robots into Gazebo
19 and launch multiple instances of the navigation stack, each controlling one robot.
20 The robots co-exist on a shared environment and are controlled by independent nav stacks.
24 from pathlib
import Path
27 from ament_index_python.packages
import get_package_share_directory
28 from launch
import LaunchDescription
29 from launch.actions
import (AppendEnvironmentVariable, DeclareLaunchArgument, ExecuteProcess,
30 GroupAction, IncludeLaunchDescription, LogInfo, OpaqueFunction,
32 from launch.conditions
import IfCondition
33 from launch.event_handlers
import OnShutdown
34 from launch.launch_description_sources
import PythonLaunchDescriptionSource
35 from launch.substitutions
import LaunchConfiguration, TextSubstitution
38 def generate_launch_description() -> LaunchDescription:
40 bringup_dir = get_package_share_directory(
'nav2_bringup')
41 launch_dir = os.path.join(bringup_dir,
'launch')
42 sim_dir = get_package_share_directory(
'nav2_minimal_tb3_sim')
67 world = LaunchConfiguration(
'world')
70 map_yaml_file = LaunchConfiguration(
'map')
71 graph_filepath = LaunchConfiguration(
'graph')
73 autostart = LaunchConfiguration(
'autostart')
74 rviz_config_file = LaunchConfiguration(
'rviz_config')
75 use_robot_state_pub = LaunchConfiguration(
'use_robot_state_pub')
76 use_rviz = LaunchConfiguration(
'use_rviz')
77 log_settings = LaunchConfiguration(
'log_settings', default=
'true')
80 declare_world_cmd = DeclareLaunchArgument(
82 default_value=os.path.join(sim_dir,
'worlds',
'tb3_sandbox.sdf.xacro'),
83 description=
'Full path to world file to load',
86 declare_map_yaml_cmd = DeclareLaunchArgument(
88 default_value=os.path.join(bringup_dir,
'maps',
'tb3_sandbox.yaml'),
89 description=
'Full path to map file to load',
92 declare_graph_file_cmd = DeclareLaunchArgument(
94 default_value=os.path.join(bringup_dir,
'graphs',
'turtlebot3_graph.geojson'),
97 declare_robot1_params_file_cmd = DeclareLaunchArgument(
99 default_value=os.path.join(
100 bringup_dir,
'params',
'nav2_params.yaml'
102 description=
'Full path to the ROS2 parameters file to use for robot1 launched nodes',
105 declare_robot2_params_file_cmd = DeclareLaunchArgument(
106 'robot2_params_file',
107 default_value=os.path.join(
108 bringup_dir,
'params',
'nav2_params.yaml'
110 description=
'Full path to the ROS2 parameters file to use for robot2 launched nodes',
113 declare_autostart_cmd = DeclareLaunchArgument(
115 default_value=
'false',
116 description=
'Automatically startup the stacks',
119 declare_rviz_config_file_cmd = DeclareLaunchArgument(
121 default_value=os.path.join(bringup_dir,
'rviz',
'nav2_default_view.rviz'),
122 description=
'Full path to the RVIZ config file to use.',
125 declare_use_robot_state_pub_cmd = DeclareLaunchArgument(
126 'use_robot_state_pub',
127 default_value=
'True',
128 description=
'Whether to start the robot state publisher',
131 declare_use_rviz_cmd = DeclareLaunchArgument(
132 'use_rviz', default_value=
'True', description=
'Whether to start RVIZ'
136 world_sdf = tempfile.mktemp(prefix=
'nav2_', suffix=
'.sdf')
137 world_sdf_xacro = ExecuteProcess(
138 cmd=[
'xacro',
'-o', world_sdf, [
'headless:=',
'False'], world])
139 start_gazebo_cmd = ExecuteProcess(
140 cmd=[
'gz',
'sim',
'-r',
'-s', world_sdf],
144 remove_temp_sdf_file = RegisterEventHandler(event_handler=OnShutdown(
146 OpaqueFunction(function=
lambda _: os.remove(world_sdf))
150 nav_instances_cmds = []
152 params_file = LaunchConfiguration(f
"{robot['name']}_params_file")
156 IncludeLaunchDescription(
157 PythonLaunchDescriptionSource(
158 os.path.join(launch_dir,
'rviz_launch.py')
160 condition=IfCondition(use_rviz),
162 'namespace': TextSubstitution(text=robot[
'name']),
163 'rviz_config': rviz_config_file,
166 IncludeLaunchDescription(
167 PythonLaunchDescriptionSource(
168 os.path.join(bringup_dir,
'launch',
'tb3_simulation_launch.py')
171 'namespace': robot[
'name'],
172 'map': map_yaml_file,
173 'graph': graph_filepath,
174 'use_sim_time':
'True',
175 'params_file': params_file,
176 'autostart': autostart,
178 'use_simulator':
'False',
180 'use_robot_state_pub': use_robot_state_pub,
181 'x_pose': TextSubstitution(text=str(robot[
'x_pose'])),
182 'y_pose': TextSubstitution(text=str(robot[
'y_pose'])),
183 'z_pose': TextSubstitution(text=str(robot[
'z_pose'])),
184 'roll': TextSubstitution(text=str(robot[
'roll'])),
185 'pitch': TextSubstitution(text=str(robot[
'pitch'])),
186 'yaw': TextSubstitution(text=str(robot[
'yaw'])),
187 'robot_name': TextSubstitution(text=robot[
'name']),
191 condition=IfCondition(log_settings),
192 msg=[
'Launching ', robot[
'name']],
195 condition=IfCondition(log_settings),
196 msg=[robot[
'name'],
' map yaml: ', map_yaml_file],
199 condition=IfCondition(log_settings),
200 msg=[robot[
'name'],
' params yaml: ', params_file],
203 condition=IfCondition(log_settings),
204 msg=[robot[
'name'],
' rviz config file: ', rviz_config_file],
207 condition=IfCondition(log_settings),
210 ' using robot state pub: ',
215 condition=IfCondition(log_settings),
216 msg=[robot[
'name'],
' autostart: ', autostart],
221 nav_instances_cmds.append(group)
223 set_env_vars_resources = AppendEnvironmentVariable(
224 'GZ_SIM_RESOURCE_PATH', os.path.join(sim_dir,
'models'))
225 set_env_vars_resources2 = AppendEnvironmentVariable(
226 'GZ_SIM_RESOURCE_PATH',
227 str(Path(os.path.join(sim_dir)).parent.resolve()))
230 ld = LaunchDescription()
231 ld.add_action(set_env_vars_resources)
232 ld.add_action(set_env_vars_resources2)
235 ld.add_action(declare_world_cmd)
236 ld.add_action(declare_map_yaml_cmd)
237 ld.add_action(declare_graph_file_cmd)
238 ld.add_action(declare_robot1_params_file_cmd)
239 ld.add_action(declare_robot2_params_file_cmd)
240 ld.add_action(declare_use_rviz_cmd)
241 ld.add_action(declare_autostart_cmd)
242 ld.add_action(declare_rviz_config_file_cmd)
243 ld.add_action(declare_use_robot_state_pub_cmd)
246 ld.add_action(world_sdf_xacro)
247 ld.add_action(start_gazebo_cmd)
248 ld.add_action(remove_temp_sdf_file)
250 for simulation_instance_cmd
in nav_instances_cmds:
251 ld.add_action(simulation_instance_cmd)