As explained in this section <recorder_getting_started_project_overview>
, a instance stores (by default) all data regardless of whether their associated data type is received or not. However, some applications require this information to be recorded and written in the resulting MCAP file, and for this to occur the publishing applications must send it via Dynamic Types<DynamicTypes>
.
This tutorial focuses on how to send the data type information using Fast DDS DynamicTypes and other relevant aspects of DynamicTypes. More specifically, this tutorial implements a DDS Publisher configured to send its data type, a DDS Subscriber that collects the data type and is able to read the incoming data, and a DDS Recorder is launched to save all the data published on the network. For more information about how to create the workspace with a basic DDS Publisher and a basic DDS Subscriber, please refer to Writing a simple C++ publisher and subscriber application .
The source code of this tutorial can be found in the public GitHub repository with an explanation of how to build and run it.
Warning
This tutorial works with this branch of Fast DDS.
Ensure that is installed together with eProsima dependencies, i.e. Fast DDS, Fast CDR and DDS Pipe.
If was installed using the recommended installation the environment is sourced by default, otherwise, just remember to source it in every terminal in this tutorial:
source <path-to-fastdds-installation>/install/setup.bash
source <path-to-ddspipe-installation>/install/setup.bash
source <path-to-ddsrecordreplay-installation>/install/setup.bash
eProsima Fast DDS-Gen is a Java application that generates eProsima Fast DDS source code using the data types defined in an IDL (Interface Definition Language) file. When generating the Types using eProsima Fast DDS Gen, the option -typeobject
must be added in order to generate the needed code to fill the TypeInformation
data.
The expected argument list of the application is:
fastddsgen -typeobject MyType.idl
The DDS publisher will be configured to act as a server of the data types of the data it publishes.
However, Fast DDS does not send the data type information by default, it must be configured to do so.
At the moment, there are two data types that can be used:
../../../resources/dds/TypeLookupService/types/v2/hello_world/HelloWorld.idl
../../../resources/dds/TypeLookupService/types/v2/complete/Complete.idl
This section explains the C++ source code of the DDS Publisher, which can also be found here.
The private data members of the class defines the DDS Topic, DataTypeKind
, DDS Topic type and DynamicType. The DataTypeKind
defines the type to be used by the application (HelloWorld
or Complete
). For simplicity, this tutorial only covers the code related to the HelloWorld
type.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.h
The next lines show the constructor of the TypeLookupServicePublisher
class that implements the publisher. The publisher is created with the topic and data type to use.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.cpp
Inside the TypeLookupServicePublisher
constructor are defined the DomainParticipantQos. As the publisher act as a server of types, its QoS must be configured to send this information. Set use_client
to false
and use_server
to true
.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.cpp
Next, we register the type in the participant:
- Generate the dynamic type through
generate_helloworld_type_()
explained below. - Set the data type.
- Create the
TypeSupport
with the dynamic type previously created. - Configure the
type
to fill automatically theTypeInformation
and notTypeObject
to be compliant with DDS-XTypes 1.2. standard.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.cpp
The function generate_helloworld_type_()
returns the dynamic type generated with the TypeObject
and TypeIdentifier
of the type.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.cpp
Then we initialized the Publisher, DDS Topic and DDS DataWriter.
To make the publication, the public member function publish()
is implemented:
- It creates the variable that will contain the user data,
dynamic_data_
. - Fill that variable with the function
fill_helloworld_data_(msg)
, explained below.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.cpp
The function fill_helloworld_data_()
returns the data to be sent with the information filled in.
First, the Dynamic_ptr
that will be filled in and returned is created. Using the DynamicDataFactory
we create the data that corresponds to our data type. Finally, data variables are assigned, in this case, index
and message
.
../../../resources/dds/TypeLookupService/TypeLookupServicePublisher.cpp
The DDS Subscriber is acting as a client of types, i.e. the subscriber will not know the types beforehand and it will discovery the data type via the type lookup service implemented on the publisher side.
This section explains the C++ source code of the DDS Subscriber, which can also be found here.
The private data members of the class defines the DDS Topic, DDS Topic type and DynamicType.
../../../resources/dds/TypeLookupService/TypeLookupServiceSubscriber.h
The next lines show the constructor of the TypeLookupServiceSubscriber
class that implements the subscriber setting the topic name as the one configured in the publisher side.
../../../resources/dds/TypeLookupService/TypeLookupServiceSubscriber.cpp
The DomainParticipantQos
are defined inside the TypeLookupServiceSubscriber
constructor. As the subscriber act as a client of types, set the QoS in order to receive this information. Set use_client
to true
and use_server
to false
.
../../../resources/dds/TypeLookupService/TypeLookupServiceSubscriber.cpp
Then, the Subscriber is initialized.
Inside on_data_available()
callback function the DynamicData_ptr
is created, which will be filled with the actual data received.
As in the subscriber, the DynamicDataFactory
is used for the creation of the data that corresponds to our data type.
../../../resources/dds/TypeLookupService/TypeLookupServiceSubscriber.cpp
The function on_type_information_received()
detects if new topic information has been received in order to proceed to register the topic in case it has the same name as the expected one. To register a remote topic, function register_remote_type_callback_()
is used. Once the topic has been discovered and registered, it is created a DataReader on this topic.
../../../resources/dds/TypeLookupService/TypeLookupServiceSubscriber.cpp
The function register_remote_type_callback_()
, which is in charge of register the topic received, is explained below. First, it creates a TypeSupport
with the corresponding type and registers it into the participant. Then, it creates the DDS Topic with the topic name set in the creation of the Subscriber and the topic type previously registered. Finally, it creates the DataReader of that topic.
../../../resources/dds/TypeLookupService/TypeLookupServiceSubscriber.cpp
Open two terminals:
In the first terminal, run the DDS Publisher:
source install/setup.bash cd DDS-Record-Replay/build/TypeLookupService ./TypeLookupService --entity publisher
- In the second terminal, run the DDS Subscriber:
source install/setup.bash
cd DDS-Record-Replay/build/TypeLookupService
./TypeLookupService --entity subscriber
At this point, we observe that the data published reach the subscriber and it can access to the content of the sample received.