Configuration

Load configuration

Integration Service must receive an argument with the XML file with the configuration to load.

$ integration_service config.xml

With this file, Integration Service creates all the components needed to do its job.

Configuration format

This XML file can contain the following sections, all inside a root <is> label.

<is>
    <is_types/>
    <profiles/>
    <bridge/>
    <connector/>
</is>

IS Types configuration

The IS Types section allows to specify what topic data types will be loaded through Types Library and define topic data types with Fast RTPS XML Types.

A Data Type that uses Keys needs a Types Library to instantiate it.

In most cases, there is no need to implement a Types Library. IS will use GenericPubSubType by default which encapsulates any Data Type without Keys defined.

This section uses Fast RTPS Dynamic Types internally, but it’s available to use them by code using the Fast RTPS API in a Types Library or using Fast-RTPS XML Types.

<is_types>
    <!-- Fast-RTPS XML Types -->
    <types>
        <type>
            <struct name="HelloWorld">
                <unsignedlong name="index"/>
                <string name="message"/>
            </struct>
        </type>
    </types>

    <!-- IS Types Libraries -->
    <type name="ShapeType">
        <library>libshape.so</library>
    </type>
    <types_library>libdefault.so</types_library>
</is_types>

This XML example shows how to define Types Library for each type like ShapeType and libshape.so, or use a default library that will try to load the rest of types (libdefault.so in the example).

IS will use GenericPubSubType to manage any Data Type that isn’t declared through Fast-RTPS XML Types and can’t instantiate from any Types Library.

If the <is_types> section doesn’t exist IS will use GenericPubSubType to manage all Data Types declared in the Fast-RTPS profiles section.

Fast-RTPS profiles

The profiles section defines participants, subscribers, publishers, etc. following the format used by Fast RTPS XML Types, with its configuration.

<profiles>
    <participant profile_name="domain0">
        <rtps>
            <builtin>
                <domainId>0</domainId>
            </builtin>
        </rtps>
    </participant>

    <participant profile_name="domain5">
        <rtps>
            <builtin>
                <domainId>5</domainId>
            </builtin>
        </rtps>
    </participant>

    <subscriber profile_name="is_subscriber">
        <topic>
            <name>TextPubSubTopic</name>
            <dataType>Text</dataType>
        </topic>
        <historyMemoryPolicy>DYNAMIC</historyMemoryPolicy>
    </subscriber>

    <publisher profile_name="is_publisher">
        <topic>
            <name>TextPubSubTopic</name>
            <dataType>Text</dataType>
        </topic>
        <historyMemoryPolicy>DYNAMIC</historyMemoryPolicy>
    </publisher>
</profiles>

Connectors

The connectors are just relationships between readers and writers, and optionally, a transformation function. IS needs at least one connector to perform work, but the XML configuration file allows to define any number of connectors. They must contain a reader and a writer. Each of them is configured by a participant or bridge name and the reader’s or writer’s name respectively.

The following example defines a connector whose reader is a Fast-RTPS’s subscriber and whose writer prints the received data into a text file. Also, the connector defines a function from a Transformation Library that adds the timestamp to the data.

<connector name="dump_to_file">
    <reader participant_profile="rtps" subscriber_profile="fastrtps_subscriber"/>
    <writer bridge_name="file" writer_name="file_writer"/>
    <transformation file="libfile.so" function="addTimestamp"/>
</connector>

There are several possible types of connectors depending on the kind of its participants. Each connector type will refer to the bottom Example.

RTPS Connector

In this kind of connector, both participants are RTPS compliant, like shapes_projection and shapes_stereo in the Example file.

_images/RTPS_connector.png
<is>
    <profiles>
        <participant profile_name="RTPS-Publisher">
            <!-- RTPS participant attributes -->
        </participant>

        <participant profile_name="RTPS-Subscriber">
            <!-- RTPS participant attributes -->
        </participant>

        <subscriber profile_name="Subscriber">
            <!-- RTPS subscriber attributes -->
        </subscriber>

        <publisher profile_name="Publisher">
            <!-- RTPS publisher attributes -->
        </publisher>
    </profiles>

    <connector name="connector">
        <reader participant_profile="RTPS-Subscriber" subscriber_profile="Subscriber"/>
        <writer participant_profile="RTPS-Publisher" publisher_profile="Publisher"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transform"/>
    </connector>
</is>

Connector from RTPS to Other protocol

This connector will communicate an RTPS environment with another protocol. Just like the shapes_protocol connector in the Example.

