diff --git a/rosidl_generator_py/cmake/custom_command.cmake b/rosidl_generator_py/cmake/custom_command.cmake index 5c9e9876..e2646d43 100644 --- a/rosidl_generator_py/cmake/custom_command.cmake +++ b/rosidl_generator_py/cmake/custom_command.cmake @@ -13,7 +13,7 @@ # limitations under the License. add_custom_command( - OUTPUT ${_generated_extension_files} ${_generated_msg_py_files} ${_generated_msg_c_files} ${_generated_srv_py_files} ${_generated_srv_c_files} + OUTPUT ${_generated_extension_files} ${_generated_msg_py_files} ${_generated_msg_c_files} ${_generated_srv_py_files} ${_generated_srv_c_files} ${_generated_action_py_files} ${_generated_action_c_files} COMMAND ${PYTHON_EXECUTABLE} ${rosidl_generator_py_BIN} --generator-arguments-file "${generator_arguments_file}" --typesupport-impls "${_typesupport_impls}" @@ -33,5 +33,7 @@ else() ${_generated_msg_c_files} ${_generated_srv_py_files} ${_generated_srv_c_files} + ${_generated_action_py_files} + ${_generated_action_c_files} ) endif() diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index e10a5558..9fb15769 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -38,6 +38,8 @@ set(_generated_msg_py_files "") set(_generated_msg_c_files "") set(_generated_srv_py_files "") set(_generated_srv_c_files "") +set(_generated_action_py_files "") +set(_generated_action_c_files "") foreach(_typesupport_impl ${_typesupport_impls}) set(_generated_extension_${_typesupport_impl}_files "") @@ -47,6 +49,7 @@ foreach(_idl_file ${rosidl_generate_interfaces_IDL_FILES}) get_filename_component(_parent_folder "${_idl_file}" DIRECTORY) get_filename_component(_parent_folder "${_parent_folder}" NAME) get_filename_component(_msg_name1 "${_idl_file}" NAME_WE) + get_filename_component(_ext "${_idl_file}" EXT) string_camel_case_to_lower_case_underscore("${_msg_name1}" _module_name) if(_parent_folder STREQUAL "msg") @@ -65,6 +68,16 @@ foreach(_idl_file ${rosidl_generate_interfaces_IDL_FILES}) list(APPEND _generated_srv_py_files "${_output_path}/${_parent_folder}/_${_module_name}.py" ) + elseif(_parent_folder STREQUAL "action") + # C files generated for .msg, _Request.msg and _Response.msg but not .srv + if(_ext STREQUAL ".msg") + list(APPEND _generated_action_c_files + "${_output_path}/${_parent_folder}/_${_module_name}_s.c" + ) + endif() + list(APPEND _generated_action_py_files + "${_output_path}/${_parent_folder}/_${_module_name}.py" + ) else() message(FATAL_ERROR "Interface file with unknown parent folder: ${_idl_file}") endif() @@ -89,7 +102,15 @@ if(NOT _generated_srv_py_files STREQUAL "") ) endif() -if(NOT _generated_msg_c_files STREQUAL "" OR NOT _generated_srv_c_files STREQUAL "") +if(NOT _generated_action_py_files STREQUAL "") + list(GET _generated_action_py_files 0 _action_file) + get_filename_component(_parent_folder "${_action_file}" DIRECTORY) + list(APPEND _generated_action_py_files + "${_parent_folder}/__init__.py" + ) +endif() + +if(NOT _generated_msg_c_files STREQUAL "" OR NOT _generated_srv_c_files STREQUAL "" OR NOT _generated_action_c_files STREQUAL "") foreach(_typesupport_impl ${_typesupport_impls}) list(APPEND _generated_extension_${_typesupport_impl}_files "${_output_path}/_${PROJECT_NAME}_s.ep.${_typesupport_impl}.c") list(APPEND _generated_extension_files "${_generated_extension_${_typesupport_impl}_files}") @@ -145,6 +166,12 @@ if(NOT _generated_srv_py_files STREQUAL "") get_filename_component(_srv_package_dir2 "${_srv_package_dir1}" NAME) endif() +if(NOT _generated_action_py_files STREQUAL "") + list(GET _generated_action_py_files 0 _action_file) + get_filename_component(_action_package_dir1 "${_action_file}" DIRECTORY) + get_filename_component(_action_package_dir2 "${_action_package_dir1}" NAME) +endif() + if(NOT rosidl_generate_interfaces_SKIP_INSTALL) ament_python_install_module("${_output_path}/__init__.py" DESTINATION_SUFFIX "${PROJECT_NAME}" @@ -167,6 +194,11 @@ if(NOT rosidl_generate_interfaces_SKIP_INSTALL) DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}/${_srv_package_dir2}" ) endif() + if(NOT _action_package_dir2 STREQUAL "") + install(FILES ${_generated_action_py_files} + DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}/${_action_package_dir2}" + ) + endif() endif() set(_target_suffix "__py") @@ -179,7 +211,7 @@ file(WRITE "${_subdir}/CMakeLists.txt" "${_custom_command}") add_subdirectory("${_subdir}" ${rosidl_generate_interfaces_TARGET}${_target_suffix}) set_property( SOURCE - ${_generated_extension_files} ${_generated_msg_py_files} ${_generated_msg_c_files} ${_generated_srv_py_files} ${_generated_srv_c_files} + ${_generated_extension_files} ${_generated_msg_py_files} ${_generated_msg_c_files} ${_generated_srv_py_files} ${_generated_srv_c_files} ${_generated_action_py_files} ${_generated_action_c_files} PROPERTY GENERATED 1) macro(set_properties _build_type) @@ -203,6 +235,7 @@ set(_target_name_lib "${rosidl_generate_interfaces_TARGET}__python") add_library(${_target_name_lib} SHARED ${_generated_msg_c_files} ${_generated_srv_c_files} + ${_generated_action_c_files} ) add_dependencies( ${_target_name_lib} @@ -331,7 +364,9 @@ if(BUILD_TESTING AND rosidl_generate_interfaces_ADD_LINTER_TESTS) NOT _generated_extension_files STREQUAL "" OR NOT _generated_msg_c_files STREQUAL "" OR NOT _generated_srv_py_files STREQUAL "" OR - NOT _generated_srv_c_files STREQUAL "" + NOT _generated_srv_c_files STREQUAL "" OR + NOT _generated_action_c_files STREQUAL "" OR + NOT _generated_action_py_files STREQUAL "" ) find_package(ament_cmake_cppcheck REQUIRED) ament_cppcheck( diff --git a/rosidl_generator_py/resource/_msg.py.em b/rosidl_generator_py/resource/_msg.py.em index 8a247963..86b59f60 100644 --- a/rosidl_generator_py/resource/_msg.py.em +++ b/rosidl_generator_py/resource/_msg.py.em @@ -43,11 +43,11 @@ class Metaclass(type): logger.debug( 'Failed to import needed modules for type support:\n' + traceback.format_exc()) else: - cls._CREATE_ROS_MESSAGE = module.create_ros_message_msg_@(module_name) - cls._CONVERT_FROM_PY = module.convert_from_py_msg_@(module_name) - cls._CONVERT_TO_PY = module.convert_to_py_msg_@(module_name) - cls._TYPE_SUPPORT = module.type_support_msg_@(module_name) - cls._DESTROY_ROS_MESSAGE = module.destroy_ros_message_msg_@(module_name) + cls._CREATE_ROS_MESSAGE = module.create_ros_message_msg__@(subfolder)_@(module_name) + cls._CONVERT_FROM_PY = module.convert_from_py_msg__@(subfolder)_@(module_name) + cls._CONVERT_TO_PY = module.convert_to_py_msg__@(subfolder)_@(module_name) + cls._TYPE_SUPPORT = module.type_support_msg__@(subfolder)_@(module_name) + cls._DESTROY_ROS_MESSAGE = module.destroy_ros_message_msg__@(subfolder)_@(module_name) @{ importable_typesupports = {} for field in spec.fields: diff --git a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em index 21d12c48..fb22ec38 100644 --- a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em +++ b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em @@ -26,7 +26,7 @@ static_includes = set([ for spec, subfolder in message_specs: if subfolder == 'msg': static_includes.add('#include ') - elif subfolder == 'srv': + elif subfolder == 'srv' or subfolder == 'action': static_includes.add('#include ') }@ @[for value in sorted(static_includes)]@ @@ -61,21 +61,21 @@ module_name = convert_camel_case_to_lower_case_underscore(type_name) msg_typename = '%s__%s__%s' % (pkg_name, subfolder, type_name) }@ -static void * @(pkg_name)__@(module_name)__create_ros_message(void) +static void * @(pkg_name)__@(subfolder)__@(module_name)__create_ros_message(void) { return @(msg_typename)__create(); } -static void @(pkg_name)__@(module_name)__destroy_ros_message(void * raw_ros_message) +static void @(pkg_name)__@(subfolder)__@(module_name)__destroy_ros_message(void * raw_ros_message) { @(msg_typename) * ros_message = (@(msg_typename) *)raw_ros_message; @(msg_typename)__destroy(ros_message); } ROSIDL_GENERATOR_C_IMPORT -bool @(pkg_name)__@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); +bool @(pkg_name)__@(subfolder)__@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); ROSIDL_GENERATOR_C_IMPORT -PyObject * @(pkg_name)__@(module_name)__convert_to_py(void * raw_ros_message); +PyObject * @(pkg_name)__@(subfolder)__@(module_name)__convert_to_py(void * raw_ros_message); @[end for]@ static PyMethodDef @(package_name)__methods[] = { @@ -105,7 +105,7 @@ const rosidl_message_type_support_t * ROSIDL_GET_MSG_TYPE_SUPPORT(@(pkg_name), @(subfolder), @(spec.msg_name)); int8_t -_register_msg_type__@(type_name)(PyObject * pymodule) +_register_msg_type__@(subfolder)__@(type_name)(PyObject * pymodule) { int8_t err; @[ for function_name in function_names]@ @@ -113,7 +113,7 @@ _register_msg_type__@(type_name)(PyObject * pymodule) PyObject * pyobject_@(function_name) = NULL; pyobject_@(function_name) = PyCapsule_New( @[ if function_name != 'type_support']@ - (void *)&@(pkg_name)__@(type_name)__@(function_name), + (void *)&@(pkg_name)__@(subfolder)__@(type_name)__@(function_name), @[ else]@ (void *)ROSIDL_GET_MSG_TYPE_SUPPORT(@(pkg_name), @(subfolder), @(spec.msg_name)), @[ end if]@ @@ -124,7 +124,7 @@ _register_msg_type__@(type_name)(PyObject * pymodule) } err = PyModule_AddObject( pymodule, - "@(function_name)_msg_@(type_name)", + "@(function_name)_msg__@(subfolder)_@(type_name)", pyobject_@(function_name)); if (err) { // the created capsule needs to be decremented @@ -144,15 +144,15 @@ function_name = 'type_support' ROSIDL_GENERATOR_C_IMPORT const rosidl_service_type_support_t * -ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME(rosidl_typesupport_c, @(spec.pkg_name), @(spec.srv_name))(); +ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME(rosidl_typesupport_c, @(spec.pkg_name), @(subfolder), @(spec.srv_name))(); int8_t -_register_srv_type__@(type_name)(PyObject * pymodule) +_register_srv_type__@(subfolder)__@(type_name)(PyObject * pymodule) { int8_t err; PyObject * pyobject_@(function_name) = NULL; pyobject_@(function_name) = PyCapsule_New( - (void *)ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME(rosidl_typesupport_c, @(spec.pkg_name), @(spec.srv_name))(), + (void *)ROSIDL_TYPESUPPORT_INTERFACE__SERVICE_SYMBOL_NAME(rosidl_typesupport_c, @(spec.pkg_name), @(subfolder), @(spec.srv_name))(), NULL, NULL); if (!pyobject_@(function_name)) { // previously added objects will be removed when the module is destroyed @@ -160,7 +160,7 @@ _register_srv_type__@(type_name)(PyObject * pymodule) } err = PyModule_AddObject( pymodule, - "@(function_name)_srv_@(type_name)", + "@(function_name)_srv__@(subfolder)_@(type_name)", pyobject_@(function_name)); if (err) { // the created capsule needs to be decremented @@ -185,7 +185,7 @@ PyInit_@(package_name)_s__@(typesupport_impl)(void) @{ type_name = convert_camel_case_to_lower_case_underscore(spec.base_type.type) }@ - err = _register_msg_type__@(type_name)(pymodule); + err = _register_msg_type__@(subfolder)__@(type_name)(pymodule); if (err) { Py_XDECREF(pymodule); return NULL; @@ -195,7 +195,7 @@ type_name = convert_camel_case_to_lower_case_underscore(spec.base_type.type) @{ type_name = convert_camel_case_to_lower_case_underscore(spec.srv_name) }@ - err = _register_srv_type__@(type_name)(pymodule); + err = _register_srv_type__@(subfolder)__@(type_name)(pymodule); if (err) { Py_XDECREF(pymodule); return NULL; diff --git a/rosidl_generator_py/resource/_msg_support.c.em b/rosidl_generator_py/resource/_msg_support.c.em index 7d297951..d35754a0 100644 --- a/rosidl_generator_py/resource/_msg_support.c.em +++ b/rosidl_generator_py/resource/_msg_support.c.em @@ -61,16 +61,16 @@ msg_typename = '%s__%s__%s' % (spec.base_type.pkg_name, subfolder, spec.base_typ @[ if spec.base_type.pkg_name != field.type.pkg_name]@ ROSIDL_GENERATOR_C_IMPORT @[ end if]@ -bool @(field.type.pkg_name)__@(lowercase_field_type)__convert_from_py(PyObject * _pymsg, void * _ros_message); +bool @(field.type.pkg_name)__msg__@(lowercase_field_type)__convert_from_py(PyObject * _pymsg, void * _ros_message); @[ if spec.base_type.pkg_name != field.type.pkg_name]@ ROSIDL_GENERATOR_C_IMPORT @[ end if]@ -PyObject * @(field.type.pkg_name)__@(lowercase_field_type)__convert_to_py(void * raw_ros_message); +PyObject * @(field.type.pkg_name)__msg__@(lowercase_field_type)__convert_to_py(void * raw_ros_message); @[ end if]@ @[end for]@ ROSIDL_GENERATOR_C_EXPORT -bool @(spec.base_type.pkg_name)__@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message) +bool @(spec.base_type.pkg_name)__@(subfolder)__@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message) { @{ full_classname = '%s.%s._%s.%s' % (spec.base_type.pkg_name, subfolder, module_name, spec.base_type.type) @@ -146,7 +146,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty @(nested_type) * dest = ros_message->@(field.name); @[ end if]@ for (Py_ssize_t i = 0; i < size; ++i) { - if (!@(field.type.pkg_name)__@(lowercase_field_type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { + if (!@(field.type.pkg_name)__msg__@(lowercase_field_type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { Py_DECREF(seq_field); Py_DECREF(field); return false; @@ -154,7 +154,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty } Py_DECREF(seq_field); @[ else]@ - if (!@(field.type.pkg_name)__@(lowercase_field_type)__convert_from_py(field, &ros_message->@(field.name))) { + if (!@(field.type.pkg_name)__msg__@(lowercase_field_type)__convert_from_py(field, &ros_message->@(field.name))) { Py_DECREF(field); return false; } @@ -302,7 +302,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty } ROSIDL_GENERATOR_C_EXPORT -PyObject * @(spec.base_type.pkg_name)__@(module_name)__convert_to_py(void * raw_ros_message) +PyObject * @(spec.base_type.pkg_name)__@(subfolder)__@(module_name)__convert_to_py(void * raw_ros_message) { /* NOTE(esteve): Call constructor of @(spec.base_type.type) */ PyObject * _pymessage = NULL; @@ -347,7 +347,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty @[ else]@ item = &(ros_message->@(field.name)[i]); @[ end if]@ - PyObject * pyitem = @(field.type.pkg_name)__@(lowercase_field_type)__convert_to_py(item); + PyObject * pyitem = @(field.type.pkg_name)__msg__@(lowercase_field_type)__convert_to_py(item); if (!pyitem) { Py_DECREF(field); return NULL; @@ -358,7 +358,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty } assert(PySequence_Check(field)); @[ else]@ - field = @(field.type.pkg_name)__@(lowercase_field_type)__convert_to_py(&ros_message->@(field.name)); + field = @(field.type.pkg_name)__msg__@(lowercase_field_type)__convert_to_py(&ros_message->@(field.name)); if (!field) { return NULL; } diff --git a/rosidl_generator_py/resource/_srv.py.em b/rosidl_generator_py/resource/_srv.py.em index eab629ec..16756abb 100644 --- a/rosidl_generator_py/resource/_srv.py.em +++ b/rosidl_generator_py/resource/_srv.py.em @@ -31,19 +31,19 @@ class Metaclass(type): logger.debug( 'Failed to import needed modules for type support:\n' + traceback.format_exc()) else: - cls._TYPE_SUPPORT = module.type_support_srv_@(module_name) + cls._TYPE_SUPPORT = module.type_support_srv__@(subfolder)_@(module_name) @{ srv_name = '_' + convert_camel_case_to_lower_case_underscore(spec.srv_name) for field_name in [srv_name + '__request', srv_name + '__response']: - print('%sfrom %s.srv import %s' % (' ' * 4 * 3, package_name, field_name)) + print('%sfrom %s.%s import %s' % (' ' * 4 * 3, package_name, subfolder, field_name)) print('%sif %s.Metaclass._TYPE_SUPPORT is None:' % (' ' * 4 * 3, field_name)) print('%s%s.Metaclass.__import_type_support__()' % (' ' * 4 * 4, field_name)) }@ class @(spec.srv_name)(metaclass=Metaclass): - from @(package_name).srv._@convert_camel_case_to_lower_case_underscore(spec.srv_name)__request import @(spec.srv_name)_Request as Request - from @(package_name).srv._@convert_camel_case_to_lower_case_underscore(spec.srv_name)__response import @(spec.srv_name)_Response as Response + from @(package_name).@(subfolder)._@convert_camel_case_to_lower_case_underscore(spec.srv_name)__request import @(spec.srv_name)_Request as Request + from @(package_name).@(subfolder)._@convert_camel_case_to_lower_case_underscore(spec.srv_name)__response import @(spec.srv_name)_Response as Response def __init__(self): raise NotImplementedError('Service classes can not be instanciated') diff --git a/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py b/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py index 6b0d20e3..2a87842a 100644 --- a/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py +++ b/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py @@ -98,7 +98,8 @@ def generate_py(generator_arguments_file, typesupport_impls): for subfolder in modules.keys(): import_list = {} for module_name, type_ in modules[subfolder]: - if subfolder == 'srv' and (type_.endswith('Request') or type_.endswith('Response')): + if (subfolder == 'srv' or subfolder == 'action') and \ + (type_.endswith('Request') or type_.endswith('Response')): continue import_list['%s # noqa\n' % type_] = 'from %s.%s._%s import %s\n' % \ (args['package_name'], subfolder, module_name, type_)