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] restructure rosidl to work with IDL files #298

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
cf56be9
copy ROS msg/srv parser
dirk-thomas Sep 18, 2018
48635bc
remove message/service specific stuff from the other module
dirk-thomas Sep 19, 2018
b1caf0d
add rosidl_adapter package
dirk-thomas Sep 19, 2018
bd944f8
use rosidl_parser in rosidl_cmake, allow passing interface files with…
dirk-thomas Sep 19, 2018
552b08c
add lark grammar and parsing functions
dirk-thomas Sep 19, 2018
9149d16
update rosidl_generator_c to use IDL files
dirk-thomas Sep 19, 2018
9b0e9d0
fix Python 3.5 issue
dirk-thomas Sep 21, 2018
43a9052
only require either messages or services
dirk-thomas Sep 21, 2018
2425af5
add u16string type and functions and use for wstring, add long double
dirk-thomas Sep 22, 2018
166d457
fix for 43a90521
dirk-thomas Sep 22, 2018
e177d0b
[rosidl_generator_c] fix (w)string with upper bound
dirk-thomas Sep 22, 2018
66f9129
get_filename_component(... EXT) includes '.'
sloretz Sep 24, 2018
34b5c46
Try to convert message and service files
sloretz Sep 24, 2018
4393367
Further work on IDL.
mjcarroll Sep 24, 2018
0a4af16
Include message name in constants module
sloretz Sep 25, 2018
028b117
1.125 is a legal floating point literal
sloretz Sep 25, 2018
75593a4
multiple annotation_appl per member
sloretz Sep 25, 2018
b5df207
add string literal escaping
sloretz Sep 25, 2018
0bee962
First attempt at char literal escaping
sloretz Sep 25, 2018
88569ee
More informative error message.
mjcarroll Sep 25, 2018
94dbeeb
Change char mapping to int8.
mjcarroll Sep 25, 2018
9cc7654
String escaping fixup.
mjcarroll Sep 25, 2018
a069cbc
Check escape before graphic char
sloretz Sep 25, 2018
7aa8d9d
.srv use string literal escape function
sloretz Sep 25, 2018
0202f3d
Allow verbatim rosidl_array_init
sloretz Sep 25, 2018
d4e108b
Remove to_character_literal since type changed to uint8
sloretz Sep 25, 2018
a5cc511
array values use verbatim annotation
sloretz Sep 25, 2018
208e063
Merge branch 'shane/rosidl-reloaded' into rosidl-reloaded
dirk-thomas Oct 15, 2018
0aee9b7
add additional rule to grammar to distinguish relevants parts of a ma…
dirk-thomas Oct 19, 2018
499028e
add priorities / weights to prefer certain rules
dirk-thomas Oct 19, 2018
25b4f1e
add new object representation for interfaces
dirk-thomas Oct 19, 2018
5fdbd8c
add parser to parse .idl files using lark and transform the AST into …
dirk-thomas Oct 19, 2018
bc9578f
add test for .idl parser
dirk-thomas Oct 19, 2018
a9fd325
working copy dump
dirk-thomas Nov 9, 2018
4635a93
extract comments and units
dirk-thomas Nov 9, 2018
6bd82b0
replace function pointer with import
dirk-thomas Nov 9, 2018
49463a6
rm obsolete file
dirk-thomas Nov 10, 2018
9116396
migrate rosidl_generator_cpp, fix rosidl_generator_c
dirk-thomas Nov 13, 2018
5ee3cb0
avoid duplicate logic
dirk-thomas Nov 14, 2018
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
22 changes: 22 additions & 0 deletions rosidl_adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.5)

project(rosidl_adapter NONE)

find_package(ament_cmake REQUIRED)
find_package(ament_cmake_python REQUIRED)

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_adapter-extras.cmake"
)

install(
DIRECTORY cmake
DESTINATION share/${PROJECT_NAME}
)
103 changes: 103 additions & 0 deletions rosidl_adapter/cmake/rosidl_adapt_interfaces.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# 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.

