Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
tb4_loopback_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 
19 from ament_index_python.packages import get_package_share_directory
20 from launch import LaunchDescription
21 from launch.actions import DeclareLaunchArgument, GroupAction, IncludeLaunchDescription
22 from launch.conditions import IfCondition
23 from launch.launch_description_sources import PythonLaunchDescriptionSource
24 from launch.substitutions import Command, LaunchConfiguration, PythonExpression
25 from launch_ros.actions import LoadComposableNodes, Node, SetParameter
26 from launch_ros.descriptions import ComposableNode, ParameterFile
27 from nav2_common.launch import LaunchConfigAsBool, RewrittenYaml
28 
29 
30 def generate_launch_description() -> LaunchDescription:
31  # Get the launch directory
32  bringup_dir = get_package_share_directory('nav2_bringup')
33  loopback_sim_dir = get_package_share_directory('nav2_loopback_sim')
34  launch_dir = os.path.join(bringup_dir, 'launch')
35  desc_dir = get_package_share_directory('nav2_minimal_tb4_description')
36 
37  # Create the launch configuration variables
38  namespace = LaunchConfiguration('namespace')
39  map_yaml_file = LaunchConfiguration('map')
40  graph_filepath = LaunchConfiguration('graph')
41  params_file = LaunchConfiguration('params_file')
42  autostart = LaunchConfigAsBool('autostart')
43  use_composition = LaunchConfigAsBool('use_composition')
44  use_intra_process_comms = LaunchConfigAsBool('use_intra_process_comms')
45  use_respawn = LaunchConfigAsBool('use_respawn')
46 
47  # Launch configuration variables specific to simulation
48  rviz_config_file = LaunchConfiguration('rviz_config_file')
49  use_robot_state_pub = LaunchConfigAsBool('use_robot_state_pub')
50  use_rviz = LaunchConfigAsBool('use_rviz')
51  container_name_full = (namespace, '/', 'nav2_container')
52 
53  remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')]
54 
55  # Declare the launch arguments
56  declare_namespace_cmd = DeclareLaunchArgument(
57  'namespace', default_value='', description='Top-level namespace'
58  )
59 
60  declare_map_yaml_cmd = DeclareLaunchArgument(
61  'map',
62  default_value=os.path.join(bringup_dir, 'maps', 'depot.yaml'), # Try warehouse.yaml!
63  description='Full path to map file to load',
64  )
65 
66  declare_graph_file_cmd = DeclareLaunchArgument(
67  'graph',
68  default_value=os.path.join(bringup_dir, 'graphs', 'depot_graph.geojson'),
69  )
70 
71  declare_params_file_cmd = DeclareLaunchArgument(
72  'params_file',
73  default_value=os.path.join(bringup_dir, 'params', 'nav2_params.yaml'),
74  description='Full path to the ROS2 parameters file to use for all launched nodes',
75  )
76 
77  declare_autostart_cmd = DeclareLaunchArgument(
78  'autostart',
79  default_value='true',
80  description='Automatically startup the nav2 stack',
81  )
82 
83  declare_use_composition_cmd = DeclareLaunchArgument(
84  'use_composition',
85  default_value='True',
86  description='Whether to use composed bringup',
87  )
88 
89  declare_use_intra_process_comms_cmd = DeclareLaunchArgument(
90  'use_intra_process_comms',
91  default_value='False',
92  description='Whether to use intra process communication',
93  )
94 
95  declare_use_respawn_cmd = DeclareLaunchArgument(
96  'use_respawn',
97  default_value='False',
98  description='Whether to respawn if a node crashes. Applied when composition is disabled.',
99  )
100 
101  declare_rviz_config_file_cmd = DeclareLaunchArgument(
102  'rviz_config_file',
103  default_value=os.path.join(bringup_dir, 'rviz', 'nav2_default_view.rviz'),
104  description='Full path to the RVIZ config file to use',
105  )
106 
107  declare_use_robot_state_pub_cmd = DeclareLaunchArgument(
108  'use_robot_state_pub',
109  default_value='True',
110  description='Whether to start the robot state publisher',
111  )
112 
113  declare_use_rviz_cmd = DeclareLaunchArgument(
114  'use_rviz', default_value='True', description='Whether to start RVIZ'
115  )
116 
117  sdf = os.path.join(desc_dir, 'urdf', 'standard', 'turtlebot4.urdf.xacro')
118  start_robot_state_publisher_cmd = Node(
119  condition=IfCondition(use_robot_state_pub),
120  package='robot_state_publisher',
121  executable='robot_state_publisher',
122  name='robot_state_publisher',
123  namespace=namespace,
124  output='screen',
125  parameters=[
126  {'use_sim_time': True, 'robot_description': Command(['xacro', ' ', sdf])}
127  ],
128  remappings=remappings,
129  )
130 
131  rviz_cmd = IncludeLaunchDescription(
132  PythonLaunchDescriptionSource(os.path.join(launch_dir, 'rviz_launch.py')),
133  condition=IfCondition(use_rviz),
134  launch_arguments=[
135  ('namespace', namespace),
136  ('use_sim_time', 'True'),
137  ('rviz_config', rviz_config_file),
138  ],
139  )
140 
141  bringup_cmd = IncludeLaunchDescription(
142  PythonLaunchDescriptionSource(os.path.join(launch_dir, 'bringup_launch.py')),
143  launch_arguments={
144  'namespace': namespace,
145  'map': map_yaml_file,
146  'graph': graph_filepath,
147  'use_sim_time': 'True',
148  'params_file': params_file,
149  'autostart': autostart,
150  'use_composition': use_composition,
151  'use_intra_process_comms': use_intra_process_comms,
152  'use_respawn': use_respawn,
153  'use_keepout_zones': 'False', # Keepout zones not used in loopback simulation
154  'use_speed_zones': 'False', # Speed zones not used in loopback simulation
155  'use_localization': 'False', # Don't use SLAM, AMCL
156  'container_name': 'nav2_container',
157  }.items(),
158  )
159 
160  loopback_sim_cmd = IncludeLaunchDescription(
161  PythonLaunchDescriptionSource(
162  os.path.join(loopback_sim_dir, 'loopback_simulation.launch.py')),
163  launch_arguments=[
164  ('params_file', params_file),
165  ('scan_frame_id', 'rplidar_link'),
166  ],
167  )
168 
169  static_publisher_cmd = Node(
170  package='tf2_ros',
171  executable='static_transform_publisher',
172  arguments=[
173  '--x', '0.0', '--y', '0.0', '--z', '0.0',
174  '--roll', '0', '--pitch', '0', '--yaw', '0',
175  '--frame-id', 'base_footprint', '--child-frame-id', 'base_link']
176  )
177 
178  configured_params = ParameterFile(
179  RewrittenYaml(
180  source_file=params_file,
181  root_key=namespace,
182  param_rewrites={},
183  convert_types=True,
184  ),
185  allow_substs=True,
186  )
187 
188  start_map_server = GroupAction(
189  condition=IfCondition(PythonExpression(['not ', use_composition])),
190  actions=[
191  SetParameter('use_sim_time', True),
192  Node(
193  package='nav2_map_server',
194  executable='map_server',
195  name='map_server',
196  output='screen',
197  respawn=use_respawn,
198  respawn_delay=2.0,
199  parameters=[configured_params, {'yaml_filename': map_yaml_file}],
200  remappings=remappings,
201  ),
202  Node(
203  package='nav2_lifecycle_manager',
204  executable='lifecycle_manager',
205  name='lifecycle_manager_map_server',
206  output='screen',
207  parameters=[
208  configured_params,
209  {'autostart': autostart}, {'node_names': ['map_server']}],
210  ),
211  ]
212  )
213 
214  start_composable_map_server = GroupAction(
215  condition=IfCondition(use_composition),
216  actions=[
217  SetParameter('use_sim_time', True),
218  LoadComposableNodes(
219  target_container=container_name_full,
220  composable_node_descriptions=[
221  ComposableNode(
222  package='nav2_map_server',
223  plugin='nav2_map_server::MapServer',
224  name='map_server',
225  parameters=[configured_params, {'yaml_filename': map_yaml_file}],
226  remappings=remappings,
227  ),
228  ComposableNode(
229  package='nav2_lifecycle_manager',
230  plugin='nav2_lifecycle_manager::LifecycleManager',
231  name='lifecycle_manager_map_server',
232  parameters=[
233  configured_params,
234  {'autostart': autostart}, {'node_names': ['map_server']}
235  ],
236  extra_arguments=[{'use_intra_process_comms': use_intra_process_comms}]
237  ),
238  ],
239  ),
240  ],
241  )
242 
243  # Create the launch description and populate
244  ld = LaunchDescription()
245 
246  # Declare the launch options
247  ld.add_action(declare_namespace_cmd)
248  ld.add_action(declare_map_yaml_cmd)
249  ld.add_action(declare_graph_file_cmd)
250  ld.add_action(declare_params_file_cmd)
251  ld.add_action(declare_autostart_cmd)
252  ld.add_action(declare_use_composition_cmd)
253  ld.add_action(declare_use_intra_process_comms_cmd)
254 
255  ld.add_action(declare_rviz_config_file_cmd)
256  ld.add_action(declare_use_robot_state_pub_cmd)
257  ld.add_action(declare_use_rviz_cmd)
258  ld.add_action(declare_use_respawn_cmd)
259 
260  # Add the actions to launch all of the navigation nodes
261  ld.add_action(start_robot_state_publisher_cmd)
262  ld.add_action(static_publisher_cmd)
263  ld.add_action(start_map_server)
264  ld.add_action(start_composable_map_server)
265  ld.add_action(loopback_sim_cmd)
266  ld.add_action(rviz_cmd)
267  ld.add_action(bringup_cmd)
268 
269  return ld