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

REP 2007: Type Adaptation #303

Merged
merged 29 commits into from
May 26, 2021
Merged
Changes from 6 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cfde98f
Add draft of rep-2007
audrow Jan 28, 2021
f2f05b3
Update draft of 2007
audrow Jan 29, 2021
6362c65
Minor edits
audrow Feb 1, 2021
d2a7a4c
Update type to Standards Track
audrow Feb 1, 2021
07a6e84
Change status to "Draft"
audrow Feb 1, 2021
953677d
Update wording of the abstract
audrow Feb 1, 2021
658c209
Change to `AdaptType` and update including "Type" discussion
audrow Feb 2, 2021
eb04fad
Add a link to the REPL
audrow Feb 2, 2021
eb552ae
Update examples to use `make_shared`
audrow Feb 2, 2021
7b354e5
Remove placeholders
audrow Feb 2, 2021
13ff3d4
Update abstract
audrow Feb 2, 2021
f4b3e5f
Number publishers created in examples
audrow Feb 2, 2021
3d4a17f
Add performance reason to motivation
audrow Feb 2, 2021
ff47a6e
Apply suggestions from code review
wjwwood Feb 18, 2021
11f3e81
Add ticks around cv::Mat
audrow Mar 15, 2021
44d845c
Update title and abstract
audrow Mar 16, 2021
3cae547
Update the specification to include services and actions
audrow Mar 16, 2021
941fb04
Change Adapt to Adapter
audrow Mar 16, 2021
09c1444
Include note that ROS types can be used with custom types
audrow Mar 16, 2021
9d1eeec
Add several design considerations
audrow Mar 16, 2021
f75c452
Fix typo
paudrow Mar 16, 2021
7d45aa6
Improve wording
paudrow Mar 22, 2021
e70bd59
Fix glossary
paudrow Apr 14, 2021
fc8c5ed
Make headings consistent
paudrow Apr 14, 2021
ad253d7
Add feature progress section
paudrow Apr 14, 2021
970325e
Fix bullet list
paudrow Apr 15, 2021
149bc87
Apply suggestions from code review
paudrow May 11, 2021
2f5d434
Update feature progress with issues and PRs
paudrow May 13, 2021
84260c9
Update meta info
paudrow May 13, 2021
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
252 changes: 252 additions & 0 deletions rep-2007.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
REP: 2007
Title: Adapting C++ Types
Author: Audrow Nash <audrow@openrobotics.org>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 28-Jan-2020
Post-History: 28-Jan-2020


Abstract
========

A short (~200 word) description of the technical issue being addressed.
audrow marked this conversation as resolved.
Show resolved Hide resolved

This REP proposes an extension to publishers and subscribers in `rclcpp` to make it easier to convert between ROS 2 interfaces and custom C++ data structures.
audrow marked this conversation as resolved.
Show resolved Hide resolved


Motivation
==========

The motivation is critical for REPs that want to change the ROS APIs. It should clearly explain why the existing API specification is inadequate to address the problem that the REP solves. REP submissions without sufficient motivation may be rejected outright.

The primary reason for this change is to improve the developer's experience working with ROS 2.
audrow marked this conversation as resolved.
Show resolved Hide resolved
Currently, developers often write code to convert a ROS interface into another custom data structure for use in their programs.
This can be trivial, in the case accessing the ``data`` field in ``std_msgs::msg::String``;
or more involved such when converting OpenCV's ``cv::Map`` to ROS's ``sensor_msgs/msg/Image`` type [1]_.
audrow marked this conversation as resolved.
Show resolved Hide resolved
Such conversions are additional work for the programmer and are potential sources of errors.

Terminology
===========

.. glossary::
Custom type (in code, ``CustomType``)
A data structure that *is not* a ROS 2 interface, such as ``std::string`` or ``cv::Mat``.
ROS type (in code, ``RosType``)
A data structure that *is* a ROS 2 interface, such as ``std_msgs::msg::String`` or ``sensor_msgs::msg::Image``.

Specification
=============

The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations for any of the current ROS client libraries, if applicable (roscpp, rospy, roslisp, etc...).

There are different tiers of expressivity in the syntax for type adaptation, including both explicit to implicit forms.
The explicit forms require the custom type and the ROS type to be specified;
while the implicit form makes an assumption about the ROS type based on the custom type.
The explicit forms may be used to clearly communicate what is happening, which could be useful in examples or tutorials, or may be used depending on the preferences of the developer.
While the implicit, and most concise, form will primarily be used for its convenience (although it lacks some of the functionality of the explicit forms).

Below are examples of different syntaxes for type adaptation.
In these examples and using the terminology above, ``std::string`` will be considered the custom type and the ROS interface ``std_msgs::msg::String`` will be considered the ROS type.
Note that, for every publisher created in the examples below, a ``std::string`` type variable (the custom type) would be adapted to be published on the ROS network as a ``std_msgs::msg::String`` (the ROS type).

.. code-block:: cpp

// Explicit Form 1: Most explicit
using MsgT = rclcpp::TypeAdapt<std::string>::to<std_msgs::msg::String>;
rclcpp::Publisher<MsgT>::SharedPtr publisher1_;

The most explicit form could be shortened in the following to ways:
wjwwood marked this conversation as resolved.
Show resolved Hide resolved

.. code-block:: cpp

// Explicit Form 2
rclcpp::Publisher<TypeAdapt<std::string, std_msgs::msg::String>>::SharedPtr publisher2_;

// Explicit Form 3
rclcpp::Publisher<std::string, std_msgs::msg::String>::SharedPtr publisher_3;
audrow marked this conversation as resolved.
Show resolved Hide resolved

Note that the 3rd explicit form may be prohibitively complicated to implement since there are multiple template arguments already for publishers and subscribers.

