|
| 1 | +import argparse |
| 2 | +import os |
| 3 | +import pathlib |
| 4 | +import sys |
| 5 | + |
| 6 | +from ament_index_python import get_package_share_directory |
| 7 | + |
| 8 | +from catkin_pkg.package import package_exists_at |
| 9 | +from catkin_pkg.package import parse_package |
| 10 | + |
| 11 | +from rosidl_adapter.action import convert_action_to_idl |
| 12 | +from rosidl_adapter.msg import convert_msg_to_idl |
| 13 | +from rosidl_adapter.srv import convert_srv_to_idl |
| 14 | + |
| 15 | +from rosidl_cmake import read_generator_arguments |
| 16 | + |
| 17 | +from rosidl_cli.command.helpers import interface_path_as_tuple |
| 18 | +from rosidl_cli.command.helpers import legacy_generator_arguments_file |
| 19 | +from rosidl_cli.command.translate.extensions import TranslateCommandExtension |
| 20 | +from rosidl_cli.command.translate.api import translate |
| 21 | + |
| 22 | +from rosidl_adapter_proto import generate_proto |
| 23 | +from rosidl_adapter_proto import compile_proto |
| 24 | + |
| 25 | +def convert_to_proto(generator_arguments_file, protoc_path): |
| 26 | + generator_args = read_generator_arguments(generator_arguments_file) |
| 27 | + |
| 28 | + # Generate .proto files |
| 29 | + rc = generate_proto(generator_arguments_file) |
| 30 | + if rc : |
| 31 | + raise RuntimeError |
| 32 | + |
| 33 | + # Compile .proto files using protoc |
| 34 | + cpp_out_dir = str(pathlib.Path(generator_args["output_dir"] + "/..").resolve()) |
| 35 | + proto_path_list = [str(pathlib.Path(generator_args["output_dir"] + "/..").resolve())] |
| 36 | + proto_files = [] |
| 37 | + package_name = generator_args["package_name"] |
| 38 | + |
| 39 | + if "additional_files" in generator_args: |
| 40 | + proto_path_list += generator_args["additional_files"] |
| 41 | + |
| 42 | + pathlib.Path(cpp_out_dir).mkdir(parents=True, exist_ok=True) |
| 43 | + |
| 44 | + for idl_tuple in generator_args.get('idl_tuples', []): |
| 45 | + idl_parts = idl_tuple.rsplit(':', 1) |
| 46 | + assert len(idl_parts) == 2 |
| 47 | + idl_rel_path = pathlib.Path(idl_parts[1]) |
| 48 | + idl_stem = idl_rel_path.stem |
| 49 | + generated_file = os.path.join( |
| 50 | + generator_args['output_dir'], |
| 51 | + str(idl_rel_path.parent), |
| 52 | + idl_stem + ".proto" |
| 53 | + ) |
| 54 | + proto_files.append(str(pathlib.Path(generated_file).resolve())) |
| 55 | + |
| 56 | + # compile proto files with protoc |
| 57 | + rc = compile_proto(protoc_path = protoc_path, |
| 58 | + proto_path_list = proto_path_list, |
| 59 | + cpp_out_dir = cpp_out_dir, |
| 60 | + proto_files = proto_files, |
| 61 | + package_name = package_name |
| 62 | + ) |
| 63 | + if rc : |
| 64 | + raise RuntimeError |
| 65 | + |
| 66 | + return proto_files |
| 67 | + |
| 68 | + |
| 69 | +def convert_files_to_idl(extension, conversion_function, argv=sys.argv[1:]): |
| 70 | + parser = argparse.ArgumentParser( |
| 71 | + description=f'Convert {extension} files to .idl') |
| 72 | + parser.add_argument( |
| 73 | + 'interface_files', nargs='+', |
| 74 | + help='The interface files to convert') |
| 75 | + args = parser.parse_args(argv) |
| 76 | + |
| 77 | + for interface_file in args.interface_files: |
| 78 | + interface_file = pathlib.Path(interface_file) |
| 79 | + package_dir = interface_file.parent.absolute() |
| 80 | + while ( |
| 81 | + len(package_dir.parents) and |
| 82 | + not package_exists_at(str(package_dir)) |
| 83 | + ): |
| 84 | + package_dir = package_dir.parent |
| 85 | + if not package_dir.parents: |
| 86 | + print( |
| 87 | + f"Could not find package for '{interface_file}'", |
| 88 | + file=sys.stderr) |
| 89 | + continue |
| 90 | + warnings = [] |
| 91 | + pkg = parse_package(package_dir, warnings=warnings) |
| 92 | + |
| 93 | + conversion_function( |
| 94 | + package_dir, pkg.name, |
| 95 | + interface_file.absolute().relative_to(package_dir), |
| 96 | + interface_file.parent) |
| 97 | + |
| 98 | + |
| 99 | +class TranslateToProto(TranslateCommandExtension): |
| 100 | + |
| 101 | + output_format = 'proto' |
| 102 | + |
| 103 | + def translate( |
| 104 | + self, |
| 105 | + package_name, |
| 106 | + interface_files, |
| 107 | + include_paths, |
| 108 | + output_path |
| 109 | + ): |
| 110 | + |
| 111 | + generated_files = [] |
| 112 | + |
| 113 | + package_share_path = pathlib.Path( |
| 114 | + get_package_share_directory('rosidl_adapter_proto')) |
| 115 | + templates_path = package_share_path / 'resource' |
| 116 | + |
| 117 | + |
| 118 | + idl_interface_files = [] |
| 119 | + non_idl_interface_files = [] |
| 120 | + for path in interface_files: |
| 121 | + if not path.endswith('.idl'): |
| 122 | + non_idl_interface_files.append(path) |
| 123 | + else: |
| 124 | + idl_interface_files.append(path) |
| 125 | + if non_idl_interface_files: |
| 126 | + idl_interface_files.extend(translate( |
| 127 | + package_name=package_name, |
| 128 | + interface_files=non_idl_interface_files, |
| 129 | + include_paths=include_paths, |
| 130 | + output_format='idl', |
| 131 | + output_path=output_path / 'tmp', |
| 132 | + )) |
| 133 | + |
| 134 | + |
| 135 | + # Generate code |
| 136 | + with legacy_generator_arguments_file( |
| 137 | + package_name=package_name, |
| 138 | + interface_files=idl_interface_files, |
| 139 | + include_paths=include_paths, |
| 140 | + templates_path=templates_path, |
| 141 | + output_path=output_path |
| 142 | + ) as path_to_arguments_file: |
| 143 | + generated_files.extend(convert_to_proto(path_to_arguments_file, '/usr/bin/protoc')) |
| 144 | + return generated_files |
| 145 | + |
| 146 | + |
| 147 | + |
| 148 | +class TranslateMsgToProto(TranslateToProto): |
| 149 | + input_format = 'msg' |
| 150 | + |
| 151 | + |
| 152 | +class TranslateSrvToProto(TranslateToProto): |
| 153 | + input_format = 'srv' |
| 154 | + |
| 155 | + |
| 156 | +class TranslateActionToProto(TranslateToProto): |
| 157 | + input_format = 'action' |
0 commit comments