5.1. Understanding Topic and Type Aliasing
5.1.1. ROS 2 Topic and Type Mangling
In ROS 2, topic and type names undergo “topic mangling,” meaning that
the topic name set in an application is not the topic name sent
on the wire. For example, topics in ROS 2 are prefixed with rt/. If
creating the topic Foo, the announced topic would be
rt/Foo. Similarly, a type name in ROS 2 has dds_::
inserted between the namespace and the final typename, and is suffixed
with _, so a type name Foo becomes dds_::Foo_ on the wire and a type
name namespace::Foo becomes namespace::dds_::Foo_.
As a result, ROS2 applications can’t communicate with DDS
applications that are created with the same topic name, because the names
on the wire are not the same.
Starting in Connext 7.5.0, ROS 2 and DDS applications can communicate using a simple setting described in Configuring ROS 2 Topic and Type Aliasing in Connext. You can turn the property on or off with an XML QoS profile, rather than having to regenerate your types and recompile your code with the “mangled” topic and type names.
5.1.2. Connext Topic and Type Aliasing
Using the dds.ros.enable_interoperability
property (see Configuring ROS 2 Topic and Type Aliasing in Connext), Connext can perform the ROS 2 topic and type “mangling”
automatically. Topic and type aliasing in Connext works by propagating
aliases in the endpoint discovery data that can be considered as valid
alternatives to the primary topic and type names. If you are using
Wireshark® to look at the endpoint data, the aliases are propagated with
the parameter IDs PID_TOPIC_NAME_ALIASES and PID_TYPE_NAME_ALIASES.
The rules that Connext uses to generate the topic aliases when
dds.ros.enable_interoperability is set to true are as follows:
Prefix normal topic names with
rt/. For example, Connext transforms the normal topic nameFoointort/Foo.Prefix requester topic names created using the RTI Request/Reply API with
rq/and suffix them withRequest. For example, Connext transforms the requester topic nameFoointorq/FooRequest.Prefix replier topics created using the RTI Request/Reply API with
rr/and suffix them withReply. For example, Connext transforms the replier topic nameFoointorr/FooReply.
Type names are also subject to a slightly different form of mangling. ROS 2 types often have a namespace (in IDL, this is indicated with the module name). Consider a type created in ROS 2 with the following IDL:
module tutorial_interfaces {
module msg {
struct Num {
int64 num;
};
};
};
Type names in ROS 2 have dds_:: inserted between the namespace and the
final type name, or at the beginning of the type name if no namespace is
present (we identify a namespace as fields separated with ::). They
are then suffixed with _. For example, the above IDL file would
result in the typename tutorial_interfaces::msg::Num::num in Connext,
but in ROS 2 would become tutorial_interfaces::msg::dds_::Num::num_.
This also applies to types without namespaces: the typename FooType
(without a namespace) in Connext would become dds_::FooType_ in ROS 2.
When a 7.5.0-or-later Connext application encounters another 7.5.0-or-later Connext application that announces topic aliases, it compares its own topic name (and topic name alias if it exists) to both the topic name and topic name alias of the other application when performing topic matching. (See Configuring ROS 2 Topic and Type Aliasing in Connext for information on setting the properties.) If either the topic name or topic name alias matches, the endpoint is considered compatible and discovery takes place.
For example, a Connext application creates a writer with the following code snippet:
// Get the default participant QoS
dds::domain::qos::DomainParticipantQos participant_qos = dds::core::QosProvider::Default().participant_qos();
// Add dds.ros.enable_interoperability as a property to the participant QoS
rti::core::policy::Property property = participant_qos.policy<rti::core::policy::Property>();
property.set(rti::core::policy::Property::Entry("dds.ros.enable_interoperability", "TRUE"));
participant_qos << property;
// Create a participant with the dds.ros.enable_interoperability property
dds::domain::DomainParticipant participant(0, participant_qos);
// Create a topic and endpoint on the participant
dds::topic::Topic<Foo> topic(participant, "Foo");
dds::pub::Publisher publisher(participant);
dds::dds::pub::DataWriter<Foo> writer(publisher, topic);
In this case, the “primary” topic name that the topic is created with is
Foo. If dds.ros.enable_interoperability
is set to true, the topic alias will be rt/Foo; however, if
dds.ros.use_mangled_names_as_default is also set to true (see
Configuring ROS 2 Topic and Type Aliasing in Connext), the “primary” topic that Connext sends on
the wire will be rt/Foo, with Foo sent as the topic alias. When a
reader in another application discovers this writer, it will see that its
“primary” topic name is rt/Foo:
// Get the publication data of the remote writer in the reader application
std::vector<dds::topic::PublicationBuiltinTopicData> matched_writers =
rti::sub::matched_publication_data(reader);
for (const auto& pub_data : matched_pubs) {
// This will print "rt/Foo"
std::cout << "Matched publication topic: " << pub_data.topic_name() << std::endl;
}
This behavior, enabled by the properties discussed in
Configuring ROS 2 Topic and Type Aliasing in Connext, allows ROS 2 applications to believe that the
Connext writer was created on the topic rt/Foo (to match the ROS 2
topic), when it was really created on the topic Foo.
The same is done when encountering a type name alias; however, this type name comparison only occurs if TypeCode and TypeObject propagation is not enabled. If TypeCodes or TypeObjects are propagated, the type representation will be compared to perform matching and the type name will be ignored. See Introduction to TypeCode in the Core Libraries User’s Manual for more information.