#
# Adapt interface input files to a coherent set of `.idl` files.
#
# The input file might already be an `.idl` file or any other format for which
# a plugin exist which converts the incoming file into an `.idl` file.
# E.g. `.msg` and `.srv` files are being supported for backward compatibility.
#
# Each output `.idl` file contains either a single message or a single service.
#
# :param target: the _name of the generation target,
# specific generators might use the _name as a prefix for their own
# generation step
# :type target: string
# :param ARGN: a list of interface files where each value might be either an
# absolute path or path relative to the CMAKE_CURRENT_SOURCE_DIR.
# :type ARGN: list of strings
# :param DEPENDENCIES: the packages from which message types are
# being used
# :type DEPENDENCIES: list of strings
# :param LIBRARY_NAME: the base name of the library, specific generators might
# append their own suffix
# :type LIBRARY_NAME: string
# :param SKIP_INSTALL: if set skip installing the interface files
# :type SKIP_INSTALL: option
# :param SKIP_GROUP_MEMBERSHIP_CHECK: if set, skip enforcing the appartenance
# to the rosidl_interface_packages group
# :type SKIP_GROUP_MEMBERSHIP_CHECK: option
# :param ADD_LINTER_TESTS: if set lint the interface files using
# the ``ament_lint`` package
# :type ADD_LINTER_TESTS: option
#
# @public
#
function(rosidl_adapt_interfaces idl_var)
cmake_parse_arguments(ARG "" "TARGET" ""
${ARGN})
if(NOT ARG_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "rosidl_adapt_interfaces() called without any "
"interface files")
endif()

if(NOT rosidl_adapter_FOUND)
message(FATAL_ERROR "rosidl_adapt_interfaces() called without "
"find_package(rosidl_adapter) successfuly being called")
endif()

find_package(PythonInterp REQUIRED)
if(NOT PYTHON_EXECUTABLE)
message(FATAL_ERROR "Variable 'PYTHON_EXECUTABLE' must not be empty")
endif()

set(_idl_output "${CMAKE_CURRENT_BINARY_DIR}/rosidl_adapter/${ARG_TARGET}.idls")
# TODO needs to use a JSON file for arguments otherwise the command might become too long
set(cmd
"${PYTHON_EXECUTABLE}" -m rosidl_adapter
--package-name ${PROJECT_NAME}
--interface-files ${ARG_UNPARSED_ARGUMENTS}
--output-dir "${CMAKE_CURRENT_BINARY_DIR}/rosidl_adapter"
--output-file "${_idl_output}")
execute_process(
COMMAND ${cmd}
OUTPUT_QUIET
ERROR_VARIABLE error
RESULT_VARIABLE result
)
if(NOT result EQUAL 0)
string(REPLACE ";" " " cmd_str "${cmd}")
message(FATAL_ERROR
"execute_process(${cmd_str}) returned error code ${result}:\n${error}")
endif()

file(STRINGS "${_idl_output}" idl_files)

# split each absolute file into a tuple
set(idl_tuples "")
set(basepath "${CMAKE_CURRENT_BINARY_DIR}/rosidl_adapter/${PROJECT_NAME}")
string(LENGTH "${basepath}" length)
foreach(idl_file ${idl_files})
string(SUBSTRING "${idl_file}" 0 ${length} prefix)
if(NOT "${prefix}" STREQUAL "${basepath}")
message(FATAL_ERROR "boom")
endif()
math(EXPR index "${length} + 1")
string(SUBSTRING "${idl_file}" ${index} -1 rel_idl_file)
list(APPEND idl_tuples "${basepath}:${rel_idl_file}")
endforeach()

set(${idl_var} ${idl_tuples} PARENT_SCOPE)
endfunction()
22 changes: 22 additions & 0 deletions rosidl_adapter/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_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>rosidl_adapter</name>
<version>0.5.1</version>
<description>
Scripts to convert .msg/.srv files to .idl.
</description>
<maintainer email="[email protected]">Dirk Thomas</maintainer>
<license>Apache License 2.0</license>

<build_depend>ament_cmake</build_depend>

<exec_depend>python3-empy</exec_depend>

<test_depend>ament_lint_common</test_depend>
<test_depend>ament_lint_auto</test_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
17 changes: 17 additions & 0 deletions rosidl_adapter/rosidl_adapter-extras.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 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.

# copied from rosidl_adapter/rosidl_adapter-extras.cmake

include("${rosidl_adapter_DIR}/rosidl_adapt_interfaces.cmake")
32 changes: 32 additions & 0 deletions rosidl_adapter/rosidl_adapter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# 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.


def convert_to_idl(package_dir, package_name, interface_file, output_dir):
# TODO use plugin approach rather than hard coded alternatives

if interface_file.suffix == '.msg':
from rosidl_adapter.msg import convert_msg_to_idl
return convert_msg_to_idl(
package_dir, package_name, interface_file,
output_dir / package_name / 'msg')

if interface_file.suffix == '.srv':
from rosidl_adapter.srv import convert_srv_to_idl
return convert_srv_to_idl(
package_dir, package_name, interface_file,
output_dir / package_name / 'srv')

