19. ROS2

Video tutorial about ROS2.

AGX Dynamics for Unreal has built in ROS2 support with no need for a separate ROS2 installation to work. What is currently supported is message passing via the ROS2 Publisher and ROS2 Subscriber Components. See Message passing for details about how these are used. All messages types in the following packages are supported:

std_msgs, sensor_msgs, builtin_interfaces, rosgraph_msgs, geometry_msgs and agx_msgs.

There is also a mechanism for passing custom data types using the ROS2 Any Message Builder and ROS2 Any Message Parser Components, see Using Custom Types for details.

Specifying QOS (Quality of Service) such as reliability, durability, history type and depth as well as domain ID is also supported, see QOS (Quality of Service).

ROS2 in AGX Dynamics for Unreal targets the version ROS2 Humble and specifically the DDS implementation Fast-DDS which is the default DDS implementation in ROS2 Humble. ROS2 generally does not guarantee compatibility between ROS2 versions and DDS vendors, but it should work in practice, especially when matching the DDS vendor types. For details regarding troubleshooting, see Troubleshooting.

19.1. Message passing

Sending and receiving ROS2 messages in AGX Dynamics for Unreal is done via the ROS2 Publisher and ROS2 Subscriber Components.

19.1.1. Sending a ROS2 Message

To send a ROS2 message, simply add a new ROS2 Publisher Component in a Blueprint. Then call one of the Send functions for the message type wanted. Specify a topic and pass a message struct of the appropriate type. Below is an example of sending a std_msgs::Float32 on topic mytopic.

Send ROS2 message

Sending a ROS2 message.

Note that a single ROS2 Publisher Component can be used to send messages on multiple topics and message types. This is possible because the Component uses a pool of publishers internally, one for each topic. Using multiple ROS2 Publisher Components is supported as well. Passing messages of different types to the same topic is not supported.

If using C++, the same can be done by calling the appropriate Send function:

Pub->SendStdMsgsFloat32(Msg, "mytopic");

19.1.2. Receiving a ROS2 Message

To receive a ROS2 message, simply add a new ROS2 Subscriber Component in a Blueprint. Then call one of the Receive functions for the message type wanted. Specify a topic and remember to always check the return value. true is returned if a message was received, false otherwise. Below is an example of receiving a std_msgs::Float32 on topic mytopic and printing the received data to the screen.

Receive ROS2 message

Receiving a ROS2 message.

Note that a single ROS2 Subscriber Component can be used to receive messages on multiple topics and message types. This is possible because the Component uses a pool of subscribers internally, one for each topic. Using multiple ROS2 Subscriber Components is supported as well.

If using C++, the same can be done by calling the appropriate Receive function:

if (Sub->ReceiveStdMsgsFloat32(OutMsg, "mytopic"))
{
  /* Use OutMsg */
}

19.2. Using Custom Types

Passing custom data types is possible by using the ROS2 Any Message Builder and ROS2 Any Message Parser Components. These are helper classes that can serialize and deserialize custom data to and from a agx_msgs::Any message. These support some of the more common built in integer, floating point, boolean, and string types as well as sequences of these.

The agx_msgs::Any message type as well as AnyMessageBuilder and AnyMessageParser are also avaiable open-source on GitHub so that these can be used on machines that does not have AGX Dynamics or AGX Dynamics for Unreal installed.

By serializing a custom data type to an agx_msgs::Any message using a ROS2 Any Message Builder, the agx_msgs::Any message can then be sent via ROS2. On the receiving side, the agx_msgs::Any message is deserialized using a ROS2 Any Message Parser to retrieve the custom data. Below is an example of serializing and passing the equivalent of the following C++ struct:

struct MyStruct
{
   float MyFloat;
   std::vector<std::string> MyStrings;
};
Sending a custom data type.

Sending a custom data type.

Note that the Begin Message function must be called before starting to build a new message using the ROS2 Any Message Builder Component, as the image above shows.

To retrieve the custom data type, we receive the message and then use the ROS2 Any Message Parser Component to read the data back:

Receiving a custom data type.

Receiving a custom data type.

Note that the Begin Parse function must be called each time before starting to read (or “parse”) a new agx_msgs::Any message. Also note that the order of write and read when using the ROS2 Any Message Builder and ROS2 Any Message Parser Components must match on the sending and receiving side. The layout of the custom data type must also be known by both sides and serialized according to its data members.

19.3. QOS (Quality of Service)

QOS or Quality of Service determines the lifetime behaviour of ROS2 messages. QOS can be set for each ROS2 Publisher and ROS2 Subscriber Component in the Details Panel.

ROS2 Quality of Service settings.

ROS2 Quality of Service settings.

Setting the Reliability, Durability, History and History Depth is supported. By default these will be set to the same values as in ROS2 Humble. Changing the QOS setting on an existing ROS2 Publisher or ROS2 Subscriber during Play is not supported.

19.4. Limitations

Since only integer types uint8, int32 and int64 is currently supported by Blueprints, some of the built in message types exposed in AGX Dynamics for Unreal has been modified to use these in place of other non-supported integer types. These are converted internally to the correct integer types, so as a User no special logic needs to be written to convert these values.

Passing messages of different types to the same topic is not supported. Changing the QOS setting on an existing ROS2 Publisher or ROS2 Subscriber during Play is not supported.

Since the type uint64 is not supported in Blueprints, data loss may occur when receiving messages containing members of uint64 type. These will be cast to int64 automatically to work in Blueprints.

19.5. Troubleshooting

If messages are missed, or the first couple of messages are missed, it may be of use to check the QOS settings used. By default the QOS settings are the same as in ROS2 Humble. More details on these settings can be seen (here).

If no communication between a built in ROS2 Publisher and ROS2 Subscriber can be established it is possible that it is blocked by a firewall on the computer. Check the firewall settings and unblock the process in case it has been blocked.

If no communication between a built in ROS2 Publisher or ROS2 Subscriber and an external ROS2 node running on a complete ROS2 installation can be established, ensure that the same version of ROS2 is used. The built in ROS2 support in AGX Dynamics for Unreal targets ROS2 Humble. If this does not solve the problem, ensure that the DDS implementation Fast-DDS is used in the ROS2 installation. This can be forced by setting the environment variable RMW_IMPLEMENTATION=rmw_fastrtps_cpp. See the (ROS2 documentation) for details. Also check the firewall settings if necessary.

If the creation of a agxIO::ROS2::Publisher or agxIO::ROS2::Subscriber hangs forever it is possible a seemingly rare bug in Fast-DDS is the culprit. This seems to happen when creating a DDS Participant (which is done automatically by AGX Dynamcis) on Windows on rare occations. The underlying reason why this can happen is not known, but a manual workaround is to do the following: 1. Turn off any process using ROS2. 2. Manually remove all files in C:\ProgramData\eprosima\fastrtps_interprocess (replace drive-letter if applicable).