Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
35 changes: 35 additions & 0 deletions rosidl_actions/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.5)

project(rosidl_actions)

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)

ament_export_dependencies(ament_cmake)
ament_python_install_package(${PROJECT_NAME})

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
endif()

ament_package(
CONFIG_EXTRAS
"rosidl_actions-extras.cmake.in"
)

if(BUILD_TESTING)
find_package(ament_cmake_pytest REQUIRED)
# TODO(sloretz) add test here
# ament_add_pytest_test(pytest test)
endif()

install(
PROGRAMS bin/rosidl_actions
DESTINATION lib/rosidl_actions
)

install(
DIRECTORY cmake
DESTINATION share/${PROJECT_NAME}
)
40 changes: 40 additions & 0 deletions rosidl_actions/bin/rosidl_actions
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3

import argparse
import os
import sys

try:
from rosidl_actions import generate_msg_and_srv
except ImportError:
# modifying sys.path and importing the Python package with the same
# name as this script does not work on Windows
rosidl_actions_root = os.path.dirname(os.path.dirname(__file__))
rosidl_actions_module = os.path.join(
rosidl_actions_root, 'rosidl_actions', '__init__.py')
if not os.path.exists(rosidl_actions_module):
raise
from importlib.machinery import SourceFileLoader

loader = SourceFileLoader('rosidl_actions', rosidl_actions_module)
rosidl_actions = loader.load_module()
generate_msg_and_srv = rosidl_actions.generate_msg_and_srv


def main(argv=sys.argv[1:]):
parser = argparse.ArgumentParser(
description='Generate .msg and .srv files for actions.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'--generator-arguments-file',
required=True,
help='The location of the file containing the generator arguments')
args = parser.parse_args(argv)

return generate_msg_and_srv(
args.generator_arguments_file,
)


if __name__ == '__main__':
sys.exit(main())
23 changes: 23 additions & 0 deletions rosidl_actions/cmake/register_actions.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2018 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

macro(rosidl_actions_extras BIN GENERATOR_FILES)
find_package(ament_cmake_core QUIET REQUIRED)

normalize_path(BIN "${BIN}")
set(rosidl_actions_BIN "${BIN}")

normalize_path(GENERATOR_FILES "${GENERATOR_FILES}")
set(rosidl_actions_GENERATOR_FILES "${GENERATOR_FILES}")
endmacro()
22 changes: 22 additions & 0 deletions rosidl_actions/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>rosidl_actions</name>
<version>0.5.1</version>
<description>Converts action files into message and service files.</description>
<maintainer email="sloretz@openrobotics.org">Shane Loretz</maintainer>
<license>Apache License 2.0</license>

<buildtool_depend>ament_cmake</buildtool_depend>

<depend>rosidl_parser</depend>

<test_depend>ament_cmake_pytest</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>python3-pytest</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
7 changes: 7 additions & 0 deletions rosidl_actions/rosidl_actions-extras.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# generated from rosidl_actions/rosidl_actions-extras.cmake

include("${CMAKE_CURRENT_LIST_DIR}/register_actions.cmake")
rosidl_actions_extras(
"${rosidl_actions_DIR}/../../../lib/rosidl_actions/rosidl_actions"
"${rosidl_actions_DIR}/../../../@PYTHON_INSTALL_DIR@/rosidl_actions/__init__.py"
)
48 changes: 48 additions & 0 deletions rosidl_actions/rosidl_actions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2018 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os

from rosidl_cmake import read_generator_arguments
from rosidl_parser import parse_action_file


def generate_msg_and_srv(generator_arguments_file):
"""Write 'msg' and 'srv' files from 'action' files."""
args = read_generator_arguments(generator_arguments_file)

for ros_interface_file in args['ros_interface_files']:
extension = os.path.splitext(ros_interface_file)[1]
subfolder = os.path.basename(os.path.dirname(ros_interface_file))
if extension == '.action':
services, message = parse_action_file(args['package_name'], ros_interface_file)

