Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
tb4_simulation_launch.py
1 # Copyright (C) 2024 Open Navigation LLC
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 """This is all-in-one launch script intended for use by nav2 developers."""
16 
17 import os
18 import tempfile
19 
20 from ament_index_python.packages import get_package_share_directory
21 
22 from launch import LaunchDescription
23 from launch.actions import (
24  AppendEnvironmentVariable,
25  DeclareLaunchArgument,
26  ExecuteProcess,
27  IncludeLaunchDescription,
28  OpaqueFunction,
29  RegisterEventHandler,
30 )
31 from launch.conditions import IfCondition
32 from launch.event_handlers import OnShutdown
33 from launch.launch_description_sources import PythonLaunchDescriptionSource
34 from launch.substitutions import Command, LaunchConfiguration, PythonExpression
35 
36 from launch_ros.actions import Node
37 
38 
39 def generate_launch_description():
40  # Get the launch directory
41  bringup_dir = get_package_share_directory('nav2_bringup')
42  launch_dir = os.path.join(bringup_dir, 'launch')
43  # This checks that tb4 exists needed for the URDF / simulation files.
44  # If not using TB4, its safe to remove.
45  sim_dir = get_package_share_directory('nav2_minimal_tb4_sim')
46  desc_dir = get_package_share_directory('nav2_minimal_tb4_description')
47 
48  # Create the launch configuration variables
49  slam = LaunchConfiguration('slam')
50  namespace = LaunchConfiguration('namespace')
51  use_namespace = LaunchConfiguration('use_namespace')
52  map_yaml_file = LaunchConfiguration('map')
53  use_sim_time = LaunchConfiguration('use_sim_time')
54  params_file = LaunchConfiguration('params_file')
55  autostart = LaunchConfiguration('autostart')
56  use_composition = LaunchConfiguration('use_composition')
57  use_respawn = LaunchConfiguration('use_respawn')
58 
59  # Launch configuration variables specific to simulation
60  rviz_config_file = LaunchConfiguration('rviz_config_file')
61  use_simulator = LaunchConfiguration('use_simulator')
62  use_robot_state_pub = LaunchConfiguration('use_robot_state_pub')
63  use_rviz = LaunchConfiguration('use_rviz')
64  headless = LaunchConfiguration('headless')
65  world = LaunchConfiguration('world')
66  pose = {
67  'x': LaunchConfiguration('x_pose', default='-8.00'), # Warehouse: 2.12
68  'y': LaunchConfiguration('y_pose', default='0.00'), # Warehouse: -21.3
69  'z': LaunchConfiguration('z_pose', default='0.01'),
70  'R': LaunchConfiguration('roll', default='0.00'),
71  'P': LaunchConfiguration('pitch', default='0.00'),
72  'Y': LaunchConfiguration('yaw', default='0.00'), # Warehouse: 1.57
73  }
74  robot_name = LaunchConfiguration('robot_name')
75  robot_sdf = LaunchConfiguration('robot_sdf')
76 
77  remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')]
78 
79  # Declare the launch arguments
80  declare_namespace_cmd = DeclareLaunchArgument(
81  'namespace', default_value='', description='Top-level namespace'
82  )
83 
84  declare_use_namespace_cmd = DeclareLaunchArgument(
85  'use_namespace',
86  default_value='false',
87  description='Whether to apply a namespace to the navigation stack',
88  )
89 
90  declare_slam_cmd = DeclareLaunchArgument(
91  'slam', default_value='False', description='Whether run a SLAM'
92  )
93 
94  declare_map_yaml_cmd = DeclareLaunchArgument(
95  'map',
96  default_value=os.path.join(bringup_dir, 'maps', 'depot.yaml'), # Try warehouse.yaml!
97  description='Full path to map file to load',
98  )
99 
100  declare_use_sim_time_cmd = DeclareLaunchArgument(
101  'use_sim_time',
102  default_value='true',
103  description='Use simulation (Gazebo) clock if true',
104  )
105 
106  declare_params_file_cmd = DeclareLaunchArgument(
107  'params_file',
108  default_value=os.path.join(bringup_dir, 'params', 'nav2_params.yaml'),
109  description='Full path to the ROS2 parameters file to use for all launched nodes',
110  )
111 
112  declare_autostart_cmd = DeclareLaunchArgument(
113  'autostart',
114  default_value='true',
115  description='Automatically startup the nav2 stack',
116  )
117 
118  declare_use_composition_cmd = DeclareLaunchArgument(
119  'use_composition',
120  default_value='True',
121  description='Whether to use composed bringup',
122  )
123 
124  declare_use_respawn_cmd = DeclareLaunchArgument(
125  'use_respawn',
126  default_value='False',
127  description='Whether to respawn if a node crashes. Applied when composition is disabled.',
128  )
129 
130  declare_rviz_config_file_cmd = DeclareLaunchArgument(
131  'rviz_config_file',
132  default_value=os.path.join(bringup_dir, 'rviz', 'nav2_default_view.rviz'),
133  description='Full path to the RVIZ config file to use',
134  )
135 
136  declare_use_simulator_cmd = DeclareLaunchArgument(
137  'use_simulator',
138  default_value='True',
139  description='Whether to start the simulator',
140  )
141 
142  declare_use_robot_state_pub_cmd = DeclareLaunchArgument(
143  'use_robot_state_pub',
144  default_value='True',
145  description='Whether to start the robot state publisher',
146  )
147 
148  declare_use_rviz_cmd = DeclareLaunchArgument(
149  'use_rviz', default_value='True', description='Whether to start RVIZ'
150  )
151 
152  declare_simulator_cmd = DeclareLaunchArgument(
153  'headless', default_value='True', description='Whether to execute gzclient)'
154  )
155 
156  declare_world_cmd = DeclareLaunchArgument(
157  'world',
158  default_value=os.path.join(sim_dir, 'worlds', 'depot.sdf'), # Try warehouse.sdf!
159  description='Full path to world model file to load',
160  )
161 
162  declare_robot_name_cmd = DeclareLaunchArgument(
163  'robot_name', default_value='nav2_turtlebot4', description='name of the robot'
164  )
165 
166  declare_robot_sdf_cmd = DeclareLaunchArgument(
167  'robot_sdf',
168  default_value=os.path.join(desc_dir, 'urdf', 'standard', 'turtlebot4.urdf.xacro'),
169  description='Full path to robot sdf file to spawn the robot in gazebo',
170  )
171 
172  start_robot_state_publisher_cmd = Node(
173  condition=IfCondition(use_robot_state_pub),
174  package='robot_state_publisher',
175  executable='robot_state_publisher',
176  name='robot_state_publisher',
177  namespace=namespace,
178  output='screen',
179  parameters=[
180  {'use_sim_time': use_sim_time, 'robot_description': Command(['xacro', ' ', robot_sdf])}
181  ],
182  remappings=remappings,
183  )
184 
185  rviz_cmd = IncludeLaunchDescription(
186  PythonLaunchDescriptionSource(os.path.join(launch_dir, 'rviz_launch.py')),
187  condition=IfCondition(use_rviz),
188  launch_arguments={
189  'namespace': namespace,
190  'use_namespace': use_namespace,
191  'use_sim_time': use_sim_time,
192  'rviz_config': rviz_config_file,
193  }.items(),
194  )
195 
196  bringup_cmd = IncludeLaunchDescription(
197  PythonLaunchDescriptionSource(os.path.join(launch_dir, 'bringup_launch.py')),
198  launch_arguments={
199  'namespace': namespace,
200  'use_namespace': use_namespace,
201  'slam': slam,
202  'map': map_yaml_file,
203  'use_sim_time': use_sim_time,
204  'params_file': params_file,
205  'autostart': autostart,
206  'use_composition': use_composition,
207  'use_respawn': use_respawn,
208  }.items(),
209  )
210 
211  # The SDF file for the world is a xacro file because we wanted to
212  # conditionally load the SceneBroadcaster plugin based on wheter we're
213  # running in headless mode. But currently, the Gazebo command line doesn't
214  # take SDF strings for worlds, so the output of xacro needs to be saved into
215  # a temporary file and passed to Gazebo.
216  world_sdf = tempfile.mktemp(prefix='nav2_', suffix='.sdf')
217  world_sdf_xacro = ExecuteProcess(
218  cmd=['xacro', '-o', world_sdf, ['headless:=', headless], world])
219  gazebo_server = ExecuteProcess(
220  cmd=['gz', 'sim', '-r', '-s', world_sdf],
221  output='screen',
222  condition=IfCondition(use_simulator)
223  )
224 
225  remove_temp_sdf_file = RegisterEventHandler(event_handler=OnShutdown(
226  on_shutdown=[
227  OpaqueFunction(function=lambda _: os.remove(world_sdf))
228  ]))
229 
230  set_env_vars_resources = AppendEnvironmentVariable(
231  'GZ_SIM_RESOURCE_PATH',
232  os.path.join(sim_dir, 'worlds'))
233  gazebo_client = IncludeLaunchDescription(
234  PythonLaunchDescriptionSource(
235  os.path.join(get_package_share_directory('ros_gz_sim'),
236  'launch',
237  'gz_sim.launch.py')
238  ),
239  condition=IfCondition(PythonExpression(
240  [use_simulator, ' and not ', headless])),
241  launch_arguments={'gz_args': ['-v4 -g ']}.items(),
242  )
243 
244  gz_robot = IncludeLaunchDescription(
245  PythonLaunchDescriptionSource(
246  os.path.join(sim_dir, 'launch', 'spawn_tb4.launch.py')),
247  launch_arguments={'namespace': namespace,
248  'use_simulator': use_simulator,
249  'use_sim_time': use_sim_time,
250  'robot_name': robot_name,
251  'robot_sdf': robot_sdf,
252  'x_pose': pose['x'],
253  'y_pose': pose['y'],
254  'z_pose': pose['z'],
255  'roll': pose['R'],
256  'pitch': pose['P'],
257  'yaw': pose['Y']}.items())
258 
259  # Create the launch description and populate
260  ld = LaunchDescription()
261 
262  # Declare the launch options
263  ld.add_action(declare_namespace_cmd)
264  ld.add_action(declare_use_namespace_cmd)
265  ld.add_action(declare_slam_cmd)
266  ld.add_action(declare_map_yaml_cmd)
267  ld.add_action(declare_use_sim_time_cmd)
268  ld.add_action(declare_params_file_cmd)
269  ld.add_action(declare_autostart_cmd)
270  ld.add_action(declare_use_composition_cmd)
271 
272  ld.add_action(declare_rviz_config_file_cmd)
273  ld.add_action(declare_use_simulator_cmd)
274  ld.add_action(declare_use_robot_state_pub_cmd)
275  ld.add_action(declare_use_rviz_cmd)
276  ld.add_action(declare_simulator_cmd)
277  ld.add_action(declare_world_cmd)
278  ld.add_action(declare_robot_name_cmd)
279  ld.add_action(declare_robot_sdf_cmd)
280  ld.add_action(declare_use_respawn_cmd)
281 
282  ld.add_action(set_env_vars_resources)
283  ld.add_action(world_sdf_xacro)
284  ld.add_action(remove_temp_sdf_file)
285  ld.add_action(gz_robot)
286  ld.add_action(gazebo_server)
287  ld.add_action(gazebo_client)
288 
289  # Add the actions to launch all of the navigation nodes
290  ld.add_action(start_robot_state_publisher_cmd)
291  ld.add_action(rviz_cmd)
292  ld.add_action(bringup_cmd)
293 
294  return ld