This tutorial assumes that you have completed the steps in ROS Types in YARP: writing a portable.
That tutorial showed how to use types defined in a ROS-style .msg file within YARP. Now, we will work on sending data from YARP to ROS.
At the beginning of this tutorial, we assume you have a YARP server running, without any special configuration. During the tutorial, we will reconfigure the name server to communicate with ROS.
The sender
program from ROS Types in YARP: writing a portable looks like this:
This program was written using a yarp::os::Port
, a very flexible creature. It can communicate with ROS, if we tame it a little bit to fit in with ROS's expectations that promise to never change the type of data sent, and promise to always send data in a particular direction. We can make those promises by calls to yarp::os::Port::setWriteOnly and yarp::os::Port::promiseType, or we can switch to using the helper class yarp::os::Publisher
that is already correctly configured. We can also add a yarp::os::Node
to make ROS even happier.
Great, at this point our port is nice and tame by ROS standards. And the code will still work just fine without ROS. For example, we can run our existing receiver
program from ROS Types in YARP: writing a portable. We're now using a topic called /data
so after running the receiver
you'll need to subscribe it to the topic:
yarp connect topic://data /receiver
We can also update the receiver
code to use the yarp::os::Subscriber helper class:
Now let's make our programs visible with ROS. Stop running them, and then also stop the yarp name server. Make sure you have a ROS name server running ("roscore"/"rosmaster"), and that the ROS_MASTER_URI
environment variable is correctly set. Then run the yarp name server with the –ros
flag:
$ yarpserver --ros ... start-up messages omitted .. Using ROS with ROS_MASTER_URI=http://127.0.0.1:11311 ... start-up messages omitted .. Ok. Ready!
Done! Now, if we rerun the sender and receiver programs, they should work as before. The (invisible) difference is that they are being connected by ROS rather than YARP. A visible difference is that the programs are now visible within ROS. Try:
$ rostopic list ... /data ...
$ rosnode list ... /receiver/node /sender/node ...
$ rostopic info /data Type: yarp/SharedData Publishers: * /sender/node (http://192.168.1.3:10005) Subscribers: * /receiver/node (http://192.168.1.3:10003)
$ rosnode info /receiver/node Node [/receiver/node] Publications: None Subscriptions: * /data [yarp/SharedData] Services: None contacting node http://192.168.1.3:10003 ... Pid: [12432]
Notice that ROS is reporting the topic /data
as having the type yarp/SharedData
. ROS needs types to include a "package" name, and we haven't specified one yet, so YARP has added a fake one. To get full interoperation, we now need to add our SharedData
type in ROS (not just YARP), and as part of that process we'll end up making a real ROS package.
In ROS Types in YARP: writing a portable we defined a SharedData
structure in a SharedData.msg
file and used it to communicate between sender and receiver programs written using YARP. Now we need to make that file visible to ROS. ROS expects .msg
files to be in a directory called msg
within a ROS "package". If you already have a package set up for your work, you can just use that. For completeness, we give a very minimal ROS package here, just enough to experiment with, but you can also just follow ROS tutorials, there's nothing YARP-specific here. Do the following:
yarpros_tutorial
.src
.yarp
.yarp
, create an empty directory called msg
.SharedData.msg
into yarpros_tutorial/src/yarp/msg/
.yarpros_tutorial/src/yarp/package.xml
and place the following in it:yarpros_tutorial/src/CMakeLists.txt
and place the following in it:yarpros_tutorial
directory, run catkin_make
. You should see something like:... -- +++ processing catkin package: 'yarp' ... Generating C++ code from yarp/SharedData.msg [ 50%] Generating Python from MSG yarp/SharedData ... [100%] Built target yarp_generate_messages
Now we need to tell ROS about the existence of yarpros_tutorial. There are many ways to do that. In a bash shell, the simplest is to do (from the yarpros_tutorial
directory):
$ source devel/setup.bash
At this point, the rosmsg
command should be able to find our type:
$ rosmsg show yarp/SharedData string text float64[] content
And if we run the sender
program, we can print it from ROS:
$ rostopic echo /data text: Hello from sender content: [4794.0, 4795.0] --- text: Hello from sender content: [4796.0, 4797.0] --- text: Hello from sender content: [4798.0, 4799.0] --- text: Hello from sender content: [4800.0, 4801.0] ---
If we stop the sender
program and run the receiver
, we can publish to if from ROS. If we do this:
rostopic pub /data yarp/SharedData "hello from ROS" "[1.1,2.2,3.3]"
The receiver
program prints this:
0 Received SharedData: hello from ROS 1.1 2.2 3.3