Thanks ChuiV, this is helpful. After poking around some more, was able to get some topic communication to and from a standalone fastrtps app and a ROS2 node. I had five challenges, four of which if figured out, and one of which i found a work around on, but am still not sure the best solution:
Things I figured out:
- the necessity of the
rt/
topic prefix. - I needed to make sure the
domainID
is the the same on the ROS2 side as what i am setting in my fastrtps application. this means, of course setting, an env var in the terminal i am running my ROS2 node (export ROS_DOMAIN_ID=42
) - I needed to make sure the messages were registered using the appropriate "ROS format" prefixes. In other words
<msg_package_name>::msg::dds_::<MsgType>_
By default, fastrtps seemed to be trying to use shared memory as its transport layer, but ROS2 wants UDP (v4). By adding the following to my fastrtps applications, things connected:
auto localhostUdpv4Transport = std::make_shared<UDPv4TransportDescriptor>();
PParam.rtps.useBuiltinTransports = false;
PParam.rtps.userTransports.push_back(localhostUdpv4Transport);
It's probably worth sharing the whole init()
function for my fastrtps application that publishes a (custom) HelloWorld.msg that my ROS2 app can subscribe to:
bool HelloWorldPublisher::init()
{
ParticipantAttributes PParam;
auto localhostUdpv4Transport = std::make_shared<UDPv4TransportDescriptor>();
PParam.rtps.useBuiltinTransports = false;
PParam.rtps.userTransports.push_back(localhostUdpv4Transport);
PParam.rtps.builtin.discovery_config.leaseDuration = c_TimeInfinite;
PParam.domainId = 42;
PParam.rtps.setName("hello_world");
mp_participant = Domain::createParticipant(PParam);
if (mp_participant == nullptr)
{
return false;
}
//REGISTER THE TYPE
Domain::registerType(mp_participant, &m_type);
//CREATE THE PUBLISHER
PublisherAttributes Wparam;
Wparam.topic.topicKind = NO_KEY;
Wparam.topic.topicDataType = "hello_world_msgs::msg::dds_::HelloWorld_";
Wparam.topic.topicName = "rt/hello_world";
// fill in the data to the msg to send, can overwrite later
m_Hello.message("hi from RTPS");
mp_publisher = Domain::createPublisher(mp_participant, Wparam, (PublisherListener*)&m_listener);
if (mp_publisher == nullptr)
{
return false;
}
return true;
}
In this example, I am publishing a custom hello_world_msgs/HelloWorld.msg
onto a ROS2 topic /hello_world
, and with ROS_DOMAIN_ID=42.
A simple ROS2 subscriber can will read this topic accordingly.
The thing I have not yet found a great answer/solution to is how to get a "shared" message type that's used by ROS2 and my fastrtps application.
My hacky work-around was to build my ROS2 message package, then go find the generated .idl file in the build directory, and manually copy it to my fastrtps workspace. I then used the fastrtps tools to generate the necessary DDS classes/files that I could compile against on my dds application side.
Ideally, there would be a way to do this directly from the ROS2 generated files, but I haven't figured this out yet. Any insights or suggestions on this?