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

Type hash in interface codegen (rep2011) #722

Merged
merged 65 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
8e6aac6
WIP generating type hash during code gen
emersonknapp Jan 21, 2023
cd8e81c
WIP starting to look at referenced types as well
emersonknapp Jan 22, 2023
ce77ab1
Refactoring type hash to other file
emersonknapp Jan 23, 2023
6d582ea
Including referenced type desrciptions now
emersonknapp Jan 23, 2023
a51bf43
Added type version hash to all 3 generators
emersonknapp Jan 24, 2023
e37e8e5
Minor cleanup for readability
emersonknapp Jan 24, 2023
4834bfa
Output a json file (for every generator, want to fix this)
emersonknapp Jan 27, 2023
edc61c2
WIP just copying generator C feeling out what I really need for this …
emersonknapp Feb 2, 2023
50e6c5d
WIP refactoring as a new rosidl generator
emersonknapp Feb 3, 2023
fcc5bd8
Cleanup some C artifacts
emersonknapp Feb 4, 2023
9044094
rosidl generator creating and installing expected files
emersonknapp Feb 7, 2023
8b5d892
Revert pycommon changes
emersonknapp Feb 7, 2023
7e79cee
Generate action struct
emersonknapp Feb 7, 2023
7dde0c2
Type hash depended upon and loaded by C and C++ generators
emersonknapp Feb 7, 2023
572f13f
Cleanup cmake comments
emersonknapp Feb 7, 2023
6f9620d
Use arguments json file instead of direct arguments
emersonknapp Feb 8, 2023
fd82445
Generate separate hashes and jsons for interface subtypes - not yet p…
emersonknapp Feb 8, 2023
048cc98
Pretty print the type hashes in C/Cpp
emersonknapp Feb 8, 2023
9d4636a
Code cleanup pass
emersonknapp Feb 8, 2023
c5b1364
WIP defining type hash structure i need by usage patterns
emersonknapp Feb 9, 2023
713132b
New nested version working for msg/srv
emersonknapp Feb 9, 2023
ce87154
Add action breakdown
emersonknapp Feb 9, 2023
9185874
Simplify subinterface generation
emersonknapp Feb 10, 2023
70c5903
dedupe repetition in individual type description serializing
emersonknapp Feb 10, 2023
deade42
Individually filtered includes for all subinterfaces
emersonknapp Feb 10, 2023
b7600fe
No indent on json outs
emersonknapp Feb 10, 2023
b3fb444
Ad dtoplevel for action and service
emersonknapp Feb 10, 2023
27fce61
Code cleanup pass
emersonknapp Feb 10, 2023
8fc293a
Need extra declaration for constexpr static template member
emersonknapp Feb 17, 2023
9977f34
Add type hash to introspection
emersonknapp Feb 20, 2023
0d2a67f
Service introspection type hash todo
emersonknapp Feb 21, 2023
f6a50b7
Remove CLI
emersonknapp Feb 21, 2023
ec75b02
Jsonschemas first pass
emersonknapp Feb 21, 2023
ff5135a
Add rosidl_type_hash_t to rosidl_runtime_c
emersonknapp Feb 22, 2023
4d27998
Type hash struct
emersonknapp Feb 22, 2023
2e17955
Type hash cpp
emersonknapp Feb 22, 2023
3c57119
Extern c for the helper functions, and extra includes
emersonknapp Feb 22, 2023
d457eb4
Use rosidl def not sha256
emersonknapp Feb 22, 2023
8fa6359
Parse type hash string utility
emersonknapp Feb 22, 2023
afbfb41
Fix off-by-one stringifying
emersonknapp Feb 22, 2023
ec3126a
Code cleanup pass
emersonknapp Feb 22, 2023
226a0d1
Add docs and tests for rosidl_type_hash
emersonknapp Feb 22, 2023
b2a4132
Clean up schemata
emersonknapp Feb 22, 2023
9dbd2c6
Add schema checking test
emersonknapp Feb 23, 2023
ec45a34
Fix tests
emersonknapp Feb 23, 2023
166e16e
Fix length/string_length field serialization and add a test
emersonknapp Feb 24, 2023
705aed0
Address review comments
emersonknapp Feb 24, 2023
82ed9b4
Not bytes to file
emersonknapp Feb 24, 2023
d744244
Move type hash declarer to rosidl_generator_c
emersonknapp Feb 28, 2023
41b1d13
Reimplement type hash string parsing without sscanf
emersonknapp Mar 1, 2023
4843fb1
Easier to read and maintain, slightly longer, fieldtype serialization
emersonknapp Mar 1, 2023
f803291
Use new FieldType field names
emersonknapp Mar 2, 2023
b22b6c6
Type hashes single-file simplified flow
emersonknapp Mar 2, 2023
eb127f2
Rename rosidl_generator_type_hash to rosidl_generator_type_description
emersonknapp Mar 7, 2023
3fce7b5
Address review comments
emersonknapp Mar 8, 2023
0b08862
Go full-constant for windows complaints
emersonknapp Mar 9, 2023
db50587
Fix type hash validation error and stringify-reversing error, add tes…
emersonknapp Mar 9, 2023
1f2c6ca
Fix windows build: path handling fix, and type hash define initializer
emersonknapp Mar 10, 2023
7d291cc
Windows paths have colons
emersonknapp Mar 10, 2023
f6571ac
Fix linter error by adding a futureproofing check
emersonknapp Mar 10, 2023
fa9bf55
Address review comments
emersonknapp Mar 10, 2023
6fff5a6
Add new test for nested types
emersonknapp Mar 10, 2023
d642a48
Generate hashes in C for services of action
emersonknapp Mar 13, 2023
cfd74df
Rename type_description to type_description_msg
emersonknapp Mar 13, 2023
a339dd9
Add comment note about __INIT defines
emersonknapp Mar 13, 2023
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ See [documentation](https://docs.ros.org/en/rolling/Concepts/About-Internal-Inte
* Generate the ROS interfaces in C
* [rosidl_generator_cpp](./rosidl_generator_cpp)
* Generate the ROS interfaces in C++
* [rosidl_generator_type_hash](./rosidl_generator_type_hash)
* Generate SHA256 hash values for ROS 2 interface descriptions for use by other generators
* [rosidl_parser](./rosidl_parser)
* Parser for `.idl` ROS interface files
* [rosidl_runtime_c](./rosidl_runtime_c)
Expand Down
2 changes: 2 additions & 0 deletions rosidl_cmake/cmake/rosidl_write_generator_arguments.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ function(rosidl_write_generator_arguments output_file)
set(OPTIONAL_MULTI_VALUE_KEYWORDS
"ROS_INTERFACE_DEPENDENCIES" # since the dependencies can be empty
"TARGET_DEPENDENCIES"
"TYPE_HASH_TUPLES"
"INCLUDE_PATHS"
"ADDITIONAL_FILES")

cmake_parse_arguments(
Expand Down
1 change: 1 addition & 0 deletions rosidl_generator_c/cmake/register_c.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

macro(rosidl_generator_c_extras BIN GENERATOR_FILES TEMPLATE_DIR)
find_package(ament_cmake_core QUIET REQUIRED)
find_package(rosidl_generator_type_hash QUIET REQUIRED)
ament_register_extension(
"rosidl_generate_idl_interfaces"
"rosidl_generator_c"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ rosidl_write_generator_arguments(
OUTPUT_DIR "${_output_path}"
TEMPLATE_DIR "${rosidl_generator_c_TEMPLATE_DIR}"
TARGET_DEPENDENCIES ${target_dependencies}
TYPE_HASH_TUPLES "${${rosidl_generate_interfaces_TARGET}__HASH_TUPLES}"
)

find_package(Python3 REQUIRED COMPONENTS Interpreter)
Expand Down Expand Up @@ -142,6 +143,9 @@ target_link_libraries(${rosidl_generate_interfaces_TARGET}${_target_suffix} PUBL
rosidl_runtime_c::rosidl_runtime_c
rosidl_typesupport_interface::rosidl_typesupport_interface
rcutils::rcutils)
add_dependencies(
methylDragon marked this conversation as resolved.
Show resolved Hide resolved
${rosidl_generate_interfaces_TARGET}${_target_suffix}
${rosidl_generate_interfaces_TARGET}__rosidl_generator_type_hash)

# Make top level generation target depend on this generated library
add_dependencies(
Expand Down
2 changes: 2 additions & 0 deletions rosidl_generator_c/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@
<buildtool_export_depend>python3</buildtool_export_depend>
<buildtool_export_depend>rosidl_pycommon</buildtool_export_depend>

<build_export_depend>rosidl_generator_type_hash</build_export_depend>
<build_export_depend>rosidl_typesupport_interface</build_export_depend>
<build_export_depend>rcutils</build_export_depend>

<exec_depend>ament_index_python</exec_depend>
<exec_depend>rosidl_cli</exec_depend>
<exec_depend>rosidl_parser</exec_depend>
<exec_depend>rcutils</exec_depend>
<exec_depend>rosidl_generator_type_hash</exec_depend>

<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
Expand Down
49 changes: 35 additions & 14 deletions rosidl_generator_c/resource/idl__struct.h.em
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
@# - content (IdlContent, list of elements, e.g. Messages or Services)
@#######################################################################
@{
from rosidl_generator_c import idl_structure_type_to_c_typename
from rosidl_generator_c import type_hash_to_c_definition
from rosidl_pycommon import convert_camel_case_to_lower_case_underscore
include_parts = [package_name] + list(interface_path.parents[0].parts) + [
'detail', convert_camel_case_to_lower_case_underscore(interface_path.stem)]
Expand All @@ -32,6 +34,8 @@ extern "C"
#include <stddef.h>
#include <stdint.h>

#include "rosidl_runtime_c/type_hash.h"

@#######################################################################
@# Handle message
@#######################################################################
Expand All @@ -43,7 +47,7 @@ from rosidl_parser.definition import Message
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=message, include_directives=include_directives)
message=message, include_directives=include_directives, type_hash=type_hash)
}@

@[end for]@
Expand All @@ -55,25 +59,30 @@ TEMPLATE(
from rosidl_parser.definition import Service
}@
@[for service in content.get_elements_of_type(Service)]@
static const @(type_hash_to_c_definition(idl_structure_type_to_c_typename(service.namespaced_type) + "__TYPE_VERSION_HASH", type_hash['service']))@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=service.request_message, include_directives=include_directives)
message=service.request_message, include_directives=include_directives,
type_hash=type_hash['request_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=service.response_message, include_directives=include_directives)
message=service.response_message, include_directives=include_directives,
type_hash=type_hash['response_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=service.event_message, include_directives=include_directives)
message=service.event_message, include_directives=include_directives,
type_hash=type_hash['event_message'])
}@

@[end for]@
Expand All @@ -85,74 +94,86 @@ TEMPLATE(
from rosidl_parser.definition import Action
}@
@[for action in content.get_elements_of_type(Action)]@
static const @(type_hash_to_c_definition(idl_structure_type_to_c_typename(action.namespaced_type) + "__TYPE_VERSION_HASH", type_hash['action']))@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.goal, include_directives=include_directives)
message=action.goal, include_directives=include_directives,
type_hash=type_hash['goal'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.result, include_directives=include_directives)
message=action.result, include_directives=include_directives,
type_hash=type_hash['result'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.feedback, include_directives=include_directives)
message=action.feedback, include_directives=include_directives,
type_hash=type_hash['feedback'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.send_goal_service.request_message, include_directives=include_directives)
message=action.send_goal_service.request_message, include_directives=include_directives,
type_hash=type_hash['send_goal_service']['request_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.send_goal_service.response_message, include_directives=include_directives)
message=action.send_goal_service.response_message, include_directives=include_directives,
type_hash=type_hash['send_goal_service']['response_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.send_goal_service.event_message, include_directives=include_directives)
message=action.send_goal_service.event_message, include_directives=include_directives,
type_hash=type_hash['send_goal_service']['event_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.get_result_service.request_message, include_directives=include_directives)
message=action.get_result_service.request_message, include_directives=include_directives,
type_hash=type_hash['get_result_service']['request_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.get_result_service.response_message, include_directives=include_directives)
message=action.get_result_service.response_message, include_directives=include_directives,
type_hash=type_hash['get_result_service']['response_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.get_result_service.event_message, include_directives=include_directives)
message=action.get_result_service.event_message, include_directives=include_directives,
type_hash=type_hash['get_result_service']['event_message'])
}@

@{
TEMPLATE(
'msg__struct.h.em',
package_name=package_name, interface_path=interface_path,
message=action.feedback_message, include_directives=include_directives)
message=action.feedback_message, include_directives=include_directives,
type_hash=type_hash['feedback_message'])
}@

@[end for]@
Expand Down
4 changes: 4 additions & 0 deletions rosidl_generator_c/resource/msg__struct.h.em
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ from rosidl_generator_c import idl_structure_type_sequence_to_c_typename
from rosidl_generator_c import idl_structure_type_to_c_include_prefix
from rosidl_generator_c import idl_structure_type_to_c_typename
from rosidl_generator_c import interface_path_to_string
from rosidl_generator_c import type_hash_to_c_definition
from rosidl_generator_c import value_to_c
}@
@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Expand Down Expand Up @@ -177,6 +178,9 @@ typedef struct @(idl_structure_type_to_c_typename(message.structure.namespaced_t
@(idl_declaration_to_c(member.type, member.name));
@[end for]@
} @(idl_structure_type_to_c_typename(message.structure.namespaced_type));

// Type Version Hash for interface
static const @(type_hash_to_c_definition(idl_structure_type_to_c_typename(message.structure.namespaced_type) + "__TYPE_VERSION_HASH", type_hash['message']))@
@#>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

@#<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Expand Down
25 changes: 25 additions & 0 deletions rosidl_generator_c/rosidl_generator_c/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import re

from rosidl_parser.definition import AbstractGenericString
from rosidl_parser.definition import AbstractSequence
from rosidl_parser.definition import AbstractString
Expand Down Expand Up @@ -219,3 +221,26 @@ def escape_string(s):

def escape_wstring(s):
return escape_string(s)


def type_hash_to_c_definition(variable_name, hash_string, indent=0):
"""Generate empy for rosidl_type_hash_t instance with 8 bytes per line for readability."""
hash_length = 32
bytes_per_line = 8

indent_str = ' ' * (indent + 2)
pattern = re.compile(r'RIHS([0-9a-f]{2})_([0-9a-f]{64})')
emersonknapp marked this conversation as resolved.
Show resolved Hide resolved
match = pattern.match(hash_string)
if not match:
raise Exception('Type hash string does not match expected RIHS format')
version, value = match.group(1, 2)

result = f'rosidl_type_hash_t {variable_name} = {{{version}, {{'
for i in range(hash_length):
if i % bytes_per_line == 0:
result += f'\n{indent_str} '
result += f'0x{value[i * 2:i * 2 + 2]},'
if i % bytes_per_line != bytes_per_line - 1:
result += ' '
result += f'\n{indent_str}}}}};\n'
return result
1 change: 1 addition & 0 deletions rosidl_generator_cpp/cmake/register_cpp.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

macro(rosidl_generator_cpp_extras BIN GENERATOR_FILES TEMPLATE_DIR)
find_package(ament_cmake_core QUIET REQUIRED)
find_package(rosidl_generator_type_hash QUIET REQUIRED)
ament_register_extension(
"rosidl_generate_idl_interfaces"
"rosidl_generator_cpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ rosidl_write_generator_arguments(
OUTPUT_DIR "${_output_path}"
TEMPLATE_DIR "${rosidl_generator_cpp_TEMPLATE_DIR}"
TARGET_DEPENDENCIES ${target_dependencies}
TYPE_HASH_TUPLES "${${rosidl_generate_interfaces_TARGET}__HASH_TUPLES}"
)

find_package(Python3 REQUIRED COMPONENTS Interpreter)
Expand All @@ -99,6 +100,9 @@ add_custom_target(
DEPENDS
${_generated_headers}
)
add_dependencies(
${rosidl_generate_interfaces_TARGET}__cpp
${rosidl_generate_interfaces_TARGET}__rosidl_generator_type_hash)

set(_target_suffix "__rosidl_generator_cpp")
add_library(${rosidl_generate_interfaces_TARGET}${_target_suffix} INTERFACE)
Expand Down
1 change: 1 addition & 0 deletions rosidl_generator_cpp/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

<exec_depend>ament_index_python</exec_depend>
<exec_depend>rosidl_cli</exec_depend>
<exec_depend>rosidl_generator_type_hash</exec_depend>
<exec_depend>rosidl_parser</exec_depend>

<test_depend>ament_lint_auto</test_depend>
Expand Down
21 changes: 15 additions & 6 deletions rosidl_generator_cpp/resource/action__struct.hpp.em
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@# Included from rosidl_generator_cpp/resource/idl__struct.hpp.em
@{
from rosidl_generator_c import type_hash_to_c_definition
from rosidl_parser.definition import ACTION_FEEDBACK_MESSAGE_SUFFIX
from rosidl_parser.definition import ACTION_FEEDBACK_SUFFIX
from rosidl_parser.definition import ACTION_GOAL_SERVICE_SUFFIX
Expand All @@ -17,42 +18,48 @@ action_name = '::'.join(action.namespaced_type.namespaced_name())
TEMPLATE(
'msg__struct.hpp.em',
package_name=package_name, interface_path=interface_path,
message=action.goal, include_directives=include_directives)
message=action.goal, include_directives=include_directives,
type_hash=type_hash['goal'])
}@

@{
TEMPLATE(
'msg__struct.hpp.em',
package_name=package_name, interface_path=interface_path,
message=action.result, include_directives=include_directives)
message=action.result, include_directives=include_directives,
type_hash=type_hash['result'])
}@

