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
.
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;
}
return open(desiredWidth,desiredHeight);
}
return true;
}
return h;
}
virtual int width()
const {
return w;
}
};
fakeFrameGrabber: A fake camera for testing.
int width() const override
Return the width of each frame.
int height() const override
Return the height of each frame.
FakeFrameGrabber()=default
bool open(yarp::os::Searchable &config) override
yarp::dev::ReturnValue getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
Get an image from the frame grabber.
bool close() override
Close the DeviceDriver.
Interface implemented by all device drivers.
A base class for nested structures that can be searched.
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
A single value (typically within a Bottle).
And add this as fake_grabber/FakeFrameGrabber.cpp
:
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;
}
return open(desiredWidth,desiredHeight);
}
return true;
}
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
:
#include <stdio.h>
int main(
int argc,
char *argv[]) {
if (!dd.isValid()) {
printf(
"fake_grabber not available\n");
return 1;
}
printf(
"*** Device failed to supply images\n");
return 1;
}
printf(
"*** Device can supply images\n");
} else {
printf(
"Failed to read an image\n");
return 1;
}
return 0;
}
A factory for creating driver objects of a particular type.
A base class for factories that create driver objects.
A container for a device driver.
A mini-server for performing network communication in the background.
size_t width() const
Gets width of image in pixels.
size_t height() const
Gets height of image in pixels.
int main(int argc, char *argv[])
For streams capable of holding different kinds of content, check what they actually have.
An interface to the operating system, including Port based communication.
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
):
# SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
# SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.19)
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
EXTRA_CONFIG WRAPPER=frameGrabber_nws_yarp
)
if(NOT SKIP_fake_grabber)
yarp_add_plugin(fake_grabber)
target_sources(fake_grabber
PRIVATE
)
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.16)
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:
# SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
# SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.19)
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
:
#include <stdio.h>
int main(
int argc,
char *argv[]) {
if (!dd.isValid()) {
printf(
"fake_grabber not available\n");
return 1;
}
printf(
"Was able to instantiate a fake_grabber\n");
return 0;
}
#define YARP_DECLARE_PLUGINS(name)
#define YARP_REGISTER_PLUGINS(name)
Utilities for manipulating the YARP network, including initialization and shutdown.
The main, catch-all namespace for YARP.
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
and portmonitors in $YARP_ROOT/src/portmonitors/CMakeLists.txt
.