uorb: add message format compatibility check

This can be used by DDS/ROS 2 to check for matching message definitions.
This commit is contained in:
Beat Küng
2023-11-15 13:18:58 +01:00
parent 0dcecf0666
commit 22acb08406
9 changed files with 162 additions and 2 deletions
@@ -171,6 +171,61 @@ def get_children_fields(base_type, search_path):
return spec_temp.parsed_fields()
def get_message_fields_str_for_message_hash(msg_fields, search_path):
"""
Get all fields (including for nested types) in the form of:
'''
uint64 timestamp
uint8 esc_count
uint8 esc_online_flags
EscReport[8] esc
uint64 timestamp
uint32 esc_errorcount
int32 esc_rpm
float32 esc_voltage
uint16 failures
int8 esc_power
'''
"""
all_fields_str = ''
for field in msg_fields:
if field.is_header:
continue
type_name = field.type
# detect embedded types
sl_pos = type_name.find('/')
if sl_pos >= 0:
type_name = type_name[sl_pos + 1:]
all_fields_str += type_name + ' ' + field.name + '\n'
if sl_pos >= 0: # nested type, add all nested fields
children_fields = get_children_fields(field.base_type, search_path)
all_fields_str += get_message_fields_str_for_message_hash(children_fields, search_path)
return all_fields_str
def hash_32_fnv1a(data: str):
hash_val = 0x811c9dc5
prime = 0x1000193
for i in range(len(data)):
value = ord(data[i])
hash_val = hash_val ^ value
hash_val *= prime
hash_val &= 0xffffffff
return hash_val
def get_message_hash(msg_fields, search_path):
"""
Get a 32 bit message hash over all fields
"""
all_fields_str = get_message_fields_str_for_message_hash(msg_fields, search_path)
return hash_32_fnv1a(all_fields_str)
def add_padding_bytes(fields, search_path):
"""
Add padding fields before the embedded types, at the end and calculate the
+2 -1
View File
@@ -58,6 +58,7 @@ from px_generate_uorb_topic_helper import * # this is in Tools/
uorb_struct = '%s_s'%name_snake_case
message_hash = get_message_hash(spec.parsed_fields(), search_path)
sorted_fields = sorted(spec.parsed_fields(), key=sizeof_field_type, reverse=True)
struct_size, padding_end_size = add_padding_bytes(sorted_fields, search_path)
}@
@@ -74,7 +75,7 @@ struct_size, padding_end_size = add_padding_bytes(sorted_fields, search_path)
@[for topic in topics]@
static_assert(static_cast<orb_id_size_t>(ORB_ID::@topic) == @(all_topics.index(topic)), "ORB_ID index mismatch");
ORB_DEFINE(@topic, struct @uorb_struct, @(struct_size-padding_end_size), static_cast<orb_id_size_t>(ORB_ID::@topic));
ORB_DEFINE(@topic, struct @uorb_struct, @(struct_size-padding_end_size), @(message_hash)u, static_cast<orb_id_size_t>(ORB_ID::@topic));
@[end for]
void print_message(const orb_metadata *meta, const @uorb_struct& message)