The final shorthand performs an implicit type adaptation with the custom type ``std::string`` which will be adapted to the ROS type``std_msgs::msg::String``:

.. code-block:: cpp

// Implicit Form
rclcpp::Publisher<std::string>::SharedPtr publisher_4;

In this final form, if the custom type (``std::string``) has multiple ROS types that it could represent, then an error will be raised during compilation.
wjwwood marked this conversation as resolved.
Show resolved Hide resolved


Rationale
=========

The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages.

Selecting a term
----------------

There are various terms that may be suitable for type adapting feature described.
In selecting a term,

:High priority:

* Clearly communicate the described feature
* Clearly communicate the order of custom type and ROS type arguments

:Low priority:

* The custom type should be the first argument so that
* the custom type is the first argument in both the explicit and implicit syntax
* the custom type is read first, for convenience
* The syntax reads well

Candidate terms
^^^^^^^^^^^^^^^

Several possible terms were considered.
Here is a brief summary of the discussion around different terms.

Masquerade
""""""""""

There is some precident for using masquerade in similar settings, IP Masquerading in the Linux kernel [2]_ for example.
wjwwood marked this conversation as resolved.
Show resolved Hide resolved
"Masquerade" is also a verb, which may make it easier to discuss among developers.
However, it was thought that "Masquerade" would be a confusing word for non-English and non-French speakers.
One disadvantage of "Masquerade" is that there is ambiguity in its usage.
For example,

.. code-block:: cpp

Masquerade<std_msgs::msg::String>::as<std::string>

and

.. code-block:: cpp

Masquerade<std::string>::as<std_msgs::msg::String>

both seem to make sense.
This ambiguity may result in frustration on the part of the ROS 2 developer:

* frequently having to refer back to documentation
* possibly opaque error messages

Facade
^^^^^^

"Facade" seems to be a more common English word than "masquerade".
It also is commonly used as a design pattern in object oriented programming.
However, the "Facade pattern" is typically used to simplify a complex interface [3]_, which is not the major feature being proposed here.

It was thought to use "Facade" in the following form:

.. code-block:: cpp

Facade<std::string>::instead_of<std_msgs::msg::String>


Adapt
^^^^^

"Adapt" is certainly a common English word, and the "Adapter pattern" is a common design pattern for adjusting an interface [4]_, which matches well with the feature being suggested here.
Also, using "Adapt" is consistent with the documentation of a similar feature in ROS 1 (i.e., "Adapting C++ Types" [5]_).

"Adapt" also has the advantage of being a verb and of being related to the noun "Adapter".
This flexiblity may make it easier for developers to discuss its use.

"Adapt" could be used in the following syntax:

.. code-block:: cpp

Adapt<std::string>::to<std_msgs::msg::String>

Additional terms considered
^^^^^^^^^^^^^^^^^^^^^^^^^^^

Here is a brief listing of additional terms that were considered and why they were not selected:

:Convert: Passed in favor of "Adapt", which expresses a similar idea and has a common design pattern.

:Decorate: Passed in favor of "Fascade", which seems to be more common.

:Mask: Overloaded as a computer science term [6]_.

:Map: Expresses the idea well, but has a lot of meanings in math and programming.

:Use: Possibly confusing with C++'s ``using`` keyword; also not terribly descriptive.

:Wrap: Passed in favor of "Adapt", which seems to be more common.


Prepending the selected term with "Type"
----------------------------------------

Most of the terms being considered refer to general design patterns and, thus, using just the pattern's name may cause naming collisions or confusion as those design patterns may be used in other parts of the ROS codebase.
To reduce ambiguity, prefixing the term selected with "Type" would make its usage clearer and help avoid name collisions;
it should also make it easier for developers to find relevant documentation.


Adding this feature in ``rclcpp``
---------------------------------

Placing this feature in ROS 2's C client library, ``rcl``, would allow this feature to be used in other client libraries, such as ``rclcpp`` and ``rclpy``.
However, it is not clear that the difficulty of implementing this feature in ``rcl`` is worth the benefit to other client libraries.
The primary client library that is expected to use this feature is ROS 2's C++ client library, ``rclcpp``.
Placing this feature in ``rclcpp`` would allow implementation to take advantage of C++'s standard template library, and thus, speed up development.
wjwwood marked this conversation as resolved.
Show resolved Hide resolved


Backwards Compatibility
=======================

All REPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The REP must explain how the author proposes to deal with these incompatibilities. REP submissions without a sufficient backwards compatibility treatise may be rejected outright.

The proposed feature adds new functionality while not modifying existing functionality.


Reference Implementation
========================

The reference implementation must be completed before any REP is given status "Final", but it need not be completed before the REP is accepted. It is better to finish the specification and rationale first and reach consensus on it before writing code.

The final implementation must include test code and documentation.

TK.

References
==========

.. [1] ``cam2image.cpp`` demo
(https://github.com/ros2/demos/blob/11e00ecf7eec25320f950227531119940496d615/image_tools/src/cam2image.cpp#L277-L291)

.. [2] IP Masquerading in the Linux Kernel
(http://linuxdocs.org/HOWTOs/IP-Masquerade-HOWTO-2.html)

.. [3] Facade Pattern
(https://en.wikipedia.org/wiki/Facade_pattern)

.. [4] Adapter pattern
(https://en.wikipedia.org/wiki/Adapter_pattern)

.. [5] Adapting C++ Types
(http://wiki.ros.org/roscpp/Overview/MessagesSerializationAndAdaptingTypes#Adapting_C.2B-.2B-_Types)

.. [6] Masking (computing)
(https://en.wikipedia.org/wiki/Mask_(computing))


Copyright
=========

This document has been placed in the public domain.


..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
coding: utf-8
End: