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