IndexNextUpPreviousUrbi SDK 3.0.0

Chapter 22
Communication with ROS

This chapter is not an introduction to using ROS from Urbi, see Listing 12 for a tutorial.

Urbi provides a set of tools to communicate with ROS (Robot Operating System). For more information about ROS, please refer to http://www.ros.org. Urbi, acting as a ROS node, is able to interact with the ROS world.

 22.1 Ros
  22.1.1 Construction
  22.1.2 Slots
 22.2 Ros.Topic
  22.2.1 Construction
  22.2.2 Slots
  22.2.3 Example
 22.3 Ros.Service
  22.3.1 Construction
  22.3.2 Slots

Requirements You need to have installed ROS (possibly a recent version), and compiled all of the common ROS tools (rxconsole, roscore, roscpp, …).

You also need to have a few environment variables set, normally provided with ROS installation: ROS_ROOT, ROS_MASTER_URI and ROS_PACKAGE_PATH.

Usage The classes are implemented as UObjects (see Listing IV): Ros, Ros.Topic, and Ros.Service.

This module is loaded automatically if ROS_ROOT is set in your environment. If roscore is not launched, you will be warned and Urbi will check regularly for roscore.

If for any reason you need to load this module manually, use:

 
loadModule("urbi/ros");  

22.1 Ros

This object provides some handy tools to know the status of roscore, to list the different nodes, topics, services, …It also serves as a namespace entry point for ROS entities, such as Ros.Topic and so forth.

22.1.1 Construction

There is no construction, since this class only provides a set of tools related to ROS in general, or the current node (which is unique per instance of Urbi).

22.1.2 Slots

22.2 Ros.Topic

This UObject provides a handy way to communicate through ROS topics, by subscribing to existent topics or advertising to them.

22.2.1 Construction

To create a new topic, call Ros.topic.new with a string (the name of the topic you want to subscribe to / advertise on).

The topic name can only contain alphanumerical characters, ‘/’ and ‘_’, and cannot be empty. If the topic name is invalid, an exception is thrown and the topic is not created.

Until you decide what you want to do with your topic (subscribe or advertise), you are free to call init to change its name.

22.2.2 Slots

Some slots on this UObject have no interest once the type of instance is determined. For example, you cannot call unsubscribe if you advertise, and in the same way you cannot call publish if you subscribed to a topic.

22.2.2.1 Common

22.2.2.2 Subscription

22.2.2.3 Advertising

22.2.3 Example

This is a typical example of the creation of a publisher, a subscriber, and message transmission between both of them.

First we need to declare our Publisher, the topic name is ‘/example’, and the type of message that will be sent on this topic is ‘std_msgs/String’. This type contains a single field called ‘data’, holding a string. We also set up handlers for onConnect and onDisconnect to be noticed when someone subscribes to us.

 
var publisher = Ros.Topic.new("/example")| 
at (publisher.onConnect?(var name)) 
  echo(name[0,5] + " is now listening on " + publisher.name); 
at (publisher.onDisconnect?(var name)) 
  echo(name[0,5] + " is no longer listening on " + publisher.name); 
publisher.advertise("std_msgs/String");  

Then we subscribe to the freshly created topic, and for each message, we display the ‘data’ section (which is the content of the message). Thanks to the previous at above, a message is displayed at subscription time.

 
var subscriber = Ros.Topic.new("/example")| 
at (subscriber.onMessage?(var m)) 
  echo(m["data"]); 
subscriber.subscribe; 
// Let the "is now listening" message arrive. 
sleep(200ms); 
[00026580] *** /urbi is now listening on /example  

The structure for the messages are, of course, equal between the subscriber and the publisher.

 
subscriber.structure == publisher.structure;  

Now we can send a message, and get it back through the at in the section above. To do this we first copy the template structure and then fill the field ‘data’ with our message.

 
var message = publisher.structure.new; 
[00098963] ["data" => ""] 
message["data"] = "Hello world!"|; 
 
// publish the message. 
publisher << message; 
// Leave some time to asynchronous communications before shutting down. 
sleep(200ms); 
[00098964] *** Hello world! 
 
subscriber.unsubscribe; 
// Let the "is no longer" message arrive. 
sleep(200ms); 
[00252566] *** /urbi is no longer listening on /example  

22.3 Ros.Service

This UObject provides a handy way to call services provided by other ROS nodes.

22.3.1 Construction

To create a new instance of this object, call Ros.Service.new with a string representing which service you want to use, and a Boolean stating whether the connection between you and the service provider should be kept opened (pass true for better performances on multiple requests).

The service name can only contain alphanumerical characters, ‘/’, ‘_’, and cannot be empty. If the service name is invalid, an exception is thrown, and the object is not created.

Then if the service does not exist, an other exception is thrown. Since the initialization is asynchronous internally, you need to wait for service.initialized to be true to be able to call request.

22.3.2 Slots