5.16. Application Generation Using XML¶
RTI Connext Micro’s Application Generation feature enables you to specify an application in XML. It simplifies and accelerates application development by enabling the creation of DDS Entities (and registration of the factories) used in an application by compiling an XML configuration file, linking the result to an application, and calling a single API. Once created, all Entities can be retrieved from the application code using standard “lookup_by_name” operations so that they can be used to read and write data. UDP transport, DPDE (Dynamic Participant Dynamic Endpoint), and DPSE (Dynamic Participant Static Endpoint) discovery configuration can also be configured as needed. C or C++ source code is generated from the XML configuration and compiled with the application.
Once you have your XML file definition, you must use the Micro Application Generator (MAG) tool to load the XML file definition into Connext Micro. MAG is needed because Connext Micro does not include an XML parser (this would significantly increase code size and amount of memory needed). MAG generates C source code from the XML configuration that you must then compile with the application. The generated C source code contains the same information as the XML configuration file. The generated C source code can be used from both the C API Reference and C++ API Reference.
The Connext Micro Application Generation is enabled by default in this release when compiling with rtime-make. However, future releases may disable the feature by default. Thus, it is advised to always compile with the Connext Micro Application Generation feature enabled (-DRTIME_DDS_ENABLE_APPGEN=1 to CMake). See Examples.
5.16.1. Defining an Application in XML¶
Each Entity configured in the XML file is given a name. This name is used to retrieve the entities at runtime using the Connext Micro API.
In the XML file, you need to distinguish between two names:
Configuration name: The name of a specific Entity’s configuration. It is given by the name attribute of the corresponding element.
Entity name in the Entity’s QoS: The Entity name in the Entity’s QoS.
At runtime, the Entity will be created using the Entity name in the Entity’s QoS; the configuration name will be used if this is an empty string.
The attribute multiplicity indicates that a set of Entities should be created from the same configuration. Since each Entity must have a unique name, the system will automatically append a number to the Entity name in the Entity’s QoS (or, if it is an empty string, the configuration name) to obtain the Entity name. For example, if we specified a multiplicity of “N”, then for each index “i” between 0 and N-1, the system will assign Entity names according to the table below:
Entity Name |
Index: i |
---|---|
“configuration_name” |
0 |
“configuration_name#i” |
[1,N-1] |
That is, the Entity name followed by the token “#” and an index.
See A “Hello, World” Example for an example XML file.
5.16.1.1. Important Points¶
Applications can create a RTI Connext Micro Entity from a DomainParticipant configuration described in the XML configuration file. All the Entities defined by such DomainParticipant configuration are created automatically as part of the creation. In addition, multiple DomainParticipant configurations may be defined within a single XML configuration file.
All the Entities created from a DomainParticipant configuration are automatically assigned an entity name. Entities can be retrieved via “lookup_by_name” operations specifying their name. Each Entity stores its own name in the QoS policies of the Entity so that they can be retrieved locally (via a lookup) and communicated via discovery.
A configuration file is not tied to the application that uses it. Different applications may run using the same configuration file. A single file may define multiple DomainParticipant configurations. Normally, a single application will instantiate only one DomainParticipant, but an application can instantiate as many DomainParticipants as needed.
Changes in the XML configuration file require regenerating the C/C++ source code and recompiling the application.
5.16.2. Generating the Application from XML¶
Connext Micro comes with a tool, the Micro Application Generator (MAG). This tool is used to generate supporting files to create XML-defined applications at runtime.
5.16.2.1. Micro Application Generator (MAG) Tool¶
Micro Application Generator (MAG) is a required tool to configure Connext Micro applications by generating code from an XML configuration file; it creates DDS entities and registers all the components needed for a Connext Micro-based application. MAG can process your own XML configuration file, or it can process an XML-Based Application Creation file that you created for RTI Connext Professional.
Connext Micro Application Generation, in combination with MAG, enables two important use cases:
Users who may eventually develop with Connext Micro, but who haven’t determined their final platform, can prototype applications on a generic platform and validate that the QoS and DDS Entity configuration is within scope of what Connext Micro supports. MAG ignores fields in the XML file that Connext Micro doesn’t use (and produces an error for the few fields it cannot ignore; see “Unsupported values” in Errors Caused by Invalid Configurations and QoS).
Users who want to develop directly with Connext Micro can simplify their development efforts through shared XML files that can be configuration-managed. This reduces the burden on system integrators who want to configure Connext Micro systems without having to manually code in static configurations.
The main features of MAG are:
Generates code for the languages supported by Connext Micro: C and C++.
Automatically configures the remote entities that are needed to communicate with applications that use static discovery.
Automatically tries to use the default values used by Connext Micro, to reduce the size of the generated code.
Optimizes the components used by your application. By default, MAG generates code that will unregister transports that your application is not using.
Ignores fields and transports not supported by Connext Micro (any fields or transports not described in the API Reference) and raises errors for things it can’t ignore. See Errors Caused by Invalid Configurations and QoS.
Note
MAG has been tested with Java 17.0.6, which is included in the Connext Professional installation.
MAG does not support customizable templates. (It doesn’t support the functionality described in Customizing the Generated Code in the Code Generator User’s Manual.)
5.16.2.2. Generating the Application with MAG¶
5.16.2.2.1. Running MAG¶
To run the MAG tool, use the following command:
For example, on a Windows system:
<RTIMEHOME>/rtiddsmag/scripts/rtiddsmag.bat -language C -referencedFile HelloWorldQos.xml HelloWorld.xml
For example, on a Linux or macOS system:
<RTIMEHOME>/rtiddsmag/scripts/rtiddsmag -language C -referencedFile HelloWorldQos.xml HelloWorld.xml
Please refer to MAG Command-Line Options for valid command-line options.
5.16.2.2.2. Generated Files¶
The following table shows the files that MAG creates for an example XML file, HelloWorld.xml (which contains the application definition) and a referenced file, HelloWorldQos.xml (which contains the QoS definition). This second file is optional; you can define the QoS in the application file.
Note
Changes in the XML configuration file require regenerating the C/C++ source code and recompiling the application.
Generated Files |
Description |
---|---|
HelloWorldAppgen.h (C and C++) |
Generated code for each DDS Entity and its run-time components. |
HelloWorldAppgen.c (C and C++) |
Generated code for each Entity Model; also contains the values of each array used in the header file. |
HelloWorldAppgen_plugin.h (C++ only) |
Header file that contains the declarations of all the wrappers. |
HelloWorldAppgen_plugin.cxx (C++ only) |
A wrapper for the _get() call (get_plugin_type): struct DDS_TypePluginI *HelloWorldPlugin_get_cpp(void)
{
return HelloWorldPlugin_get();
}
|
Warning
You should not modify the generated code. MAG will overwrite your modifications
when it regenerates the C/C++ code from XML if the -replace
argument is used.
5.16.2.3. MAG Command-Line Options¶
The following table shows the options available when using rtiddsmag to generate code for Connext Micro applications.
Option |
Description |
---|---|
-d <outdir> |
Generates the output in the specified directory. By default, MAG will generate files in the directory where the XML file is located. |
-dontAddLocations |
Use this flag to avoid adding the input file location of fields into the generated files. By default (when this flag is not used), MAG will add the location where an entity was defined in the XML file. The location will be placed above the definition of that entity in the generated code. |
-dontOptimizeSE |
Use this flag to avoid static endpoint discovery optimization. Then MAG will include all DataWriters and DataReaders when calculating the remote entities. By default (when this option is not used) MAG will optimize the number of remote entities by only including Data Writers and DataReaders that use the same Topic in the remote model. |
-dontUpdateResourceLimits |
Use this flag to avoid automatically updating the resource limit settings for the DomainParticipantFactory, DomainParticipants, DataReaders, and DataWriters. Note: The use of this flag for the DomainParticipantFactory is currently not supported. By default (when this flag is not used), MAG will update the resource limits so it will at least be able to support the entities defined in the XML file. If your applications communicate with more remote entities that the ones specified in the XML file, you might need to manually update them. |
-dontUseDefaultValues |
Use this flag to avoid automatically generating code using default QoS policy values when possible. By default (when this flag is not used), MAG will check whether the values that are set in every element of the QoS policies for each entity are the same as the defaults used by Connext Micro. If that’s the case, the generated code will contain the default values for those policies, instead of the values set by the user. |
-dpdeName <name> |
Specifies the name used by MAG when registering a DPDE discovery plugin. By default, this name is dpde. |
-dpseName <name> |
Specifies the name used by MAG when registering a DPSE discovery plugin. By default, this name is dpse. |
-help |
Prints out the command-line options for MAG. |
-idlFile <file> |
Specifies the IDL file name used by rtiddsgen to generate the code. This value is used by MAG to specify the Plugin header generated by rtiddsgen. By default, MAG uses the name of the XML file. |
-inputXml <file> |
Specifies the XML configuration file used to generate code. The XML configuration file can be passed directly to MAG without using the -inputXml option, by default MAG knows that any argument with no option is the input file. |
-language <C|C++> |
Specifies the language to use for the generated files. The default language is C. |
-onlyValidate |
Causes MAG to just validate the input file. It will not generate any code. |
-outputFinalQoS <QosLibrary::QosProfile> |
Use this flag to display the final values of the specified QoS profile after applying inheritance. Although MAG currently doesn’t generate code to set the QoS for Connext Micro, using this flag will determine the final values in the profile after applying inheritance. For complex XML files, with multiple levels of inheritance, it might be a challenge to determine the final QoS values. Using this flag simplifies the process. Note: This option does not check whether or not the final values are supported by Connext Micro. |
-referencedFile <file> |
Specifies a file which is referenced from the one being used to generate code. In general, it is recommended to split the application definition from the QoS definition. This way, the QoS can be shared among various applications. Note: Can be repeated.
|
-replace |
Use this flag to overwrite existing generated files. |
-shmemName <name> |
Specifies the name used by MAG when registering a shared memory (SHMEM) transport plugin. By default, this name is shmem. |
-udpName <name> |
Specifies the name used by MAG when registering a UDP transport plugin. By default, this name is udp. |
-verbosity [1-4] |
Sets the MAG verbosity: 1: Exceptions. 2: Exceptions and warnings. 3: Exceptions, warnings, and information. (Default) 4: Exceptions, warnings, information, and debug. |
-version |
Displays the version of MAG being used, such as 4.0.1. |
5.16.2.4. Integrating Generated Files into Your Application’s Build¶
Integrating the generated files into your application is as easy as including the generated files HelloWorldAppgen.h and HelloWorldAppgen.c in your application. If your application uses C++, you will also need to include HelloWorldAppgen_plugin.h and HelloWorldAppgen_plugin.cxx.
Then you can create entities using the standard DDS_DomainParticipantFactory_create_participant_from_config() operation and retrieve all the entities from your application code using the standard lookup_<entity>_by_name() operations, such as lookup_datawriter_by_name(). For details on these operations, see the DomainParticipantFactory module in the Connext Micro API reference HTML documentation.
5.16.3. Creating the Application¶
5.16.3.1. Call API to Create DomainParticipant¶
To create the application that MAG generates from the XML definition, you must call the API create_participant_from_config() to create the DomainParticipant. All applications start with the DomainParticipant. This API receives the configuration name and creates all the Entities defined by that configuration.
5.16.3.2. Retrieve Entities by Name¶
After creation, you can retrieve the defined Entities by using the lookup_by_name() operations available in the C API Reference and C++ API Reference.
5.16.4. A “Hello, World” Example¶
This simple scenario consists of two applications: HelloWorld_publisher, which writes the Topic, HelloWorldTopic, and HelloWorld_subscriber, which subscribes to that Topic.
The files for this example are provided when you install Connext Micro. You will find them in the directory <path to Micro examples>/C/HelloWorld_appgen. The following examples are provided:
Domain Participant “HelloWorldDPDEPubDP”
This application defines a publisher which uses DPDE discovery.
The application has one named “HelloWorldDPDEPubDP”, one named “HelloWorldDPDEPub”, and one named “HelloWorldDPDEDW” which uses topic name “Example HelloWorld”. The application registers one type with name “HelloWorld” and defines one with name “Example HelloWorld” which uses the type “HelloWorld”.
Domain Participant “HelloWorldDPDESubDP”
This application defines a subscriber which uses DPDE discovery.
The application has one named “HelloWorldDPDESubDP”, one named “HelloWorldDPDESub”, and one named “HelloWorldDPDEDR” which uses topic name “Example HelloWorld”. The application registers one type with name “HelloWorld” and defines one with name “Example HelloWorld” which uses the type “HelloWorld”.
Domain Participant “HelloWorldDPSEPubDP”
This application defines a publisher which uses DPSE discovery.
The application has one named “HelloWorldDPSEPubDP”, one named “HelloWorldDPSEPub”, and one named “HelloWorldDPSEDW” which uses topic name “Example HelloWorld” and has RTPS id 100. The application registers one type with name “HelloWorld” and defines one with name “Example HelloWorld” which uses type “HelloWorld”.
The application asserts one remote participant named “HelloWorldDPSESubDP” and one remote subscription with ID 200, type name “HelloWorld”, and topic name “Example HelloWorld”.
Domain Participant “HelloWorldDPSESubDP”
This application defines a subscriber which uses DPSE discovery.
The application has one named “HelloWorldDPSESubDP”, one named “HelloWorldDPSESub”, and one named “HelloWorldDPSEDR” which uses topic name “Example HelloWorld” and has RTPS id 200. The application registers one type with name “HelloWorld” and defines one with name “Example HelloWorld” which uses the type “HelloWorld”.
The application asserts one remote participant named “HelloWorldDPSEPubDP” and one remote subscription with ID 100, type name “HelloWorld”, and topic name “Example HelloWorld”.
5.16.4.1. Generate Type-Support Code from the Type Definition¶
The first step is to describe the data type in a programming language-neutral manner. Three languages are supported by RTI Code Generator: XML, IDL, and XSD. These three languages provide equivalent type-definition capabilities, so you can choose whichever one you prefer. You can even transform between one of these three languages and another with RTI Code Generator. That said, since the rest of the configuration files use XML, it is often more convenient to also use XML to describe the data types, so they can be shared or moved to other XML configuration files.
The file HelloWorld.xml contains the XML description of the data type. You can find this file in <path to Micro examples>/C/HelloWorld_appgen.
Let’s examine the type used in this example:
<types>
<const name="MAX_NAME_LEN" type="long" value="64"/>
<const name="MAX_MSG_LEN" type="long" value="128"/>
<struct name="HelloWorld">
<member name="sender" type="string" stringMaxLength="MAX_NAME_LEN" key="true"/>
<member name="message" type="string" stringMaxLength="MAX_MSG_LEN"/>
<member name="count" type="long"/>
</struct>
</types>
The data associated with the HelloWorld Topic consists of two strings and a numeric counter:
The first string contains the name of the sender of the message. This field is marked as the “key” since it signals the identity of the data-object.
The second string contains a message.
The third field is a simple counter, which the application increments with each message.
Once the type has been defined, we use rtiddsgen to generate the code for the HelloWorld data type.
We will use the C language in this example.
To generate code with rtiddsgen:
On a Windows system:
From your command shell, change directory to <path to Micro examples>CHelloWorld_appgen and type:
<RTIMEHOME>\rtiddsgen\scripts\rtiddsgen.bat -language C HelloWorld.xml
Note
The Visual Studio solution in the example folder automatically calls rtiddsgen.
On a Linux or macOS system:
From your command shell, change directory to <path to Micro examples>/C/HelloWorld_appgen and type:
<RTIMEHOME>/rtiddsgen/scripts/rtiddsgen -language C HelloWorld.xml
After running rtiddsgen, you will see the following files in the HelloWorld_appgen directory:
HelloWorld.h
HelloWorld.c
HelloWorldPlugin.h
HelloWorldPlugin.c
HelloWorldSupport.h
HelloWorldSupport.c
The most notable files are HelloWorld.h and HelloWorldPlugin.h:
HelloWorld.h contains the declaration of the C structure, built according to the specification in the XML file:
typedef struct HelloWorld { CDR_String sender; CDR_String message; CDR_Long count; } HelloWorld;
HelloWorldPlugin.h contains the get_plugin_type() function that MAG will use when generating the code to create all the DDS entities:
NDDSUSERDllExport extern struct NDDS_Type_Plugin* HelloWorldTypePlugin_get(void);
5.16.4.2. Generate DDS Entities from the System Definition¶
This step uses rtiddsmag to generate code to support the creation of DDS entities using Application Generation in Connext Micro.
rtiddsmag supports C and C++. We will use C in this example.
Note
You can do this step before or after generating Type-Support from the Type definition since the type code doesn’t need to exist when running rtiddsmag.
To generate code with rtiddsmag:
On a Windows system:
From your command shell, change directory to <path to Micro examples>CHelloWorld_appgen and type:
<RTIMEHOME>\rtiddsmag\scripts\rtiddsmag.bat -language C -referencedFile HelloWorldQos.xml HelloWorld.xml
Note
The Visual Studio solution in the example folder automatically calls rtiddsmag.
On a Linux or macOS system:
From your command shell, change directory to <path to Micro examples>/C/HelloWorld_appgen and type:
<RTIMEHOME>/rtiddsmag/scripts/rtiddsmag -language C -referencedFile HelloWorldQos.xml HelloWorld.xml
We will examine the content of the generated files in the next section.
5.16.4.3. Examine the XML Configuration Files and the Generated Code¶
The entire HelloWorld.xml file is shown below. Let’s review its content to see how this scenario was constructed. The main sections in the file are:
<?xml version="1.0"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/current/rti_dds_profiles.xsd">
<!-- Type Definition -->
<types>
<const name="MAX_NAME_LEN" type="int32" value="64"/>
<const name="MAX_MSG_LEN" type="int32" value="128"/>
<struct name="HelloWorld">
<member name="sender" type="string" stringMaxLength="MAX_NAME_LEN" key="true"/>
<member name="message" type="string" stringMaxLength="MAX_MSG_LEN"/>
<member name="count" type="int32"/>
</struct>
</types>
<!-- Domain Library -->
<domain_library name="HelloWorldLibrary">
<domain name="HelloWorldDomain" domain_id="0">
<register_type name="HelloWorldType" type_ref="HelloWorld">
</register_type>
<topic name="HelloWorldTopic" register_type_ref="HelloWorldType">
<registered_name>HelloWorldTopic</registered_name>
</topic>
</domain>
</domain_library>
<!-- Participant Library -->
<domain_participant_library name="HelloWorldAppLibrary">
<domain_participant name="HelloWorldDPDEPubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<publisher name="HelloWorldDPDEPub">
<data_writer topic_ref="HelloWorldTopic" name="HelloWorldDPDEDW">
<datawriter_qos base_name="QosLibrary::DPDEProfile"/>
</data_writer>
</publisher>
<domain_participant_qos base_name="QosLibrary::DPDEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPDESubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<subscriber name="HelloWorldDPDESub">
<data_reader topic_ref="HelloWorldTopic" name="HelloWorldDPDEDR">
<datareader_qos base_name="QosLibrary::DPDEProfile"/>
</data_reader>
</subscriber>
<domain_participant_qos base_name="QosLibrary::DPDEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPSEPubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<publisher name="HelloWorldDPSEPub">
<data_writer topic_ref="HelloWorldTopic" name="HelloWorldDPSEDW">
<datawriter_qos base_name="QosLibrary::DPSEProfile"/>
</data_writer>
</publisher>
<domain_participant_qos base_name="QosLibrary::DPSEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPSESubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<subscriber name="HelloWorldDPSESub">
<data_reader topic_ref="HelloWorldTopic" name="HelloWorldDPSEDR">
<datareader_qos base_name="QosLibrary::DPSEProfile"/>
</data_reader>
</subscriber>
<domain_participant_qos base_name="QosLibrary::DPSEProfile"/>
</domain_participant>
</domain_participant_library>
</dds>
5.16.4.3.1. Type Definition¶
rtiddsmag doesn’t use the types section of the XML file to generate any code. This section is used by rtiddsgen to generate the code to support the direct use of the structure ‘HelloWorld’ from application code (see Generate Type-Support Code from the Type Definition).
<types>
<const name="MAX_NAME_LEN" type="int32" value="64"/>
<const name="MAX_MSG_LEN" type="int32" value="128"/>
<struct name="HelloWorld">
<member name="sender" type="string" stringMaxLength="MAX_NAME_LEN" key="true"/>
<member name="message" type="string" stringMaxLength="MAX_MSG_LEN"/>
<member name="count" type="int32"/>
</struct>
</types>
5.16.4.3.2. Domain Definition¶
The domain section defines the system’s Topics and their corresponding data types. To define a Topic, the associated data type must be registered with the domain, giving it a registered type name. The registered type name is used to refer to that data type within the domain when the Topic is defined.
In this example, the configuration file registers the previously defined HelloWorld type under the name HelloWorldType. Then it defines a Topic named HelloWorldTopic, which is associated with the registered type, referring to its registered name, HelloWorldType. The value used in get_plugin_type depends on how the registration of the data-type is configured inside the domain:
If a <register_type> tag is specified without a type_ref attribute, the value of get_type_plugin is generated from the <register_type> tag plus the string “Plugin_get”.
If a <register_type> tag is specified with a type_ref attribute, the value of get_type_plugin is generated from that attribute plus the string “TypePlugin_get”. Our example has type_ref = “HelloWorld”, so the value of get_type_plugin will be HelloWorldTypePlugin_get.
<!-- Domain Library -->
<domain_library name="HelloWorldLibrary">
<domain name="HelloWorldDomain" domain_id="0">
<register_type name="HelloWorldType" type_ref="HelloWorld">
</register_type>
<topic name="HelloWorldTopic" register_type_ref="HelloWorldType">
</topic>
</domain>
</domain_library>
rtiddsmag generates the following code for each entity that uses this Topic:
HelloWorldAppgen.c
const struct APPGEN_TypeRegistrationModel HelloWorldAppLibrary_HelloWorldDPDEPubDP_type_registrations[1] = { { "HelloWorldType", /* registered_type_name */ HelloWorldTypePlugin_get /* get_type_plugin */ } }; const struct APPGEN_TopicModel HelloWorldAppLibrary_HelloWorldDPDEPubDP_topics[1] = { { "HelloWorldTopic", /* topic_name */ "HelloWorldType", /* type_name */ DDS_TopicQos_INITIALIZER /* topic_qos*/ } };
These two structures are used in the DomainParticipant definition, where they will be registered by Connext Micro when calling the Micro Application Generation API.
HelloWorldAppgen.h
extern const struct APPGEN_TypeRegistrationModel HelloWorldAppLibrary_HelloWorldDPDEPubDP_type_registrations[1]; extern const struct APPGEN_TopicModel HelloWorldAppLibrary_HelloWorldDPDEPubDP_topics[1]; #define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPDEPubDP \ { \ ... 1UL, /* type_registration_count */ \ HelloWorldAppLibrary_HelloWorldDPDEPubDP_type_registrations, /* type_registrations*/ \ 1UL, /* topic_count */ \ HelloWorldAppLibrary_HelloWorldDPDEPubDP_topics, /* topics */ \ ... }
Note
Connext Micro automatically registers the types that rtiddsmag generates. This means the content inside the Domain definition must match the types generated by rtiddsgen.
5.16.4.3.3. DomainParticipant Definition¶
The DomainParticipant section defines the DomainParticipants in the system and the DataWriters and DataReaders that each DomainParticipant has. DomainParticipants are defined within the <domain_participant_library> tag.
Each DomainParticipant:
Has a unique name (within the library) which will be used later by the application that creates it.
Is associated with a domain, which defines the domain_id, Topics, and the data types the DomainParticipant will use.
Defines the Publishers and Subscribers within the DomainParticipant. Publishers contain DataWriters, Subscribers contain DataReaders.
Defines the set of DataReaders it will use to read data. Each DataReader has a QoS and a unique name which can be used from application code to retrieve it.
Defines the set of DataWriters it will use to write data. Each DataWriter has a QoS and a unique name which can be used from application code to retrieve it.
Optionally, the DomainParticipants, Publishers, Subscribers, DataWriters, and DataReaders can specify a QoS profile that will be used to configure them.
The example below defines four DomainParticipants, two of them (HelloWorldDPDEPubDP and HelloWorldDPDESubDP) use Dynamic Participant/Dynamic Endpoint (DPDE) and the other two (HelloWorldDPSEPubDP and HelloWorldDPSESubDP) use Dynamic Participant/Static Endpoint (DPSE) discovery:
<!-- Participant Library -->
<domain_participant_library name="HelloWorldAppLibrary">
<domain_participant name="HelloWorldDPDEPubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<publisher name="HelloWorldDPDEPub">
<data_writer topic_ref="HelloWorldTopic" name="HelloWorldDPDEDW">
<datawriter_qos base_name="QosLibrary::DPDEProfile"/>
</data_writer>
</publisher>
<domain_participant_qos base_name="QosLibrary::DPDEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPDESubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<subscriber name="HelloWorldDPDESub">
<data_reader topic_ref="HelloWorldTopic" name="HelloWorldDPDEDR">
<datareader_qos base_name="QosLibrary::DPDEProfile"/>
</data_reader>
</subscriber>
<domain_participant_qos base_name="QosLibrary::DPDEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPSEPubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<publisher name="HelloWorldDPSEPub">
<data_writer topic_ref="HelloWorldTopic" name="HelloWorldDPSEDW">
<datawriter_qos base_name="QosLibrary::DPSEProfile"/>
</data_writer>
</publisher>
<domain_participant_qos base_name="QosLibrary::DPSEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPSESubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<subscriber name="HelloWorldDPSESub">
<data_reader topic_ref="HelloWorldTopic" name="HelloWorldDPSEDR">
<datareader_qos base_name="QosLibrary::DPSEProfile"/>
</data_reader>
</subscriber>
<domain_participant_qos base_name="QosLibrary::DPSEProfile"/>
</domain_participant>
</domain_participant_library>
Examining the XML, we see that:
Each DomainParticipant is bound to the Domain, HelloWorldLibrary::HelloWorldDomain.
The two DomainParticipants that use DPDE as their discovery mechanism inherit from the profile QosLibrary::DPDELibrary, while the other two that use DPSE as their discovery mechanism inherit from QosLibrary::DPSELibrary.
Each DomainParticipant contains a single Publisher or Subscriber, which it turn contains a single DataWriter or DataReader that inherits from QosLibrary::DPDELibrary or QosLibrary::DPSELibrary, depending on the discovery mechanism used by its DomainParticipant.
Each DataWriter writes the Topic HelloWorldTopic, which is defined in the domain HelloWorldLibrary::HelloWorldDomain. Each DataReader reads the same Topic.
Since both Dynamic DomainParticipants (those which are using DPDE as their discovery mechanism) are in the same the domain and the DataWriter writes the same Topic that the DataReader reads, the two DomainParticipants will communicate. This also apply to both static participants (those which are using DPSE as their discovery mechanism); the only difference is that rtiddsmag will generate extra code to configure the remote entities (for details, see Static Discovery).
Let’s look at the content of a DomainParticipant definition to explain the code generated by rtiddsmag.
<domain_participant name="HelloWorldDPDEPubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<publisher name="HelloWorldDPDEPub">
<data_writer topic_ref="HelloWorldTopic" name="HelloWorldDPDEDW">
<datawriter_qos base_name="QosLibrary::DPDEProfile"/>
</data_writer>
</publisher>
<domain_participant_qos base_name="QosLibrary::DPDEProfile"/>
</domain_participant>
rtiddsmag generates the code needed to register each component used by this DomainParticipant and unregister those components that are not being used. In our example, for each DomainParticipant, rtiddsmag registers the discovery transport, dpde or dpse; registers the UDP transport used by each DomainParticipant (since they use the same configuration, only one UDP transport configuration is generated); and unregisters the default UDP and INTRA transports, since they are not being used (these two are the only ones that can be unregistered by rtiddsmag).
It also creates the code for each entity. In this case, it generates the code needed to create:
A Publisher named HelloWorldDPDEPub
A DataWriter named HelloWorldDPDEDW
A DomainParticipant named HelloWorldDPDEPubDP
The QoS used by this DomainParticipant (see QoS Definition)
HelloWorldAppgen.c
const struct ComponentFactoryUnregisterModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_unregister_components[2] =
{
{
"_udp", /* NETIO_DEFAULT_UDP_NAME */
NULL, /* udp struct RT_ComponentFactoryProperty** */
NULL /* udp struct RT_ComponentFactoryListener** */
},
{
"_intra", /* NETIO_DEFAULT_INTRA_NAME */
NULL, /* _intra struct RT_ComponentFactoryProperty** */
NULL /* _intra struct RT_ComponentFactoryListener** */
}
};
struct DPDE_DiscoveryPluginProperty
HelloWorldAppLibrary_HelloWorldDPDEPubDP_dpde[1] =
{
RTI_APP_GEN___dpde__HelloWorldAppLibrary_HelloWorldDPDEPubDP_dpde1
};
struct UDP_InterfaceFactoryProperty
HelloWorldAppLibrary_HelloWorldDPDEPubDP_udpv4[1] =
{
RTI_APP_GEN___udpv4__HelloWorldAppLibrary_HelloWorldDPDEPubDP_udp1
};
const struct ComponentFactoryRegisterModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_register_components[2] =
{
{
"dpde1", /* register_name */
DPDE_DiscoveryFactory_get_interface, /* register_intf */
&HelloWorldAppLibrary_HelloWorldDPDEPubDP_dpde[0]._parent, /* register_property */
NULL /* register_listener */
},
{
"udp1", /* register_name */
UDP_InterfaceFactory_get_interface, /* register_intf */
&HelloWorldAppLibrary_HelloWorldDPDEPubDP_udpv4[0]._parent._parent, /* register_property */
NULL /* register_listener */
}
};
...
const struct APPGEN_DataWriterModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_publisher_HelloWorldDPDEPub_data_writers[1] =
{
{
"HelloWorldDPDEDW", /* name */
1UL, /* multiplicity */
"HelloWorldTopic", /* topic_name */
RTI_APP_GEN___DW_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP_HelloWorldDPDEPub_HelloWorldDPDEDW /* writer_qos */
}
};
const struct APPGEN_PublisherModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_publishers[1] =
{
{
"HelloWorldDPDEPub", /* name */
1UL, /* multiplicity */
DDS_PublisherQos_INITIALIZER, /* publisher_qos */
1UL, /* writer_count */
HelloWorldAppLibrary_HelloWorldDPDEPubDP_publisher_HelloWorldDPDEPub_data_writers /* data_writers */
}
};
HelloWorldAppgen.h
extern struct DPDE_DiscoveryPluginProperty HelloWorldAppLibrary_HelloWorldDPDEPubDP_dpde[1];
extern struct UDP_InterfaceFactoryProperty HelloWorldAppLibrary_HelloWorldDPDEPubDP_udpv4[1];
extern const struct ComponentFactoryUnregisterModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_unregister_components[2];
extern const struct ComponentFactoryRegisterModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_register_components[2];
#define RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPDEPubDP \
{ \
2UL, /* unregister_count */ \
HelloWorldAppLibrary_HelloWorldDPDEPubDP_unregister_components, /* unregister_components */\
2UL, /* register_count */ \
HelloWorldAppLibrary_HelloWorldDPDEPubDP_register_components, /* register_components */ \
RTI_APP_GEN___DPF_QOS_QosLibrary_DefaultProfile /* factory_qos */ \
}
extern const struct APPGEN_TypeRegistrationModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_type_registrations[1];
extern const struct APPGEN_TopicModel HelloWorldAppLibrary_HelloWorldDPDEPubDP_topics[1];
extern const struct APPGEN_PublisherModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_publishers[1];
#define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPDEPubDP \
{ \
"HelloWorldDPDEPubDP", /* name */ \
RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPDEPubDP, /* domain_participant_factory */ \
RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP, /* domain_participant_qos */ \
0L, /* domain_id */ \
1UL, /* type_registration_count */ \
HelloWorldAppLibrary_HelloWorldDPDEPubDP_type_registrations, /* type_registrations */ \
1UL, /* topic_count */ \
HelloWorldAppLibrary_HelloWorldDPDEPubDP_topics, /* topics */ \
1UL, /* publisher_count */ \
HelloWorldAppLibrary_HelloWorldDPDEPubDP_publishers, /* publishers */ \
0UL, /* subscriber_count */ \
NULL, /* subscribers */ \
0UL, /* remote_participant_count */ \
NULL, /* remote_participants */ \
0UL, /* flow_controller_count */ \
NULL /* flow_controllers */ \
}
5.16.4.4. QoS Definition¶
The defined DDS Entities have an associated QoS Policy, which can be defined in a separate file such as HelloWorldQos.xml or within the System XML file.
For more information on how to configure DDS Entities in an XML file, see Configuring QoS with XML (if you have internet access).
See the entire file below. Then we will examine the file section by section, showing the code generated by rtiddsmag.
<?xml version="1.0"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/current/rti_dds_profiles.xsd">
<qos_library name="QosLibrary">
<qos_profile name="DefaultProfile" is_default_participant_factory_profile="true">
<!-- Participant Factory Qos -->
<participant_factory_qos>
<entity_factory>
<autoenable_created_entities>false</autoenable_created_entities>
</entity_factory>
</participant_factory_qos>
<!-- Participant Qos -->
<domain_participant_qos>
<discovery>
<accept_unknown_peers>false</accept_unknown_peers>
<initial_peers>
<element>127.0.0.1</element>
<element>239.255.0.1</element>
</initial_peers>
<enabled_transports>
<element>udpv4</element>
</enabled_transports>
<multicast_receive_addresses>
<element>udpv4://127.0.0.1</element>
<element>udpv4://239.255.0.1</element>
</multicast_receive_addresses>
</discovery>
<default_unicast>
<value>
<element>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</default_unicast>
<transport_builtin>
<mask>UDPv4</mask>
</transport_builtin>
<resource_limits>
<local_writer_allocation>
<max_count>1</max_count>
</local_writer_allocation>
<local_reader_allocation>
<max_count>1</max_count>
</local_reader_allocation>
<local_publisher_allocation>
<max_count>1</max_count>
</local_publisher_allocation>
<local_subscriber_allocation>
<max_count>1</max_count>
</local_subscriber_allocation>
<local_topic_allocation>
<max_count>1</max_count>
</local_topic_allocation>
<local_type_allocation>
<max_count>1</max_count>
</local_type_allocation>
<remote_participant_allocation>
<max_count>8</max_count>
</remote_participant_allocation>
<remote_writer_allocation>
<max_count>8</max_count>
</remote_writer_allocation>
<remote_reader_allocation>
<max_count>8</max_count>
</remote_reader_allocation>
<max_receive_ports>32</max_receive_ports>
<max_destination_ports>32</max_destination_ports>
</resource_limits>
</domain_participant_qos>
<!-- DataWriter Qos -->
<datawriter_qos>
<history>
<depth>32</depth>
</history>
<resource_limits>
<max_instances>2</max_instances>
<max_samples>64</max_samples>
<max_samples_per_instance>32</max_samples_per_instance>
</resource_limits>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<protocol>
<rtps_reliable_writer>
<heartbeat_period>
<nanosec>250000000</nanosec>
<sec>0</sec>
</heartbeat_period>
</rtps_reliable_writer>
</protocol>
<!-- transports -->
<unicast>
<value>
<element>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</unicast>
</datawriter_qos>
<!-- DataReader Qos -->
<datareader_qos>
<history>
<depth>32</depth>
</history>
<resource_limits>
<max_instances>2</max_instances>
<max_samples>64</max_samples>
<max_samples_per_instance>32</max_samples_per_instance>
</resource_limits>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<reader_resource_limits>
<max_remote_writers>10</max_remote_writers>
<max_remote_writers_per_instance>10</max_remote_writers_per_instance>
</reader_resource_limits>
<!-- transports -->
<unicast>
<value>
<element>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</unicast>
<multicast>
<value>
<element>
<receive_address>127.0.0.1</receive_address>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</multicast>
</datareader_qos>
</qos_profile>
<qos_profile name="DPDEProfile" base_name="DefaultProfile">
<domain_participant_qos>
<discovery_config>
<builtin_discovery_plugins>SDP</builtin_discovery_plugins>
</discovery_config>
</domain_participant_qos>
</qos_profile>
<qos_profile name="DPSEProfile" base_name="DefaultProfile">
<domain_participant_qos>
<discovery_config>
<builtin_discovery_plugins>DPSE</builtin_discovery_plugins>
</discovery_config>
</domain_participant_qos>
</qos_profile>
</qos_library>
</dds>
Note
rtiddsmag only generates code for the QoS policies used by at least one entity, unless the QoS profile has either of the default flags is_default_participant_factory_profile or is_default_qos set to true.
5.16.4.4.1. DomainParticipant Factory QoS¶
rtiddsmag only generates code for the <participant_factory_qos> in the <qos_profile> that has the flag is_default_participant_factory_profile set to true. The log verbosity can also be configured by using <verbosity> inside <logging>. For example:
<!-- Participant Factory Qos -->
<participant_factory_qos>
<entity_factory>
<autoenable_created_entities>false</autoenable_created_entities>
</entity_factory>
<resource_limits>
<max_participants>4</max_participants>
<max_components>20</max_components>
</resource_limits>
</participant_factory_qos>
rtiddsmag generates the following code:
HelloWorldAppgen.h
#define RTI_APP_GEN___DPF_QOS_QosLibrary_DefaultProfile \
{ \
{ /* entity_factory */ \
DDS_BOOLEAN_FALSE /* autoenable_created_entities */ \
}, \
{ /* resource_limits */ \
4L, /* max_participants */ \
20L /* max_components */ \
} \
}
#define RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPDEPubDP \
{ \
...,
RTI_APP_GEN___DPF_QOS_QosLibrary_DefaultProfile /* factory_qos */ \
}
5.16.4.4.2. DomainParticipant QoS¶
The example defines a base profile named DefaultProfile, which contains the base QoSs used by each DomainParticipant. You can see the content of the DomainParticipant QoS below.
<domain_participant_qos>
<discovery>
<accept_unknown_peers>false</accept_unknown_peers>
<initial_peers>
<element>127.0.0.1</element>
<element>239.255.0.1</element>
</initial_peers>
<enabled_transports>
<element>udpv4</element>
</enabled_transports>
<multicast_receive_addresses>
<element>udpv4://127.0.0.1</element>
<element>udpv4://239.255.0.1</element>
</multicast_receive_addresses>
</discovery>
<default_unicast>
<value>
<element>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</default_unicast>
<transport_builtin>
<mask>UDPv4</mask>
</transport_builtin>
<resource_limits>
<local_writer_allocation>
<max_count>1</max_count>
</local_writer_allocation>
<local_reader_allocation>
<max_count>1</max_count>
</local_reader_allocation>
<local_publisher_allocation>
<max_count>1</max_count>
</local_publisher_allocation>
<local_subscriber_allocation>
<max_count>1</max_count>
</local_subscriber_allocation>
<local_topic_allocation>
<max_count>1</max_count>
</local_topic_allocation>
<local_type_allocation>
<max_count>1</max_count>
</local_type_allocation>
<remote_participant_allocation>
<max_count>8</max_count>
</remote_participant_allocation>
<remote_writer_allocation>
<max_count>8</max_count>
</remote_writer_allocation>
<remote_reader_allocation>
<max_count>8</max_count>
</remote_reader_allocation>
<max_receive_ports>32</max_receive_ports>
<max_destination_ports>32</max_destination_ports>
</resource_limits>
</domain_participant_qos>
This DomainParticipant is then inherited by two different profiles, which set up the discovery mechanism:
<domain_participant_qos>
<discovery_config>
<builtin_discovery_plugins>SDP</builtin_discovery_plugins>
</discovery_config>
</domain_participant_qos>
<domain_participant_qos>
<discovery_config>
<builtin_discovery_plugins>DPSE</builtin_discovery_plugins>
</discovery_config>
</domain_participant_qos>
rtiddsmag generates the following code for each DomainParticipant whose QoS inherits from any of the previous ones, adding those values that are specified in the XML configuration file (which is not the case in our example).
HelloWorldAppgen.c
const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_initial_peers[2] =
{
"127.0.0.1",
"239.255.0.1"
};
const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_discovery_enabled_transports[3] =
{
"udp1://",
"udp1://127.0.0.1",
"udp1://239.255.0.1"
};
const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_transport_enabled_transports[1] =
{
"udp1"
};
const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_user_traffic_enabled_transports[1] =
{
"udp1://"
};
HelloWorldAppgen.h
extern const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_initial_peers[2];
extern const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_discovery_enabled_transports[3];
extern const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_transport_enabled_transports[1];
extern const char *const HelloWorldAppLibrary_HelloWorldDPDEPubDP_user_traffic_enabled_transports[1];
#define RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP \
{ \
{ /* entity_factory */ \
DDS_BOOLEAN_TRUE /* autoenable_created_entities */ \
}, \
{ /* discovery */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_initial_peers, 2, 2), /* initial_peers */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_discovery_enabled_transports, 3, 3), /* enabled_transports */ \
{ \
{ { "dpde1" } }, /* RT_ComponentFactoryId_INITIALIZER */ \
NDDS_Discovery_Property_INITIALIZER \
}, /* discovery_component */ \
DDS_BOOLEAN_FALSE /* accept_unknown_peers */ \
}, \
{ /* resource_limits */ \
1L, /* local_writer_allocation */ \
1L, /* local_reader_allocation */ \
1L, /* local_publisher_allocation */ \
1L, /* local_subscriber_allocation */ \
1L, /* local_topic_allocation */ \
1L, /* local_type_allocation */ \
8L, /* remote_participant_allocation */ \
8L, /* remote_writer_allocation */ \
8L, /* remote_reader_allocation */ \
32L, /* matching_writer_reader_pair_allocation */ \
32L, /* matching_reader_writer_pair_allocation */ \
32L, /* max_receive_ports */ \
32L, /* max_destination_ports */ \
65536, /* unbound_data_buffer_size */ \
500UL, /* shmem_ref_transfer_mode_max_segments */ \
0L, /* participant_user_data_max_length */ \
DDS_SIZE_AUTO, /* participant_user_data_max_count */ \
0L, /* topic_data_max_length */ \
DDS_SIZE_AUTO, /* topic_data_max_count */ \
0L, /* publisher_group_data_max_length */ \
DDS_SIZE_AUTO, /* publisher_group_data_max_count */ \
0L, /* subscriber_group_data_max_length */ \
DDS_SIZE_AUTO, /* subscriber_group_data_max_count */ \
0L, /* writer_user_data_max_length */ \
DDS_SIZE_AUTO, /* writer_user_data_max_count */ \
0L, /* reader_user_data_max_length */ \
DDS_SIZE_AUTO, /* reader_user_data_max_count */ \
64L, /* max_partitions */ \
256L, /* max_partition_cumulative_characters */ \
DDS_LENGTH_UNLIMITED, /* max_partition_string_size */ \
DDS_LENGTH_UNLIMITED /* max_partition_string_allocation */ \
}, \
DDS_ENTITY_NAME_QOS_POLICY_DEFAULT, \
DDS_WIRE_PROTOCOL_QOS_POLICY_DEFAULT, \
{ /* transports */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_transport_enabled_transports, 1, 1) /* enabled_transports */ \
}, \
{ /* user_traffic */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_user_traffic_enabled_transports, 1, 1) /* enabled_transports */ \
}, \
DDS_TRUST_QOS_POLICY_DEFAULT, \
DDS_PROPERTY_QOS_POLICY_DEFAULT, \
DDS_USER_DATA_QOS_POLICY_DEFAULT \
}
5.16.4.4.3. Publisher QoS¶
Our example doesn’t specify any value for Publisher QoS, however rtiddsmag would generate code if it was specified.
5.16.4.4.4. DataWriter QoS¶
The example defines a base profile named DefaultProfile, which contains the base QoSs used by each DomainParticipant. You can see the content of the DataWriter QoS below.
<!-- DataWriter Qos -->
<datawriter_qos>
<history>
<depth>32</depth>
</history>
<resource_limits>
<max_instances>2</max_instances>
<max_samples>64</max_samples>
<max_samples_per_instance>32</max_samples_per_instance>
</resource_limits>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<protocol>
<rtps_reliable_writer>
<heartbeat_period>
<nanosec>250000000</nanosec>
<sec>0</sec>
</heartbeat_period>
</rtps_reliable_writer>
</protocol>
<!-- transports -->
<unicast>
<value>
<element>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</unicast>
</datawriter_qos>
rtiddsmag generates the following code:
HelloWorldAppgen.c
const char *const
HelloWorldAppLibrary_HelloWorldDPDEPubDP_HelloWorldDPDEPub_HelloWorldDPDEDW_transport_enabled_transports[1] =
{
"udp1://"
};
HelloWorldAppgen.h
extern const char *const
HelloWorldAppLibrary_HelloWorldDPDEPubDP_HelloWorldDPDEPub_HelloWorldDPDEDW_transport_enabled_transports[1];
#define RTI_APP_GEN___DW_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP_HelloWorldDPDEPub_HelloWorldDPDEDW \
{ \
DDS_DEADLINE_QOS_POLICY_DEFAULT, \
DDS_LIVELINESS_QOS_POLICY_DEFAULT, \
{ /* history */ \
DDS_KEEP_LAST_HISTORY_QOS, /* kind */ \
32L /* depth */ \
}, \
{ /* resource_limits */ \
64L, /* max_samples */ \
2L, /* max_instances */ \
32L /* max_samples_per_instance */ \
}, \
DDS_OWNERSHIP_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_STRENGTH_QOS_POLICY_DEFAULT, \
DDS_LATENCY_BUDGET_QOS_POLICY_DEFAULT, \
{ /* reliability */ \
DDS_RELIABLE_RELIABILITY_QOS, /* kind */ \
{ /* max_blocking_time */ \
0L, /* sec */ \
100000000L /* nanosec */ \
} \
}, \
DDS_DURABILITY_QOS_POLICY_DEFAULT, \
DDS_DESTINATION_ORDER_QOS_POLICY_DEFAULT, \
DDS_TRANSPORT_ENCAPSULATION_QOS_POLICY_DEFAULT, \
DDS_DATA_REPRESENTATION_QOS_POLICY_DEFAULT, \
{ /* protocol */ \
DDS_RTPS_AUTO_ID, /* rtps_object_id */ \
{ /* rtps_reliable_writer */ \
{ /* heartbeat_period */ \
0L, /* sec */ \
250000000L /* nanosec */ \
}, \
1L, /* heartbeats_per_max_samples */ \
DDS_LENGTH_UNLIMITED, /* max_send_window */ \
DDS_LENGTH_UNLIMITED, /* max_heartbeat_retries */ \
{ /* first_write_sequence_number */ \
0, /* high */ \
1 /* low */ \
} \
}, \
DDS_BOOLEAN_TRUE /* serialize_on_write */ \
}, \
DDS_TYPESUPPORT_QOS_POLICY_DEFAULT, \
{ /* transports */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_HelloWorldDPDEPub_HelloWorldDPDEDW_transport_enabled_transports, 1, 1) /* enabled_transports */ \
}, \
RTI_MANAGEMENT_QOS_POLICY_DEFAULT, \
DDS_DATAWRITERRESOURCE_LIMITS_QOS_POLICY_DEFAULT, \
DDS_PUBLISH_MODE_QOS_POLICY_DEFAULT, \
DDS_USER_DATA_QOS_POLICY_DEFAULT, \
DDS_DATAWRITERQOS_TRUST_INITIALIZER \
DDS_DATAWRITERQOS_APPGEN_INITIALIZER \
NULL, \
DDS_DataWriterTransferModeQosPolicy_INITIALIZER \
}
5.16.4.4.5. Subscriber QoS¶
Our example doesn’t specify any value for Subscriber QoS, however rtiddsmag would generate code if it was specified.
5.16.4.4.6. DataReader QoS¶
The example defines a base profile named DefaultProfile, which contains the base QoSs used by each DomainParticipant. You can see the content of the DataReader QoS below.
<!-- DataReader QoS -->
<datareader_qos>
<history>
<depth>32</depth>
</history>
<resource_limits>
<max_instances>2</max_instances>
<max_samples>64</max_samples>
<max_samples_per_instance>32</max_samples_per_instance>
</resource_limits>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<reader_resource_limits>
<max_remote_writers>10</max_remote_writers>
<max_remote_writers_per_instance>10</max_remote_writers_per_instance>
</reader_resource_limits>
<!-- transports -->
<unicast>
<value>
<element>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</unicast>
<multicast>
<value>
<element>
<receive_address>127.0.0.1</receive_address>
<transports>
<element>udpv4</element>
</transports>
</element>
</value>
</multicast>
</datareader_qos>
rtiddsmag generates the following code:
HelloWorldAppgen.c
const char *const
HelloWorldAppLibrary_HelloWorldDPDESubDP_HelloWorldDPDESub_HelloWorldDPDEDR_transport_enabled_transports[2] =
{
"udp1://",
"udp1://127.0.0.1"
};
HelloWorldAppgen.h
extern const char *const
HelloWorldAppLibrary_HelloWorldDPDESubDP_HelloWorldDPDESub_HelloWorldDPDEDR_transport_enabled_transports[2];
#define RTI_APP_GEN___DR_QOS_HelloWorldAppLibrary_HelloWorldDPDESubDP_HelloWorldDPDESub_HelloWorldDPDEDR \
{ \
DDS_DEADLINE_QOS_POLICY_DEFAULT, \
DDS_LIVELINESS_QOS_POLICY_DEFAULT, \
{ /* history */ \
DDS_KEEP_LAST_HISTORY_QOS, /* kind */ \
32L /* depth */ \
}, \
{ /* resource_limits */ \
64L, /* max_samples */ \
2L, /* max_instances */ \
32L /* max_samples_per_instance */ \
}, \
DDS_OWNERSHIP_QOS_POLICY_DEFAULT, \
DDS_LATENCY_BUDGET_QOS_POLICY_DEFAULT, \
{ /* reliability */ \
DDS_RELIABLE_RELIABILITY_QOS, /* kind */ \
{ /* max_blocking_time */ \
0L, /* sec */ \
0L /* nanosec */ \
} \
}, \
DDS_DURABILITY_QOS_POLICY_DEFAULT, \
DDS_DESTINATION_ORDER_QOS_POLICY_DEFAULT, \
DDS_TRANSPORT_ENCAPSULATION_QOS_POLICY_DEFAULT, \
DDS_DATA_REPRESENTATION_QOS_POLICY_DEFAULT, \
DDS_TYPESUPPORT_QOS_POLICY_DEFAULT, \
DDS_DATA_READER_PROTOCOL_QOS_POLICY_DEFAULT, \
{ /* transports */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDESubDP_HelloWorldDPDESub_HelloWorldDPDEDR_transport_enabled_transports, 2, 2) /* enabled_transports */ \
}, \
{ /* reader_resource_limits */ \
10L, /* max_remote_writers */ \
10L, /* max_remote_writers_per_instance */ \
1L, /* max_samples_per_remote_writer */ \
1L, /* max_outstanding_reads */ \
DDS_NO_INSTANCE_REPLACEMENT_QOS, /* instance_replacement */ \
4L, /* max_routes_per_writer */ \
DDS_MAX_AUTO, /* max_fragmented_samples */ \
DDS_MAX_AUTO, /* max_fragmented_samples_per_remote_writer */ \
DDS_SIZE_AUTO /* shmem_ref_transfer_mode_attached_segment_allocation */ \
}, \
RTI_MANAGEMENT_QOS_POLICY_DEFAULT, \
DDS_USER_DATA_QOS_POLICY_DEFAULT, \
DDS_DATAREADERQOS_TRUST_INITIALIZER \
DDS_DATAREADERQOS_APPGEN_INITIALIZER \
NULL \
}
5.16.4.4.7. Topic QoS¶
Our example doesn’t specify any value for Topic QoS; however, rtiddsmag would generate code if it were specified.
5.16.4.5. Transport and Discovery Configuration¶
rtiddsmag creates the code necessary to configure each one of the available transports used by Connext Micro (UDP and SHMEM) and the discovery mechanism (Dynamic and Static discovery). It also generates the name automatically for each component regardless of if it is a transport or discovery; for this rtiddsmag will add a DomainParticipant number at the end of its name, only if that configuration is not used by any other DomainParticipant:
UDP Transport: udp + participant_number.
SHMEM Transport: shmem + participant_number.
DPDE: dpde + participant_number.
DPSE: dpse + participant_number.
These names can be changed by using the …Names options described in MAG Command-Line Options.
Note
rtiddsmag will only create the transport configuration based on the strongly typed XML elements in the schema. rtiddsmag will not use the values in the property tag to configure the transport.
If the length of one of these names exceeds the maximum length, rtiddsmag will throw an error.
The following configuration specifies dynamic discovery:
<domain_participant_qos>
<discovery_config>
<builtin_discovery_plugins>SDP</builtin_discovery_plugins>
</discovery_config>
</domain_participant_qos>
HelloWorldAppgen.h
#define RTI_APP_GEN___dpde__HelloWorldAppLibrary_HelloWorldDPDEPubDP_dpde1 \
{ \
RT_ComponentFactoryProperty_INITIALIZER, /* _parent */ \
{ /*participant_liveliness_assert_period */ \
30L, /* sec */ \
0L /* nanosec */ \
}, \
{ /*participant_liveliness_lease_duration */ \
100L, /* sec */ \
0L /* nanosec */ \
}, \
5, /* initial_participant_announcements */ \
{ /*initial_participant_announcement_period */ \
1L, /* sec */ \
0L /* nanosec */ \
}, \
DDS_BOOLEAN_FALSE, /* cache_serialized_samples */ \
DDS_LENGTH_AUTO, /* max_participant_locators */ \
4, /* max_locators_per_discovered_participant */ \
8, /* max_samples_per_builtin_endpoint_reader */ \
DDS_LENGTH_UNLIMITED, /* builtin_writer_max_heartbeat_retries */ \
{ /*builtin_writer_heartbeat_period */ \
0L, /* sec */ \
100000000L /* nanosec */ \
}, \
1L /* builtin_writer_heartbeats_per_max_samples */ \
DDS_PARTICIPANT_MESSAGE_READER_RELIABILITY_KIND_INITIALIZER \
}
#define RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP \
{ \
...
{ /* discovery */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_initial_peers, 2, 2), /* initial_peers */ \
REDA_StringSeq_INITIALIZER_W_LOAN(HelloWorldAppLibrary_HelloWorldDPDEPubDP_discovery_enabled_transports, 3, 3), /* enabled_transports */ \
{ \
{ { "dpde1" } }, /* RT_ComponentFactoryId_INITIALIZER */ \
NDDS_Discovery_Property_INITIALIZER \
}, /* discovery_component */ \
DDS_BOOLEAN_FALSE /* accept_unknown_peers */ \
}, \
...
}
Note
rtiddsmag will throw an error if the list of available transports for the DomainParticipant, DataWriter, and DataReader contains a transport alias that is not part of the transport_builtin mask.
rtiddsmag will not generate code for the SHMEM or UDPv4 transport if it is not specified in the transport_builtin mask.
UDP transformation is not supported in XML.
When using the transport alias to specify the enabled_transports for the discovery DomainParticipant, DataWriter or DataReader, you could use the transport names for the built-in transport plugins: shmem and udpv4. rtiddsmag will automatically modify this alias to match the new one with the DomainParticipant number at the end of the name.
5.16.4.6. Flow Controllers¶
rtiddsmag creates code which will be used by Connext Micro to create a flow controller. The flow controller is configured through properties in the XML file. Let’s see an example of how to configure a flow controller named custom_flowcontroller and the code that rtiddsmag generates:
<domain_participant_qos>
...
<property>
<value>
<element>
<name>
dds.flow_controller.token_bucket.custom_flowcontroller.token_bucket.max_tokens
</name>
<value>2</value>
</element>
<element>
<name>
dds.flow_controller.token_bucket.custom_flowcontroller.token_bucket.tokens_added_per_period
</name>
<value>2</value>
</element>
<element>
<name>
dds.flow_controller.token_bucket.custom_flowcontroller.token_bucket.tokens_leaked_per_period
</name>
<!-- The value -1 means LENGTH_UNLIMITED -->
<value>-1</value>
</element>
<element>
<name>
dds.flow_controller.token_bucket.custom_flowcontroller.token_bucket.period.sec
</name>
<value>0</value>
</element>
<element>
<name>
dds.flow_controller.token_bucket.custom_flowcontroller.token_bucket.period.nanosec
</name>
<value>100000000</value>
</element>
<element>
<name>
dds.flow_controller.token_bucket.custom_flowcontroller.token_bucket.bytes_per_token
</name>
<value>1024</value>
</element>
</value>
</property>
</domain_participant_qos>
<datawriter_qos>
<publish_mode>
<flow_controller_name>
dds.flow_controller.token_bucket.custom_flowcontroller
</flow_controller_name>
<kind>ASYNCHRONOUS_PUBLISH_MODE_QOS</kind>
<priority>12</priority>
</publish_mode>
</datawriter_qos>
HelloWorldAppgen.c
const struct APPGEN_FlowControllerModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_flow_controllers[1] =
{
{
"custom_flowcontroller", /* name */
RTI_APP_GEN___FC_P_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP_custom_flowcontroller /* flow_controller_property */
}
};
HelloWorldAppgen.h
#define
RTI_APP_GEN___FC_P_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP_custom_flowcontroller \
{ \
NETIO_FlowControllerProperty_INITIALIZER, \
DDS_EDF_FLOW_CONTROLLER_SCHED_POLICY, /* scheduling_policy */ \
{ /* token_bucket */ \
2L, /* max_tokens */ \
2L, /* tokens_added_per_period */ \
-1L, /* tokens_leaked_per_period */ \
{ /* period */ \
0L, /* sec */ \
100000000L /* nanosec */ \
}, \
1024L /* bytes_per_token */ \
}, \
DDS_BOOLEAN_FALSE /* is_vendor_specific */ \
}
#define
RTI_APP_GEN___DW_QOS_HelloWorldAppLibrary_HelloWorldDPDEPubDP_HelloWorldDPDEPub_HelloWorldDPDEDW \
{ \
...
{ /* publish_mode */ \
DDS_ASYNCHRONOUS_PUBLISH_MODE_QOS, /* max_remote_readers */ \
"custom_flowcontroller", /* flow_controller_name */ \
12L /* priority */ \
}, \
...
}
extern const struct APPGEN_FlowControllerModel
HelloWorldAppLibrary_HelloWorldDPDEPubDP_flow_controllers[1];
#define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPDEPubDP \
{ \
...
1UL, /* flow_controller_count */ \
HelloWorldAppLibrary_HelloWorldDPDEPubDP_flow_controllers /* flow_controllers */ \
}
5.16.4.7. Static Discovery¶
rtiddsmag iterates through each DomainParticipant definition in the XML configuration file, creating the remote entities that are needed to communicate with applications that use static discovery, and updating the object_id of each DataWriter or DataReader involved if they don’t have a valid value or they are using the default value.
Let’s see an example of two applications that use static discovery and how rtiddsmag generates the necessary code that will be asserted by Connext Micro to communicate with both applications:
<domain_participant name="HelloWorldDPSEPubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<publisher name="HelloWorldDPSEPub">
<data_writer topic_ref="HelloWorldTopic" name="HelloWorldDPSEDW">
<datawriter_qos base_name="QosLibrary::DPSEProfile"/>
</data_writer>
</publisher>
<domain_participant_qos base_name="QosLibrary::DPSEProfile"/>
</domain_participant>
<domain_participant name="HelloWorldDPSESubDP"
domain_ref="HelloWorldLibrary::HelloWorldDomain">
<subscriber name="HelloWorldDPSESub">
<data_reader topic_ref="HelloWorldTopic" name="HelloWorldDPSEDR">
<datareader_qos base_name="QosLibrary::DPSEProfile"/>
</data_reader>
</subscriber>
<domain_participant_qos base_name="QosLibrary::DPSEProfile"/>
</domain_participant>
For these two DomainParticipants, rtiddsmag will update the rtps_object_id for the DataWriter and DataReader, since they didn’t have any values set in the XML file. You can see this in the following snippet from HelloWorldAppgen.h:
#define
RTI_APP_GEN___DW_QOS_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldDPSEPub_HelloWorldDPSEDW \
{ \
...
{ /* protocol */ \
1UL, /* rtps_object_id */ \
{ /* rtps_reliable_writer */ \
{ /* heartbeat_period */ \
0L, /* sec */ \
250000000UL /* nanosec */ \
}, \
1L, /* heartbeats_per_max_samples */ \
DDS_LENGTH_UNLIMITED, /* max_send_window */ \
DDS_LENGTH_UNLIMITED, /* max_heartbeat_retries */ \
{ /* first_write_sequence_number */ \
0, /* high */ \
1 /* low */ \
} \
}, \
DDS_BOOLEAN_TRUE /* serialize_on_write */ \
}, \
...
}
#define
RTI_APP_GEN___DR_QOS_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldDPSESub_HelloWorldDPSEDR \
{ \
...
{ /* protocol */ \
2UL /* rtps_object_id */ \
}, \
...
}
rtiddsmag will also generate the remote DomainParticipants, DataWriters, and DataReaders that need to be asserted in order for endpoints to match:
HelloWorldAppgen.c
const struct APPGEN_RemoteSubscriptionModel
HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_subscribers[1] =
{
RTI_APP_GEN__RSD_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldDPSESub_HelloWorldDPSEDR
};
const struct APPGEN_RemoteParticipantModel
HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_participants[1] =
{
{
"HelloWorldDPSESubDP", /* name */
0UL, /* remote_publisher_count */
NULL, /* remote_publishers */
1UL, /* remote_subscriber_count */
HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_subscribers /* remote_subscribers */
}
};
const struct APPGEN_RemotePublicationModel
HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_publishers[1] =
{
RTI_APP_GEN__RPD_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldDPSEPub_HelloWorldDPSEDW
};
const struct APPGEN_RemoteParticipantModel
HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_participants[1] =
{
{
"HelloWorldDPSEPubDP", /* name */
1UL, /* remote_publisher_count */
HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_publishers, /* remote_publishers */
0UL, /* remote_subscriber_count */
NULL /* remote_subscribers */
}
};
HelloWorldAppgen.h
#define RTI_APP_GEN__RSD_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldDPSESub_HelloWorldDPSEDR \
{ \
{ /* subscription_data */ \
{ \
{ 0, 0, 0, 2 } /* key */ \
}, \
{ \
{ 0, 0, 0, 0 } /* participant_key */ \
}, \
"HelloWorldTopic", /* topic_name */ \
"HelloWorldType", /* type_name */ \
DDS_DEADLINE_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_QOS_POLICY_DEFAULT, \
DDS_LATENCY_BUDGET_QOS_POLICY_DEFAULT, \
{ /* reliability */ \
DDS_RELIABLE_RELIABILITY_QOS, /* kind */ \
{ /* max_blocking_time */ \
0L, /* sec */ \
0L /* nanosec */ \
} \
}, \
DDS_LIVELINESS_QOS_POLICY_DEFAULT, \
DDS_DURABILITY_QOS_POLICY_DEFAULT, \
DDS_DESTINATION_ORDER_QOS_POLICY_DEFAULT, \
DDS_SEQUENCE_INITIALIZER, \
DDS_SEQUENCE_INITIALIZER, \
DDS_DATA_REPRESENTATION_QOS_POLICY_DEFAULT \
DDS_TRUST_SUBSCRIPTION_DATA_INITIALIZER \
}, \
HelloWorldTypePlugin_get /* get_type_plugin */ \
}
extern const struct APPGEN_RemoteSubscriptionModel HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_subscribers[1];
extern const struct APPGEN_RemoteParticipantModel HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_participants[1];
#define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPSEPubDP \
{ \
"HelloWorldDPSEPubDP", /* name */ \
RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPSEPubDP, /* domain_participant_factory */ \
RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPSEPubDP, /* domain_participant_qos */ \
0L, /* domain_id */ \
1UL, /* type_registration_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_type_registrations, /* type_registrations */ \
1UL, /* topic_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_topics, /* topics */ \
1UL, /* publisher_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_publishers, /* publishers */ \
0UL, /* subscriber_count */ \
NULL, /* subscribers */ \
1UL, /* remote_participant_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_participants /* remote_participants */ \
0UL, /* flow_controller_count */ \
NULL, /* flow_controllers */ \
}
#define RTI_APP_GEN__RPD_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldDPSEPub_HelloWorldDPSEDW \
{ \
{ /* publication_data */ \
{ \
{ 0, 0, 0, 1 } /* key */ \
}, \
{ \
{ 0, 0, 0, 0 } /* participant_key */ \
}, \
"HelloWorldTopic", /* topic_name */ \
"HelloWorldType", /* type_name */ \
DDS_DEADLINE_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_STRENGTH_QOS_POLICY_DEFAULT, \
DDS_LATENCY_BUDGET_QOS_POLICY_DEFAULT, \
{ /* reliability */ \
DDS_RELIABLE_RELIABILITY_QOS, /* kind */ \
{ /* max_blocking_time */ \
0L, /* sec */ \
100000000L /* nanosec */ \
} \
}, \
DDS_LIVELINESS_QOS_POLICY_DEFAULT, \
DDS_DURABILITY_QOS_POLICY_DEFAULT, \
DDS_DESTINATION_ORDER_QOS_POLICY_DEFAULT, \
DDS_SEQUENCE_INITIALIZER, \
DDS_DATA_REPRESENTATION_QOS_POLICY_DEFAULT \
DDS_TRUST_PUBLICATION_DATA_INITIALIZER \
}, \
HelloWorldTypePlugin_get /* get_type_plugin */ \
}
extern const struct APPGEN_RemotePublicationModel HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_publishers[1];
extern const struct APPGEN_RemoteParticipantModel HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_participants[1];
#define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPSESubDP \
{ \
"HelloWorldDPSESubDP", /* name */ \
RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPSESubDP, /* domain_participant_factory */ \
RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPSESubDP, /* domain_participant_qos */ \
0L, /* domain_id */ \
1UL, /* type_registration_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_type_registrations, /* type_registrations */ \
1UL, /* topic_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_topics, /* topics */ \
0UL, /* publisher_count */ \
NULL, /* publishers */ \
1UL, /* subscriber_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_subscribers, /* subscribers */ \
1UL, /* remote_participant_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_participants /* remote_participants */ \
0UL, /* flow_controller_count */ \
NULL /* flow_controllers */ \
#define RTI_APP_GEN__RSD_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldDPSESub_HelloWorldDPSEDR \
{ \
{ /* subscription_data */ \
{ \
{ 0, 0, 0, 2 } /* key */ \
}, \
{ \
{ 0, 0, 0, 0 } /* participant_key */ \
}, \
"HelloWorldTopic", /* topic_name */ \
"HelloWorldType", /* type_name */ \
DDS_DEADLINE_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_QOS_POLICY_DEFAULT, \
DDS_LATENCY_BUDGET_QOS_POLICY_DEFAULT, \
{ /* reliability */ \
DDS_RELIABLE_RELIABILITY_QOS, /* kind */ \
{ /* max_blocking_time */ \
0L, /* sec */ \
0L /* nanosec */ \
} \
}, \
DDS_LIVELINESS_QOS_POLICY_DEFAULT, \
DDS_DURABILITY_QOS_POLICY_DEFAULT, \
DDS_DESTINATION_ORDER_QOS_POLICY_DEFAULT, \
DDS_SEQUENCE_INITIALIZER, \
DDS_SEQUENCE_INITIALIZER, \
DDS_DATA_REPRESENTATION_QOS_POLICY_DEFAULT \
DDS_TRUST_SUBSCRIPTION_DATA_INITIALIZER \
}, \
HelloWorldTypePlugin_get /* get_type_plugin */ \
}
extern const struct APPGEN_RemoteSubscriptionModel HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_subscribers[1];
extern const struct APPGEN_RemoteParticipantModel HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_participants[1];
#define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPSEPubDP \
{ \
"HelloWorldDPSEPubDP", /* name */ \
RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPSEPubDP, /* domain_participant_factory */ \
RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPSEPubDP, /* domain_participant_qos */ \
0L, /* domain_id */ \
1UL, /* type_registration_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_type_registrations, /* type_registrations */ \
1UL, /* topic_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_topics, /* topics */ \
1UL, /* publisher_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_publishers, /* publishers */ \
0UL, /* subscriber_count */ \
NULL, /* subscribers */ \
1UL, /* remote_participant_count */ \
HelloWorldAppLibrary_HelloWorldDPSEPubDP_remote_participants /* remote_participants */ \
0UL, /* flow_controller_count */ \
NULL, /* flow_controllers */ \
}
#define RTI_APP_GEN__RPD_HelloWorldAppLibrary_HelloWorldDPSESubDP_HelloWorldAppLibrary_HelloWorldDPSEPubDP_HelloWorldDPSEPub_HelloWorldDPSEDW \
{ \
{ /* publication_data */ \
{ \
{ 0, 0, 0, 1 } /* key */ \
}, \
{ \
{ 0, 0, 0, 0 } /* participant_key */ \
}, \
"HelloWorldTopic", /* topic_name */ \
"HelloWorldType", /* type_name */ \
DDS_DEADLINE_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_QOS_POLICY_DEFAULT, \
DDS_OWNERSHIP_STRENGTH_QOS_POLICY_DEFAULT, \
DDS_LATENCY_BUDGET_QOS_POLICY_DEFAULT, \
{ /* reliability */ \
DDS_RELIABLE_RELIABILITY_QOS, /* kind */ \
{ /* max_blocking_time */ \
0L, /* sec */ \
100000000L /* nanosec */ \
} \
}, \
DDS_LIVELINESS_QOS_POLICY_DEFAULT, \
DDS_DURABILITY_QOS_POLICY_DEFAULT, \
DDS_DESTINATION_ORDER_QOS_POLICY_DEFAULT, \
DDS_SEQUENCE_INITIALIZER, \
DDS_DATA_REPRESENTATION_QOS_POLICY_DEFAULT \
DDS_TRUST_PUBLICATION_DATA_INITIALIZER \
}, \
HelloWorldTypePlugin_get /* get_type_plugin */ \
}
extern const struct APPGEN_RemotePublicationModel HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_publishers[1];
extern const struct APPGEN_RemoteParticipantModel HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_participants[1];
#define RTI_APP_GEN__DP_HelloWorldAppLibrary_HelloWorldDPSESubDP \
{ \
"HelloWorldDPSESubDP", /* name */ \
RTI_APP_GEN__DPF_HelloWorldAppLibrary_HelloWorldDPSESubDP, /* domain_participant_factory */ \
RTI_APP_GEN___DP_QOS_HelloWorldAppLibrary_HelloWorldDPSESubDP, /* domain_participant_qos */ \
0L, /* domain_id */ \
1UL, /* type_registration_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_type_registrations, /* type_registrations */ \
1UL, /* topic_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_topics, /* topics */ \
0UL, /* publisher_count */ \
NULL, /* publishers */ \
1UL, /* subscriber_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_subscribers, /* subscribers */ \
1UL, /* remote_participant_count */ \
HelloWorldAppLibrary_HelloWorldDPSESubDP_remote_participants /* remote_participants */ \
0UL, /* flow_controller_count */ \
NULL /* flow_controllers */ \
}
5.16.5. Errors Caused by Invalid Configurations and QoS¶
This section explains the different results thrown by MAG if it receives invalid configuration files.
Invalid XML content
MAG will fail to validate the configuration file if it contains invalid content, such as elements/attributes that don’t exist in the schema or values that aren’t supported by any of the existing types. For example:
<dds> ... <!-- Participant Library --> <domain_participant_library name="FeatureTestLibrary"> <domain_participant name="01_EmptyDomainParticipant" domain_ref="HelloWorldLibrary::HelloWorldDomain"> <invalid_tag></invalid_tag> </domain_participant> </domain_participant_library> ... </dds>
Unsupported elements
MAG will throw a warning for any elements that are not supported by Connext Micro. Unsupported elements will be ignored, such as the user_data in the following:
<dds> ... <!-- Participant Library --> <domain_participant_library name="FeatureTestLibrary"> <domain_participant name="01_EmptyDomainParticipant" domain_ref="HelloWorldLibrary::HelloWorldDomain"> <domain_participant_qos> <!-- user_data is not supported by Micro --> <user_data/> </domain_participant_qos> </domain_participant> </domain_participant_library> </dds>
Unsupported values
MAG will throw an error if it finds a value that is not supported by Connext Micro.
<dds> ... <!-- Participant Library --> <domain_participant_library name="FeatureTestLibrary"> <domain_participant name="01_EmptyDomainParticipant" domain_ref="HelloWorldLibrary::HelloWorldDomain"> <publisher name ="test"> <data_writer topic_ref="HelloWorldTopic1" name="testW"> <datawriter_qos> <durability> <!-- transient is not supported by Micro --> <kind>TRANSIENT_DURABILITY_QOS</kind> </durability> </datawriter_qos> </data_writer> </publisher> </domain_participant> </domain_participant_library> </dds>
MAG will throw an error if the QoS values are not consistent with values supported in Connext Micro. For example, the following XML contains a deadline period that is too large.
<dds> ... <!-- Participant Library --> <domain_participant_library name="FeatureTestLibrary"> <domain_participant name="01_EmptyDomainParticipant" domain_ref="HelloWorldLibrary::HelloWorldDomain"> <publisher name ="test"> <data_writer topic_ref="HelloWorldTopic1" name="testW"> <datawriter_qos> <deadline> <!-- this deadline exceeds the maximum --> <period> <sec>123213123</sec> <nanosec>12</nanosec> </period> </deadline> </datawriter_qos> </data_writer> </publisher> </domain_participant> </domain_participant_library> </dds>MAG will throw an error if the dds.xtypes.compliance_mask property uses a different value than 0x00000008.
Unsupported QoS
Not all the QoS policies supported by Connext Micro can be configured in XML.
QoS settings related to UDP transformation cannot be configured in XML. See the UDP Transport section for more information on UDP transformation.
MAG does not support any PROPERTY QoS policy properties except the dds.xtypes.compliance_mask property.