eProsima Micro XRCE-DDS Client

In eProsima Micro XRCE-DDS, a Client can communicate with the DDS Network as any other DDS actor could do. Clients can either publish and subscribe to data Topics in the DDS Global Data Space, or act as a client/service application following a request-reply pattern.

This section explains how the Client-Agent communication happens through streams that can be either best-effort or Reliable. After this, it is explained how users can configure Clients applications and the communication with the Agent via sets of CMake flags (-D<parameter>=<value>) that enable/disable profiles and/or allow customize the size of several parameters. Finally, a table is presented to explain the creation mode options of the Clients on the Agent’s side. The section is organized as follows:

eProsima Micro XRCE-DDS provides the user with a C API to create eProsima Micro XRCE-DDS Clients applications. Find the full Client API in the dedicated page.

Streams

The Client-Agent communication is performed by streams. The streams can be seen as communication channels. There are two types of streams: best-effort and reliable. The user can define a maximum of 127 best-effort streams and 128 reliable streams, but for the majority of purposes, only one stream in either best-effort or reliable mode is used.

Best-effort streams

Best-effort streams send and receive the data leaving the reliability to the transport layer. As a result, they consume fewer resources than reliable streams. Also, no history is stored and so the message size sent or received by a best-effort stream must be less or equal than the MTU defined in the transport layer.

Reliable streams

Reliable streams perform the communication without loss, regardless of the transport layer used, and allow for message fragmentation to send and receive messages longer than the MTU.

To avoid loss of data, reliable streams use additional messages to confirm the delivery. Moreover, reliable streams have a history associated, used to store messages that can not be processed due to issues such as delivery order or incomplete fragments or messages that can not be confirmed yet. The size of the history can be tailored to fit the specific requirements of the application. The size of the stream corresponds to the MTU defined in the transport layer times the history.

If the history is full:

  • The messages written to the Agent will be discarded until the history is freed and has space to store the new messages.

  • The messages received from the agent will be discarded. The library will try to recover the discarded messages requesting them to the agent (increasing the bandwidth consumption in the process).

Summarizing:

  • A short history causes more messages to be discarded, increasing the data traffic because they need to be sent again. At the same time, it consumes less memory.

  • A long history will reduce the traffic of confirmation messages when the loss rate is high.

This internal management of the communication implies that a reliable stream is more expensive than a best-effort stream, in both memory and bandwidth, but it is possible to play with these values using the history size.

The streams are probably the highest memory load part of the application. For that, the choice of a right configuration for the application is highly recommendable, especially when the target is a limited resource device. The Memory optimization page explains more in detail how to achieve this.

Profiles

The Client library follows a profile concept that enables to choose, add or remove some features at compile-time, thus allowing to customize the Client library size, if there are features that are not used.

The profiles can be chosen using CMake arguments and start with the prefix UCLIENT_PROFILE (-D<parameter>=<value>) before the compilation.

By means of these profiles, the user can choose which transport to use, and whether to enable or not the discovery and framing functionalities.

Definition

Description

Values

Default

UCLIENT_PROFILE_UDP

Enables or disables the possibility to connect with the Agent by UDP.

<bool>

ON

UCLIENT_PROFILE_TCP

Enables or disables the possibility to connect with the Agent by TCP.

<bool>

ON

UCLIENT_PROFILE_SERIAL

Enables or disables the possibility to connect with the Agent by Serial.

<bool>

ON

UCLIENT_PROFILE_CUSTOM_TRANSPORT

Enables or disables the possibility to connect with the Agent by Custom Transport.

<bool>

ON

UCLIENT_PROFILE_DISCOVERY

Enables or disables the functions of the discovery feature
(currently, only for POSIX).

<bool>

ON

UCLIENT_PROFILE_STREAM_FRAMING

Enables or disables the stream framing protocol.

<bool>

ON

Transport profiles

The implementation of the transport depends on the platform. As mentioned in the Introductory page, the Client is supported by the following platforms: Linux, Windows, FreeRTOS, Zephyr and NuttX. Linux and all three RTOSes present a POSIX-compliant API to some degree. Find below a table summarizing the compatibility of each these Operating Systems, according to their POSIX compliance, with the transports supported by the eProsima Micro XRCE-DDS Client.

The table below shows the current implementation.