The Bridge Library must define at least a writer, following the ISWriter interface, responsible for communicate with the desired protocol. By default, the ISBridge's on_received_data method applies the transformation function internally. It’s mandatory to override the complete data flow to change this behavior.

_images/RTPS_other_connector.png
<is>
    <profiles>
        <participant profile_name="RTPS">
            <!-- RTPS participant attributes -->
        </participant>

        <subscriber profile_name="Subscriber">
            <!-- RTPS subscriber attributes -->
        </subscriber>
    </profiles>

    <bridge name="Other protocol">
        <library>/path/to/bridge/library/libprotocol.so</library>
        <!-- Other protocol properties -->

        <writer name="Other">
            <!-- Other protocol writer properties -->
        </writer>
    </bridge>

    <connector name="connector">
        <reader participant_profile="RTPS" subscriber_profile="Subscriber"/>
        <writer bridge_name="Other protocol" writer_name="Other"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transform"/>
    </connector>
</is>

Connector from Other protocol to RTPS

This case is the opposite connector that the previous one, as in the connector protocol_shapes of the example.

The same logic applies in this connectors as in the Connector from RTPS to Other protocol case, but in this case, the RTPS participant is the writer. FIROS2 has an example of this connector.

_images/Other_RTPS_connector.png
<is>
    <profiles>
        <participant profile_name="RTPS">
            <!-- RTPS participant attributes -->
        </participant>

        <publisher profile_name="Publisher">
            <!-- RTPS publisher attributes -->
        </publisher>
    </profiles>

    <bridge name="Other protocol">
        <library>/path/to/bridge/library/libprotocol.so</library>
        <!-- Other protocol properties -->

        <reader name="Other">
            <!-- Other protocol reader properties -->
        </reader>
    </bridge>

    <connector name="connector">
        <reader bridge_name="Other protocol" reader_name="Other"/>
        <writer participant_profile="RTPS" publisher_profile="Publisher"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transformFromA"/>
    </connector>
</is>

Bidirectional connector

This case is not a connector, but the consequence of setting two connectors with the correct parameters. In the Example, the combination of shapes_projection and shapes_stereo is a bidirectional connector, as well as, shapes_protocol and protocol_shapes.

A combination of both logics Connector from RTPS to Other protocol and Connector from Other protocol to RTPS applies here. The example TIS_NGSIv2 of FIROS2 uses a bridge of this type.

_images/Bidirectional_connector.png
<is>
    <profiles>
        <participant profile_name="RTPS">
            <!-- RTPS participant attributes -->
        </participant>

        <subscriber profile_name="Subscriber">
            <!-- RTPS subscriber attributes -->
        </subscriber>

        <publisher profile_name="Publisher">
            <!-- RTPS publisher attributes -->
        </publisher>
    </profiles>

    <bridge name="Other protocol">
        <library>/path/to/bridge/library/libprotocol.so</library>
        <!-- Other protocol properties -->

        <reader name="OtherSub">
            <!-- Other protocol reader properties -->
        </reader>

        <writer name="OtherPub">
            <!-- Other protocol writer properties -->
        </writer>
    </bridge>

    <connector name="connector">
        <reader bridge_name="Other protocol" reader_name="OtherSub"/>
        <writer participant_profile="RTPS" publisher_profile="Publisher"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transformFromA"/>
    </connector>

    <connector name="connector">
        <reader participant_profile="RTPS" subscriber_profile="Subscriber"/>
        <writer bridge_name="Other protocol" writer_name="OtherPub"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transform"/>
    </connector>
</is>

Bridge configuration

Bridge sections allow defining new endpoints to implement new protocols. Inside the tag <bridge>, a Bridge Library must be defined. It contains the methods to create the bridge (implementing ISBridge), writers (implementing ISWriter) and readers (implementing ISReader). If any of them uses the default implementation, its method can simply return nullptr.

Inside the <bridge>, <writer> and <reader> can be defined <properties>. They are pairs <name> and <value> to configure the elements that can be accessible to the elements in code, without affecting the XML parsing. The next example shows how to create some properties to create attributes for the bridge and some to configure a writer. Each property set will be sent to its component as a vector of pairs of strings, and if no properties are provided, then the create_ method will be called with nullptr or an empty vector as parameter config.

<bridge name="file">
    <library>build/libisfile.so</library>
    <properties>
        <property>
            <name>propertyA</name>
            <value>valueA</value>
        </property>
        <property>
            <name>propertyB</name>
            <value>valueB</value>
        </property>
    </properties>

    <writer name="file_writer">
        <property>
            <name>filename</name>
            <value>output.txt</value>
        </property>
        <property>
            <name>format</name>
            <value>txt</value>
        </property>
        <property>
            <name>append</name>
            <value>true</value>
        </property>
    </writer>