assert False, "Unsupported interface type '{interface_file.suffix}'" \
.format_map(locals())
19 changes: 19 additions & 0 deletions rosidl_adapter/rosidl_adapter/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 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 sys

from rosidl_adapter.main import main

sys.exit(main())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be an entry point to work on windows?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't since it is invoked with python -m rosidl_adapter.

53 changes: 53 additions & 0 deletions rosidl_adapter/rosidl_adapter/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 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 argparse
import os
import pathlib
import sys


from rosidl_adapter import convert_to_idl


def main(argv=sys.argv[1:]):
parser = argparse.ArgumentParser(
description='Convert interface files to .idl')
parser.add_argument(
'--package-name', required=True,
help='The name of the package')
parser.add_argument(
'--interface-files', nargs='+',
help='The interface files to convert to .idl')
parser.add_argument(
'--output-dir', required=True,
help='The base directory to create .idl files in')
parser.add_argument(
'--output-file', required=True,
help='The output file containing the absolute paths to the .idl files')
args = parser.parse_args(argv)
output_dir = pathlib.Path(args.output_dir)

idl_files = []
for interface_tuple in args.interface_files:
basepath, relative_path = interface_tuple.split(':', 1)
idl_file = convert_to_idl(
pathlib.Path(basepath), args.package_name,
pathlib.Path(relative_path), output_dir)
idl_files.append(idl_file)

os.makedirs(os.path.dirname(args.output_file), exist_ok=True)
with open(args.output_file, 'w') as h:
for idl_file in idl_files:
h.write('{idl_file}\n'.format_map(locals()))
104 changes: 104 additions & 0 deletions rosidl_adapter/rosidl_adapter/msg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# 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.

from rosidl_adapter.msg.parser import parse_message_string
from rosidl_adapter.resource import expand_template


def convert_msg_to_idl(package_dir, package_name, input_file, output_dir):
assert package_dir.is_absolute()
assert not input_file.is_absolute()
assert input_file.suffix == '.msg'

print('Reading input file: {input_file}'.format_map(locals()))
abs_input_file = package_dir / input_file
content = abs_input_file.read_text(encoding='utf-8')
msg = parse_message_string(package_name, input_file.stem, content)

output_file = output_dir / input_file.with_suffix('.idl').name
print('Writing output file: {output_file}'.format_map(locals()))
data = {
'pkg_name': package_name,
'relative_input_file': input_file,
'msg': msg,
}

expand_template('msg.idl.em', data, output_file)
return output_file


MSG_TYPE_TO_IDL = {
'bool': 'boolean',
'byte': 'octet',
'char': 'uint8',
'int8': 'int8',
'uint8': 'uint8',
'int16': 'int16',
'uint16': 'uint16',
'int32': 'int32',
'uint32': 'uint32',
'int64': 'int64',
'uint64': 'uint64',
'float32': 'float',
'float64': 'double',
'string': 'string',
}


def to_idl_literal(idl_type, value):
if idl_type[-1] in (']', '>'):
elements = [repr(v) for v in value]
while len(elements) < 2:
elements.append('')
return '"(%s)"' % ', '.join(e.replace('"', r'\"') for e in elements)

if 'boolean' == idl_type:
return 'TRUE' if value else 'FALSE'
if 'string' == idl_type:
return string_to_idl_string_literal(value)
return value


def string_to_idl_string_literal(string):
"""Convert string to character literal as described in IDL 4.2 section 7.2.6.3 ."""
estr = string.encode().decode('unicode_escape')
estr = estr.replace('"', r'\"')
return '"{0}"'.format(estr)


def get_include_file(base_type):
if base_type.is_primitive_type():
return None
return '{base_type.pkg_name}/msg/{base_type.type}.idl'.format_map(locals())


def get_idl_type(type_):
if isinstance(type_, str):
identifier = MSG_TYPE_TO_IDL[type_]
elif type_.is_primitive_type():
identifier = MSG_TYPE_TO_IDL[type_.type]
else:
identifier = '{type_.pkg_name}::msg::{type_.type}' \
.format_map(locals())

if isinstance(type_, str) or not type_.is_array:
return identifier

if type_.is_fixed_size_array():
return '{identifier}[{type_.array_size}]'.format_map(locals())

if not type_.is_upper_bound:
return 'sequence<{identifier}>'.format_map(locals())

return 'sequence<{identifier}, {type_.array_size}>'.format_map(locals())
Loading