Real-time behavior¶
Fast RTPS can be configured to offer real-time features. These features will guarantee Fast RTPS responses within specified time constrains. To maintain this compromise Fast RTPS is able to have the following behavior:
- Not allocate memory after the initialization of Fast RTPS entities.
- Several methods are blocked for a maximum period of time.
This section explains how to configure Fast RTPS to achieve this behavior. For easier understanding it was divided in two subsections:
- Tuning allocations: configuration to avoid memory allocation after initialization.
- Non-blocking calls: usage of non-blocking methods for real-time behavior.
Tuning allocations¶
Some important non-deterministic operating system calls are the ones for allocating and deallocating memory. Most real-time systems have the need to operate in a way that all dynamic memory is allocated on the application startup, and avoid calls to memory management APIs on the main loop.
Fast-RTPS provides some configuration parameters to meet these requirements, allowing the items of internal data collections to be preallocated. In order to choose the correct values for these parameters, the user should be aware of the topology of the whole domain, so the number of participants and endpoints should be known when setting them.
Parameters on the participant¶
All the allocation related parameters on the participant are grouped into the rtps.allocation
field of the
ParticipantAttributes
struct.
Limiting the number of discovered participants¶
Every participant in Fast-RTPS holds an internal collection of ParticipantProxyData
objects with the
information of the local and the remote participants.
Field participants
inside RTPSParticipantAllocationAttributes
allows the configuration of
the allocation behavior of that collection.
The user can specify the initial
number of elements preallocated, the maximum
number of elements
allowed, and the allocation increment
.
By default, a full dynamic behavior is used.
Limiting the number of discovered endpoints¶
Every ParticipantProxyData
object holds internal collections with the ReaderProxyData
and
WriterProxyData
objects with the information of the readers and writers of a participant.
In a similar way to the participants
field, RTPSParticipantAllocationAttributes
has fields
readers
and writers
to set the configuration of the allocation behavior of those collections.
The user can specify the initial
number of elements preallocated, the maximum
number of elements
allowed, and the allocation increment
.
By default, a full dynamic behavior is used.
Parameters on the publisher¶
Every publisher holds a collection with some information regarding the subscribers it has matched to.
Field matched_subscriber_allocation
inside PublisherAttributes
allows the configuration of
the allocation behavior of that collection.
The user can specify the initial
number of elements preallocated, the maximum
number of elements
allowed, and the allocation increment
.
By default, a full dynamic behavior is used.
Parameters on the subscriber¶
Every subscriber holds a collection with some information regarding the publishers it has matched to.
Field matched_publisher_allocation
inside SubscriberAttributes
allows the configuration of
the allocation behavior of that collection.
The user can specify the initial
number of elements preallocated, the maximum
number of elements
allowed, and the allocation increment
.
By default, a full dynamic behavior is used.
Full example¶
Given a system with the following topology:
Participant P1 | Participant P2 | Participant P3 |
---|---|---|
Topic 1 publisher | Topic 1 subscriber | Topic 2 subscriber |
Topic 1 subscriber | Topic 2 publisher | |
Topic 1 subscriber | Topic 2 subscriber |
- All the subscribers match exactly with 1 publisher.
- The publisher for topic 1 matches with 3 subscribers, and the publisher for topic 2 matches with 2 subscribers.
- The maximum number of publishers per participant is 1, and the maximum number of subscribers per participant is 2.
- The total number of participants is 3.
The following piece of code shows the set of parameters needed for the use case depicted in this example.
C++ |
// Before creating a participant:
// We know we have 3 participants on the domain
participant_attr.rtps.allocation.participants = eprosima::fastrtps::ResourceLimitedContainerConfig::fixed_size_configuration(3u);
// We know we have at most 2 readers on each participant
participant_attr.rtps.allocation.readers = eprosima::fastrtps::ResourceLimitedContainerConfig::fixed_size_configuration(2u);
// We know we have at most 1 writer on each participant
participant_attr.rtps.allocation.writers = eprosima::fastrtps::ResourceLimitedContainerConfig::fixed_size_configuration(1u);
// Before creating the publisher for topic 1:
// we know we will only have three matching subscribers
publisher_attr.matched_subscriber_allocation = eprosima::fastrtps::ResourceLimitedContainerConfig::fixed_size_configuration(3u);
// Before creating the publisher for topic 2:
// we know we will only have two matching subscribers
publisher_attr.matched_subscriber_allocation = eprosima::fastrtps::ResourceLimitedContainerConfig::fixed_size_configuration(2u);
// Before creating a subscriber:
// we know we will only have one matching publisher
subscriber_attr.matched_publisher_allocation = eprosima::fastrtps::ResourceLimitedContainerConfig::fixed_size_configuration(1u);
|
XML |
<participant profile_name="participant_alloc_qos_example">
<rtps>
<allocation>
<!-- We know we have 3 participants on the domain -->
<total_participants>
<initial>3</initial>
<maximum>3</maximum>
<increment>0</increment>
</total_participants>
<!-- We know we have at most 2 readers on each participant -->
<total_readers>
<initial>2</initial>
<maximum>2</maximum>
<increment>0</increment>
</total_readers>
<!-- We know we have at most 1 writer on each participant -->
<total_writers>
<initial>1</initial>
<maximum>1</maximum>
<increment>0</increment>
</total_writers>
</allocation>
</rtps>
</participant>
<publisher profile_name="alloc_qos_example_pub_for_topic_1">
<!-- we know we will have three matching subscribers -->
<matchedSubscribersAllocation>
<initial>3</initial>
<maximum>3</maximum>
<increment>0</increment>
</matchedSubscribersAllocation>
</publisher>
<publisher profile_name="alloc_qos_example_pub_for_topic_2">
<!-- we know we will have two matching subscribers -->
<matchedSubscribersAllocation>
<initial>2</initial>
<maximum>2</maximum>
<increment>0</increment>
</matchedSubscribersAllocation>
</publisher>
<subscriber profile_name="alloc_qos_example_sub">
<!-- we know we will only have one matching publisher -->
<matchedPublishersAllocation>
<initial>1</initial>
<maximum>1</maximum>
<increment>0</increment>
</matchedPublishersAllocation>
</subscriber>
|
Non-blocking calls¶
Note: This feature is not fully supported on OSX. It doesn’t support necessary POSIX Real-time features. The feature is limited by the implementation of std::timed_mutex and std::condition_variable_any.
It is important that a method isn’t blocked for indeterminate time to achieve real-time.
A method must only be blocked for a maximum period of time.
In Fast-RTPS API there are several methods that permit to set this. But first Fast-RTPS should be configured with the
CMake option -DSTRICT_REALTIME=ON
. The list of these functions is displayed in the table below.
Method | Description |
---|---|
Publisher::write() | These methods are blocked for a period of time. ReliabilityQosPolicy.max_blocking_time on PublisherAttributes defines this period of time. Default value is 100 milliseconds. |
Subscriber::takeNextData() | This methods is blocked for a period of time. ReliabilityQosPolicy.max_blocking_time on SubscriberAttributes defines this period of time. Default value is 100 milliseconds. |
Subscriber::readNextData() | This method is blocked for a period of time. ReliabilityQosPolicy.max_blocking_time on SubscriberAttributes defines this period of time. Default value is 100 milliseconds. |
Subscriber::wait_for_unread_samples() | Accepts an argument specifying how long the method can be blocked. |