Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WiP] Package whitelist resp. blacklist #294

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ find_package(rclcpp REQUIRED)
find_package(rmw_implementation_cmake REQUIRED)
find_package(std_msgs REQUIRED)

# include / ignore lists
include(cmake/find_ignore_include_lists.cmake)

# find ROS 1 packages
set(cmake_extras_files cmake/find_ros1_package.cmake cmake/find_ros1_interface_packages.cmake)
include(cmake/find_ros1_package.cmake)
Expand Down Expand Up @@ -44,6 +47,7 @@ find_ros1_package(std_msgs REQUIRED)
# find ROS 1 packages with messages / services
include(cmake/find_ros1_interface_packages.cmake)
find_ros1_interface_packages(ros1_message_packages)
filter_packages("ros1_message_packages")

set(prefixed_ros1_message_packages "")
foreach(ros1_message_package ${ros1_message_packages})
Expand All @@ -52,6 +56,8 @@ foreach(ros1_message_package ${ros1_message_packages})
if(NOT "${ros1_message_package}" STREQUAL "nodelet")
find_ros1_package(${ros1_message_package} REQUIRED)
list(APPEND prefixed_ros1_message_packages "ros1_${ros1_message_package}")
else()
message(STATUS "Ignoring module '${ros1_message_package}'")
endif()
endforeach()

Expand Down Expand Up @@ -90,6 +96,8 @@ list(APPEND generated_files "${generated_path}/get_mappings.cpp")

# generate per interface compilation units to keep the memory usage low
ament_index_get_resources(ros2_interface_packages "rosidl_interfaces")
filter_packages("ros2_interface_packages")

# actionlib_msgs is deprecated, but we will quiet the warning until the bridge has support for
# ROS actions: https://github.com/ros2/design/issues/195
set(actionlib_msgs_DEPRECATED_QUIET TRUE)
Expand All @@ -110,6 +118,8 @@ foreach(package_name ${ros2_interface_packages})
get_filename_component(interface_name "${interface_name}" NAME_WE)
list(APPEND generated_files "${generated_path}/${package_name}__${interface_name}__factories.cpp")
endforeach()
else()
message(STATUS " ignoring.")
endif()
endforeach()

