-
Notifications
You must be signed in to change notification settings - Fork 71
Add custom transport tutorial #287
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
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
73fa3da
Add custom transport tutorial
pablogs9 ed3349f
Update
pablogs9 d60e95d
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 5f372ee
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 45d6a5a
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 e5baab1
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 c5170e7
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 6c799f1
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 c70db56
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 d781e87
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 383b6be
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 9288e35
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 de7239f
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 e2b4cd5
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 0d6016e
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 86b5096
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 3bbb2e6
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 bf78a56
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 98625d6
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 43fbbb9
Add jose's endpoints
pablogs9 7c29608
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 9de8ecd
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 806eba6
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 1eefe2b
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 4255a4e
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 9f1a2bc
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 99d1700
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 25a8921
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 d7b6193
Update _docs/tutorials/advanced/create_custom_transports/index.md
pablogs9 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
241 changes: 241 additions & 0 deletions
241
_docs/tutorials/advanced/create_custom_transports/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,241 @@ | ||
| --- | ||
| title: Creating custom micro-ROS transports | ||
| permalink: /docs/tutorials/advanced/create_custom_transports/ | ||
| --- | ||
|
|
||
| This tutorial aims at providing step-by-step guidance for those users interested in creating micro-ROS custom transports, instead of using the ones provided by default in the micro-ROS tools set. | ||
|
|
||
| This tutorial starts from a previously created micro-ROS environment. Check the first steps of [**First micro-ROS application on an RTOS**](../../core/first_application_rtos/) for instructions on how to create a micro-ROS environment for embedded platforms. | ||
|
|
||
| The micro-ROS middleware, *eProsima Micro XRCE-DDS*, provides a user API that allows interfacing with the lowest level transport layer at runtime, | ||
| which enables users to implement their own transports in both the micro-ROS Client and micro-ROS Agent libraries. | ||
| Thanks to this, the Micro XRCE-DDS wire protocol can be transmitted over virtually any protocol, network or communication | ||
| mechanism. In order to do so, two general communication modes are provided: | ||
|
|
||
| * **Stream-oriented mode**: the communication mechanism implemented does not have the concept of packet. | ||
| [HDLC framing](https://micro-xrce-dds.docs.eprosima.com/en/latest/transport.html?highlight=hdlc#custom-serial-transport) will be used. | ||
| * **Packet-oriented mode**: the communication mechanism implemented is able to send a whole packet that includes an XRCE message. | ||
|
|
||
| These two modes can be selected by activating and deactivating the `framing` parameter in both the micro-ROS Client and the micro-ROS Agent functions. | ||
|
|
||
| ## micro-ROS Client | ||
|
|
||
| An example on how to set these external transport callbacks in the micro-ROS Client API is: | ||
|
|
||
| ```c | ||
| #include <rmw_uros/options.h> | ||
|
|
||
| ... | ||
|
|
||
| struct custom_args { | ||
| ... | ||
| } | ||
|
|
||
| struct custom_args args; | ||
|
|
||
| rmw_uros_set_custom_transport( | ||
| true, // Framing enabled here. Using Stream-oriented mode. | ||
| (void *) &args, | ||
| my_custom_transport_open, | ||
| my_custom_transport_close, | ||
| my_custom_transport_write, | ||
| my_custom_transport_read | ||
| ); | ||
| ``` | ||
|
|
||
| It is important to notice that in `rmw_uros_set_custom_transport` a pointer to custom arguments is set. This reference will be available to every callbacks call. | ||
|
|
||
| In general, four functions must be implemented. The behaviour of these functions is slightly different, depending on the selected mode: | ||
|
|
||
| ### Open function | ||
|
|
||
| ```c | ||
| bool my_custom_transport_open(uxrCustomTransport* transport) | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should open and init the custom transport. It returns a boolean indicating if the opening was successful. | ||
| `transport->args` holds the arguments passed through `uxr_init_custom_transport`. | ||
|
|
||
| ### Close function | ||
| ```c | ||
| bool my_custom_transport_close(uxrCustomTransport* transport) | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should close the custom transport. It returns a boolean indicating if closing was successful. | ||
| `transport->args` holds the arguments passed through `uxr_init_custom_transport`. | ||
|
|
||
| ### Write function | ||
| ```c | ||
| size_t my_custom_transport_write( | ||
| uxrCustomTransport* transport, | ||
| const uint8_t* buffer, | ||
| size_t length, | ||
| uint8_t* errcode) | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should write data to the custom transport. It returns the number of bytes written. | ||
| `transport->args` holds the arguments passed through `uxr_init_custom_transport`. | ||
|
|
||
| * **Stream-oriented mode:** The function can send up to `length` bytes from `buffer`. | ||
|
|
||
| * **Packet-oriented mode:** The function should send `length` bytes from `buffer`. If less than `length` bytes are written, `errcode` can be set. | ||
|
|
||
| ### Read function | ||
| ```c | ||
| size_t my_custom_transport_read( | ||
| uxrCustomTransport* transport, | ||
| uint8_t* buffer, | ||
| size_t length, | ||
| int timeout, | ||
| uint8_t* errcode) | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should read data from the custom transport. It returns the number of bytes read. | ||
| `transport->args` have the arguments passed through `uxr_init_custom_transport`. | ||
|
|
||
| * **Stream-oriented mode:** The function should retrieve up to `length` bytes from the transport | ||
| and write them into `buffer` in `timeout` milliseconds. | ||
|
|
||
| * **Packet-oriented mode:** The function should retrieve `length` Bytes from transport | ||
| and write them into `buffer` in `timeout` milliseconds. If less than `length` bytes are read, `errcode` can be set. | ||
|
|
||
|
|
||
|
|
||
| ## Micro XRCE-DDS Agent | ||
|
|
||
| The micro-ROS Agent profile for custom transports is enabled by default. | ||
|
|
||
| An example on how to set the external transport callbacks in the micro-ROS Agent API is: | ||
|
|
||
| ```cpp | ||
| eprosima::uxr::Middleware::Kind mw_kind(eprosima::uxr::Middleware::Kind::FASTDDS); | ||
| eprosima::uxr::CustomEndPoint custom_endpoint; | ||
|
|
||
| // Add transport endpoing parameters | ||
| custom_endpoint.add_member<uint32_t>("param1"); | ||
| custom_endpoint.add_member<uint16_t>("param2"); | ||
| custom_endpoint.add_member<std::string>("param3"); | ||
|
|
||
| eprosima::uxr::CustomAgent custom_agent( | ||
| "my_custom_transport", | ||
| &custom_endpoint, | ||
| mw_kind, | ||
| true, // Framing enabled here. Using Stream-oriented mode. | ||
| my_custom_transport_open, | ||
| my_custom_transport_close, | ||
| my_custom_transport_write | ||
| my_custom_transport_read); | ||
|
|
||
| custom_agent.start(); | ||
| ``` | ||
| As in the *Client* API, four functions should be implemented. The behavior of these functions is sightly different | ||
| depending on the selected mode. | ||
|
|
||
| ### CustomEndPoint | ||
|
|
||
| The `custom_endpoint` is an object of type `eprosima::uxr::CustomEndPoint` and it is in charge of handling the endpoint parameters. The *Agent*, unlike the *Client*, can receive | ||
| messages from multiple *Clients* so it must be able to differentiate between them. | ||
| Therefore, the `eprosima::uxr::CustomEndPoint` should be provided with information about the origin of the message | ||
| in the read callback, and with information about the destination of the message in the write callback. | ||
|
|
||
| In general, the members of a `eprosima::uxr::CustomEndPoint` object can be unsigned integers and strings. | ||
|
|
||
| `CustomEndPoint` defines three methods: | ||
|
|
||
| Add member | ||
| ```cpp | ||
| bool eprosima::uxr::CustomEndPoint::add_member<*KIND*>(const std::string& member_name); | ||
| ``` | ||
| This function allows to dynamically add a new member to the endpoint definition. | ||
|
|
||
| Ir returns ``true`` if the member was correctly added, ``false`` if something went wrong (for example, if the member already exists). | ||
|
|
||
| - **KIND**: To be chosen from: `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`, `uint128_t` or `std::string`. | ||
| - **member_name**: The tag used to identify the endpoint member. | ||
|
|
||
| Set member value | ||
| ```cpp | ||
| void eprosima::uxr::CustomEndPoint::set_member_value(const std::string& member_name, const *KIND* & value); | ||
| ``` | ||
|
|
||
| This function sets the specific value (numeric or string) for a certain member, which must previously exist in the `CustomEndPoint`. | ||
|
|
||
| - **member_name**: The member whose value is going to be modified. | ||
| - **value**: The value to be set, of `KIND`: `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`, `uint128_t` or `std::string`. | ||
|
|
||
| Get member | ||
| ```cpp | ||
| const *KIND* & eprosima::uxr::CustomEndPoint::get_member(const std::string& member_name); | ||
| ``` | ||
|
|
||
| This function gets the current value of the member registered with the given parameter. | ||
| The retrieved value might be an `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`, `uint128_t` or `std::string`. | ||
|
|
||
| - **member_name**: The `CustomEndPoint` member name whose current value is requested. | ||
|
|
||
| ### Open function | ||
| ```cpp | ||
| eprosima::uxr::CustomAgent::InitFunction my_custom_transport_open = [&]() -> bool | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should open and init the custom transport. It returns a boolean indicating if the opening was successful. | ||
|
|
||
| ### Close function | ||
| ```cpp | ||
| eprosima::uxr::CustomAgent::FiniFunction my_custom_transport_close = [&]() -> bool | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should close the custom transport. It returns a boolean indicating if the closing was successful. | ||
|
|
||
| ### Write function | ||
| ```cpp | ||
| eprosima::uxr::CustomAgent::SendMsgFunction my_custom_transport_write = [&]( | ||
| const eprosima::uxr::CustomEndPoint* destination_endpoint, | ||
| uint8_t* buffer, | ||
| size_t length, | ||
| eprosima::uxr::TransportRc& transport_rc) -> ssize_t | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should write data to the custom transport. It must use | ||
| the `destination_endpoint` members to set the data destination. It returns the number of bytes written. | ||
| It should set `transport_rc` indicating the result of the operation. | ||
|
|
||
| * **Stream-oriented mode:** The function can send up to `length` Bytes from `buffer`. | ||
|
|
||
| * **Packet-oriented mode:** The function should send `length` Bytes from `buffer`. If less than `length` bytes are written, `transport_rc` can be set. | ||
|
|
||
| ### Read function | ||
| ```cpp | ||
| eprosima::uxr::CustomAgent::RecvMsgFunction my_custom_transport_read = [&]( | ||
| eprosima::uxr::CustomEndPoint* source_endpoint, | ||
| uint8_t* buffer, | ||
| size_t length, | ||
| int timeout, | ||
| eprosima::uxr::TransportRc& transport_rc) -> ssize_t | ||
| { | ||
| ... | ||
| } | ||
| ``` | ||
| This function should read data to the custom transport. It must fill `source_endpoint` members with data source. | ||
| It returns the number of bytes read. | ||
| It should set `transport_rc` indicating the result of the operation. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not totally clear what this means. |
||
|
|
||
| * **Stream-oriented mode:** The function should retrieve up to `length` bytes from the transport | ||
| and write them into `buffer` in `timeout` milliseconds. | ||
|
|
||
| * **Packet-oriented mode:** The function should retrieve `length` bytes from the transport | ||
| and write them into `buffer` in `timeout` milliseconds. If less than `length` bytes are read, `transport_rc` can be set. | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.