I want to get a native rti DDS 5.3.1 application running with ROS2 eloquent. For this, I have written a plugin for the rti routing service and set it up to convert messages from native DDS topic to ROS2 eloquent topics.
According to the rtiadminconsole everyting seems fine. The Match Analyses has no complains and I can subscribe and receive the ROS2 topic within the rtiadminconsole. However, in the ROS2 subscriber the subscriber callback method is never called.
How can I further investiagte this issue?
Hi Andreas,
This sounds like something within the RS plugin, separate from anything specific to ROS2.
Depending on your needs, you may be able to do this directly (without RS); since ROS2 is typically built on top of DDS, all of its communications are on DDS as well.
This means that interop between native DDS apps and ROS2(on DDS) apps enjoy the standards-based interoperability of DDS, with any version of Connext.
The key is to use ROS2 data types in your native DDS applications, for any topics that you'd like to interop with ROS2 applications.
That, and (of course): compatible QoS, and a matching topic name.
For example, suppose I wanted a native DDS application to move the default turtle in 'turtlesim'; this would need:
- Data type: geometry_msgs::msg::dds_::Twist_
- Topic name: rt/turtle1/cmd_vel
- QoS: Reliable or BestEffort (ROS2 has limited options).
That's it. No RS needed, and it's similarly straightforward for a native DDS app to interact with ROS2 services, actions, or parameters.
You have complete freedom to intermix native DDS and ROS2 components -- because ROS2 is a DDS application.
I've placed an IDL file of all of the data type definitions used in ROS2 'eloquent' at: https://github.com/neil-rti/ros-data-types/blob/master/all_msgs/ros2interop/ros2-eloquent-all.idl
-- this can be used with RTI DDS code generator to create the typesupport code for whatever part of ROS2 you'd like to use in your native DDS applications.
Please reply if this seems like a better option -- or if not, so we can get some attention onto the trouble with the RS plug-in you're creating.
Thanks!
Hi neil-rti
Thanks for your explanation. The reason we decided to use the routing service is that moving our whole code base from our own data types to the ROS2 data types is too much effort especially when we don't know yet if it really works. We believe that the routing service allows us the integration of some ROS2 components into our system. This way we don't have to rebuild the whole system with ROS2 but can move step by step.
Below I have a screenshot showing that the topics match (between the RTI Routing Service and the ROS2 node (transform_subscriber)). I can subscrube to the "rt/rcv_transform" topic within the rtiadminconsole and do receive the messages. Therefore, I believe the data types match and the QoS settings as well. You can also see that field names of the ROS2 node have a "_" at the end.
I appreciate any further help. It would be so great if we could integrate ROS2 into our native rti DDS application.
Hi neil-rti
Me again. Do you have a ROS2 template USER_QOS_PROFIL.xml? If yes, could you please share it.
Cheers,
Andreas
Hi Andreas,
Actually, I've been using the default USER_QOS_PROFILE.xml file that is created by RTI Codegen, and will sometimes change it to use Generic.BestEffort reliability -- but otherwise, have not needed any special settings to interoperate with ROS2.
Try using RTI CodeGen to create a pub&sub example for geometry_msgs::msg::dds_::TransformStamped_ data type, and publish to ROS2 using the unmodified USER_QOS_PROFILES.xml file from the generated example.
Questions: does the callback in the ROS2 application (for received samples) get called when another ROS2 application publishes to it?
Also -- what is the ROS2 application that is receiving the published samples? Can they be received by (for instance) rqt?
Thanks - Neil
Hi neil-rti
I created a geometry_msgs::msg::dds_::TransformStamped_ publisher. When I don't have any USER_QOS_PROFILES.xml present, the publisher and the subscriber match (seen in the rtiadminconsole) and the subscriber receives the messages. Then, I created a USER_QOS_PROFILES.xml with the command
/opt/rti_connext_dds-5.3.1/bin/rtiddsgen -create examplefiles -update typefiles -language C++11 -I idl idl/geometry_msgs/msg/TransformStamped.idl
. Now when I start the publisher, I get the following error:PRESParticipant_checkTransportInfoMatching:Warning: discovered remote participant 'RTI Administration Console' using the 'shmem' transport with class ID 16777216. This class ID does not match the class ID 2 of the same transport in the local participant 'minimal_publisher'. These two participants will not communicate over the 'shmem' transport. Check the value of the property 'dds.transport.use_510_compatible_locator_kinds' in the local participant. See https://community.rti.com/kb/what-causes-error-discovered-remote-participant for additional info. COMMENDBeWriterService_assertRemoteReader:Discovered remote reader with GUID 0X101B8B9,0XF38BCC9E,0XB4C09B41,0X200C7 using a non-addressable locator. This can occur if the transport is not installed and/or enabled in the local participant. See https://community.rti.com/kb/what-does-cant-reach-locator-error-message-mean for additional info. can't reach: locator: shmem://508B:2F0F:1EDD:2470:D06A:ACC9:0000:0000:7410 COMMENDSrWriterService_assertRemoteReader:Discovered remote reader with GUID 0X101B8B9,0XF38BCC9E,0XB4C09B41,0X20087 using a non-addressable locator. This can occur if the transport is not installed and/or enabled in the local participant. See https://community.rti.com/kb/what-does-cant-reach-locator-error-message-mean for additional info. can't reach: locator: shmem://508B:2F0F:1EDD:2470:D06A:ACC9:0000:0000:7410 COMMENDSrWriterService_assertRemoteReader:Discovered remote reader with GUID 0X101B8B9,0XF38BCC9E,0XB4C09B41,0X4C7 using a non-addressable locator. This can occur if the transport is not installed and/or enabled in the local participant. See https://community.rti.com/kb/what-does-cant-reach-locator-error-message-mean for additional info. can't reach: locator: shmem://508B:2F0F:1EDD:2470:D06A:ACC9:0000:0000:7410 COMMENDSrWriterService_assertRemoteReader:Discovered remote reader with GUID 0X101B8B9,0XF38BCC9E,0XB4C09B41,0X3C7 using a non-addressable locator. This can occur if the transport is not installed and/or enabled in the local participant. See https://community.rti.com/kb/what-does-cant-reach-locator-error-message-mean for additional info. can't reach: locator: shmem://508B:2F0F:1EDD:2470:D06A:ACC9:0000:0000:7410 DDS_ResourceLimitsQosPolicy_is_consistent_w_historyI:inconsistent QoS policies: history.depth and resource_limits.max_samples (max_samples_per_instance is unlimited)
DDS_Subscriber_create_datareader_disabledI:ERROR: Inconsistent QoS DDSDataReader_impl::create_disabledI:!create reader DDSDataReader_impl::createI:!create reader initialize:!create DataReader connext::details::EntityUntypedImpl::initialize:!failed (see previous errors) >>> [rcutils|error_handling.c:107] rcutils_set_error_state() This error state is being overwritten: 'C++ exception during construction of Requester, at /tmp/binarydeb/ros-eloquent-rcl-interfaces-0.8.0/obj-x86_64-linux-gnu/rosidl_typesupport_connext_cpp/rcl_interfaces/srv/dds_connext/get_parameters__type_support.cpp:704' with this new error message: 'failed to create replier, at /tmp/binarydeb/ros-eloquent-rmw-connext-cpp-0.8.1/src/rmw_service.cpp:138' rcutils_reset_error() should be called after error handling to avoid this. <<< terminate called after throwing an instance of 'rclcpp::exceptions::RCLError' what(): could not create service: failed to create replier, at /tmp/binarydeb/ros-eloquent-rmw-connext-cpp-0.8.1/src/rmw_service.cpp:138, at /tmp/binarydeb/ros-eloquent-rcl-0.8.4/src/rcl/service.c:179
I guess the first part comes from the fact that I have the rtiadminconsole open but the errors on the buttom seems some rti DDS / ROS2 problem. Do you ever encoutered this? I attached the USER_QOS_PROFILES.xml
Hi neil-rti
Are you still here? I would really appreciate your help.
Kind Regards,
Andreas
Hi Andreas,
Apologies for the delay -- I'm not sure why I'm not getting notifications on this thread; will investigate.
Yes, that warning is caused by the use of "510 compatibility" in the Connext ROS2 RMW.
(this is being removed in the upcoming 'Foxy' release of ROS 2, see this link)
To resolve, add the following to your participant_qos settings on the non-ROS2 side:
<participant_qos>
<property>
<value>
<element>
<name>dds.transport.use_510_compatible_locator_kinds</name>
<value>1</value>
</element>
</value>
</property>
</participant_qos>
Hope this helps (will look into notifications here).
Hi neil-rti
After a clean rebuild (after I "activated" rti DDS 5.3.1 as middelware) it seems to work. Do I assume correctly that a rebuild is needed when the rmw is changed e.g. from standard to rti? What actually is this "510 compatibility mode"?
Kind regards,
Andreas
Hi Andreas,
This gets a little bit into the internals of DDS: 510 compatibility mode is a way of dealing with earlier implementations of DDS wherein the transport identifier for Shared Memory was using a different value than what is used today. When an earlier and a recent DDS would try to connect on the same platform with shared memory transport enabled, the ID's would not match and no shared memory connection would be made, even though everything else would otherwise work (and a connection using some other transport might then be selected, such as UDP loopback). The QoS setting tells the newer DDS to accept the older transport ID as valid for shared memory.
More details on the message can be found here.
BTW, I toggled the notifications checkbox and I'm now back to receiving email updates on this thread.
Thanks -- Neil
Hi neil-rti,
I'm trying to do something similar to the example you mentioned here, using RTI Connector for python to move the default turtle in turtlesim.
I have a question regarding the data type. It seems like ROS2 does some serialization of the data before RTI DDS publishes it (and deserializes subscribed messages), with the resulting data type being ConnextStaticSerializedData. Does that mean that when I create the data type in the QoS to be published by the connector, it should be ConnextStaticSerializedData type instead of geometry_msgs::msg::dds_::Twist_? Since the data type turtlesim subscribes to will be of ConnextStaticSerializedData type as well.
Thanks!
Hello,
Yes, it's a little annoying. That data type is used to represent all ROS2 user ("rt/*") data types when using the Connext RMW under ROS2, regardless of their actual data type.
The underlying data serialization is correct for the original data type, it's just the reported data type that is confusing (and results in a data type mismatch on discovery, and no connection).
To work around this, put the following into the QoS settings for the ROS2 application (TurtleSim or whatever).
This can be done with a local USER_QOS_PROFILES.xml file, placed into the directory from which the ROS2 application (TurtleSim) is launched:
<participant_qos>
<resource_limits>
<type_code_max_serialized_length>0</type_code_max_serialized_length>
<type_object_max_serialized_length>0</type_object_max_serialized_length>
</resource_limits>
</participant_qos>
This will suppress the reporting of the (incorrect) data type from ROS2 turtlesim, and the Python Connector side will be able to match and connect.
You probably already know this, but just in case:
Turtlesim is useful in that 4 different ROS2 communcations patterns are available: messages, services, actions, and parameters.
These are all very straightforward to interface with RTI Connector or a (compiled) native DDS application.
Let me know if you'd like some pointers or code samples.
Thanks -- Neil
Hi Neil,
Thanks for your help.
I tried adding the qos settings above to my USER_QOS_PROFILES.xml, but it still doesn't seem to connect.
Here's my USER_QOS_PROFILES.xml placed into the directory where I launched the turtlebot:
<?xml version="1.0"?>
<!--
Description
XML QoS Profile for Twist_
The QoS configuration of the DDS entities in the generated example is loaded
from this file.
This file is used only when it is in the current working directory or when the
environment variable NDDS_QOS_PROFILES is defined and points to this file.
The profile in this file inherits from the builtin QoS profile
BuiltinQosLib::Generic.StrictReliable. That profile, along with all of the
other built-in QoS profiles can be found in the
BuiltinProfiles.documentationONLY.xml file located in the
$NDDSHOME/resource/xml/ directory.
You may use any of these QoS configurations in your application simply by
referring to them by the name shown in the
BuiltinProfiles.documentationONLY.xml file and listed below:
* In library "BuiltinQosLib":
** Baseline
** Baseline.5.0.0
** Baseline.5.1.0
** Baseline.5.2.0
** Generic.Common
** Generic.510TransportCompatibility
** Generic.Monitoring.Common
** Generic.ConnextMicroCompatibility
** Generic.OtherDDSVendorCompatibility
* In library "BuiltinQosLibExp":
** Generic.StrictReliable
** Generic.KeepLastReliable
** Generic.BestEffort
** Generic.StrictReliable.HighThroughput
** Generic.StrictReliable.LowLatency
** Generic.Participant.LargeData
** Generic.Participant.LargeData.Monitoring
** Generic.StrictReliable.LargeData
** Generic.KeepLastReliable.LargeData
** Generic.StrictReliable.LargeData.FastFlow
** Generic.StrictReliable.LargeData.MediumFlow
** Generic.StrictReliable.LargeData.SlowFlow
** Generic.KeepLastReliable.LargeData.FastFlow
** Generic.KeepLastReliable.LargeData.MediumFlow
** Generic.KeepLastReliable.LargeData.SlowFlow
** Generic.KeepLastReliable.TransientLocal
** Generic.KeepLastReliable.Transient
** Generic.KeepLastReliable.Persistent
** Generic.AutoTuning
** Pattern.PeriodicData
** Pattern.Streaming
** Pattern.ReliableStreaming
** Pattern.Event
** Pattern.AlarmEvent
** Pattern.Status
** Pattern.AlarmStatus
** Pattern.LastValueCache
You should not edit the file BuiltinProfiles.documentationONLY.xml directly.
However, if you wish to modify any of the values in a built-in profile, the
recommendation is to create a profile of your own and inherit from the built-in
profile you wish to modify. The NDDS_QOS_PROFILES.example.xml file (contained in
the same directory as the BuiltinProfiles.documentationONLY.xml file) shows how
to inherit from the built-in profiles.
For more information about XML QoS Profiles see Chapter 17 in the
RTI Connext user manual.
-->
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="/opt/rti.com/rti_connext_dds-5.3.1/resource/schema/rti_dds_qos_profiles.xsd"
version="5.3.1">
<qos_library name="Twist__Library">
<qos_profile name="Twist__Profile" base_name="BuiltinQosLibExp::Generic.StrictReliable" is_default_qos="true">
<!-- QoS used to configure the data writer created in the example code -->
<datawriter_qos>
<publication_name>
<name>Twist_DataWriter</name>
</publication_name>
<history>
<kind>KEEP_LAST_HISTORY_QOS</kind>
<depth>1000</depth>
</history>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
</datawriter_qos>
<!-- QoS used to configure the data reader created in the example code -->
<datareader_qos>
<subscription_name>
<name>Twist_DataReader</name>
</subscription_name>
<resource_limits>
<max_samples>-1</max_samples>
<max_samples_per_instance>-1</max_samples_per_instance>
</resource_limits>
</datareader_qos>
<participant_qos>
<!--
The participant name, if it is set, will be displayed in the
RTI tools, making it easier for you to tell one
application from another when you're debugging.
-->
<participant_name>
<name>Twist_Participant</name>
<role_name>Twist_ParticipantRole</role_name>
</participant_name>
</participant_qos>
<participant_qos>
<property>
<value>
<element>
<name>dds.transport.use_510_compatible_locator_kinds</name>
<value>1</value>
</element>
</value>
</property>
</participant_qos>
<participant_qos>
<resource_limits>
<type_code_max_serialized_length>0</type_code_max_serialized_length>
<type_object_max_serialized_length>0</type_object_max_serialized_length>
</resource_limits>
</participant_qos>
</qos_profile>
</qos_library>
</dds>
And here is the Connector script I used to try to move the turtlebot:
# rticonnextdds-connector
from sys import path as sys_path
from os import path as os_path
file_path = os_path.dirname(os_path.realpath(__file__))
sys_path.append(file_path + "/../../../")
import rticonnextdds_connector as rti
connector = rti.Connector("MyParticipantLibrary::MyPubParticipant", "test_profile.xml")
output = connector.getOutput("MyPublisher::MySquareWriter")
output.instance.setNumber("linear_.x_", 0)
output.instance.setNumber("linear_.y_", 0)
output.instance.setNumber("linear_.z_", 0)
output.instance.setNumber("angular_.x_", 0)
output.instance.setNumber("angular_.y_", 0)
output.instance.setNumber("angular_.z_", 0.2)
output.write()
print("Exiting...")
test_profile.xml:
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/5.3.1/rti_dds_profiles.xsd"
version="5.3.1">
<!-- Qos Library -->
<qos_library name="QosLibrary">
<qos_profile name="DefaultProfile" base_name="BuiltinQosLibExp::Generic.StrictReliable"
is_default_qos="true">
<datawriter_qos>
<history>
<kind>KEEP_LAST_HISTORY_QOS</kind>
<depth>1000</depth>
</history>
<reliability>
<kind>RELIABLE_RELIABILITY_QOS</kind>
</reliability>
<durability>
<kind>VOLATILE_DURABILITY_QOS</kind>
</durability>
</datawriter_qos>
<participant_qos>
<transport_builtin>
<mask>UDPV4 | SHMEM</mask>
</transport_builtin>
<property>
<value>
<element>
<name>dds.transport.use_510_compatible_locator_kinds</name>
<value>1</value>
</element>
</value>
</property>
</participant_qos>
</qos_profile>
</qos_library>
<!-- types -->
<types>
<module name="geometry_msgs">
<module name="msg">
<module name="dds_">
<struct name= "Vector3_">
<member name="x_" type="float64"/>
<member name="y_" type="float64"/>
<member name="z_" type="float64"/>
</struct>
</module>
</module>
</module>
<enum name="ShapeFillKind" extensibility="extensible">
<enumerator name="SOLID_FILL" value="0"/>
<enumerator name="TRANSPARENT_FILL" value="1"/>
<enumerator name="HORIZONTAL_HATCH_FILL" value="2"/>
<enumerator name="VERTICAL_HATCH_FILL" value="3"/>
</enum>
<module name="geometry_msgs">
<module name="msg">
<module name="dds_">
<struct name= "Twist_">
<member name="linear_" type="nonBasic" nonBasicTypeName= "geometry_msgs::msg::dds_::Vector3_"/>
<member name="angular_" type="nonBasic" nonBasicTypeName= "geometry_msgs::msg::dds_::Vector3_"/>
</struct>
</module>
</module>
</module>
</types>
<!-- Domain Library -->
<domain_library name="MyDomainLibrary">
<domain name="MyDomain" domain_id="30">
<register_type name="geometry_msgs::msg::dds_::Twist_" type_ref="geometry_msgs::msg::dds_::Twist_" />
<topic name="rt/cmd_vel" register_type_ref="geometry_msgs::msg::dds_::Twist_"/>
</domain>
</domain_library>
<!-- Participant library -->
<domain_participant_library name="MyParticipantLibrary">
<domain_participant name="MyPubParticipant" domain_ref="MyDomainLibrary::MyDomain">
<publisher name="MyPublisher">
<data_writer name="MySquareWriter" topic_ref="rt/cmd_vel" />
</publisher>
</domain_participant>
<!-- We use separate participants because we run the writer and the reader
on different applications, and wouldn't want to create the reader
in writer.py, or the writer in reader.py -->
<domain_participant name="MySubParticipant" domain_ref="MyDomainLibrary::MyDomain">
<subscriber name="MySubscriber">
<data_reader name="MySquareReader" topic_ref="rt/cmd_vel" />
</subscriber>
</domain_participant>
</domain_participant_library>
</dds>
Running this script did not result in the turtlebot turning, and the RTI Admin Console also raises a mismatched error for that topic(attached image). Is there something I missed out in getting the connector to connect properly?
Thanks!
Hi Neil,
I tried creating a datawriter with the ConnextStaticSerializedData type instead, and encountered a Key Consistency mismatched error:
The error shows that the datawriter created is keyed, but the datareader is not. I'm not sure why is this the case since both are of the same data type:
and Equivalent idl:
struct ConnextStaticSerializedData {
octet key_hash[16]; //@key
//@ID 0
sequence<octet,2147483647> serialized_key; //@ID 1
sequence<octet,2147483647> serialized_data; //@ID 2
};
//@Extensibility EXTENSIBLE_EXTENSIBILITY
Is there a way to make the datawriter topic unkeyed as well to match the datareader topic?
Thanks!
Hello,
I've tried the script on a local install & found some small issues (with the help of RTI Admin Console) which were fixed in the test_profile.xml file:
1. The topic name from the Connector implementation is not matching the one used in turtlesim, so I changed:
"rt/cmd_vel" to "rt/turtle1/cmd_vel"
2. The domain number specified in the xml file (30) was not matching the default domain used in an unmodified install of ROS 2 (0), so I edited the file to put the Connector instance on domain 0.
After that -- the script would move the default turtle (turtle1) in turtlesim.
I tested this against the ROS2 "Foxy" release, using Connext and 2 other RMW implementations under turtlesim.
Also tested briefly against ROS2 "Eloquent" -
- which version of ROS2 are you using?
As for the "ConnextStaticSerializedData" type -- don't try to create a matching type for it.
The USER_QOS_PROFILES.xml example has 2 separate participant_qos sections; edit the file to move the resource_limits addition to be within the main participant_qos section under the default=true profile.
This will suppress the announcement of this incorrect data type from ROS2.
Let me know if this isn't working for you, I can send an edited file set to you directly.
Thanks!
Neil
Hi Neil,
I'm using ROS2 dashing.
After making the above mentioned changes, I managed to get the turtlesim moving through using Connector.
Thanks so much for your help!