VRPN Tutorial : Sending data from an external application to OpenViBE

  • NB: last update for OpenViBE 0.18.0 (19.nov.2014).
The VRPN interfaces and the example program are part of the OpenViBE source tree since 0.18. See under applications/examples/vrpn-to-openvibe/ for the most up-to-date versions. The visual studio subproject is openvibe-examples-vrpn-to-openvibe. The source code in this documentation is for illustrative purposes only and may be outdated.

Some external applications may want to send data to OpenViBE. This can be done quite easily by using VRPN and the appropriate Analog VRPN Client or Button VRPN Client.

Implementing a VRPN  server in an application is not difficult, but for the sake of simplicity we are going to use an object oriented interface designed specially for OpenViBE (but still usable anywhere).

The interface

The generic interface consists of a single class GenericVRPNServer. This server enables you to use a single object to manage any number of named VRPN buttons and analog controls.

Only basic functionality of the GenericVRPNServer class will be treated in this tutorial, for more information refer to the header file.

A simple program

The best explanation is done by example. Let us look at a very simple piece of code – this program generates a sine and cosine waves and sends them through a VRPN analog connection. Additionally a button is created, this changes state (on/off) on the beginning every period.

The Code

#include "GenericVRPNServer.h"
#include <iostream>
#include <cmath>

#define DEFAULT_PORT 50555

int main(int argc, char** argv)
{
    GenericVRPNServer* vrpnServer = GenericVRPNServer::getInstance(DEFAULT_PORT);

    vrpnServer->addButton("button_test", 1);
    vrpnServer->addAnalog("analog_test", 2);

    double time = 0;
    double period = 0;

    while (true)
    {
        if (period >= 2 * M_PI)
        {
            vrpnServer->changeButtonState("button_test", 0, 1 - vrpnServer->getButtonState("button_test", 0));
            period = 0;
        }

        vrpnServer->changeAnalogState("analog_test", sin(time), cos(time));

        time = time + 0.01;
        period = period + 0.01;

        vrpnServer->loop();

        // sleep for 10 miliseconds (on Unix)
        usleep(10000);
    }

    return 0;
}

Detailed explanation

Some includes at the beginning (only the GenericVRPNServer.h is really needed for the VRPN connection itself)

#include "GenericVRPNServer.h"
#include <iostream>
#include <cmath>

VRPN has to operate on a specific port, in order to avoid using an already taken port let us use a sensible big value (greater than 1024).

#define DEFAULT_PORT 50555

Now we have to create the Server object itself. There can be only one server, it has to be created through a function. The only parameter needed is the port on which the server will operate.

    GenericVRPNServer* vrpnServer = GenericVRPNServer::getInstance(DEFAULT_PORT);

Once we have an instance of the server we can add any number of buttons and analog controls to it. Each Button/Analog is identified by its name and number of outputs (buttons for Button, channels for Analog)

Let us create a Button control called “button_test” with one button and an Analog control called “analog_test” with two channels

    vrpnServer->addButton("button_test", 1);
    vrpnServer->addAnalog("analog_test", 2);

The program will use an endless loop to generate the sinusoidal signal. At each step of the loop it is necessary to call the loop() method of the server object.

        vrpnServer->loop();

In order to change the state of a button the server provides a method to call. The parameters are name, index (begins by 0) and state (0 or 1).

Note that if you want to change several buttons of one Button control you will have to call this method once for every button you want to change.

        vrpnServer->changeButtonState("button_test", 0, 1 - vrpnServer->getButtonState("button_test", 0));

The analogs behave a bit differently. The quickest method to change the values of an Analog control is to use the changeAnalogState method. It takes a name and a list of new values. Important : it is your responsibility to enter the correct number of parameters. Also assure yourself that the values you are passing are standard c++ double.

        vrpnServer->changeAnalogState("analog_test", sin(time), cos(time));

The rest of the code is self explanatory. Two examples are included, one for Windows and one for Linux. Remove the one you do not use before compilation.

Compilation and linking

In order to compile this program you will have to add the vrpn headers to the include directory. The best way is to use VRPN directly from the OpenViBE dependencies. The path is dependencies/vrpn/include. On Windows, you will get the dependencies/ directory by running scripts/win32-install-dependencies.exe of the OpenViBE source distribution.

You will have to link the executable against the vrpn library as well. On Linux you need to add -lvrpn and -lvrpnserver, on Windows vrpn.a is sufficient.

Connecting with OpenViBE

A very simple scenario will acquire data from both VRPN Button and Analog and display the information in a signal display.

This entry was posted in Connecting OpenViBE and other applications. Bookmark the permalink.