Configuring and compiling VRPN using the architecture-specific build scripts is described below under Compiling. You can also use CMake. In either case, be sure to have use a recursive clone or else run the command git submodule update --init in the vrpn source directory before trying to build VRPN.
The quick summary to get a server running is:
- Build vrpn_server (in Visual Studio, this is the "Main_Server" project).
- Put the sample vrpn.cfg in the same directory as the vrpn_server executable.
- Edit vrpn.cfg to uncommment whatever device(s) you have connected. (If you are using a 3DConnexion and you also want to use it to fly, you will need to uncomment an analogFly description and change it to point at the name of the 3DConnexion device).
- Run vrpn_server. (On the Mac, if you run vrpn_server by double-clicking on it, this will by default run on a terminal application in your home directory, so it will not be able to find vrpn.cfg. If you open a terminal, then cd into the directory and run it from there it will work fine.)
To test the server, you can then compile the vrpn_print_devices program and run it, giving it the names and machine for the devices you configured in vrpn.cfg (perhaps Tracker0@localhost). It will print out messages from the device and let you know that the system is working.
Writing a client-side application is described below under Client Side. The quick summary to get your application running is:
- Instantiate whichever of vrpn_Button_Remote, vrpn_Analog_Remote, or vrpn_Tracker_Remote objects you want to use.
- Write appropriate handlers for each device, and then register those handlers on the objects.
- Call the mainloop() function on each of the objects regularly to handle any new incoming messages.
- VRPN will call your handlers whenever a button is pressed, an analog changes, etc.
Writing your own server application or an application that includes both server and client objects is described on the Writing Servers page.
VR Geeks tutorials
Once you have downloaded a version of VRPN and unzipped it, you will find the vrpn/ directory , which contains the source code to the library and the applications. How you make depends on whether you are compiling using Visual C++, a command-line system (Unix, Linux or Cygwin), or CMake.
If you use CMake to build the code, then you do not need to follow the rest of the instructions listed below; all of the configuration and build options are included within the CMake build itself. Once you have run CMake, just build the resulting project in the build system you selected.
Hand-configuring and compiling
Before compiling on any architecture, you should take a look at the file vrpn_Configuration.h and see if you want to change any of the default configuration options. In particular, DirectInput is configured off by default because it requires the Direct X software development kit to be installed in order to compile VRPN. You can comment out or uncomment any of the definitions in the first section of this file to set VRPN to work the way you want it to.
Compiling on Windows
To compile on Visual C++ 6.0 under Windows, you enter the vrpn/ folder and double-click on the file vrpn.dsw, which is a workspace file. To compile under Visual Studio 2005+, you use the vrpn.sln file. You click on the "FileView" tab to show the various projects within the workspace. Some of these projects are specific to particular uses (client_and_server is an example of running VRPN client and server objects in the same application, printcereal tests a B&G CerealBox). Others are germane to standard installations (vrpn_print_devices is a good client-side test program, quat is the quaternion library, test_vrpn is a good stand-alone test program, vrpn is the library itself and vrpn_server is a generic and configurable server that can run many different devices).
To get started, build the quat, vrpn, vrpn_server, printvals and test_vrpn projects (just building test_vrpn will cause the others to build as well). You can do this by right-clicking on the name and selecting Build. VRPN will hopefully build without any warnings (If there are warnings, like in ForceDevice, ignore them unless you run into trouble later). The applications build with perhaps minor errors. The library vrpn.lib ends up in pc_win32/Debug. The executables end up in pc_win32/client_src/[SERVER_NAME]/Debug and pc_win32/server_src/[SERVER_NAME]/Debug.
Important safety tip: All projects that are used to build an application using Visual Studio must use the same code generation method. The VRPN and quat libraries are set by default to use "Multithreaded DLL" (debug or not). This must be the method used by an application, or else the settings in VRPN and quat need be changed (and then the projects cleaned and rebuilt). To set this for a project, use Project/Settings from the menu, select the C/C++ tab, then use the pull-down menu to switch from General to Code Generation. On the pull-down menu on that page, select Debug Multithreaded DLL or the option that matches your build.
Compiling on non-Windows
On other architectures, you go into the quat directory and edit makefile, uncommenting out the line that sets HW_OS for the architecture you are on. Then type gmake inside that directory. You then go into the main vrpn directory and do the same, that is, editing Makefile and typing gmake. This will compile the VRPN client and server libraries. Then, you go into the client_src subdirectory and edit Makefile and then compile with gmake (you may need to make a directory for the hw_os you select first). Then you go into the server_src subdirectory and edit Makefile and then compile with gmake. The applications will build in a subdirectory named for the hw_os you set. For example, on Linux they will build into pc_linux/.
Running the test applications
The first test of the build is to run the test_vrpn program. You can do this either by double-clicking it in explorer (in NT) or else by opening a DOS shell and going to that directory. The program should run and print messages about how it is deleting and restarting _Remote objects, and also print tracker positions, dial changes, buttons and perhaps other messages. If it runs without crashing, you're in good shape. Kill it when you're finished watching it.
The vrpn_server.exe program is a generic server that is able to control many kinds of devices. It reads the information about what devices to run from a configuration file, as described below in the Servers section. You run the server by copying the example configuration file or making your own new one that lists the devices you want. A good one to start with is to uncomment the line for the vrpn_Tracker_NULL device. You then run 'vrpn_server -f NAME_OF_YOUR_FILE.cfg'. If you require extreme low latency or have a CPU to spare, you can leave use the '-millisleep 0' option.
Windows: The other applications (vrpn_server and printvals) must be run from within a DOS shell or you must fill in the debugging field in Visual Studio because they require command-line arguments to work correctly.
The vrpn_print_devices.exe program will connect to a server and print out the results from devices at that server. You run it as 'vrpn_print_devices device@hostname', where hostname is the name of the computer that is running the server and devicename is the name of the device there (for example, Tracker0@localhost). It will begin to print reports from the device, whether it is a tracker, button, analog or dial device. You stop the program with ^C.
John Stone from the Beckman Institute provided several examples of using a Phantom (vrpn_Tracker, vrpn_Button, vrpn_ForceDevice), including hooking these to openGL programs under Irix. These can be found in the client_src/haptic directory of the source code tree.
An application uses one or more VRPN devices by creating one or more VRPN application objects. Examples and descriptions of currently-implemented client-side application objects include vrpn_Tracker_Remote, vrpn_Poser_Remote, vrpn_Button_Remote, vrpn_Analog_Remote, vrpn_Analog_Output_Remote, vrpn_Dial_Remote, vrpn_ForceDevice_Remote, and vrpn_Sound_Remote (see Devices page). Each type of object has its own include file (vrpn_Tracker.h and so on), but all are found in the VRPN library (libvrpn.a on unix systems). You can follow the links to each object type above for a detailed description of using that object type. General information is provided below.
The name of application (client) objects all begin with vrpn_ and all end with _Remote. The base class for the object (from which both client and server objects are derived) lacks the _Remote. Server objects have names specific to the device or class of devices that they serve (for example, _Fastrak for a certain kind of tracker).
Objects of each type are normally created by calling their constructor and passing the name of the device you wish to open. The name includes the local name and the name of the machine on which the device is found. For example, to open the device called Tracker0 on the machine ioceiling.cs.unc.edu, you would do the following:
#include <vrpn_Tracker.h> vrpn_Tracker_Remote myTracker("Tracker0@ioglab.cs.unc.edu");
For object types vrpn_Tracker_Remote, vrpn_Analog_Remote, vrpn_Dial_Remote, and vrpn_Button_Remote the application defines a callback function to the object. This function is called whenever a new data value is received from the device. For trackers, this callback records new tracker reports. For buttons, it reports when a button is pressed or released. Each update includes (by default) the local time at which the value changed.
For object types vrpn_Analog_Output_Remote, vrpn_Poser_Remote, vrpn_ForceDevice_Remote, and vrpn_Sound_Remote, the application calls member functions to provide commands to the remote device. VRPN handles packaging the requests and sending them to the remote device.
Examples of using each type of remote device listed above can be found on the pages describing the device itself.
mainloop() -- important to call this!
For all object types, the code should call the object's mainloop() member function once each time through the program's main loop. It is at this time that the incoming network buffers are checked and application callbacks are called, once for each incoming message. Also, for outgoing network connections, this is when the data are actually put on the wire.
In the future, shared-memory or multi-threaded VRPN connections may be created. For these, the callbacks may be called in the remote system as soon as the member function is called on the local system. For this reason, the semantics of the callback handlers is that they will be called sometime from when the member function creating the message is called until the next time mainloop() finishes on the object.