Skip to content

Commit 5f34bc3

Browse files
Added keepout filter for depot and warehouse maps (#5125)
* Added keepout region to warehouse map. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Support keepout_map as a launch argument. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Added a dictionary to switch between tb4 maps. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Added dedicated launch file for map modifiers. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Added support for depot keepout filter. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Updated keepout masks for depot and warehouse. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Renamed keepout filter launch arguments to keepout zones. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Renamed keepout map launch argument to keepout mask Signed-off-by: Leander Stephen D'Souza <[email protected]> * Renamed map_modifier.launch.py to keepout_zone_launch.py. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Preserve duplication of nodes for keepout test. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Removed padding from keepout zones from depot map. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Added keepout zone at the centre of the warehouse map. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Added utility script to handle namespaces for keepout_filter. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Used utility function to simplify namespace calls. Signed-off-by: Leander Stephen D'Souza <[email protected]> * Moved joinWithParentNamespace to the Layer object. Signed-off-by: Leander Stephen D'Souza <[email protected]> --------- Signed-off-by: Leander Stephen D'Souza <[email protected]>
1 parent 6a51f1a commit 5f34bc3

File tree

14 files changed

+364
-44
lines changed

14 files changed

+364
-44
lines changed

nav2_bringup/launch/bringup_launch.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def generate_launch_description() -> LaunchDescription:
3535
namespace = LaunchConfiguration('namespace')
3636
slam = LaunchConfiguration('slam')
3737
map_yaml_file = LaunchConfiguration('map')
38+
keepout_mask_yaml_file = LaunchConfiguration('keepout_mask')
3839
graph_filepath = LaunchConfiguration('graph')
3940
use_sim_time = LaunchConfiguration('use_sim_time')
4041
params_file = LaunchConfiguration('params_file')
@@ -43,6 +44,7 @@ def generate_launch_description() -> LaunchDescription:
4344
use_respawn = LaunchConfiguration('use_respawn')
4445
log_level = LaunchConfiguration('log_level')
4546
use_localization = LaunchConfiguration('use_localization')
47+
use_keepout_zones = LaunchConfiguration('use_keepout_zones')
4648

4749
# Map fully qualified names to relative ones so the node's namespace can be prepended.
4850
remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')]
@@ -73,6 +75,11 @@ def generate_launch_description() -> LaunchDescription:
7375
'map', default_value='', description='Full path to map yaml file to load'
7476
)
7577

78+
declare_keepout_mask_yaml_cmd = DeclareLaunchArgument(
79+
'keepout_mask', default_value='',
80+
description='Full path to keepout mask yaml file to load'
81+
)
82+
7683
declare_graph_file_cmd = DeclareLaunchArgument(
7784
'graph',
7885
default_value='', description='Path to the graph file to load'
@@ -83,6 +90,11 @@ def generate_launch_description() -> LaunchDescription:
8390
description='Whether to enable localization or not'
8491
)
8592

93+
declare_use_keepout_zones_cmd = DeclareLaunchArgument(
94+
'use_keepout_zones', default_value='True',
95+
description='Whether to enable keepout zones or not'
96+
)
97+
8698
declare_use_sim_time_cmd = DeclareLaunchArgument(
8799
'use_sim_time',
88100
default_value='false',
@@ -160,6 +172,23 @@ def generate_launch_description() -> LaunchDescription:
160172
'container_name': 'nav2_container',
161173
}.items(),
162174
),
175+
176+
IncludeLaunchDescription(
177+
PythonLaunchDescriptionSource(
178+
os.path.join(launch_dir, 'keepout_zone_launch.py')
179+
),
180+
condition=IfCondition(PythonExpression([use_keepout_zones])),
181+
launch_arguments={
182+
'namespace': namespace,
183+
'keepout_mask': keepout_mask_yaml_file,
184+
'use_sim_time': use_sim_time,
185+
'params_file': params_file,
186+
'use_composition': use_composition,
187+
'use_respawn': use_respawn,
188+
'container_name': 'nav2_container',
189+
}.items(),
190+
),
191+
163192
IncludeLaunchDescription(
164193
PythonLaunchDescriptionSource(
165194
os.path.join(launch_dir, 'navigation_launch.py')
@@ -188,6 +217,7 @@ def generate_launch_description() -> LaunchDescription:
188217
ld.add_action(declare_namespace_cmd)
189218
ld.add_action(declare_slam_cmd)
190219
ld.add_action(declare_map_yaml_cmd)
220+
ld.add_action(declare_keepout_mask_yaml_cmd)
191221
ld.add_action(declare_graph_file_cmd)
192222
ld.add_action(declare_use_sim_time_cmd)
193223
ld.add_action(declare_params_file_cmd)
@@ -196,6 +226,7 @@ def generate_launch_description() -> LaunchDescription:
196226
ld.add_action(declare_use_respawn_cmd)
197227
ld.add_action(declare_log_level_cmd)
198228
ld.add_action(declare_use_localization_cmd)
229+
ld.add_action(declare_use_keepout_zones_cmd)
199230

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

0 commit comments

Comments
 (0)