YARP
Yet Another Robot Platform
Add a plugin to YARP

In YARP, a "plugin" is an implementation of some service for which there are many choices and alternatives.

There are two basic types of plugin for YARP: devices and carriers. Devices implement interfaces to cameras, controlboards, and other hardware. Carriers implement different network protocols. Users select which devices and carriers they want to have included in YARP (or they can compile them separately).

Optional devices and carriers are enabled or disabled via CMake options. Enabling a device or carrier may require extra libraries to be installed.

Before discussing how to add new devices or carriers into the YARP library itself, we look at how a user can make their own library of plugins. This is a useful first step in getting confident about how plugins work.

Making a single plugin

Let's take the FakeFrameGrabber example device developed in Getting Started with YARP Devices and turn it into a plugin. Make a directory called "fake_grabber" (or whatever you like), and add the following as "fake_grabber/FakeFrameGrabber.h".

/*
* Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
* Copyright (C) 2006-2010 RobotCub Consortium
* All rights reserved.
*
* This software may be modified and distributed under the terms of the
* BSD-3-Clause license. See the accompanying LICENSE file for details.
*/
#include <yarp/os/all.h>
#include <yarp/dev/all.h>
private:
int w, h;
public:
h = w = 0;
}
bool open(int w, int h) {
this->w = w;
this->h = h;
return w>0 && h>0;
}
virtual bool open(yarp::os::Searchable& config) {
// extract width and height configuration, if present
// otherwise use 128x128
int desiredWidth = config.check("w",yarp::os::Value(128)).asInt32();
int desiredHeight = config.check("h",yarp::os::Value(128)).asInt32();
return open(desiredWidth,desiredHeight);
}
virtual bool close() {
return true; // easy
}
virtual int height() const {
return h;
}
virtual int width() const {
return w;
}
};

And add this as "fake_grabber/FakeFrameGrabber.cpp":

/*
* Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
* Copyright (C) 2006-2010 RobotCub Consortium
* All rights reserved.
*
* This software may be modified and distributed under the terms of the
* BSD-3-Clause license. See the accompanying LICENSE file for details.
*/
#include <yarp/os/all.h>
#include <yarp/dev/all.h>
private:
int w, h;
public:
h = w = 0;
}
bool open(int w, int h) {
this->w = w;
this->h = h;
return w>0 && h>0;
}
virtual bool open(yarp::os::Searchable& config) {
// extract width and height configuration, if present
// otherwise use 128x128
int desiredWidth = config.check("w",yarp::os::Value(128)).asInt32();
int desiredHeight = config.check("h",yarp::os::Value(128)).asInt32();
return open(desiredWidth,desiredHeight);
}
virtual bool close() {
return true; // easy
}
virtual int height() const {
return h;
}
virtual int width() const {
return w;
}
};

Here's a quick test program for the device, call it "fake_grabber/test_fake_grabber.cpp":

/*
* Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
* Copyright (C) 2006-2010 RobotCub Consortium
* All rights reserved.
*
* This software may be modified and distributed under the terms of the
* BSD-3-Clause license. See the accompanying LICENSE file for details.
*/
#include <stdio.h>
using namespace yarp::os;
using namespace yarp::sig;
using namespace yarp::dev;
int main(int argc, char *argv[]) {
DriverCreator *fake_factory =
new DriverCreatorOf<FakeFrameGrabber>("fake_grabber","grabber","FakeFrameGrabber");
Drivers::factory().add(fake_factory); // hand factory over to YARP
PolyDriver dd("fake_grabber");
if (!dd.isValid()) {
printf("fake_grabber not available\n");
return 1;
}
dd.view(grabber);
if (grabber==NULL) {
printf("*** Device failed to supply images\n");
return 1;
}
printf("*** Device can supply images\n");
if (grabber->getImage(img)) {
printf("*** Got a %dx%d image\n", img.width(), img.height());
} else {
printf("Failed to read an image\n");
return 1;
}
return 0;
}

YARP plugins need a CMakeLists.txt that says how to build them. The CMakeLists.txt is written in the following style (this would be "fake_grabber/CMakeLists.txt"):

# Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
# Copyright (C) 2006-2010 RobotCub Consortium
# All rights reserved.
#
# This software may be modified and distributed under the terms of the
# BSD-3-Clause license. See the accompanying LICENSE file for details.
cmake_minimum_required(VERSION 3.12)
find_package(YARP COMPONENTS os dev REQUIRED)
# Declare a device called "fake_grabber", with C++ type
# "FakeFrameGrabber" defined in FakeFrameGrabber.h. This code sets
# up a CMake option for selecting the device, and prepares
# some initialization boilerplate code if needed.
# If the device is not selected, "SKIP_foo" will be defined.
yarp_prepare_plugin(fake_grabber
CATEGORY device
INCLUDE FakeFrameGrabber.h
EXTRA_CONFIG WRAPPER=grabberDual)
if(NOT SKIP_fake_grabber)
yarp_add_plugin(fake_grabber)
target_sources(fake_grabber PRIVATE FakeFrameGrabber.cpp
target_link_libraries(fake_grabber PRIVATE ${YARP_LIBRARIES})
option(COMPILE_TEST "Compile fake grabber test")
if(COMPILE_TEST)
add_executable(test_fake_grabber)
target_sources(test_fake_grabber PRIVATE test_fake_grabber.cpp
target_link_libraries(test_fake_grabber PRIVATE ${YARP_LIBRARIES})
endif()
endif()

This style is used so that individual plugin directories can be compiled standalone for testing purposes, but will also work when bundled into a larger library. If we configure and compile this directory, we get a test program that we can run straight away. If it works, then we could immediately plug this device into YARP.

Making a plugin library

Here we put together a library of YARP plugins from scratch.

First, let's start with a stub test program, "userlib/test_userlib.cpp":

#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Test program stub\n");
return 0;
}

Here's a CMakeLists.txt ("userlib/CMakeLists.txt") to compile this:

cmake_minimum_required(VERSION 3.12)
find_package(YARP COMPONENTS os REQUIRED)
add_executable(test_userlib)
target_sources(test_userlib PRIVATE test_userlib.cpp)
target_link_libraries(test_userlib PRIVATE YARP::YARP_os
                                           YARP::YARP_init)

Now, let's prepare a plugin library. We need to include YarpPlugin in order to get some helper functions for this. We'll just have one plugin for now, the fake_grabber device. Here's the modified "userlib/CMakeLists.txt" file:

# Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
# Copyright (C) 2006-2010 RobotCub Consortium
# All rights reserved.
#
# This software may be modified and distributed under the terms of the
# BSD-3-Clause license. See the accompanying LICENSE file for details.
cmake_minimum_required(VERSION 3.12)
find_package(YARP COMPONENTS os dev REQUIRED)
yarp_begin_plugin_library(userlib)
add_subdirectory(fake_grabber)
yarp_end_plugin_library(userlib)
add_executable(test_userlib)
target_sources(test_userlib PRIVATE test_userlib.cpp)
target_link_libraries(test_userlib PRIVATE ${YARP_LIBRARIES})
target_link_libraries(test_userlib PRIVATE userlib)

This assumes that we have moved "fake_grabber" into the "userlib" directory.

Now, let's update our test program, "userlib/test_userlib.cpp":

/*
* Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
* Copyright (C) 2006-2010 RobotCub Consortium
* All rights reserved.
*
* This software may be modified and distributed under the terms of the
* BSD-3-Clause license. See the accompanying LICENSE file for details.
*/
#include <stdio.h>
#include <yarp/os/all.h>
#include <yarp/dev/all.h>
using namespace yarp::os;
using namespace yarp::dev;
int main(int argc, char *argv[]) {
PolyDriver dd("fake_grabber");
if (!dd.isValid()) {
printf("fake_grabber not available\n");
return 1;
}
printf("Was able to instantiate a fake_grabber\n");
return 0;
}

We can now use cmake to configure and build, either in the "userlib" directory, or in the "userlib/fake_grabber" directory. These files are available in the YARP source package, under the directory "example/plugins".

Adding a plugin into YARP

In directory ${YARP_ROOT}/src/devices/CMakeLists.txt, there is a list of device directories. We could just add another line to insert fake_grabber. There is no requirement that the fake_grabber subdirectory be in any particular location. Similarly, carriers can be added in $YARP_ROOT/src/carriers/CMakeLists.txt.

FakeFrameGrabber::height
int height() const override
Return the height of each frame.
Definition: FakeFrameGrabber.cpp:177
yarp::os::Searchable
A base class for nested structures that can be searched.
Definition: Searchable.h:69
all.h
yarp::sig
Signal processing.
Definition: Image.h:25
FakeFrameGrabber.h
yarp::dev::DriverCreatorOf
A factory for creating driver objects of a particular type.
Definition: Drivers.h:85
yarp::dev::DeviceDriver
Interface implemented by all device drivers.
Definition: DeviceDriver.h:38
FakeFrameGrabber::getImage
bool getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
Get an rgb image from the frame grabber, if required demosaicking/color reconstruction is applied.
Definition: FakeFrameGrabber.cpp:236
main
int main(int argc, char *argv[])
Definition: yarpros.cpp:261
FakeFrameGrabber::FakeFrameGrabber
FakeFrameGrabber()
Constructor.
Definition: FakeFrameGrabber.cpp:34
yarp::dev
An interface for the device drivers.
Definition: audioBufferSizeData.cpp:17
yarp::sig::ImageOf< yarp::sig::PixelRgb >
all.h
YARP_DECLARE_PLUGINS
#define YARP_DECLARE_PLUGINS(name)
Definition: Network.h:31
yarp::dev::IFrameGrabberImage
Read a YARP-format image from a device.
Definition: FrameGrabberInterfaces.h:241
YARP_REGISTER_PLUGINS
#define YARP_REGISTER_PLUGINS(name)
Definition: Network.h:32
yarp::dev::IFrameGrabberImage::getImage
virtual bool getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image)=0
Get an rgb image from the frame grabber, if required demosaicking/color reconstruction is applied.
yarp::dev::PolyDriver
A container for a device driver.
Definition: PolyDriver.h:27
yarp::dev::DriverCreator
A base class for factories that create driver objects.
Definition: Drivers.h:31
yarp::os::Searchable::check
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
FakeFrameGrabber::open
bool open(yarp::os::Searchable &config) override
Configure with a set of options.
Definition: FakeFrameGrabber.cpp:73
FakeFrameGrabber::close
bool close() override
Close the DeviceDriver.
Definition: FakeFrameGrabber.cpp:69
FakeFrameGrabber
fakeFrameGrabber: A fake camera for testing.
Definition: FakeFrameGrabber.h:45
yarp::os
An interface to the operating system, including Port based communication.
Definition: AbstractCarrier.h:17
yarp::os::Network
Utilities for manipulating the YARP network, including initialization and shutdown.
Definition: Network.h:786
yarp
The main, catch-all namespace for YARP.
Definition: environment.h:18
FakeFrameGrabber::width
int width() const override
Return the width of each frame.
Definition: FakeFrameGrabber.cpp:181
yarp::os::Value
A single value (typically within a Bottle).
Definition: Value.h:47