Expand All @@ -125,7 +135,9 @@ set(target_dependencies
add_custom_command(
OUTPUT ${generated_files}
COMMAND ${PYTHON_EXECUTABLE} bin/ros1_bridge_generate_factories
--output-path "${generated_path}" --template-dir resource
--output-path '${generated_path}' --template-dir resource
--pkg-includes '${BRIDGE_INCLUDE_PKGS}'
--pkg-ignores '${BRIDGE_IGNORE_PKGS}'
DEPENDS ${target_dependencies}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating factories for interface types")
Expand Down
10 changes: 10 additions & 0 deletions bin/ros1_bridge_generate_factories
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,22 @@ def main(argv=sys.argv[1:]):
'--template-dir',
required=True,
help='The location of the template files')
parser.add_argument(
'--pkg-includes',
required=False,
help='ROS packages to include in the bridge')
parser.add_argument(
'--pkg-ignores',
required=False,
help='ROS packages to ignore in the bridge')
args = parser.parse_args(argv)

try:
return generate_cpp(
args.output_path,
args.template_dir,
args.pkg_includes,
args.pkg_ignores,
)
except RuntimeError as e:
print(str(e), file=sys.stderr)
Expand Down
68 changes: 68 additions & 0 deletions cmake/find_ignore_include_lists.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Module/Package resp. message ignores and includes
#
# Finds lists of ROS modules/packages resp. messages that shall
# be included resp. ignored by the ROS bridge according to the
# following rules:
# - Include lists over ignore lists. I.e. if an include list is
# present, the ignore list will be ... well, ignored.)

set(USE_PKG_IGNORE OFF)
set(USE_PKG_INCLUDE OFF)
set(USE_MSG_IGNORE OFF)
set(USE_MSG_INCLUDE OFF)

set(BRIDGE_IGNORE_PKGS "")
set(BRIDGE_IGNORE_MSGS "")
set(BRIDGE_INCLUDE_PKGS "")
set(BRIDGE_INCLUDE_MSGS "")

# File with packages to ignore/include in ROS 1 Bridge
set(BRIDGE_PACKAGE_IGNORE "${CMAKE_SOURCE_DIR}/../../../BridgePackageIgnore.List")
set(BRIDGE_PACKAGE_INCLUDE "${CMAKE_SOURCE_DIR}/../../../BridgePackageInclude.List")

# File with messages to ignore/include in ROS 1 Bridge
set(BRIDGE_MSG_IGNORE "${CMAKE_SOURCE_DIR}/../../../BridgePackageIgnore.List")
set(BRIDGE_MSG_INCLUDE "${CMAKE_SOURCE_DIR}/../../../BridgePackageInclude.List")

if(EXISTS "${BRIDGE_PACKAGE_INCLUDE}")
set(USE_PKG_INCLUDE ON)
else() # EXISTS "${BRIDGE_PACKAGE_INCLUDE}"
if(EXISTS "${BRIDGE_PACKAGE_IGNORE}")
set(USE_PKG_IGNORE ON)
endif() # EXISTS "${BRIDGE_PACKAGE_IGNORE}"
endif() # EXISTS "${BRIDGE_PACKAGE_INCLUDE}"

if(${USE_PKG_INCLUDE})
FILE(READ "${BRIDGE_PACKAGE_INCLUDE}" BRIDGE_INCLUDE_PKGS)
STRING(REGEX REPLACE ";" "\\\\;" BRIDGE_INCLUDE_PKGS "${BRIDGE_INCLUDE_PKGS}")
STRING(REGEX REPLACE "\n" ";" BRIDGE_INCLUDE_PKGS "${BRIDGE_INCLUDE_PKGS}")
list(REMOVE_DUPLICATES BRIDGE_INCLUDE_PKGS)
message(STATUS "Found package include list, including: ${BRIDGE_INCLUDE_PKGS}")
endif() # USE_PKG_INCLUDE

if(${USE_PKG_IGNORE})
FILE(READ "${BRIDGE_PACKAGE_IGNORE}" BRIDGE_IGNORE_PKGS)
STRING(REGEX REPLACE ";" "\\\\;" BRIDGE_IGNORE_PKGS "${BRIDGE_IGNORE_PKGS}")
STRING(REGEX REPLACE "\n" ";" BRIDGE_IGNORE_PKGS "${BRIDGE_IGNORE_PKGS}")
list(REMOVE_DUPLICATES BRIDGE_IGNORE_PKGS)
message(STATUS "Found package ignore list, ignoring: ${BRIDGE_IGNORE_PKGS}")
endif() # USE_PKG_IGNORE

function(filter_packages pkg_list)
set(ros2_packages ${${pkg_list}})
if(BRIDGE_INCLUDE_PKGS)
foreach(pkg ${ros2_packages})
if(NOT ${pkg} IN_LIST BRIDGE_INCLUDE_PKGS)
list(REMOVE_ITEM ros2_packages ${pkg})
endif(NOT ${pkg} IN_LIST BRIDGE_INCLUDE_PKGS)
endforeach()
elseif(BRIDGE_IGNORE_PKGS)
foreach(pkg ${ros2_packages})
if(${pkg} IN_LIST BRIDGE_IGNORE_PKGS)
list(REMOVE_ITEM ros2_packages ${pkg})
endif(${pkg} IN_LIST BRIDGE_IGNORE_PKGS)
endforeach()
endif(BRIDGE_INCLUDE_PKGS)

set(${pkg_list} "${ros2_packages}" PARENT_SCOPE)
endfunction(filter_packages ros2_packages)
37 changes: 25 additions & 12 deletions ros1_bridge/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@
import rosmsg # noqa


def generate_cpp(output_path, template_dir):
def generate_cpp(output_path, template_dir, pkg_includes, pkg_ignores):
rospack = rospkg.RosPack()
data = generate_messages(rospack)
data = generate_messages(rospack, pkg_includes, pkg_ignores)
message_string_pairs = {
(
'%s/%s' % (m.ros1_msg.package_name, m.ros1_msg.message_name),
'%s/%s' % (m.ros2_msg.package_name, m.ros2_msg.message_name))
for m in data['mappings']}
data.update(
generate_services(rospack, message_string_pairs=message_string_pairs))
generate_services(rospack, message_string_pairs=message_string_pairs, includes=pkg_includes, ignores=pkg_ignores))

