1.4.4. Static Discovery

1.4.4.1. Background

OMG DDS Interoperability specification defines the basic discovery mechanism that allows distributed systems to automatically find and match Endpoints sharing the same Topic. This mechanism is performed in two phases as explained in Fast DDS documentation:

  • Participant Discovery Phase (PDP): DDS DomainParticipants discover and acknowledge the existence of remote DomainParticipants. Usually done sending periodic announcements to well-known multicast addresses and ports defined in the specification.

  • Endpoint Discovery Phase (EDP): each DDS DomainParticipant send information about its own endpoints (DataWriters and DataReaders) through the communication channels established in the previous phase.

Standard discovery has its caveats, like the required multicast traffic being sent periodically, that can saturate the network bandwidth in constraint network architectures with a large number of DDS DomainParticipants. Vulcanexus leverages latest eProsima Fast DDS release to improve ROS 2 middleware layer. Being aware of the standard discovery mechanism caveats, eProsima Fast DDS provides alternative discovery mechanisms:

  • Fast DDS Discovery Server reduces the discovery metatraffic using a centralized client-server discovery mechanism instead of a distributed one. More information can be found in Using Fast DDS Discovery Server as discovery protocol tutorial. This schema reduces discovery metatraffic from both PDP and EDP phases because the information is sent exclusively to the DomainParticipants in a need-to-know basis.

  • Setting an initial peers list and disabling multicast also decreases the discovery traffic for the PDP phase, sending each DomainParticipant the announcement to the locators where the announcement is expected.

  • Fast DDS Static Discovery removes completely any EDP discovery metatraffic by configuring the endpoints, topics and data types beforehand. This tutorial deals on how to use this discovery mechanism within Vulcanexus. More information about Static EDP discovery can be found in Fast DDS documentation.

1.4.4.2. Prerequisites

This tutorial uses ROS 2 demo_nodes_cpp package which is provided with Vulcanexus Desktop distribution. If another Vulcanexus distribution is used, please ensure that this package and its dependencies are installed.

Wireshark is also used to capture and analyze the network traffic.

Please, remember to source the environment in every terminal used during this tutorial.

source /opt/vulcanexus/iron/setup.bash

1.4.4.3. Overview

This tutorial will use ROS 2 demo_nodes_cpp talker and listener applications to showcase the different configurations:

  1. Talker-listener communication using Standard discovery. Shared memory transport is explicitly disabled to ensure EDP discovery traffic can be captured.

  2. Talker-listener communication using Static EDP discovery.

  3. Talker-listener full-fledged communication.

1.4.4.4. Standard discovery

eProsima Fast DDS enables by default a Shared Memory (SHM) transport and a UDP transport. With this configuration, PDP discovery metatraffic will always be performed through the UDP transport. However, if the SHM transport requirements are met, EDP discovery metatraffic and user data traffic will be sent through this transport. In order to capture the traffic and analyze it, the SHM transport is going to be disabled. Save the following XML configuration file at the desired location, which will be referred as <path_to_xml_config_file> from here onwards, with vulcanexus_disable_shm.xml name.

<?xml version="1.0" encoding="UTF-8" ?>
<dds>
    <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles" >
        <transport_descriptors>
            <transport_descriptor>
                <transport_id>udp_transport</transport_id>
                <type>UDPv4</type>
            </transport_descriptor>
        </transport_descriptors>

        <participant profile_name="default_participant_profile" is_default_profile="true">
            <rtps>
                <userTransports>
                    <transport_id>udp_transport</transport_id>
                </userTransports>
                <useBuiltinTransports>false</useBuiltinTransports>
            </rtps>
        </participant>
    </profiles>
</dds>

This configuration disables the builtin transports and registers a user-defined UDPv4 transport.

After launching Wireshark (with administrative privileges to be able to capture network traffic), start capturing the traffic going through any interface. The traffic shown can be filtered using as parameter rtps to see only traffic of interest. Next, run the talker and the listener:

source /opt/vulcanexus/iron/setup.bash
FASTRTPS_DEFAULT_PROFILES_FILE=<path_to_xml_config_file>/vulcanexus_disable_shm.xml ros2 run demo_nodes_cpp listener

