ROS2 - Frontend Contribution

ROS2 is the preferred way of communication in the robot backend. The robot platform provides an easy way of communicating with the ROS2 backend using a Web API called the Ros2Client. The Ros2Client can be used to listen to ROS2 Topics or to call ROS2 services.

See ROS2 Topics and Services for namespace rules and the list of topics and services supported by the Robot. For each topic or service, the message column shows what message type is supported by that topic or service. For details on messages in the urinterfaces package see URInterfaces API reference.

Accessing the Ros2Client

The Ros2Client can be accessed in presenters and in workers from the contribution-api package. The Ros2Client can be used with the following APIs:

  • ApplicationBehaviorAPI

  • ProgramBehaviorAPI

  • ApplicationPresenterAPI

  • ProgramPresenterAPI

  • SourcePresenterAPI

To access the Ros2Client from a program node presenter use add the following line method:

this.ros2Client = this.presenterAPI.ros2Client;

Using the Ros2Client

The following 4 methods are available on the Ros2Client:

    .getTopicPath(prependRobotNamespace, topic, ...namespaces);

    .createSubscription(messageType, topicPath, qosProfile);

    .getServicePath(prependRobotNamespace, serviceName, ...namespaces);

    .callService(serviceType, servicePath, argumentValues, qosProfile, timeout);

The first 2 methods are for subscribing to a ROS2 topic and the last 2 methods are for setting argument values on a ROS2 service.

The getTopicPath method

    ros2client.getTopicPath(prependRobotNamespace, topic, ...namespaces);

The getTopicPath method is for getting a topic path containing the correct namespace. Return type is TopicPath. The method takes the following parameters:

prependRobotNamespace : A boolean that if true will prepend the local robot namespace to the topic. This is required for communicating with the ROS2 node for Robot Arm.

topic : A string that is the topic to subscribe to.

namespaces : Optional list of string parameters that are namespaces to prepend to the topic. Here the string constant called URCAP_ROS_NAMESPACE should be used if frontend needs to communicate with a ROS2 backend contribution from the same URCap.

The createSubscription method

    ros2client.createSubscription(messageType, topicPath, qosProfile);

The createSubscription method will create an observable for a ROS2 topic. Return type is Observable. Subscribe to this observable to receive messages. The method takes up to 3 parameters:

messageType : A string that is the message type of the topic to subscribe to.

topicPath : The full path of the topic to subscribe to. It may include namespaces.

qosProfile : An optional quality of service profile to apply to the subscription. The default is QoSProfile.default.

See About QoS settings for details on Quality of Service Profile settings.

The getServicePath method

    ros2client.getServicePath(prependRobotNamespace, serviceName, ...namespaces);

The getServicePath method is for getting a service name path containing the correct namespace. Return type is ServicePath. The same namespace rules and parameters apply here as the for the TopicPath but here it is for the full path to the service name.

The callService method

    ros2client.callService(serviceType, servicePath, argumentValues, qosProfile, timeout);

The callService method is for setting values on or receiving values from a service. Return type is a Promise containing the return value of the call. This values depends on the service type used. The method takes up to 4 parameters:

serviceType : A string that is the service type of the service name to set values on.

servicePath : The full path of the service name to set values on. It may include namespaces.

argumentValues : An instance of a class containing the argument values to set.

qosProfile : An optional quality of service profile to apply to the service client. The default is QoSProfile.default.

timeout : An optional timeout for how long to wait for a service response. The default is 30 seconds.

Sample code for using the ROS2Client

Subscribing to an analog output topic on the Robot using default QoS profile:

import { IRosTypeUrinterfacesAnalog } from '@universal-robots/ros2-interfaces';
...
const messageType = 'urinterfaces/msg/Analog';

const topicPath = this.ros2Client.getTopicPath(true, 'standard_analog_output_0');

this.subscription = this.ros2Client.createSubscription<IRosTypeUrinterfacesAnalog>(messageType, topicPath)
    .subscribe((msg) => console.log(msg.value));
...

Note that the messageType must match the interface IRosTypeUrinterfacesAnalog. The messages received (msg) will be of the type IRosTypeUrinterfacesAnalog. Also note that all the interfaces for message- and service-types, that can be imported is found in the @universal-robots/contribution-api package.

Subscribing to a string topic using URCap namespace and custom QoS profile:

import { IRosTypeStdMsgsString } from '@universal-robots/ros2-interfaces';
...
const messageType = 'std_msgs/msg/String';

const topicPath = this.ros2Client.getTopicPath(true, 'my_docker_ros_string', URCAP_ROS_NAMESPACE);

const qosProfile = QoSProfile.default;
qosProfile.depth = 1;
qosProfile.history = HistoryPolicy.KEEP_LAST;
qosProfile.reliability = ReliabilityPolicy.BEST_EFFORT;
qosProfile.durability = DurabilityPolicy.TRANSIENT_LOCAL;

this.subscription = this.ros2Client.createSubscription<IRosTypeStdMsgsString>(messageType, topicPath, qosProfile)
    .subscribe((msg) => console.log(msg));
...

Note that the messageType must match the interface IRosTypeStdMsgsString. The messages received (msg) will be of the type IRosTypeStdMsgsString. Also note that QoS profile ‘depth = 1’ setting only has effect if ‘history’ is set to ‘KEEP_LAST’.

Setting a value of 0.5 on an analog output on the Robot using default QoS profile:

import { IRosTypeUrinterfacesSetAnalogOutputResponse } from '@universal-robots/ros2-interfaces';
...
const serviceType = 'urinterfaces/srv/SetAnalogOutput';

const servicePath = this.ros2Client.getServicePath(true, 'set_standard_analog_output');

const argumentValues = { pin: 0, output_type: true, 0.5 };

this.ros2Client.callService(serviceType, servicePath, argumentValues)
    .then((returnValue: IRosTypeUrinterfacesSetAnalogOutputResponse) => console.log(returnValue.success));
...

Note that the serviceType and argumentValues must match the interface IRosTypeUrinterfacesSetAnalogOutRequest.

For a general ROS2 overview, guides and documentation visit ROS2 Humble. s