Transport

POSIX

Windows

UDP

X

X

TCP

X

X

Serial

X

Custom

X

X

Each available transport can be activated or desactivated via the opportune CMake flag: UCLIENT_PROFILE_<transport>, where <transport> = UDP, TCP, SERIAL, or UCLIENT_PROFILE_CUSTOM_TRANSPORT in the case Custom transport is to be used.

eProsima Micro XRCE-DDS provides a user API that allows interfacing with the lowest level transport layer at runtime. In this way, a user is enabled to implement its own transports based on one of the two communication approaches: stream-oriented or packet-oriented. By means of this API, a user can set four callbacks which will be in charge of opening and closing the transport, and writing and reading from it. This custom transport API is enabled by setting the CMake argument UCLIENT_PROFILE_CUSTOM_TRANSPORT=<bool> to true. In the case that stream-oriented transport is used UCLIENT_PROFILE_STREAM_FRAMING=<bool> should also be enabled.

Find out more in the Transport section of the Client API.

Discovery profile

The discovery profile allows discovering Agents in the network by UDP. The reachable Agents will respond to the discovery call sending information about themselves, as their IP and port. This can happen in two ways: multicast or unicast. The discovery phase can be performed before the uxr_create_session call to determine the Agent to connect with. The declaration of these functions can be found in uxr/client/profile/discovery/discovery.h. This profile is enabled when the UCLIENT_DISCOVERY_PROFILE is ON.

Find out more in the dedicated section of the API.

Note

This feature is only available on Linux.

Framing profile

The framing profile enables HDLC Framing for using stream-oriented transports such as Serial transports or Custom transports that require framing.

Configurations

There are several definitions for configuring and building the Client library at compile-time. These definitions allow users to create a version of the library according to their requirements. These parameters can be selected as CMake flags (-D<parameter>=<value>) before the compilation. By means of these flags, the user can change the default value of all the parameters listed below.

Definition

Description

Values

Default

UCLIENT_MAX_OUTPUT_BEST_EFFORT_STREAMS

Configures the maximum output best-effort streams that a session could
have. The calls to the uxr_create_output_best_effort_stream function
for a session must be less than or equal to this value.

<number>

1

UCLIENT_MAX_OUTPUT_RELIABLE_STREAMS

Configures the maximum output reliable streams that a session could have.
The calls to the uxr_create_output_realiable_stream function for a
session must be less than or equal to this value.

<number>

1

UCLIENT_MAX_INPUT_BEST_EFFORT_STREAMS

Configures the maximum input best-effort streams that a session could
have. The calls to the uxr_create_input_best_effort_stream function
for a session must be less than or equal to this value.

<number>

1

UCLIENT_MAX_INPUT_RELIABLE_STREAMS

Configures the maximum input reliable streams that a session could have.
The calls to the uxr_create_input_realiable_stream function for a
session must be less than or equal to this value.

<number>

1

UCLIENT_MAX_SESSION_CONNECTION_ATTEMPTS

This value indicates the number of attempts that create_session and
delete_session will perform until receiving a status message.

<number>

10

UCLIENT_MIN_SESSION_CONNECTION_INTERVAL

This value represents how long it will take to send a new create_session
or delete_session if the first attempt was left answered.

<number>

1000

UCLIENT_MIN_HEARTBEAT_TIME_INTERVAL

In a reliable communication, this value represents how long it will take for
the first heartbeat to be sent. The wait time for the next heartbeat will be
double. It is measured in milliseconds.

<number>

1

UCLIENT_BIG_ENDIANNESS

This value must correspond to the memory endianness of the device in
which the Client is running. OFF implies that the machine is little-endian
and ON implies big-endian.

<bool>

OFF

UCLIENT_UDP_TRANSPORT_MTU

This value corresponds to the Maximum Transmission Unit (MTU) that can
be sent and/or received by UDP. It is measured in bytes and, internally, it
corresponds to the creation of a buffer this size.

<number>

512

UCLIENT_TCP_TRANSPORT_MTU

This value corresponds to the Maximum Transmission Unit (MTU) that can
be sent and/or received by TCP. It is measured in bytes and, internally, it
corresponds to the creation of a buffer this size.

<number>

512

UCLIENT_SERIAL_TRANSPORT_MTU

