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