template_file = os.path.join(template_dir, 'get_mappings.cpp.em')
output_file = os.path.join(output_path, 'get_mappings.cpp')
Expand Down Expand Up @@ -158,11 +158,11 @@ def generate_cpp(output_path, template_dir):
expand_template(template_file, data_idl_cpp, output_file)


def generate_messages(rospack=None):
def generate_messages(rospack=None, includes=[], ignores=[]):
ros1_msgs = get_ros1_messages(rospack=rospack)
ros2_package_names, ros2_msgs, mapping_rules = get_ros2_messages()
ros2_package_names, ros2_msgs, mapping_rules = get_ros2_messages(includes, ignores)

package_pairs = determine_package_pairs(ros1_msgs, ros2_msgs, mapping_rules)
package_pairs = determine_package_pairs(ros1_msgs, ros2_msgs, mapping_rules, includes, ignores)
message_pairs = determine_message_pairs(ros1_msgs, ros2_msgs, package_pairs, mapping_rules)

mappings = []
Expand Down Expand Up @@ -225,9 +225,9 @@ def generate_messages(rospack=None):
}


def generate_services(rospack=None, message_string_pairs=None):
def generate_services(rospack=None, message_string_pairs=None, includes=[], ignores=[]):
ros1_srvs = get_ros1_services(rospack=rospack)
ros2_pkgs, ros2_srvs, mapping_rules = get_ros2_services()
ros2_pkgs, ros2_srvs, mapping_rules = get_ros2_services(includes, ignores)
services = determine_common_services(
ros1_srvs, ros2_srvs, mapping_rules,
message_string_pairs=message_string_pairs)
Expand All @@ -249,14 +249,17 @@ def get_ros1_messages(rospack=None):
return msgs


def get_ros2_messages():
def get_ros2_messages(includes=[], ignores=[]):
pkgs = []
msgs = []
rules = []
# get messages from packages
resource_type = 'rosidl_interfaces'
resources = ament_index_python.get_resources(resource_type)
for package_name, prefix_path in resources.items():
if (includes and not package_name in includes) or (ignores and package_name in ignores):
# Ignore package
continue
pkgs.append(package_name)
resource, _ = ament_index_python.get_resource(resource_type, package_name)
interfaces = resource.splitlines()
Expand Down Expand Up @@ -303,13 +306,16 @@ def get_ros1_services(rospack=None):
return srvs


def get_ros2_services():
def get_ros2_services(includes=[], ignores=[]):
pkgs = []
srvs = []
rules = []
resource_type = 'rosidl_interfaces'
resources = ament_index_python.get_resources(resource_type)
for package_name, prefix_path in resources.items():
if (includes and not package_name in includes) or (ignores and package_name in ignores):
# Ignore package
continue
pkgs.append(package_name)
resource, _ = ament_index_python.get_resource(resource_type, package_name)
interfaces = resource.splitlines()
Expand Down Expand Up @@ -473,19 +479,26 @@ def __str__(self):
return 'ServiceMappingRule(%s <-> %s)' % (self.ros1_package_name, self.ros2_package_name)


def determine_package_pairs(ros1_msgs, ros2_msgs, mapping_rules):
def determine_package_pairs(ros1_msgs, ros2_msgs, mapping_rules, includes, ignores):
pairs = []
# determine package names considered equal between ROS 1 and ROS 2
ros1_suffix = '_msgs'
ros2_suffixes = ['_msgs', '_interfaces']
ros1_package_names = {m.package_name for m in ros1_msgs}
ros2_package_names = {m.package_name for m in ros2_msgs}
for ros1_package_name in ros1_package_names:
if not ros1_package_name.endswith(ros1_suffix):
if (not ros1_package_name.endswith(ros1_suffix)):
continue
if (includes and not ros1_package_name in includes) or (ignores and ros1_package_name in ignores):
# Ignore package
continue
ros1_package_basename = ros1_package_name[:-len(ros1_suffix)]

for ros2_package_name in ros2_package_names:
if (includes and not ros2_package_name in includes) or (ignores and ros2_package_name in ignores):
# Ignore package
continue

for ros2_suffix in ros2_suffixes:
if ros2_package_name.endswith(ros2_suffix):
break
Expand Down