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

Expose .msg/.srv/.action to .idl conversion via rosidl translate CLI #576

Merged
merged 6 commits into from
Mar 9, 2021
Merged
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
7 changes: 2 additions & 5 deletions rosidl_adapter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ find_package(ament_cmake_python REQUIRED)
ament_python_install_package(${PROJECT_NAME})

if(BUILD_TESTING)
find_package(ament_cmake_pytest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
ament_add_pytest_test(pytest test)
endif()

ament_package(
Expand All @@ -25,8 +27,3 @@ install(PROGRAMS
scripts/msg2idl.py
scripts/srv2idl.py
DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
find_package(ament_cmake_pytest REQUIRED)
ament_add_pytest_test(pytest test)
endif()
1 change: 1 addition & 0 deletions rosidl_adapter/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<build_depend>ament_cmake</build_depend>

<exec_depend>python3-empy</exec_depend>
<exec_depend>rosidl_cli</exec_depend>

<test_depend>ament_cmake_pytest</test_depend>
<test_depend>ament_lint_common</test_depend>
Expand Down
2 changes: 1 addition & 1 deletion rosidl_adapter/rosidl_adapter/action/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def convert_action_to_idl(package_dir, package_name, input_file, output_dir):
print(f'Writing output file: {abs_output_file}')
data = {
'pkg_name': package_name,
'relative_input_file': input_file,
'relative_input_file': input_file.as_posix(),
'action': action,
}

Expand Down
58 changes: 58 additions & 0 deletions rosidl_adapter/rosidl_adapter/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
from catkin_pkg.package import package_exists_at
from catkin_pkg.package import parse_package

from rosidl_adapter.action import convert_action_to_idl
from rosidl_adapter.msg import convert_msg_to_idl
from rosidl_adapter.srv import convert_srv_to_idl

from rosidl_cli.command.helpers import interface_path_as_tuple
from rosidl_cli.command.translate.extensions import TranslateCommandExtension


def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]):
parser = argparse.ArgumentParser(
Expand Down Expand Up @@ -48,3 +55,54 @@ def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]):
package_dir, pkg.name,
interface_file.absolute().relative_to(package_dir),
interface_file.parent)


class TranslateToIDL(TranslateCommandExtension):

output_format = 'idl'

def translate(
self,
package_name,
interface_files,
include_paths,
output_path
):
translated_interface_files = []
for interface_file in interface_files:
prefix, interface_file = interface_path_as_tuple(interface_file)
output_dir = output_path / interface_file.parent
translated_interface_file = self.conversion_function(
prefix, package_name, interface_file, output_dir)
translated_interface_file = \
translated_interface_file.relative_to(output_path)
translated_interface_files.append(
f'{output_path}:{translated_interface_file.as_posix()}'
)
return translated_interface_files


class TranslateMsgToIDL(TranslateToIDL):

input_format = 'msg'

@property
def conversion_function(self):
return convert_msg_to_idl


class TranslateSrvToIDL(TranslateToIDL):

input_format = 'srv'

@property
def conversion_function(self):
return convert_srv_to_idl


class TranslateActionToIDL(TranslateToIDL):
input_format = 'action'

@property
def conversion_function(self):
return convert_action_to_idl
2 changes: 1 addition & 1 deletion rosidl_adapter/rosidl_adapter/msg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def convert_msg_to_idl(package_dir, package_name, input_file, output_dir):
print(f'Writing output file: {abs_output_file}')
data = {
'pkg_name': package_name,
'relative_input_file': input_file,
'relative_input_file': input_file.as_posix(),
'msg': msg,
}

Expand Down
2 changes: 1 addition & 1 deletion rosidl_adapter/rosidl_adapter/srv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def convert_srv_to_idl(package_dir, package_name, input_file, output_dir):
print(f'Writing output file: {abs_output_file}')
data = {
'pkg_name': package_name,
'relative_input_file': input_file,
'relative_input_file': input_file.as_posix(),
'srv': srv,
}

Expand Down
5 changes: 5 additions & 0 deletions rosidl_adapter/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[options.entry_points]
rosidl_cli.command.translate.extensions =
msg2idl = rosidl_adapter.cli:TranslateMsgToIDL
srv2idl = rosidl_adapter.cli:TranslateSrvToIDL
action2idl = rosidl_adapter.cli:TranslateActionToIDL
21 changes: 21 additions & 0 deletions rosidl_adapter/test/data/action/Test.action
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# goal definition
bool bool_value
byte byte_value
char char_value
float32 float32_value
float64 float64_value
int8 int8_value
uint8 uint8_value
int16 int16_value
uint16 uint16_value
int32 int32_value
uint32 uint32_value
int64 int64_value
uint64 uint64_value
string string_value
---
# result definition
bool ok
---
# feedback definition
int32[] sequence
50 changes: 50 additions & 0 deletions rosidl_adapter/test/data/action/Test.expected.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// generated from rosidl_adapter/resource/action.idl.em
// with input from test_msgs/action/Test.action
// generated code does not contain a copyright notice