</bridge>

The complete explanation about bridges and their API are available here.

Writer configuration

The <writer> section exposes writer classes of the bridge library to be used by Integration Service. The only mandatory field is the <name> of the class, and with it, Integration Service is able to create instances of the writer when Connectors need them.

The complete explanation about writers and their API are available here.

Reader configuration

The <reader> section exposes reader classes of the bridge library to be used by Integration Service. The only mandatory field is the <name> of the class, and with it, Integration Service is able to create instances of the reader when Connectors need them.

The complete explanation about readers and their API are available here.

IS Libraries

There are three different kind of libraries that Integration Service manages:

  • Type Library: It defines the types and the methods that allow creating these types. More details about Types Library configuration is available in the IS Types configuration section and a deeper explanation in the Types Library section.
  • Transformation Library: Transformation libraries stores functions to manage the input and output data communicating a reader and a writer of a connector. A deeper explanation is available in the Transformation Library section.
  • Bridge Library: It includes the code to manage endpoints to implement new protocols. Its configuration is explained inside Bridge configuration and the complete description of bridges, and their API is available in the ISBridge section.

Example

In this file, there are defined two RTPS participants and a bridge. Both participants and the bridge have a subscriber and a publisher. Each connector defines the relationships between participants and subscribers/publishers, allowing sharing subscribers/publishers configurations between participants. There are four connectors defined: shapes_projection, shapes_stereo, shapes_protocol, and protocol_shapes.

_images/Complete_example.png
<is>
    <is_types>
        <type name="ShapeType">
            <library>libshapelib.so</library> <!-- Library for ShapeType -->
        </type>
        <type name="Unused type"/>
        <!-- Can be used to pack types or types without their own library -->
        <types_library>libotherlib.so</types_library>
    </is_types>

    <profiles>
        <participant profile_name="2Dshapes">
            <!-- RTPS participant attributes -->
        </participant>

        <participant profile_name="3Dshapes">
            <!-- RTPS participant attributes -->
        </participant>

        <subscriber profile_name="2d_subscriber">
            <!-- RTPS subscriber attributes -->
        </subscriber>

        <subscriber profile_name="3d_subscriber">
            <!-- RTPS subscriber attributes -->
        </subscriber>

        <publisher profile_name="2d_publisher">
            <!-- RTPS publisher attributes -->
        </publisher>

        <publisher profile_name="3d_publisher">
            <!-- RTPS publisher attributes -->
        </publisher>
    </profiles>

    <bridge name="protocol">
        <library>/path/to/bridge/library/libprotocol.so</library>
        <properties>
            <property>
                <name>property1</name>
                <value>value1</value>
            </property>
        </properties>

        <writer name="protocol_publisher">
            <property>
                <name>property1</name>
                <value>value1</value>
            </property>
            <property>
                <name>property2</name>
                <value>value2</value>
            </property>
        </writer>

        <reader name="protocol_subscriber">
            <property>
                <name>property1</name>
                <value>value1</value>
            </property>
            <property>
                <name>property2</name>
                <value>value2</value>
            </property>
        </reader>
    </bridge>

    <connector name="shapes_projection">
        <reader participant_profile="3Dshapes" subscriber_profile="3d_subscriber"/>
        <writer participant_profile="2Dshapes" publisher_profile="2d_publisher"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transform3D_to_2D"/>
    </connector>

    <connector name="shapes_stereo">
        <reader participant_profile="2Dshapes" subscriber_profile="2d_subscriber"/>
        <writer participant_profile="3Dshapes" publisher_profile="3d_publisher"/>
        <transformation file="/path/to/transform/libuserlib.so" function="transform2D_to_3D"/>
    </connector>

    <connector name="shapes_protocol">
        <reader participant_profile="2Dshapes" subscriber_profile="2d_subscriber"/>
        <writer bridge_name="protocol" writer_name="protocol_publisher"/>
        <transformation file="/path/to/transform/libprotocoltransf.so" function="transformFrom2D"/>
    </connector>

    <connector name="protocol_shapes">
        <reader bridge_name="protocol" reader_name="protocol_subscriber"/>
        <writer participant_profile="2Dshapes" publisher_profile="2d_publisher"/>
        <transformation file="/path/to/transform/libprotocoltransf.so" function="transformTo2D"/>
    </connector>
</is>