Pluginlib is a C++ library for loading and unloading plugins from within a ROS package. Plugins are dynamically loadable classes that are loaded from a runtime library (shared object)
Demo
Demo how to use pluginlib , the demo include 3 packages:
polygon_base expose the abstract class that the plugin need to implement
The plugin constructor need to haven't any parameters and for plugin initialization we use the init method
#pragma oncenamespacePolygonBase{classPolygon{public://! Necessary since constructor can't have parameters!virtualvoidinit(doubleside_length)=0;// 1virtualdoublearea()=0;virtual~Polygon(){}protected://! This costructor signature is required by pluginlibPolygon(){}};}// namespace PolygonBase
Build the package and expose the include folder downstream to other packages
ament_export_include_directories: exports your package’s include directories (e.g., include/) to downstream packages, making headers like provider_pkg/provider.hpp discoverable via ${provider_pkg_INCLUDE_DIRS}.
polygons
Implement plugins and build them as shared library and expose the to pluginlib infa using xml declaration
#include<cmath>#include<polygon_base/polygon.hpp>namespacePolygons{classTriangle:publicPolygonBase::Polygon{voidinit(doubleside_length){side_length_=side_length;}doublearea(){return0.5*side_length_*compute_height();}doublecompute_height(){returnsqrt((side_length_*side_length_)-((side_length_/2.0)*(side_length_/2.0)));}private:// (2) best practice to declare private as protected, but it's ok for basic typesdoubleside_length_;};}// namespace Polygons#include<pluginlib/class_list_macros.hpp> //(1)PLUGINLIB_EXPORT_CLASS(Polygons::Triangle,PolygonBase::Polygon)
Register the plugin in Pluginlib infra
Best practice to use internal variable as protected (Private members might cause issues in dynamic loading scenarios.)
cmake_minimum_required(VERSION3.8)project(polygons)if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()# find dependenciesfind_package(ament_cmakeREQUIRED)find_package(polygon_baseREQUIRED)find_package(pluginlibREQUIRED)add_library(triangleSHAREDsrc/triangle.cpp)target_compile_features(trianglePUBLICc_std_99cxx_std_17)# Require C99 and C++17ament_target_dependencies(trianglepluginlibpolygon_base)install(TARGETStriangleEXPORTexport_${PROJECT_NAME}#(2)LIBRARYDESTINATIONlib)pluginlib_export_plugin_description_file(polygon_baseplugins_triangle.xml)#(1)ament_package()
The macro PLUGINLIB_EXPORT_PLUGIN_DESCRIPTION_FILE is used in ROS 2 pluginlib to specify the plugin XML file that describes available plugins. This macro helps the pluginlib system locate and register plugins when loading them dynamically.
The install() command in CMake is used to define installation rules for compiled targets (executables, libraries, etc.). The EXPORT keyword allows us to export a CMake target so that other projects can easily find and use it.
Square Plugin
Add square plugin, for the purpose of the demo build it as separate library (so)
#pragma once#include<polygon_base/polygon.hpp>//! Namespaces must reflect what is written in plugins.xml!namespacePolygons{/** * Regular polygon with four sides. */classSquare:publicPolygonBase::Polygon{public:voidinit(doubleside_length)override;doublearea()override;//! There must not be any private members (best practice)protected:doubleside_length_;};}// namespace Polygons//! Necessary to register plugin classes with pluginlib#include<pluginlib/class_list_macros.hpp>PLUGINLIB_EXPORT_CLASS(Polygons::Square,PolygonBase::Polygon)
cmake_minimum_required(VERSION3.8)project(polygons)if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()# find dependenciesfind_package(ament_cmakeREQUIRED)find_package(polygon_baseREQUIRED)find_package(pluginlibREQUIRED)# square libraryadd_library(squareSHAREDsrc/square.cpp)target_compile_features(squarePUBLICc_std_99cxx_std_17)# Require C99 and C++17target_include_directories(squarePUBLIC$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>$<INSTALL_INTERFACE:include>)ament_target_dependencies(squarepluginlibpolygon_base)# square libraryadd_library(triangleSHAREDsrc/triangle.cpp)target_compile_features(trianglePUBLICc_std_99cxx_std_17)# Require C99 and C++17ament_target_dependencies(trianglepluginlibpolygon_base)install(TARGETSsquareEXPORTexport_${PROJECT_NAME}LIBRARYDESTINATIONlib)install(TARGETStriangleEXPORTexport_${PROJECT_NAME}LIBRARYDESTINATIONlib)#! link plugins with base class for pluginlibpluginlib_export_plugin_description_file(polygon_baseplugins.xml)pluginlib_export_plugin_description_file(polygon_baseplugins_triangle.xml)ament_package()
Polygon_app
ROS package that load the plugin dynamically and usage it