Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
unique_multi_tb3_simulation_launch.py
1 # Copyright (c) 2018 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 """
16 Example for spawning multiple robots in Gazebo.
17 
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.
21 """
22 
23 import os
24 from pathlib import Path
25 import tempfile
26 
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,
31  RegisterEventHandler)
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
36 
37 
38 def generate_launch_description() -> LaunchDescription:
39  # Get the launch directory
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')
43 
44  # Names and poses of the robots
45  robots = [
46  {
47  'name': 'robot1',
48  'x_pose': 0.0,
49  'y_pose': 0.5,
50  'z_pose': 0.01,
51  'roll': 0.0,
52  'pitch': 0.0,
53  'yaw': 0.0,
54  },
55  {
56  'name': 'robot2',
57  'x_pose': 0.0,
58  'y_pose': -0.5,
59  'z_pose': 0.01,
60  'roll': 0.0,
61  'pitch': 0.0,
62  'yaw': 0.0,
63  },
64  ]
65 
66  # Simulation settings
67  world = LaunchConfiguration('world')
68 
69  # On this example all robots are launched with the same settings
70  map_yaml_file = LaunchConfiguration('map')
71  graph_filepath = LaunchConfiguration('graph')
72 
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')
78 
79  # Declare the launch arguments
80  declare_world_cmd = DeclareLaunchArgument(
81  'world',
82  default_value=os.path.join(sim_dir, 'worlds', 'tb3_sandbox.sdf.xacro'),
83  description='Full path to world file to load',
84  )
85 
86  declare_map_yaml_cmd = DeclareLaunchArgument(
87  'map',
88  default_value=os.path.join(bringup_dir, 'maps', 'tb3_sandbox.yaml'),
89  description='Full path to map file to load',
90  )
91 
92  declare_graph_file_cmd = DeclareLaunchArgument(
93  'graph',
94  default_value=os.path.join(bringup_dir, 'graphs', 'turtlebot3_graph.geojson'),
95  )
96 
97  declare_robot1_params_file_cmd = DeclareLaunchArgument(
98  'robot1_params_file',
99  default_value=os.path.join(
100  bringup_dir, 'params', 'nav2_params.yaml'
101  ),
102  description='Full path to the ROS2 parameters file to use for robot1 launched nodes',
103  )
104 
105  declare_robot2_params_file_cmd = DeclareLaunchArgument(
106  'robot2_params_file',
107  default_value=os.path.join(
108  bringup_dir, 'params', 'nav2_params.yaml'
109  ),
110  description='Full path to the ROS2 parameters file to use for robot2 launched nodes',
111  )
112 
113  declare_autostart_cmd = DeclareLaunchArgument(
114  'autostart',
115  default_value='false',
116  description='Automatically startup the stacks',
117  )
118 
119  declare_rviz_config_file_cmd = DeclareLaunchArgument(
120  'rviz_config',
121  default_value=os.path.join(bringup_dir, 'rviz', 'nav2_default_view.rviz'),
122  description='Full path to the RVIZ config file to use.',
123  )
124 
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',
129  )
130 
131  declare_use_rviz_cmd = DeclareLaunchArgument(
132  'use_rviz', default_value='True', description='Whether to start RVIZ'
133  )
134 
135  # Start Gazebo with plugin providing the robot spawning service
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],
141  output='screen',
142  )
143 
144  remove_temp_sdf_file = RegisterEventHandler(event_handler=OnShutdown(
145  on_shutdown=[
146  OpaqueFunction(function=lambda _: os.remove(world_sdf))
147  ]))
148 
149  # Define commands for launching the navigation instances
150  nav_instances_cmds = []
151  for robot in robots:
152  params_file = LaunchConfiguration(f"{robot['name']}_params_file")
153 
154  group = GroupAction(
155  [
156  IncludeLaunchDescription(
157  PythonLaunchDescriptionSource(
158  os.path.join(launch_dir, 'rviz_launch.py')
159  ),
160  condition=IfCondition(use_rviz),
161  launch_arguments={
162  'namespace': TextSubstitution(text=robot['name']),
163  'rviz_config': rviz_config_file,
164  }.items(),
165  ),
166  IncludeLaunchDescription(
167  PythonLaunchDescriptionSource(
168  os.path.join(bringup_dir, 'launch', 'tb3_simulation_launch.py')
169  ),
170  launch_arguments={
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,
177  'use_rviz': 'False',
178  'use_simulator': 'False',
179  'headless': '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']),
188  }.items(),
189  ),
190  LogInfo(
191  condition=IfCondition(log_settings),
192  msg=['Launching ', robot['name']],
193  ),
194  LogInfo(
195  condition=IfCondition(log_settings),
196  msg=[robot['name'], ' map yaml: ', map_yaml_file],
197  ),
198  LogInfo(
199  condition=IfCondition(log_settings),
200  msg=[robot['name'], ' params yaml: ', params_file],
201  ),
202  LogInfo(
203  condition=IfCondition(log_settings),
204  msg=[robot['name'], ' rviz config file: ', rviz_config_file],
205  ),
206  LogInfo(
207  condition=IfCondition(log_settings),
208  msg=[
209  robot['name'],
210  ' using robot state pub: ',
211  use_robot_state_pub,
212  ],
213  ),
214  LogInfo(
215  condition=IfCondition(log_settings),
216  msg=[robot['name'], ' autostart: ', autostart],
217  ),
218  ]
219  )
220 
221  nav_instances_cmds.append(group)
222 
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()))
228 
229  # Create the launch description and populate
230  ld = LaunchDescription()
231  ld.add_action(set_env_vars_resources)
232  ld.add_action(set_env_vars_resources2)
233 
234  # Declare the launch options
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)
244 
245  # Add the actions to start gazebo, robots and simulations
246  ld.add_action(world_sdf_xacro)
247  ld.add_action(start_gazebo_cmd)
248  ld.add_action(remove_temp_sdf_file)
249 
250  for simulation_instance_cmd in nav_instances_cmds:
251  ld.add_action(simulation_instance_cmd)
252 
253  return ld