@{
TEMPLATE(
'msg__struct.hpp.em',
package_name=package_name, interface_path=interface_path,
message=action.feedback, include_directives=include_directives)
message=action.feedback, include_directives=include_directives,
type_hash=type_hash['feedback'])
}@

@{
TEMPLATE(
'srv__struct.hpp.em',
package_name=package_name, interface_path=interface_path,
service=action.send_goal_service, include_directives=include_directives)
service=action.send_goal_service, include_directives=include_directives,
type_hash=type_hash['send_goal_service'])
}@

@{
TEMPLATE(
'srv__struct.hpp.em',
package_name=package_name, interface_path=interface_path,
service=action.get_result_service, include_directives=include_directives)
service=action.get_result_service, include_directives=include_directives,
type_hash=type_hash['get_result_service'])
}@

@{
TEMPLATE(
'msg__struct.hpp.em',
package_name=package_name, interface_path=interface_path,
message=action.feedback_message, include_directives=include_directives)
message=action.feedback_message, include_directives=include_directives,
type_hash=type_hash['feedback_message'])
}@

@[for header_file in action_includes]@
Expand All @@ -72,6 +79,8 @@ namespace @(ns)
@[end for]@
struct @(action.namespaced_type.name)
{
static constexpr const @(type_hash_to_c_definition("TYPE_VERSION_HASH", type_hash['action'], indent=2))@

/// The goal message defined in the action definition.
using Goal = @(action_name)@(ACTION_GOAL_SUFFIX);
/// The result message defined in the action definition.
Expand Down
Loading