# create folder if necessary
os.makedirs(os.path.join(args['output_dir'], subfolder), exist_ok=True)

generated_folder = os.path.join(args['output_dir'], subfolder)
for service in services:
srv_file = os.path.join(generated_folder, service.srv_name + '.srv')
req_file = os.path.join(generated_folder, service.srv_name + '_Request.msg')
rsp_file = os.path.join(generated_folder, service.srv_name + '_Response.msg')
with open(srv_file, 'w+') as fout:
fout.write(str(service))
with open(req_file, 'w+') as fout:
fout.write(str(service.request))
with open(rsp_file, 'w+') as fout:
fout.write(str(service.response))

generated_file = os.path.join(args['output_dir'], subfolder, message.msg_name + '.msg')
with open(generated_file, 'w+') as fout:
fout.write(str(message))
105 changes: 105 additions & 0 deletions rosidl_cmake/cmake/rosidl_convert_actions_to_msg_and_srv.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Copyright 2018 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Convert action files from messages to services.
#
# This function declares what message and service files will be created given
# action files.
# It creates a custom target which generates messages and services when the
# .action files change.
#
# :param target: A target name to use to generate the .msg and .srv files
# :type target: string
# :param ARGN: Paths to .action files
# :type ARGN: strings
# :param OUTPUT_IDL_VAR: Set to a list of message and service files
# :type OUTPUT_IDL_VAR: list of strings
#
# @public
#
function(rosidl_convert_actions_to_msg_and_srv target)
cmake_parse_arguments(_ARG
""
"OUTPUT_IDL_VAR"
""
${ARGN})
if(NOT _ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "rosidl_convert_actions_to_msg_and_srv() must be given IDL files")
endif()
if(NOT _ARG_OUTPUT_IDL_VAR)
message(FATAL_ERROR "rosidl_convert_actions_to_msg_and_srv() needs output variable for interfaces")
endif()

set(_action_files ${_ARG_UNPARSED_ARGUMENTS})

# Make a list of files that will be generated
set(_output_path "${CMAKE_CURRENT_BINARY_DIR}/rosidl_actions/${PROJECT_NAME}")
set(_generated_action_idl_files "")
foreach(_action_file ${_action_files})
get_filename_component(_parent_folder "${_action_file}" DIRECTORY)
get_filename_component(_parent_folder "${_parent_folder}" NAME)
get_filename_component(_action_name "${_action_file}" NAME_WE)
get_filename_component(_extension "${_action_file}" EXT)

if(NOT _extension STREQUAL ".action")
message(FATAL_ERROR "action files must end in .action")
endif()

list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Goal.srv")
list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Goal_Request.msg")
list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Goal_Response.msg")
list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Result.srv")
list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Result_Request.msg")
list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Result_Response.msg")
list(APPEND _generated_action_idl_files
"${_output_path}/${_parent_folder}/${_action_name}_Feedback.msg")
endforeach()

# Write generator arguments
set(generator_arguments_file "${CMAKE_CURRENT_BINARY_DIR}/rosidl_actions_convert_actions_to_msg_and_srv__arguments.json")
rosidl_write_generator_arguments(
"${generator_arguments_file}"
PACKAGE_NAME "${PROJECT_NAME}" # TODO(sloretz) why is this required?
ROS_INTERFACE_FILES "${_action_files}"
ROS_INTERFACE_DEPENDENCIES ""
OUTPUT_DIR "${_output_path}"
TEMPLATE_DIR "dontneedthisbutitisrequired"
)

find_package(rosidl_actions REQUIRED)

# Cmake boilerplate to trigger generation
add_custom_command(
OUTPUT ${_generated_action_idl_files}
COMMAND ${PYTHON_EXECUTABLE} ${rosidl_actions_BIN}
--generator-arguments-file "${generator_arguments_file}"
DEPENDS ${_action_files}
COMMENT "Generating .msg and .srv for ROS .action interfaces"
VERBATIM
)

add_custom_target(
${target}
DEPENDS
${_generated_action_idl_files}
)