The traffic captured will show several DATA(p) messages which are the periodic DomainParticipant announcements sent to multicast (PDP) and to any DomainParticipant already matched (Liveliness). In this case, the EDP discovery traffic will also be captured as DATA(w), DataWriter discovery metatraffic, and DATA(r), DataReader discovery metatraffic. The screenshot below has been taken running this tutorial.

../../../../../_images/standard_discovery_traffic.png

1.4.4.5. Static EDP discovery

Now, Static EDP discovery is going to be enabled in order to remove any EDP discovery metatraffic. Within Vulcanexus ecosystem, Static EDP can only be enabled through XML configuration. Whereas different Endpoint profiles can be defined within the same XML file using the Topic name, it is not possible to have different DomainParticipant profiles within the same file when using Vulcanexus. Consequently, a different configuration file is required for each DomainParticipant, because the Static EDP settings include the path to the static XML configuration file which defines the Endpoints, Topics, and Data types.

Save the following XML configuration files in the path_to_xml_config_file under the names talker_profile.xml and listener_profile.xml respectively:

<?xml version="1.0" encoding="UTF-8" ?>
<dds>
    <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles" >
        <transport_descriptors>
            <transport_descriptor>
                <transport_id>udp_transport</transport_id>
                <type>UDPv4</type>
            </transport_descriptor>
        </transport_descriptors>

        <participant profile_name="talker_participant_profile" is_default_profile="true">
            <rtps>
                <name>talker</name>
                <userTransports>
                    <transport_id>udp_transport</transport_id>
                </userTransports>
                <useBuiltinTransports>false</useBuiltinTransports>
                <builtin>
                    <discovery_config>
                        <EDP>STATIC</EDP>
                        <static_edp_xml_config>file://static_edp_info.xml</static_edp_xml_config>
                    </discovery_config>
                </builtin>
            </rtps>
        </participant>

        <data_writer profile_name="/chatter">
            <userDefinedID>101</userDefinedID>
        </data_writer>
    </profiles>
</dds>

Besides setting the EDP discovery to STATIC and defining the path to the Static configuration XML file, the Endpoint userDefinedID must be set so the Endpoints can be identified in this Static configuration file. Every remote Endpoint must be defined within this configuration file, with the Topic and Data type name so matching can be performed by the local DomainParticipant statically without the need for the remote participant to send the Endpoint discovery information. The specific endpoint QoS has also to be defined or the default QoS will be assumed.

Save the static configuration XML file to the same location under the name static_edp_info.xml:

<staticdiscovery>
    <participant>
        <name>talker</name>
        <writer>
            <userId>101</userId>
            <topicName>rt/chatter</topicName>
            <topicDataType>std_msgs::msg::dds_::String_</topicDataType>
            <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
            <durabilityQos>VOLATILE_DURABILITY_QOS</durabilityQos>
        </writer>
    </participant>
    <participant>
        <name>listener</name>
        <reader>
            <userId>102</userId>
            <topicName>rt/chatter</topicName>
            <topicDataType>std_msgs::msg::dds_::String_</topicDataType>
            <reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>
            <durabilityQos>VOLATILE_DURABILITY_QOS</durabilityQos>
        </reader>
    </participant>
</staticdiscovery>

It is important to be aware of ROS 2 Topic mangling rules. Whereas the endpoint profile has to be set using the ROS 2 Topic name, the static discovery configuration must used the DDS Topic name.

Run again the talker-listener demo loading the corresponding XML configuration file using FASTRTPS_DEFAULT_PROFILES_FILE environment variable:

source /opt/vulcanexus/iron/setup.bash
FASTRTPS_DEFAULT_PROFILES_FILE=<path_to_xml_config_file>/listener_profile.xml ros2 run demo_nodes_cpp listener

If the traffic is captured again using Wireshark, this time no DATA(w) or DATA(r) is exchanged, but communication is established.

1.4.4.6. Full-fledged Static EDP discovery

ROS 2 provides several introspection tools like ros2 topic list or ros2 node list. Running these commands with the previous example will show only the default ROS 2 topics (/parameter_events and /rosout) and no node. The /chatter topic and the /talker and /listener nodes would not appear even though they are up and running and communicating. The issue is related to the internal endpoints that ROS 2 ecosystem, and by extension Vulcanexus, launch within each node to ensure these tools work as expected. Also, the vast majority of these tools depend on another DomainParticipant known as the ROS 2 Daemon. This section will complete the previous XML files so a full-fledged communication within Vulcanexus ecosystem is achieved, with working introspection tools. Information about every internal ROS 2 endpoint has been included. These endpoints are related to topic and node discovery, ROS 2 logging module, and parameters services and events.