module test_msgs {
module action {
@verbatim (language="comment", text=
" goal definition")
struct Test_Goal {
boolean bool_value;

octet byte_value;

uint8 char_value;

float float32_value;

double float64_value;

int8 int8_value;

uint8 uint8_value;

int16 int16_value;

uint16 uint16_value;

int32 int32_value;

uint32 uint32_value;

int64 int64_value;

uint64 uint64_value;

string string_value;
};
struct Test_Result {
@verbatim (language="comment", text=
" result definition")
boolean ok;
};
struct Test_Feedback {
@verbatim (language="comment", text=
" feedback definition")
sequence<int32> sequence;
};
};
};
36 changes: 36 additions & 0 deletions rosidl_adapter/test/data/msg/Test.expected.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// generated from rosidl_adapter/resource/msg.idl.em
// with input from test_msgs/msg/Test.msg
// generated code does not contain a copyright notice


module test_msgs {
module msg {
struct Test {
boolean bool_value;

octet byte_value;

uint8 char_value;

float float32_value;

double float64_value;

int8 int8_value;

uint8 uint8_value;

int16 int16_value;

uint16 uint16_value;

int32 int32_value;

uint32 uint32_value;

int64 int64_value;

uint64 uint64_value;
};
};
};
13 changes: 13 additions & 0 deletions rosidl_adapter/test/data/msg/Test.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
bool bool_value
byte byte_value
char char_value
float32 float32_value
float64 float64_value
int8 int8_value
uint8 uint8_value
int16 int16_value
uint16 uint16_value
int32 int32_value
uint32 uint32_value
int64 int64_value
uint64 uint64_value
41 changes: 41 additions & 0 deletions rosidl_adapter/test/data/srv/Test.expected.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// generated from rosidl_adapter/resource/srv.idl.em
// with input from test_msgs/srv/Test.srv
// generated code does not contain a copyright notice


module test_msgs {
module srv {
struct Test_Request {
boolean bool_value;

octet byte_value;

uint8 char_value;

float float32_value;

double float64_value;

int8 int8_value;

uint8 uint8_value;

int16 int16_value;

uint16 uint16_value;

int32 int32_value;

uint32 uint32_value;

int64 int64_value;

uint64 uint64_value;

string string_value;
};
struct Test_Response {
boolean ok;
};
};
};
16 changes: 16 additions & 0 deletions rosidl_adapter/test/data/srv/Test.srv
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
bool bool_value
byte byte_value
char char_value
float32 float32_value
float64 float64_value
int8 int8_value
uint8 uint8_value
int16 int16_value
uint16 uint16_value
int32 int32_value
uint32 uint32_value
int64 int64_value
uint64 uint64_value
string string_value
---
bool ok
85 changes: 85 additions & 0 deletions rosidl_adapter/test/test_cli_extensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copyright 2021 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 filecmp
import pathlib

from rosidl_cli.command.translate.api import translate


DATA_PATH = pathlib.Path(__file__).parent / 'data'


def test_translation_extensions(tmp_path, capsys):
# NOTE(hidmic): pytest and empy do not play along,
# the latter expects some proxy will stay in sys.stdout
# and the former insists in overwriting it

with capsys.disabled(): # so do everything in one run
# Test .msg to .idl translation
idl_files = translate(
package_name='test_msgs',
interface_files=[
f'{DATA_PATH}:msg/Test.msg'],
output_path=tmp_path,
output_format='idl',
translators=['msg2idl']
)

assert len(idl_files) == 1
idl_file = idl_files[0]
assert idl_file == f'{tmp_path}:msg/Test.idl'
assert filecmp.cmp(
tmp_path / 'msg' / 'Test.idl',
DATA_PATH / 'msg' / 'Test.expected.idl',
shallow=False
)

# Test .srv to .idl translation
idl_files = translate(
package_name='test_msgs',
interface_files=[
f'{DATA_PATH}:srv/Test.srv'],
output_path=tmp_path,
output_format='idl',
translators=['srv2idl']
)

assert len(idl_files) == 1
idl_file = idl_files[0]
assert idl_file == f'{tmp_path}:srv/Test.idl'
assert filecmp.cmp(
tmp_path / 'srv' / 'Test.idl',
DATA_PATH / 'srv' / 'Test.expected.idl',
shallow=False
)

# Test .action to .idl translation
idl_files = translate(
package_name='test_msgs',
interface_files=[
f'{DATA_PATH}:action/Test.action'],
output_path=tmp_path,
output_format='idl',
translators=['action2idl']
)

assert len(idl_files) == 1
idl_file = idl_files[0]
assert idl_file == f'{tmp_path}:action/Test.idl'
assert filecmp.cmp(
tmp_path / 'action' / 'Test.idl',
DATA_PATH / 'action' / 'Test.expected.idl',
shallow=False
)