YARP ROS Interoperation Past and Future But Not Now

From Wiki for iCub and Friends
Jump to navigation Jump to search

This page gives some details on the status of YARP/ROS interoperation.

ROS vs roscore

"ROS" is a big collection of lots or parts. The ROS middleware is called "roscore". This is the component of ROS most comparable to YARP. It will be referred to in the rest of this document as ROSCORE.

Using YARP and ROSCORE in the same program

There is no obstacle to using YARP and ROSCORE in the same program. Programs that use ROSCORE are in practice likely to be built using ROS's own build system, which is layered on CMake. Since YARP can be linked to like any regular library, and has good support for doing so from CMake, there is no problem integrating at this level. A frequent source of conflict between middleware can be in automatic code-generation steps (e.g. for generating functions/classes encoding message types). YARP has deliberately refrained from having such code-generation specifically so that it remains "just a library" from the perspective of integration. As such, YARP has been packaged within the ROS package management system:


Note that the use of YARP and ROSCORE in the same program strongly implies use of the ROS build system. This has consequences. That program will be a lot less portable than if it used YARP alone (ROS developers concentrate on Ubuntu Linux) and will be less usable from frameworks that are incompatible with ROS.

If YARP is used in a ROS program, one concern might be efficiency. Support data is received in a YARP-using part of the program and is to be processed in a ROS-using part. Translation between data types could get complicated. This matters most for large objects such as images. YARP has deliberately designed data types like images with an eye to this problem. The YARP image type is structured to match the format of an "IplImage", a venerable format that has since been propagated to the popular OpenCV library. OpenCV is the image processing library adopted by ROS, and so YARP and ROS images share a common format. This fact is used in this package (in fact the conversion here is a sub-optimal, containing an avoidable copy):


Using YARP and ROSCORE on the same network

YARP and ROSCORE provide for inter-process communication. If they had compatible protocols, then programs using YARP and programs using ROSCORE could communicate with each other. For example, one use case for this would be to make the ICUB robot (whose software is written with YARP) directly accessible from programs written using the ROS framework. More generally, a non-ROS-using program (e.g. on an unsupported OS or using an incompatible framework) could be made to communicate with ROS programs via YARP.

YARP has been deliberately designed with interoperability in mind, with a plugin system of "carriers" (network protocols) that allows for great variety in how logical data flow translates into network traffic. Some preliminary work has been done to add "carriers" for ROSCORE traffic into YARP. This is done *without* linking to ROS libraries, since doing so would reduce the portability of YARP.

The XML/RPC carrier

Administrative messages in ROSCORE are transmitted using XML/RPC. Specifically, this protocol is used by ROSCORE when communicating with the roscore "master" entity, and with "slave" entities associated with each node. These messages do not carry user data, but are essential to finding out how to reach named entities on the network, making and breaking connections, and other administrative tasks.

An "xmlrpc_carrier" plugin has been added to YARP. This means that all YARP "Ports" can now act as XML/RPC servers and clients.

YARP user data, when sent to or received from a carrier, is expressed in a logical format called the "Bottle" format, which can be thought of to a first approximation as an s-expression in Lisp -- nested lists containing sequences of primitives. This format is easy to map onto the XML model used by the "XmlRpc++" library, which is the XML parser used by ROS and by the xmlrpc_carrier plugin. Here is the mapping:

* XML/RPC integer <-> Bottle integer
* XML/RPC double (floating point number) <-> Bottle double (floating point number)
* XML/RPC string <-> Bottle string
* XML/RPC blobs <-> Bottle blobs
* XML/RPC array <-> Bottle list
* XML/RPC structure <-> Bottle list

XML/RPC structures are sets of key/value pairs. These are mapped to a list with the tag "dict" as the first element, followed by sublists with key->value mappings:

 (dict (key1 val1) (key2 val2))

With some care, the mapping can be made exact, and means that no new types need to be added to YARP in order to conveniently represent data transfer to/from XML/RPC server/clients. So it is now easy to communicate from YARP to the roscore "master" and node "slaves"; it is also possible to have YARP ports pose as ROS "slaves" (or theoretically the "master").

For example, once this carrier is available, here is how YARP can be used from the commandline to look up the address of a ROSCORE entity called "/talker". We assume the roscore "master" server is running on the machine called "zimba", on port number 11311:

 # for convenience, give the roscore master a name ("/roscore") in the YARP network
 yarp name register /roscore tcp zimba 11311
 # send a look-up message, following the master API
 echo "lookupNode yarp_contact_id /talker" | yarp rpc xmlrpc://roscore

This result is printed:

 1 "node api" "http://contact:37291/"

So we know that the entity "/talker" can be reached on the machine "contact" on port number 37291, speaking "http" (this means XML/RPC). We can in turn talk to that entity using XML/RPC to get information about it or to prod it into making connections.

The command-line operation above can be trivially converted to code. Such operations are not intended for end-users, it is given here just to show some detail of this aspect of interoperability.

The TCPROS carrier