set(${_ARG_OUTPUT_IDL_VAR} ${_generated_action_idl_files} PARENT_SCOPE)
endfunction()
20 changes: 20 additions & 0 deletions rosidl_cmake/cmake/rosidl_generate_interfaces.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ macro(rosidl_generate_interfaces target)
endforeach()
endforeach()

# Split .srv into two .msg files
foreach(_idl_file ${_idl_files})
get_filename_component(_extension "${_idl_file}" EXT)
# generate request and response messages for services
Expand Down Expand Up @@ -127,15 +128,34 @@ macro(rosidl_generate_interfaces target)
stamp("${_idl_file}")
endforeach()

# Separate action files from other interface files
rosidl_identify_action_idls(${_idl_files}
OUTPUT_ACTION_VAR _action_files
OUTPUT_IDL_VAR _idl_files)

# Convert action files into messages and services
if(_action_files)
set(_convert_actions_target "${target}+_convert_actions_to_msg_and_srv")
rosidl_convert_actions_to_msg_and_srv(${_convert_actions_target} ${_action_files}
OUTPUT_IDL_VAR _action_msg_and_srv_files)
endif()

add_custom_target(
${target} ALL
DEPENDS
${_idl_files}
${_dep_files}
${_convert_actions_target}
SOURCES
${_idl_files}
)

# Tell CMake in this directory scope that these files are generated
foreach(_idl_file ${_action_msg_and_srv_files})
list(APPEND _idl_files "${_idl_file}")
set_property(SOURCE ${_idl_file} PROPERTY GENERATED 1)
endforeach()

if(NOT _ARG_SKIP_INSTALL)
if(NOT _ARG_SKIP_GROUP_MEMBERSHIP_CHECK)
set(_group_name "rosidl_interface_packages")
Expand Down
55 changes: 55 additions & 0 deletions rosidl_cmake/cmake/rosidl_identify_action_idls.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2018 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Determine which IDL files are describing action files.
#
# :param ARGN: Paths to files that may or may not be actions
# :type ARGN: strings
# :param OUTPUT_ACTION_VAR: Set to a list of files that are actions.
# :type OUTPUT_ACTION_VAR: list of strings
# :param OUTPUT_IDL_VAR: Set to a list of files that are not actions.
# :type OUTPUT_IDL_VAR: list of strings
#
# @public
#
function(rosidl_identify_action_idls)
cmake_parse_arguments(_ARG
""
"OUTPUT_ACTION_VAR;OUTPUT_IDL_VAR"
""
${ARGN})
if(NOT _ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "rosidl_identify_action_idls() must be given IDL files")
endif()
if(NOT _ARG_OUTPUT_ACTION_VAR)
message(FATAL_ERROR "rosidl_identify_action_idls() needs output variable for actions set")
endif()
if(NOT _ARG_OUTPUT_IDL_VAR)
message(FATAL_ERROR "rosidl_identify_action_idls() needs output variable for non-actions set")
endif()

set(_action_files "")
set(_non_action_files "")
foreach(_idl_file ${_ARG_UNPARSED_ARGUMENTS})
get_filename_component(_extension "${_idl_file}" EXT)
if(_extension STREQUAL ".action")
list(APPEND _action_files ${_idl_file})
else()
list(APPEND _non_action_files ${_idl_file})
endif()
endforeach()

set(${_ARG_OUTPUT_ACTION_VAR} ${_action_files} PARENT_SCOPE)
set(${_ARG_OUTPUT_IDL_VAR} ${_non_action_files} PARENT_SCOPE)
endfunction()
1 change: 1 addition & 0 deletions rosidl_cmake/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<buildtool_export_depend>ament_cmake</buildtool_export_depend>
<buildtool_export_depend>python3-empy</buildtool_export_depend>

<exec_depend>rosidl_actions</exec_depend>
<exec_depend>rosidl_parser</exec_depend>

<test_depend>ament_lint_auto</test_depend>
Expand Down
Loading