This value corresponds to the Maximum Transmission Unit (MTU) that can
be sent and/or received by Serial. It is measured in bytes and, internally, it
corresponds to the creation of a buffer this size.

<number>

512

UCLIENT_CUSTOM_TRANSPORT_MTU

This value corresponds to the Maximum Transmission Unit (MTU) that can
be sent and/or received by Custom transport. It is measured in bytes and,
internally, it corresponds to the creation of a buffer this size.

<number>

512

Read Access Delivery Control

The Read Access Delivery Control handles the read operation from a datareader previously created on the Agent to fetch data from the middleware. It comes with an optional control argument, that allows the Client setting the following parameters:

  • max_bytes_per_second: Maximum rate at which data messages may be returned, measured in bytes per secpond.

  • max_elapsed_time: Maximum amount of time that can be spent by the Agent in delivering the topic, measured in seconds.

  • max_samples: Maximum number of topics that the Agent can send to the Client.

  • min_pace_period: Minimum elapsed time between two topics deliveries, measured in milliseconds,.

For more information, consult the Read access of the Client API.

Creation Mode: Client

The creation of Entities on the Agent which can act on behalf of the Clients in the DDS world can be done in two ways: by XML, or by reference. In this section, we explain these two creation modes and provide guidance on their usage.

XML

In the XML case, when creating the entities in the Client application, the user must provide each entity with a const char* <entity>_xml parameter containing a string of text with XML syntax, matching the DDS rules for creating a DDS entity with an XML profile, as explained here.

For instance, when creating a participant or a topic, the profiles shall look as follows:

<!-- PARTICIPANT -->
const char* participant_xml = "<dds>"
                                  "<participant>"
                                      "<rtps>"
                                          "<name>[PARTICIPANT NAME]</name>"
                                      "</rtps>"
                                  "</participant>"
                              "</dds>";

<!-- TOPIC -->
const char* topic_xml = "<dds>"
                            "<topic>"
                                "<name>[TOPIC NAME]</name>"
                                "<dataType>[TOPIC TYPE]</dataType>"
                            "</topic>"
                        "</dds>"

As detailed in the Getting started section, participants, topics, datawriters, datareaders, requesters and repliers work similarly. Publishers and subscribers, instead, inherit their XML fields from their associated dataWriters and dataReaders.

Creation by XML has the advantage of being configurable direclty within the Client application, but comes with the drawback of offering a very limited set of options as regards the QoS with which the DDS entities profiles can be configured. Indeed, only best-effort or reliable communication streams can be set with this creation mode. In many cases, these QoS configurations alone may not be enough. For these cases, eProsima Micro XRCE-DDS allows the users to use the creation by references mode.

References

Creation by references happens by feeding the Agent with an XML profile containing a string of text similar to the snippets provided above, with a label associated to it. Therefore, when creating an entity, the Client will only need to provide a reference to this label in spite of the complete XML profile. This creation mode comes with two advantages:

  • It consumes less Client memory, making the application more lightweight.

  • It allows the Clients to write their own XML QoS and run the Agent with a custom configuration which can benefit of the full set of QoS available in DDS.

For instance, when creating a participant or a topic, the profiles shall look as follows:

<!-- PARTICIPANT -->
const char* participant_ref = "participant_label";

<!-- TOPIC -->
const char* topic_ref = "topic_label"

Find more information in the Creation Mode: Agent section in the eProsima Micro XRCE-DDS Agent page.

Creation Policy Table

The following table summarizes the behaviour of the Agent under entity creation request.

Creation flags

Entity exists

Result

Don’t care

NO

Entity is created.

0

YES

No action is taken, and UXR_STATUS_ERR_ALREADY_EXITS is returned.

UXR_REPLACE

YES

Existing entity is deleted, requested entity is created and UXR_STATUS_OK is returned.

UXR_REUSE

YES

If entity matches no action is taken and UXR_STATUS_OK_MATCHED is returned.
If entity does not match any action is taken and UXR_STATUS_ERR_MISMATCH is returned.

UXR_REUSE | UXR_REPLACE

YES

If entity matches no action is taken and UXR_STATUS_OK_MATCHED is returned.
If entity does not match, exiting entity is deleted, requested entity is created and UXR_STATUS_OK
is returned.