Skip to content

Commit

Permalink
Update README to document loading from profiles
Browse files Browse the repository at this point in the history
Signed-off-by: EduPonz <eduardoponz@eprosima.com>
  • Loading branch information
EduPonz committed Dec 12, 2019
1 parent f7d062e commit 0dd60e0
Showing 1 changed file with 175 additions and 4 deletions.
179 changes: 175 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@

`rmw_fastrtps` constitutes __[ROS 2](https://index.ros.org/doc/ros2/) default middleware implementation__, providing an interface between ROS 2 and [eProsima's](https://www.eprosima.com/index.php) [Fast-RTPS](https://github.com/eProsima/Fast-RTPS) middleware.

1. [Getting started](#getting-started)
1. [Two different RMW implementations](#two-different-rmw-implementations)
1. [Advance usage](#advance-usage)
1. [Memory policy and publication mode](#memory-policy-and-publication-mode)
1. [Different profiles for different entities](#different-profiles-for-different-entities)

## Getting started
This implementation is available in all ROS 2 distributions, both from binaries and from sources.
You do not need to do anything in order to use Fast-RTPS as your ROS 2 middleware layer (since it is the default implementation).
However, you can still specify it in two different ways:

1. Exporting `RMW_IMPLEMENTATION` environment variable:

```bash
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
```
1. When launching your ROS 2 application:

```bash
RMW_IMPLEMENTATION=rmw_fastrtps_cpp ros2 run <your_package> <your application>
```
Expand All @@ -28,19 +36,32 @@ You can however set it to `rmw_fastrtps_dynamic_cpp` using the environment varia

## Advance usage

`rmw_fastrtps` sets some of the Fast-RTPS configurable parameters:
* History memory policy: `PREALLOCATED_WITH_REALLOC_MEMORY_MODE`
* Publication mode: `ASYNCHRONOUS_PUBLISH_MODE`
With `rmw_fastrtps` you can tune Fast-RTPS middleware at two different level:

1. [Set the history memory policy and the publication mode](#memory-policy-and-publication-mode)
1. [Fully configure every communication entity in you application](#different-profiles-for-different-entities)

### Memory policy and publication mode

By default, `rmw_fastrtps` sets some of the Fast-RTPS configurable parameters:

* History memory policy: `PREALLOCATED_WITH_REALLOC_MEMORY_MODE`.
This means that every publisher/subscriber in you application will allocate, on creation, a certain amount of memory to avoid dynamic allocations.
However, if that amount is not enough, a reallocation will occur to increase the history.
* Publication mode: `ASYNCHRONOUS_PUBLISH_MODE`.
This means that the user's call to `publish` will simply add the message to a ready-to-send queue, returning immediately.
The actual sending is performed by a different thread, which is awaken on the call to `publish`, sending everything in its queue.
However, it is possible to fully configure Fast-RTPS (including the history memory policy and the publication mode) using an XML file as described in [Fast-RTPS documentation](https://eprosima-fast-rtps.readthedocs.io/en/latest/xmlprofiles.html).
Then, you just need to set environment variable `RMW_FASTRTPS_USE_QOS_FROM_XML` to 1 (it is set to 0 by default).
This tells `rmw_fastrtps` that it should not override neither the history memory policy nor the publication mode.
You have two ways of telling you ROS 2 application which XML to use:
1. Placing your XML file in the running directory under the name `DEFAULT_FASTRTPS_PROFILES.xml`.
2. Setting environment variable `FASTRTPS_DEFAULT_PROFILES_FILE` to your XML file.
## Example
#### Example
The following example configures Fast-RTPS to publish synchronously, and to have a pre-allocated history that can be expanded whenever it gets filled.
Expand All @@ -67,6 +88,7 @@ The following example configures Fast-RTPS to publish synchronously, and to have
```
1. Run the talker/listener ROS 2 demo:
1. In one terminal
```bash
Expand All @@ -78,3 +100,152 @@ The following example configures Fast-RTPS to publish synchronously, and to have
```bash
FASTRTPS_DEFAULT_PROFILES_FILE=<path_to_xml_file> RMW_FASTRTPS_USE_QOS_FROM_XML=1 RMW_IMPLEMENTATION=rmw_fastrtps_cpp ros2 run demo_nodes_cpp listener
```
### Different profiles for different entities
In the previous section we were specifying a profile that would apply to all publishers or subscribers in your ROS 2 application.
However, using `rmw_fastrtps`, it is possible to configure each node, publisher, and subscriber separately, and at run time!
This feature allows you to take full control and advantage of everything that Fast-RTPS middleware has to offer, so you can tune every aspect of you application for your specific use-case.
#### Nodes configuration
Using `rmw_fastrtps`, you can write different XML profiles for different Fast-RTPS participants (which are 1-to-1 mapped to ROS 2 nodes).
To do that, you just simply use the same name for the node and the XML profile, is that easy!
If your node does not have an associated profile, it will try to load the configuration from a participant profile with the property `is_default_profile` set to true.
If that does not exist either, then your node would have the default's Fast-RTPS participant configuration.

#### Publishers and subscribers configuration

Much as the nodes configuration, you just need to use the same name for your profile and for the topic to which your publisher publishes (or your subscriber subscribes).
That is, the publisher/subscriber tag attribute should be `profile_name=topic_name`.
You can still have a profile with `is_default_profile=true` if you want to share the same profile across different publishers/subscribers.

#### ROS 2 service/client configuration

A ROS2 service uses a subscriber to listen to clients' requests, and a publisher to reply to them.
Similarly, A ROS2 client uses a publisher to send requests to a service, and a subscriber to receive the service's responses.
In this sense, you can configure those publishers and subscribers likewise any other publisher or subscriber, i.e. setting attribute `profile_name=topic_name`.
Moreover, if you want to use the same publisher/subscriber profile in all the services (or clients), you can save yourself the time of writing one profile for each one of them by setting `profile_name=service` (or `profile_name=client`).
Just be aware that if there is any publisher/subscriber profile with attribute `profile_name=topic_name`, the one with `profile_name=service` (`profile_name=client`) will not be used.

#### Summary

To summarize, `rmw_fastrtps` tries to load profiles for different entities in the following order:

##### Node

1. Profile with `profile_name=node_name`
1. Profile with `is_default_profile=true`
1. Default Fast-RTPS configuration

##### Publisher/subscriber

1. Profile with `profile_name=topic_name`
1. Profile with `is_default_profile=true`
1. Default Fast-RTPS configuration with:
* History memory policy: `PREALLOCATED_WITH_REALLOC_MEMORY_MODE`
* Publication mode: `ASYNCHRONOUS_PUBLISH_MODE`


##### Service/client

1. Profile with `profile_name=topic_name`
1. Profile with `profile_name=service` (`profile_name=client`)
1. Profile with `is_default_profile=true`
1. Default Fast-RTPS configuration with:
* History memory policy: `PREALLOCATED_WITH_REALLOC_MEMORY_MODE`
* Publication mode: `ASYNCHRONOUS_PUBLISH_MODE`

#### Example
Write an XML file
```XML
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
<profiles>
<!-- PARTICPANT PROFILES -->
<participant profile_name="node_name_1">
<!-- -->
</participant>
<participant profile_name="node_name_2">
<!-- -->
</participant>
<participant profile_name="default_participant" is_default_profile="true">
<!-- -->
</participant>
<!-- PUBLISHER PROFILES -->
<publisher profile_name="topic_name_1">
<!-- -->
</publisher>
<publisher profile_name="topic_name_2">
<!-- -->
</publisher>
<publisher profile_name="default_publisher" is_default_profile="true">
<!-- -->
</publisher>
<!-- SUBSCRIBER PROFILES -->
<subscriber profile_name="topic_name_1">
<!-- -->
</subscriber>
<subscriber profile_name="topic_name_1">
<!-- -->
</subscriber>
<subscriber profile_name="default_subscriber" is_default_profile="true">
<!-- -->
</subscriber>
<!-- SERVICE PROFILES -->
<publisher profile_name="service">
<!-- -->
</publisher>
<subscriber profile_name="service">
<!-- -->
</subscriber>
<!-- CLIENT PROFILES -->
<publisher profile_name="client">
<!-- -->
</publisher>
<subscriber profile_name="client">
<!-- -->
</subscriber>
</profiles>
</dds>
```

Then, in your application (pseudo-code)
```c++
/* CREATE NODES */
node_1 = Node("node_name_1");
node_2 = Node("node_name_2");
node_3 = Node("node_name")
// Use the system QoS, don't override anything
rclcpp::QoS custom_qos(QoSInitialization::from_rmw(
rmw_qos_profile_system_default, rmw_qos_profile_system_default);
/* CREATE PUBLISHERS */
pub_1 = node_1->create_publisher<msg_type>("topic_name_1", custom_qos);
pub_2 = node_2->create_publisher<msg_type>("topic_name_2", custom_qos);
pub_3 = node_2->create_publisher<msg_type>("publisher_name", custom_qos);
/* CREATE SUBSCRIPTIONS */
sub_1 = node_1->create_subscription<msg_type>("topic_name_1", custom_qos, callback_1);
sub_2 = node_2->create_subscription<msg_type>("topic_name_2", custom_qos, callback_2);
sub_3 = node_2->create_subscription<msg_type>("subscriber_name", custom_qos, callback_3);
/* CREATE SERVICE */
service_1 = node_1->create_service("service_1", service_callback, rmw_qos_profile_system_default);
/* CREATE CLIENT */
client_1 = node_1->create_client("client_1", rmw_qos_profile_system_default);
```

0 comments on commit 0dd60e0

Please sign in to comment.