Yarp
Introduction.

torsoPitch.val = 20 sin:2s ampli:20 &
shoulderRollR.val = 45 sin:2s ampli:45 &
shoulderRollL.val = 45 sin:2s ampli:45,
This module features a bridge between the Yarp middleware and Urbi.
It provides a low-level API to open, connect, read and write Yarp ports, and a higher-level API to automatically bridge urbiscript variables to Yarp port.
Get the module.
Pre-built binaries.
We provide binaries for some architectures and urbi-sdk version:
| urbi-sdk 2.7.5 linux lucid | http://www.gostai.com/downloads/yarp/yarp-linux32-lucid-urbi2.7.5.so |
| urbi-sdk 2.7.1 linux etch | http://www.gostai.com/downloads/yarp/yarp-linux32-etch-urbi2.7.1.so |
| urbi-sdk 2.7.1 linux lucid | http://www.gostai.com/downloads/yarp/yarp-linux32-lucid-urbi2.7.1.so |
You will also need the source package (see below) that contains support .u files.
Compiling from sources.
You can get the sources here: sources.zip
Building can be achieved using umake:
umake-shared -o yarp yarp.cc -I/PathToYarp/include \ -L/PathToYarp/lib -lYARP_dev -lYARP_OS -lYARP_sig -lYARP_init \ WARNING_CXXFLAGS= -I. -lACE
This will produce a file named yarp.so That you can load in an urbi engine.
Load the module.
As for any UObject, either pass it to your urbi-launch command line:
urbi-launch -s yarp.so -- -i --port 54000
or load it in a running urbi server using
loadModule("yarp");
Now you should be able to type YarpPort; and see the initial UObject instance.
Use the module.
Simple bridging of a value.
This is the basic use case: bridging an urbiscript variable to a Yarp port.
First create a new instance of YarpPort:
var y = YarpPort.new;
Then bridge it to a Yarp port using the bridgeTo function:
y.bridgeTo("/icubSim/cam/right", 1);
The first parameter is the port to connect to/from, the second is the connexion orientation (1 to be a reader, 2 to be a writer, 3 for both.).
This call will generate a new unique port name, and connect it to the given port name (similar to doing a yarp read and a yarp connect).
In reader mode, each received value from the Yarp port will be written to the val slot of your object. All types that can fit in a Bottle are supported. Special support is provided for images: they are converted to the standard Urbi UBinary representation.
In writer mode, each time 'val' is written to, the value is transmitted to the Yarp port (and forwarded by Yarp to all connected ports).
Supported value types.
Full conversion between yarp::Bottle and urbi::UValue is provided. There are however two quirks to remember:
- To represent a Vocabulary, prefix the vocabulary word with '$'.
- To represent an integer, prefix the value with '#'. Otherwise all numerical values are sent as double.
Dispatching vectors to multiple variables.
Specific support is provided for Yarp port outputting/accepting a list of double, as many standard motor interfaces do.
What we want is to bridge said Yarp port to multiple urbiscript variables (for instance headYaw.val, headPitch.val ...). Sensor updates from the port will update all the variables. Write to any of the variables will send an update to the Yarp command port.
The yarp.u helper script provides the function yarpToMotorInterfaces. This is a sample usage:
// Create a Naming Standard compliant setup.
var Global.robot = Component.new("robot");
robot.addComponent("body");
robot.body.addComponent("head");
yarpToMotorInterfaces("/icubSim/head", [
[robot.body.head, "yaw"],
[robot.body.head, "pitch"],
<...>
]);
robot.makeCompactNames;
This call will connect to the motor device at the given address (actually using the two Yarp ports /icubSim/head/state:o for sensor input, and /icubSim/head/rpc:i for control commands). It will then create a set of standard Urbi RotationalMotor interfaces robot.body.head.yaw, robot.body.head.pitch, ... and bridge them to their corresponding offset of the Yarp motor interface.
Now the new objects can be manipulated like any other urbiscript Motor:
at(headYaw.val > 0) echo("looking left");
tag: headPitch.val = 0 sin:2s ampli: 20,
sleep(5s) | tag.stop;
The yarpToMotorInterfaces is actually using the setIOBridge function of the YarpPort object. See the reference documentation for more information.
RPC API.
Support for the Yarp RPC mode is provided by the three function connectRPC, rpc, and rpcString. Consider this example:
var y = YarpPort.new;
// Connect to the RPC server handling simulation interaction.
y.connectRPC("/icubSim/world");
// Ask for the left hand position.
y.rpcString("world get lhand");
// Do the same, building the message Bottle ourselves:
y.rpc(["world", "get", "lhand"]);
Low-level port access.
Low-level functions to open, read, write, connect Yarp ports are provided. See the reference documentation for more information.
// Send a motor command ourselves using the low-level API, just for fun.
var y = YarpPort.new;
y.open("/myport");
y.connect("/myport", "/icubSim/head/rpc:i");
y.write(["$set", "$poss", [10, 10, 10, 10, 10, 10]]);
Specific iCub support.
Gostai Naming-Standard compliant initialization is provided for the iCub and iCub simulator in the icub.u file. It instanciates all iCub motors and its two cameras.
It also provides specific support for creating shapes in the simulated world.
Reference documentation.
See the Doxygen-generated documentation here