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

Add runtime type introspection section #3

Conversation

methylDragon
Copy link
Collaborator

No description provided.

@methylDragon methylDragon changed the base branch from master to evolving_message_types_rep June 1, 2022 01:32
@methylDragon
Copy link
Collaborator Author

I just saw the reviews from #1 and #2, let me push some changes

@methylDragon methylDragon force-pushed the ch3/runtime_type_introspection branch 3 times, most recently from ce919d9 to eeff240 Compare June 1, 2022 01:55
@wjwwood wjwwood changed the base branch from evolving_message_types_rep to methylDragon/type_description_distribution June 2, 2022 18:55
@wjwwood
Copy link
Owner

wjwwood commented Jun 2, 2022

I changed the base to point to the branch for #2, so that you don't have to keep them in sync. Once it is merged we can change the base back to the target branch and merge this one (after iterating).

@methylDragon methylDragon force-pushed the methylDragon/type_description_distribution branch from 4bbc874 to 5095037 Compare June 2, 2022 20:41
@wjwwood wjwwood deleted the branch wjwwood:evolving_message_types_rep June 10, 2022 01:01
@wjwwood wjwwood closed this Jun 10, 2022
@wjwwood wjwwood reopened this Jun 10, 2022
@wjwwood wjwwood changed the base branch from methylDragon/type_description_distribution to evolving_message_types_rep June 10, 2022 01:02
@wjwwood
Copy link
Owner

wjwwood commented Jun 10, 2022

@methylDragon can you rebase this, I had to rename the file due our REP number getting swiped (it's my fault).

Signed-off-by: methylDragon <methylDragon@gmail.com>
@methylDragon methylDragon force-pushed the ch3/runtime_type_introspection branch from eeff240 to b1550bf Compare June 10, 2022 17:34
@methylDragon
Copy link
Collaborator Author

Rebased!

Copy link
Owner

@wjwwood wjwwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fixup what makes sense here, and then continue with the nested types pr on top.

rep-2011.rst Outdated
@@ -321,7 +321,214 @@ The passed ``rosidl_message_type_support_t`` in the init call can be introspecte
Runtime Type Introspection
--------------------------

.. TODO:: terminology could be better? nothing off the top of my head, just deserves more bike-shedding.
The ability to detect type mismatches and obtain the type description in the event of a mismatch in the previous two sections enables the ability to do runtime type introspection.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically the ability to detect type mismatches doesn't support runtime type introspection. The feature could be used to parse a message from a bagfile using just the description included with it. That neither uses a version hash nor does it require type description distribution.

It's true that we do want to use those two things in conjunction with runtime type introspection, but technically they are orthogonal. So this isn't wrong, we should just reword it a bit with better qualifying statements.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the case where there exists multiple applicable plugins for a particular serialization format, the plugin matching should follow this priority order:

- user specified overrides passed to the matching function
- defaults defined in the plugin matching function, if applicable, otherwise
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mention the use case for this, i.e. connext's CDR library vs Fast-CDR, which should you use if both are available?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rep-2011.rst Outdated
Comment on lines 397 to 412
The following is an example of how this plugin matching and loading interface could look like, defining new ``rcl`` interfaces; with a plugin wrapping FastCDR v1.0.24 for serialization, with some arbitrary message type `Foo`:

.. code::

// Suppose FooDescription reports that it uses FastCDR v1.0.24 for its serialization
rcl_message_description_t FooDescription = node->get_type_description("/foo_endpoint_name");

rcl_type_introspection_t * introspection_handle;
introspection_handle->init(); // Locate local plugins here

// Plugin name: "fastcdr_v1_0_24"
const char * plugin_name = introspection_handle->match_plugin(FooDescription->get_serialization_format());
rcl_serialization_plugin_t * plugin = introspection_handle->load_plugin("fastcdr_v1_0_24");

// If we wanted to force the use of MicroCDR instead
introspection_handle->match_plugin(FooDescription->get_serialization_type(), "microcdr");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try using a concrete example, like /scan and sensor_msgs/msg/LaserScan. (or image or point cloud)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rep-2011.rst Outdated
Comment on lines 437 to 482
Plugin Deserialization
""""""""""""""""""""""

One way a serialization library plugin for FastCDR could be implemented could be as follows, relying on the serialization library to deserialize the message buffer, but with the provided type description to supply type reflection information:

.. code::

#include <FastBuffer.h>
#include <FastCdr.h>

// If the parsed description is iterable
// rcl_serialization_plugin_t->(*deserialize)
void deserialize(void *buffer,
plugin_internal_description_t *description,
rcl_deserialized_message_t *msg)
{
FastCdr * cdr = new FastCdr(new FastBuffer((char *)buffer, description->buffer_length));

msg->message_field_names = new char*[description->num_fields];
msg->message_types = new char*[description->num_fields];

for (int i = 0; i < description->num_fields; i++)
{
const char * type = description->field_types[i];

// Primitives
if (strcmp(type, "bool") == 0)
{
bool tmp;
}
else if (strcmp(type, "char") == 0)
{
char tmp;
}
...

// TODO:: What to do about nested types? A recursive unpacking call with a different description?

cdr >> tmp;
msg->message_fields[description->field_names[i]] = reinterpret_cast<void *>(tmp);

msg->message_field_names[i] = description->field_names[i];
msg->message_types[i] = description->field_types[i];
}
msg->message_field_count = description->num_fields;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on off-line discussion, let's drop this section.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +484 to +529
Example Introspection API
^^^^^^^^^^^^^^^^^^^^^^^^^

Once the serialization library plugins are able to deserialize the raw message buffer, downstream programs can then introspect the constructed deserialized message object, which should be laid out as such:

.. code::

struct rcl_deserialized_field_t {
void * value;
char * type;
}

struct rcl_deserialized_message_t {
int message_field_count;
const char** message_field_names;
const char** message_types;

// Some dynamically allocated key->value associative map type storing void * field values
rcl_associative_array message_fields;

// Function pointers
rcl_deserialized_field_t * (*get_field_by_index)(int index);
};

Now, for a given message description `Foo.msg`:

.. code::

// Foo.msg
bool bool_field
char char_field
float32 float_field

The corresponding `rcl_deserialized_message_t` can be queried accordingly:

.. code::

rcl_deserialized_message_t * foo_msg;
foo_msg->message_field_names[0]; // "bool_field"
foo_msg->message_types[0]; // "bool"

// Get the field
if (strcmp("bool", foo_msg->get_field_by_index(0)->type) == 0)
{
*((bool*)foo_msg->get_field_by_index(0)->value);
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this needs to be updated with the nested types work.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will be updated in the next PR

methylDragon and others added 2 commits July 7, 2022 14:02
Signed-off-by: methylDragon <methylDragon@gmail.com>

Co-authored-by: William Woodall <william+github@osrfoundation.org>
Signed-off-by: methylDragon <methylDragon@gmail.com>
@methylDragon methylDragon merged commit 22f6cb7 into wjwwood:evolving_message_types_rep Jul 8, 2022
@methylDragon methylDragon deleted the ch3/runtime_type_introspection branch July 15, 2022 02:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants