Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
localization_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 import os
16 
17 from ament_index_python.packages import get_package_share_directory
18 from launch import LaunchDescription
19 from launch.actions import DeclareLaunchArgument, GroupAction, SetEnvironmentVariable
20 from launch.conditions import IfCondition
21 from launch.substitutions import (EqualsSubstitution, LaunchConfiguration, NotEqualsSubstitution,
22  PythonExpression)
23 from launch_ros.actions import LoadComposableNodes, Node, PushROSNamespace, SetParameter
24 from launch_ros.descriptions import ComposableNode, ParameterFile
25 from nav2_common.launch import LaunchConfigAsBool, RewrittenYaml
26 
27 
28 def generate_launch_description() -> LaunchDescription:
29  # Get the launch directory
30  bringup_dir = get_package_share_directory('nav2_bringup')
31 
32  namespace = LaunchConfiguration('namespace')
33  map_yaml_file = LaunchConfiguration('map')
34  use_sim_time = LaunchConfigAsBool('use_sim_time')
35  autostart = LaunchConfigAsBool('autostart')
36  params_file = LaunchConfiguration('params_file')
37  use_composition = LaunchConfigAsBool('use_composition')
38  use_intra_process_comms = LaunchConfigAsBool('use_intra_process_comms')
39  container_name = LaunchConfiguration('container_name')
40  container_name_full = (namespace, '/', container_name)
41  use_respawn = LaunchConfigAsBool('use_respawn')
42  log_level = LaunchConfiguration('log_level')
43 
44  lifecycle_nodes = ['map_server', 'amcl']
45 
46  # Map fully qualified names to relative ones so the node's namespace can be prepended.
47  remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')]
48 
49  configured_params = ParameterFile(
50  RewrittenYaml(
51  source_file=params_file,
52  root_key=namespace,
53  param_rewrites={},
54  convert_types=True,
55  ),
56  allow_substs=True,
57  )
58 
59  stdout_linebuf_envvar = SetEnvironmentVariable(
60  'RCUTILS_LOGGING_BUFFERED_STREAM', '1'
61  )
62 
63  declare_namespace_cmd = DeclareLaunchArgument(
64  'namespace', default_value='', description='Top-level namespace'
65  )
66 
67  declare_map_yaml_cmd = DeclareLaunchArgument(
68  'map', default_value='', description='Full path to map yaml file to load'
69  )
70 
71  declare_use_sim_time_cmd = DeclareLaunchArgument(
72  'use_sim_time',
73  default_value='false',
74  description='Use simulation (Gazebo) clock if true',
75  )
76 
77  declare_params_file_cmd = DeclareLaunchArgument(
78  'params_file',
79  default_value=os.path.join(bringup_dir, 'params', 'nav2_params.yaml'),
80  description='Full path to the ROS2 parameters file to use for all launched nodes',
81  )
82 
83  declare_autostart_cmd = DeclareLaunchArgument(
84  'autostart',
85  default_value='true',
86  description='Automatically startup the nav2 stack',
87  )
88 
89  declare_use_composition_cmd = DeclareLaunchArgument(
90  'use_composition',
91  default_value='False',
92  description='Use composed bringup if True',
93  )
94 
95  declare_use_intra_process_comms_cmd = DeclareLaunchArgument(
96  'use_intra_process_comms',
97  default_value='False',
98  description='Use intra process communications if True',
99  )
100 
101  declare_container_name_cmd = DeclareLaunchArgument(
102  'container_name',
103  default_value='nav2_container',
104  description='the name of container that nodes will load in if use composition',
105  )
106 
107  declare_use_respawn_cmd = DeclareLaunchArgument(
108  'use_respawn',
109  default_value='False',
110  description='Whether to respawn if a node crashes. Applied when composition is disabled.',
111  )
112 
113  declare_log_level_cmd = DeclareLaunchArgument(
114  'log_level', default_value='info', description='log level'
115  )
116 
117  load_nodes = GroupAction(
118  condition=IfCondition(PythonExpression(['not ', use_composition])),
119  actions=[
120  PushROSNamespace(namespace),
121  SetParameter('use_sim_time', use_sim_time),
122  Node(
123  condition=IfCondition(
124  EqualsSubstitution(LaunchConfiguration('map'), '')
125  ),
126  package='nav2_map_server',
127  executable='map_server',
128  name='map_server',
129  output='screen',
130  respawn=use_respawn,
131  respawn_delay=2.0,
132  parameters=[configured_params],
133  arguments=['--ros-args', '--log-level', log_level],
134  remappings=remappings,
135  ),
136  Node(
137  condition=IfCondition(
138  NotEqualsSubstitution(LaunchConfiguration('map'), '')
139  ),
140  package='nav2_map_server',
141  executable='map_server',
142  name='map_server',
143  output='screen',
144  respawn=use_respawn,
145  respawn_delay=2.0,
146  parameters=[configured_params, {'yaml_filename': map_yaml_file}],
147  arguments=['--ros-args', '--log-level', log_level],
148  remappings=remappings,
149  ),
150  Node(
151  package='nav2_amcl',
152  executable='amcl',
153  name='amcl',
154  output='screen',
155  respawn=use_respawn,
156  respawn_delay=2.0,
157  parameters=[configured_params],
158  arguments=['--ros-args', '--log-level', log_level],
159  remappings=remappings,
160  ),
161  Node(
162  package='nav2_lifecycle_manager',
163  executable='lifecycle_manager',
164  name='lifecycle_manager_localization',
165  output='screen',
166  arguments=['--ros-args', '--log-level', log_level],
167  parameters=[
168  configured_params,
169  {'autostart': autostart}, {'node_names': lifecycle_nodes}
170  ],
171  ),
172  ],
173  )
174  # LoadComposableNode for map server twice depending if we should use the
175  # value of map from a CLI or launch default or user defined value in the
176  # yaml configuration file. They are separated since the conditions
177  # currently only work on the LoadComposableNodes commands and not on the
178  # ComposableNode node function itself
179  load_composable_nodes = GroupAction(
180  condition=IfCondition(use_composition),
181  actions=[
182  PushROSNamespace(namespace),
183  SetParameter('use_sim_time', use_sim_time),
184  LoadComposableNodes(
185  target_container=container_name_full,
186  condition=IfCondition(
187  EqualsSubstitution(LaunchConfiguration('map'), '')
188  ),
189  composable_node_descriptions=[
190  ComposableNode(
191  package='nav2_map_server',
192  plugin='nav2_map_server::MapServer',
193  name='map_server',
194  parameters=[configured_params],
195  remappings=remappings,
196  extra_arguments=[{'use_intra_process_comms': use_intra_process_comms}],
197  ),
198  ],
199  ),
200  LoadComposableNodes(
201  target_container=container_name_full,
202  condition=IfCondition(
203  NotEqualsSubstitution(LaunchConfiguration('map'), '')
204  ),
205  composable_node_descriptions=[
206  ComposableNode(
207  package='nav2_map_server',
208  plugin='nav2_map_server::MapServer',
209  name='map_server',
210  parameters=[
211  configured_params,
212  {'yaml_filename': map_yaml_file},
213  ],
214  remappings=remappings,
215  extra_arguments=[{'use_intra_process_comms': use_intra_process_comms}],
216  ),
217  ],
218  ),
219  LoadComposableNodes(
220  target_container=container_name_full,
221  composable_node_descriptions=[
222  ComposableNode(
223  package='nav2_amcl',
224  plugin='nav2_amcl::AmclNode',
225  name='amcl',
226  parameters=[configured_params],
227  remappings=remappings,
228  extra_arguments=[{'use_intra_process_comms': use_intra_process_comms}],
229  ),
230  ComposableNode(
231  package='nav2_lifecycle_manager',
232  plugin='nav2_lifecycle_manager::LifecycleManager',
233  name='lifecycle_manager_localization',
234  parameters=[
235  configured_params,
236  {'autostart': autostart, 'node_names': lifecycle_nodes}
237  ],
238  extra_arguments=[{'use_intra_process_comms': use_intra_process_comms}],
239  ),
240  ],
241  ),
242  ],
243  )
244 
245  # Create the launch description and populate
246  ld = LaunchDescription()
247 
248  # Set environment variables
249  ld.add_action(stdout_linebuf_envvar)
250 
251  # Declare the launch options
252  ld.add_action(declare_namespace_cmd)
253  ld.add_action(declare_map_yaml_cmd)
254  ld.add_action(declare_use_sim_time_cmd)
255  ld.add_action(declare_params_file_cmd)
256  ld.add_action(declare_autostart_cmd)
257  ld.add_action(declare_use_composition_cmd)
258  ld.add_action(declare_use_intra_process_comms_cmd)
259  ld.add_action(declare_container_name_cmd)
260  ld.add_action(declare_use_respawn_cmd)
261  ld.add_action(declare_log_level_cmd)
262 
263  # Add the actions to launch all of the localiztion nodes
264  ld.add_action(load_nodes)
265  ld.add_action(load_composable_nodes)
266 
267  return ld