Below, the complete XML files are shown. Please, replaced the previous XML configuration files with these ones and the new one required to configure the ROS 2 daemon DomainParticipant.

<?xml version="1.0" encoding="UTF-8" ?>
<dds>
    <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles" >
        <transport_descriptors>
            <transport_descriptor>
                <transport_id>udp_transport</transport_id>
                <type>UDPv4</type>
            </transport_descriptor>
        </transport_descriptors>

        <participant profile_name="talker_participant_profile" is_default_profile="true">
            <rtps>
                <name>talker</name>
                <userTransports>
                    <transport_id>udp_transport</transport_id>
                </userTransports>
                <useBuiltinTransports>false</useBuiltinTransports>
                <builtin>
                    <discovery_config>
                        <EDP>STATIC</EDP>
                        <static_edp_xml_config>file://static_edp_info.xml</static_edp_xml_config>
                    </discovery_config>
                </builtin>
            </rtps>
        </participant>

        <data_writer profile_name="/chatter">
            <userDefinedID>101</userDefinedID>
        </data_writer>
        <!-->ROS 2 Internal Endpoints<-->
        <data_writer profile_name="/parameter_events">
            <userDefinedID>201</userDefinedID>
        </data_writer>
        <data_writer profile_name="ros_discovery_info">
            <userDefinedID>202</userDefinedID>
        </data_writer>
        <data_writer profile_name="/rosout">
            <userDefinedID>203</userDefinedID>
        </data_writer>
        <data_writer profile_name="rr/talker/describe_parametersReply">
            <userDefinedID>204</userDefinedID>
        </data_writer>
        <data_writer profile_name="rr/talker/list_parametersReply">
            <userDefinedID>205</userDefinedID>
        </data_writer>
        <data_writer profile_name="rr/talker/get_parametersReply">
            <userDefinedID>206</userDefinedID>
        </data_writer>
        <data_writer profile_name="rr/talker/get_parameter_typesReply">
            <userDefinedID>207</userDefinedID>
        </data_writer>
        <data_writer profile_name="rr/talker/set_parametersReply">
            <userDefinedID>208</userDefinedID>
        </data_writer>
        <data_writer profile_name="rr/talker/set_parameters_atomicallyReply">
            <userDefinedID>209</userDefinedID>
        </data_writer>

        <data_reader profile_name="/parameter_events">
            <userDefinedID>210</userDefinedID>
        </data_reader>
        <data_reader profile_name="ros_discovery_info">
            <userDefinedID>211</userDefinedID>
        </data_reader>
        <data_reader profile_name="rq/talker/set_parametersRequest">
            <userDefinedID>212</userDefinedID>
        </data_reader>
        <data_reader profile_name="rq/talker/get_parametersRequest">
            <userDefinedID>213</userDefinedID>
        </data_reader>
        <data_reader profile_name="rq/talker/get_parameter_typesRequest">
            <userDefinedID>214</userDefinedID>
        </data_reader>
        <data_reader profile_name="rq/talker/set_parameters_atomicallyRequest">
            <userDefinedID>215</userDefinedID>
        </data_reader>
        <data_reader profile_name="rq/talker/describe_parametersRequest">
            <userDefinedID>216</userDefinedID>
        </data_reader>
        <data_reader profile_name="rq/talker/list_parametersRequest">
            <userDefinedID>217</userDefinedID>
        </data_reader>
    </profiles>
</dds>

Run again the talker-listener demo loading the corresponding XML configuration file using FASTRTPS_DEFAULT_PROFILES_FILE environment variable. This time a third terminal is required to run the ROS 2 daemon.

source /opt/vulcanexus/iron/setup.bash
FASTRTPS_DEFAULT_PROFILES_FILE=<path_to_xml_config_file>/listener_profile.xml ros2 run demo_nodes_cpp listener

Now, besides the internal ROS 2 Topics, the /chatter topic will be listed as well as the ROS 2 nodes /talker and /listener.